diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2024-10-29 14:49:26 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-29 14:49:26 +0800 |
| commit | f65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch) | |
| tree | ea1d61342cd29368e19135000ec2948813096205 /source/compiler-core | |
| parent | a729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff) | |
format
* format
* Minor test fixes
* enable checking cpp format in ci
Diffstat (limited to 'source/compiler-core')
103 files changed, 8489 insertions, 6423 deletions
diff --git a/source/compiler-core/slang-artifact-associated-impl.cpp b/source/compiler-core/slang-artifact-associated-impl.cpp index 07d69bf8e..cbecd1360 100644 --- a/source/compiler-core/slang-artifact-associated-impl.cpp +++ b/source/compiler-core/slang-artifact-associated-impl.cpp @@ -1,30 +1,28 @@ // slang-artifact-associated-impl.cpp #include "slang-artifact-associated-impl.h" -#include "../core/slang-file-system.h" - -#include "../core/slang-type-text-util.h" -#include "../core/slang-io.h" #include "../core/slang-array-view.h" - #include "../core/slang-char-util.h" - +#include "../core/slang-file-system.h" +#include "../core/slang-io.h" +#include "../core/slang-type-text-util.h" #include "slang-artifact-diagnostic-util.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnostics !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -ArtifactDiagnostics::ArtifactDiagnostics(const ThisType& rhs): - ComBaseObject(), - m_result(rhs.m_result), - m_diagnostics(rhs.m_diagnostics), - m_raw(rhs.m_raw.getLength() + 1) +ArtifactDiagnostics::ArtifactDiagnostics(const ThisType& rhs) + : ComBaseObject() + , m_result(rhs.m_result) + , m_diagnostics(rhs.m_diagnostics) + , m_raw(rhs.m_raw.getLength() + 1) { // We need to be careful with raw, we want a new *copy* not a non atomic ref counting // In initialization we should have enough space m_raw.append(rhs.m_raw.getUnownedSlice()); - + // Reallocate all the strings for (auto& diagnostic : m_diagnostics) { @@ -41,17 +39,15 @@ void* ArtifactDiagnostics::clone(const Guid& guid) { return ptr; } - // If the cast fails, we delete the item. + // If the cast fails, we delete the item. delete copy; return nullptr; } void* ArtifactDiagnostics::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || - guid == IClonable::getTypeGuid() || - guid == IArtifactDiagnostics::getTypeGuid()) + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || + guid == IClonable::getTypeGuid() || guid == IArtifactDiagnostics::getTypeGuid()) { return static_cast<IArtifactDiagnostics*>(this); } @@ -108,7 +104,7 @@ void ArtifactDiagnostics::appendRaw(const CharSlice& slice) m_raw << asStringSlice(slice); } -Count ArtifactDiagnostics::getCountAtLeastSeverity(Diagnostic::Severity severity) +Count ArtifactDiagnostics::getCountAtLeastSeverity(Diagnostic::Severity severity) { Index count = 0; for (const auto& msg : m_diagnostics) @@ -140,7 +136,9 @@ bool ArtifactDiagnostics::hasOfAtLeastSeverity(Diagnostic::Severity severity) return false; } -Count ArtifactDiagnostics::getCountByStage(Diagnostic::Stage stage, Count outCounts[Int(Diagnostic::Severity::CountOf)]) +Count ArtifactDiagnostics::getCountByStage( + Diagnostic::Stage stage, + Count outCounts[Int(Diagnostic::Severity::CountOf)]) { Int count = 0; ::memset(outCounts, 0, sizeof(Index) * Int(Diagnostic::Severity::CountOf)); @@ -174,7 +172,7 @@ void ArtifactDiagnostics::maybeAddNote(const CharSlice& in) ArtifactDiagnosticUtil::maybeAddNote(asStringSlice(in), this); } -void ArtifactDiagnostics::requireErrorDiagnostic() +void ArtifactDiagnostics::requireErrorDiagnostic() { // If we find an error, we don't need to add a generic diagnostic for (const auto& msg : m_diagnostics) @@ -193,19 +191,21 @@ void ArtifactDiagnostics::requireErrorDiagnostic() m_diagnostics.add(diagnostic); } -/* static */UnownedStringSlice _getSeverityText(ArtifactDiagnostic::Severity severity) +/* static */ UnownedStringSlice _getSeverityText(ArtifactDiagnostic::Severity severity) { typedef ArtifactDiagnostic::Severity Severity; switch (severity) { - default: return UnownedStringSlice::fromLiteral("Unknown"); - case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); - case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); - case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); + default: return UnownedStringSlice::fromLiteral("Unknown"); + case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); + case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); + case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); } } -static void _appendCounts(const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)], StringBuilder& out) +static void _appendCounts( + const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)], + StringBuilder& out) { typedef ArtifactDiagnostic::Severity Severity; @@ -218,7 +218,9 @@ static void _appendCounts(const Index counts[Int(ArtifactDiagnostic::Severity::C } } -static void _appendSimplified(const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)], StringBuilder& out) +static void _appendSimplified( + const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)], + StringBuilder& out) { typedef ArtifactDiagnostic::Severity Severity; for (Index i = 0; i < Int(Severity::CountOf); i++) @@ -276,8 +278,7 @@ void ArtifactDiagnostics::calcSimplifiedSummary(ISlangBlob** outBlob) void* ArtifactPostEmitMetadata::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactPostEmitMetadata::getTypeGuid()) { return static_cast<IArtifactPostEmitMetadata*>(this); @@ -304,13 +305,15 @@ void* ArtifactPostEmitMetadata::castAs(const Guid& guid) } Slice<ShaderBindingRange> ArtifactPostEmitMetadata::getUsedBindingRanges() -{ - return Slice<ShaderBindingRange>(m_usedBindings.getBuffer(), m_usedBindings.getCount()); +{ + return Slice<ShaderBindingRange>(m_usedBindings.getBuffer(), m_usedBindings.getCount()); } Slice<String> ArtifactPostEmitMetadata::getExportedFunctionMangledNames() { - return Slice<String>(m_exportedFunctionMangledNames.getBuffer(), m_exportedFunctionMangledNames.getCount()); + return Slice<String>( + m_exportedFunctionMangledNames.getBuffer(), + m_exportedFunctionMangledNames.getCount()); } SlangResult ArtifactPostEmitMetadata::isParameterLocationUsed( diff --git a/source/compiler-core/slang-artifact-associated-impl.h b/source/compiler-core/slang-artifact-associated-impl.h index d11498604..515cedb2d 100644 --- a/source/compiler-core/slang-artifact-associated-impl.h +++ b/source/compiler-core/slang-artifact-associated-impl.h @@ -2,17 +2,13 @@ #ifndef SLANG_ARTIFACT_ASSOCIATED_IMPL_H #define SLANG_ARTIFACT_ASSOCIATED_IMPL_H -#include "slang-com-helper.h" -#include "slang-com-ptr.h" - #include "../core/slang-com-object.h" #include "../core/slang-memory-arena.h" - #include "slang-artifact-associated.h" - -#include "slang-artifact-util.h" - #include "slang-artifact-diagnostic-util.h" +#include "slang-artifact-util.h" +#include "slang-com-helper.h" +#include "slang-com-ptr.h" namespace Slang { @@ -29,33 +25,61 @@ public: // IClonable SLANG_NO_THROW virtual void* SLANG_MCALL clone(const Guid& intf) SLANG_OVERRIDE; // IDiagnostic - SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) SLANG_OVERRIDE { return &m_diagnostics[i]; } - SLANG_NO_THROW virtual Count SLANG_MCALL getCount() SLANG_OVERRIDE { return m_diagnostics.getCount(); } - SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) SLANG_OVERRIDE; - SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE { m_diagnostics.removeAt(i); } + SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) SLANG_OVERRIDE + { + return &m_diagnostics[i]; + } + SLANG_NO_THROW virtual Count SLANG_MCALL getCount() SLANG_OVERRIDE + { + return m_diagnostics.getCount(); + } + SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE + { + m_diagnostics.removeAt(i); + } SLANG_NO_THROW virtual SlangResult SLANG_MCALL getResult() SLANG_OVERRIDE { return m_result; } - SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) SLANG_OVERRIDE { m_result = res; } + SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) SLANG_OVERRIDE + { + m_result = res; + } SLANG_NO_THROW virtual void SLANG_MCALL setRaw(const CharSlice& slice) SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL appendRaw(const CharSlice& slice) SLANG_OVERRIDE; - SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() SLANG_OVERRIDE { return SliceUtil::asTerminatedCharSlice(m_raw); } + SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() SLANG_OVERRIDE + { + return SliceUtil::asTerminatedCharSlice(m_raw); + } SLANG_NO_THROW virtual void SLANG_MCALL reset() SLANG_OVERRIDE; - SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; - SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; - SLANG_NO_THROW virtual bool SLANG_MCALL hasOfAtLeastSeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; - SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage(Diagnostic::Stage stage, Count outCounts[Int(Diagnostic::Severity::CountOf)]) SLANG_OVERRIDE; - SLANG_NO_THROW virtual void SLANG_MCALL removeBySeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Diagnostic::Severity severity) + SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Diagnostic::Severity severity) + SLANG_OVERRIDE; + SLANG_NO_THROW virtual bool SLANG_MCALL hasOfAtLeastSeverity(Diagnostic::Severity severity) + SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage( + Diagnostic::Stage stage, + Count outCounts[Int(Diagnostic::Severity::CountOf)]) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL removeBySeverity(Diagnostic::Severity severity) + SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL maybeAddNote(const CharSlice& in) SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL requireErrorDiagnostic() SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL calcSummary(ISlangBlob** outBlob) SLANG_OVERRIDE; - SLANG_NO_THROW virtual void SLANG_MCALL calcSimplifiedSummary(ISlangBlob** outBlob) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL calcSimplifiedSummary(ISlangBlob** outBlob) + SLANG_OVERRIDE; - /// Default ctor - ArtifactDiagnostics():ComBaseObject() {} - /// Copy ctor + /// Default ctor + ArtifactDiagnostics() + : ComBaseObject() + { + } + /// Copy ctor ArtifactDiagnostics(const ThisType& rhs); - /// Create - static ComPtr<IArtifactDiagnostics> create() { return ComPtr<IArtifactDiagnostics>(new ThisType); } + /// Create + static ComPtr<IArtifactDiagnostics> create() + { + return ComPtr<IArtifactDiagnostics>(new ThisType); + } protected: void* getInterface(const Guid& uuid); @@ -65,7 +89,7 @@ protected: List<Diagnostic> m_diagnostics; SlangResult m_result = SLANG_OK; - + // Raw diagnostics StringBuilder m_raw; }; @@ -79,17 +103,14 @@ struct ShaderBindingRange UInt registerIndex = 0; UInt registerCount = 0; // 0 for unsized - bool isInfinite() const - { - return registerCount == 0; - } + bool isInfinite() const { return registerCount == 0; } - bool containsBinding(slang::ParameterCategory _category, UInt _spaceIndex, UInt _registerIndex) const + bool containsBinding(slang::ParameterCategory _category, UInt _spaceIndex, UInt _registerIndex) + const { - return category == _category - && spaceIndex == _spaceIndex - && registerIndex <= _registerIndex - && (isInfinite() || registerCount + registerIndex > _registerIndex); + return category == _category && spaceIndex == _spaceIndex && + registerIndex <= _registerIndex && + (isInfinite() || registerCount + registerIndex > _registerIndex); } bool intersectsWith(const ShaderBindingRange& other) const @@ -97,8 +118,10 @@ struct ShaderBindingRange if (category != other.category || spaceIndex != other.spaceIndex) return false; - const bool leftIntersection = (registerIndex < other.registerIndex + other.registerCount) || other.isInfinite(); - const bool rightIntersection = (other.registerIndex < registerIndex + registerCount) || isInfinite(); + const bool leftIntersection = + (registerIndex < other.registerIndex + other.registerCount) || other.isInfinite(); + const bool rightIntersection = + (other.registerIndex < registerIndex + registerCount) || isInfinite(); return leftIntersection && rightIntersection; } @@ -108,8 +131,10 @@ struct ShaderBindingRange if (category != other.category || spaceIndex != other.spaceIndex) return false; - const bool leftIntersection = (registerIndex <= other.registerIndex + other.registerCount) || other.isInfinite(); - const bool rightIntersection = (other.registerIndex <= registerIndex + registerCount) || isInfinite(); + const bool leftIntersection = + (registerIndex <= other.registerIndex + other.registerCount) || other.isInfinite(); + const bool rightIntersection = + (other.registerIndex <= registerIndex + registerCount) || isInfinite(); return leftIntersection && rightIntersection; } @@ -121,7 +146,10 @@ struct ShaderBindingRange if (other.isInfinite()) registerCount = 0; else if (!isInfinite()) - registerCount = Math::Max(registerIndex + registerCount, other.registerIndex + other.registerCount) - newRegisterIndex; + registerCount = Math::Max( + registerIndex + registerCount, + other.registerIndex + other.registerCount) - + newRegisterIndex; registerIndex = newRegisterIndex; } @@ -134,10 +162,8 @@ struct ShaderBindingRange case slang::ShaderResource: case slang::UnorderedAccess: case slang::SamplerState: - case slang::DescriptorTableSlot: - return true; - default: - return false; + case slang::DescriptorTableSlot: return true; + default: return false; } } }; @@ -147,28 +173,33 @@ class ArtifactPostEmitMetadata : public ComBaseObject, public IArtifactPostEmitM public: typedef ArtifactPostEmitMetadata ThisType; - SLANG_CLASS_GUID(0x6f82509f, 0xe48b, 0x4b83, { 0xa3, 0x84, 0x5d, 0x70, 0x83, 0x19, 0x83, 0xcc }) + SLANG_CLASS_GUID(0x6f82509f, 0xe48b, 0x4b83, {0xa3, 0x84, 0x5d, 0x70, 0x83, 0x19, 0x83, 0xcc}) SLANG_COM_BASE_IUNKNOWN_ALL // ICastable SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - + // IArtifactPostEmitMetadata - SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getUsedBindingRanges() SLANG_OVERRIDE; - SLANG_NO_THROW virtual Slice<String> SLANG_MCALL getExportedFunctionMangledNames() SLANG_OVERRIDE; + SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getUsedBindingRanges() + SLANG_OVERRIDE; + SLANG_NO_THROW virtual Slice<String> SLANG_MCALL getExportedFunctionMangledNames() + SLANG_OVERRIDE; // IMetadata SLANG_NO_THROW virtual SlangResult SLANG_MCALL isParameterLocationUsed( SlangParameterCategory category, // is this a `t` register? `s` register? - SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan - SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan + SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan + SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan bool& outUsed) SLANG_OVERRIDE; void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - static ComPtr<IArtifactPostEmitMetadata> create() { return ComPtr<IArtifactPostEmitMetadata>(new ThisType); } + static ComPtr<IArtifactPostEmitMetadata> create() + { + return ComPtr<IArtifactPostEmitMetadata>(new ThisType); + } List<ShaderBindingRange> m_usedBindings; List<String> m_exportedFunctionMangledNames; diff --git a/source/compiler-core/slang-artifact-associated.h b/source/compiler-core/slang-artifact-associated.h index 91ae09aab..c8e74f98b 100644 --- a/source/compiler-core/slang-artifact-associated.h +++ b/source/compiler-core/slang-artifact-associated.h @@ -28,29 +28,29 @@ struct ArtifactDiagnostic struct Location { typedef Location ThisType; - bool operator==(const ThisType& rhs) const { return line == rhs.line && column == rhs.column; } + bool operator==(const ThisType& rhs) const + { + return line == rhs.line && column == rhs.column; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - Int line = 0; ///< One indexed line number. 0 if not defined - Int column = 0; ///< One indexed *character (not byte)* column number. 0 if not defined + Int line = 0; ///< One indexed line number. 0 if not defined + Int column = 0; ///< One indexed *character (not byte)* column number. 0 if not defined }; bool operator==(const ThisType& rhs) const { - return severity == rhs.severity && - stage == rhs.stage && - text == rhs.text && - code == rhs.code && - location == rhs.location; + return severity == rhs.severity && stage == rhs.stage && text == rhs.text && + code == rhs.code && location == rhs.location; } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - Severity severity = Severity::Unknown; ///< The severity of error - Stage stage = Stage::Compile; ///< The stage the error came from - TerminatedCharSlice text; ///< The text of the error - TerminatedCharSlice code; ///< The compiler specific error code - TerminatedCharSlice filePath; ///< The path the error originated from - Location location; ///< The location of the diagnostic in the filePath + Severity severity = Severity::Unknown; ///< The severity of error + Stage stage = Stage::Compile; ///< The stage the error came from + TerminatedCharSlice text; ///< The text of the error + TerminatedCharSlice code; ///< The compiler specific error code + TerminatedCharSlice filePath; ///< The path the error originated from + Location location; ///< The location of the diagnostic in the filePath }; /* Artifact diagnostics interface. @@ -60,58 +60,65 @@ IArtifactDiagnostics are added as associated types on an IArtifact typically. class IArtifactDiagnostics : public IClonable { public: - SLANG_COM_INTERFACE(0x91f9b857, 0xcd6b, 0x45ca, { 0x8e, 0x3, 0x8f, 0xa3, 0x3c, 0x5c, 0xf0, 0x1a }); + SLANG_COM_INTERFACE( + 0x91f9b857, + 0xcd6b, + 0x45ca, + {0x8e, 0x3, 0x8f, 0xa3, 0x3c, 0x5c, 0xf0, 0x1a}); typedef ArtifactDiagnostic Diagnostic; - /// Get the diagnostic at the index + /// Get the diagnostic at the index SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) = 0; - /// Get the amount of diangostics + /// Get the amount of diangostics SLANG_NO_THROW virtual Count SLANG_MCALL getCount() = 0; - /// Add a diagnostic + /// Add a diagnostic SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) = 0; - /// Remove the diagnostic at the index + /// Remove the diagnostic at the index SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) = 0; - /// Get raw diagnostics information + /// Get raw diagnostics information SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() = 0; - /// Set the raw diagnostic info + /// Set the raw diagnostic info SLANG_NO_THROW virtual void SLANG_MCALL setRaw(const CharSlice& slice) = 0; - /// Append to the raw diagnostic + /// Append to the raw diagnostic SLANG_NO_THROW virtual void SLANG_MCALL appendRaw(const CharSlice& slice) = 0; - /// Get the result for a compilation + /// Get the result for a compilation SLANG_NO_THROW virtual SlangResult SLANG_MCALL getResult() = 0; - /// Set the result + /// Set the result SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) = 0; - /// Reset all state + /// Reset all state SLANG_NO_THROW virtual void SLANG_MCALL reset() = 0; - /// Count the number of diagnostics which have 'severity' or greater - SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Diagnostic::Severity severity) = 0; + /// Count the number of diagnostics which have 'severity' or greater + SLANG_NO_THROW virtual Count SLANG_MCALL + getCountAtLeastSeverity(Diagnostic::Severity severity) = 0; - /// Get the number of diagnostics by severity + /// Get the number of diagnostics by severity SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Diagnostic::Severity severity) = 0; - /// True if there are any diagnostics of severity or worse + /// True if there are any diagnostics of severity or worse SLANG_NO_THROW virtual bool SLANG_MCALL hasOfAtLeastSeverity(Diagnostic::Severity severity) = 0; - /// Stores in outCounts, the amount of diagnostics for the stage of each severity - SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage(Diagnostic::Stage stage, Count outCounts[Int(Diagnostic::Severity::CountOf)]) = 0; + /// Stores in outCounts, the amount of diagnostics for the stage of each severity + SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage( + Diagnostic::Stage stage, + Count outCounts[Int(Diagnostic::Severity::CountOf)]) = 0; - /// Remove all diagnostics of the type + /// Remove all diagnostics of the type SLANG_NO_THROW virtual void SLANG_MCALL removeBySeverity(Diagnostic::Severity severity) = 0; - /// Add a note + /// Add a note SLANG_NO_THROW virtual void SLANG_MCALL maybeAddNote(const CharSlice& in) = 0; - /// If there are no error diagnostics, adds a generic error diagnostic + /// If there are no error diagnostics, adds a generic error diagnostic SLANG_NO_THROW virtual void SLANG_MCALL requireErrorDiagnostic() = 0; - /// Creates summary text and place in outBlob + /// Creates summary text and place in outBlob SLANG_NO_THROW virtual void SLANG_MCALL calcSummary(ISlangBlob** outBlob) = 0; - /// Creates a simplified summary text and places it in out blob + /// Creates a simplified summary text and places it in out blob SLANG_NO_THROW virtual void SLANG_MCALL calcSimplifiedSummary(ISlangBlob** outBlob) = 0; }; @@ -120,12 +127,16 @@ struct ShaderBindingRange; class IArtifactPostEmitMetadata : public slang::IMetadata { public: - SLANG_COM_INTERFACE(0x5d03bce9, 0xafb1, 0x4fc8, { 0xa4, 0x6f, 0x3c, 0xe0, 0x7b, 0x6, 0x1b, 0x1b }); + SLANG_COM_INTERFACE( + 0x5d03bce9, + 0xafb1, + 0x4fc8, + {0xa4, 0x6f, 0x3c, 0xe0, 0x7b, 0x6, 0x1b, 0x1b}); - /// Get the binding ranges + /// Get the binding ranges SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getUsedBindingRanges() = 0; - /// Get the list of functions that were exported in the linked IR + /// Get the list of functions that were exported in the linked IR SLANG_NO_THROW virtual Slice<String> SLANG_MCALL getExportedFunctionMangledNames() = 0; }; diff --git a/source/compiler-core/slang-artifact-container-util.cpp b/source/compiler-core/slang-artifact-container-util.cpp index 1c9bb5a69..935cabe8f 100644 --- a/source/compiler-core/slang-artifact-container-util.cpp +++ b/source/compiler-core/slang-artifact-container-util.cpp @@ -1,27 +1,27 @@ // slang-artifact-container-util.cpp #include "slang-artifact-container-util.h" -#include "slang-artifact-util.h" -#include "slang-artifact-desc-util.h" -#include "slang-artifact-representation-impl.h" - +#include "../core/slang-castable.h" #include "../core/slang-file-system.h" #include "../core/slang-io.h" -#include "../core/slang-zip-file-system.h" -#include "../core/slang-castable.h" #include "../core/slang-string-slice-pool.h" +#include "../core/slang-zip-file-system.h" +#include "slang-artifact-desc-util.h" +#include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" -namespace Slang { +namespace Slang +{ -/* +/* Artifact file structure ======================= -There is many ways this could work, with different trade offs. The approach taken here is -to make *every* artifact be a directory. There are two special case directories "associated" and "children", -which hold the artifacts associated/chidren artifacts. +There is many ways this could work, with different trade offs. The approach taken here is +to make *every* artifact be a directory. There are two special case directories "associated" and +"children", which hold the artifacts associated/chidren artifacts. -So for example if we have +So for example if we have ``` thing.spv @@ -53,11 +53,12 @@ associated/0a0a0a/0a0a0a.map associated/0b0b0b/0b0b0b.map ``` -That is a little verbose, but if the associated artifacts have children/associated, then things still work. +That is a little verbose, but if the associated artifacts have children/associated, then things +still work. ``` container - a.spv + a.spv associated diagnostics b.dxil @@ -127,7 +128,7 @@ struct ArtifactContainerWriter { push(name); - const char*const path = m_entry.path.getBuffer(); + const char* const path = m_entry.path.getBuffer(); SlangPathType pathType; if (SLANG_SUCCEEDED(m_fileSystem->getPathType(path, &pathType))) @@ -137,7 +138,7 @@ struct ArtifactContainerWriter return SLANG_FAIL; } } - + // Make sure there is a path to this return m_fileSystem->createDirectory(m_entry.path.getBuffer()); } @@ -150,12 +151,12 @@ struct ArtifactContainerWriter SlangResult getBaseName(IArtifact* artifact, String& out); - /// Write the artifact in the current scope + /// Write the artifact in the current scope SlangResult write(IArtifact* artifact); SlangResult writeInDirectory(IArtifact* artifact, const String& baseName); - ArtifactContainerWriter(ISlangMutableFileSystem* fileSystem): - m_fileSystem(fileSystem) + ArtifactContainerWriter(ISlangMutableFileSystem* fileSystem) + : m_fileSystem(fileSystem) { } @@ -175,11 +176,13 @@ SlangResult ArtifactContainerWriter::getBaseName(IArtifact* artifact, String& ou auto artifactName = artifact->getName(); if (artifactName && artifactName[0] != 0) { - baseName = ArtifactDescUtil::getBaseNameFromPath(artifactDesc, UnownedStringSlice(artifactName)); + baseName = ArtifactDescUtil::getBaseNameFromPath( + artifactDesc, + UnownedStringSlice(artifactName)); } } - // If we don't have name, use a generated one + // If we don't have name, use a generated one if (baseName.getLength() == 0) { baseName.append(m_entry.uniqueIndex++); @@ -194,7 +197,7 @@ SlangResult ArtifactContainerWriter::writeInDirectory(IArtifact* artifact, const // TODO(JS): // We could now output information about the desc/artifact, say as some json. // For now we assume the extension is good enough for most purposes. - + // If it's an "arbitrary" container, we don't need to write it if (artifact->getDesc().kind != ArtifactKind::Container) { @@ -204,7 +207,10 @@ SlangResult ArtifactContainerWriter::writeInDirectory(IArtifact* artifact, const // Get the name of the artifact StringBuilder artifactName; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcNameForDesc(artifact->getDesc(), baseName.getUnownedSlice(), artifactName)); + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcNameForDesc( + artifact->getDesc(), + baseName.getUnownedSlice(), + artifactName)); const auto combinedPath = Path::combine(m_entry.path, artifactName); // Write out the blob @@ -269,13 +275,22 @@ struct FileSystemContents struct IndexRange { SLANG_FORCE_INLINE Index getCount() const { return endIndex - startIndex; } - + SLANG_FORCE_INLINE Index begin() const { return startIndex; } SLANG_FORCE_INLINE Index end() const { return endIndex; } - void set(Index inStart, Index inEnd) { startIndex = inStart; endIndex = inEnd; } + void set(Index inStart, Index inEnd) + { + startIndex = inStart; + endIndex = inEnd; + } - static IndexRange make(Index inStart, Index inEnd) { IndexRange range; range.set(inStart, inEnd); return range; } + static IndexRange make(Index inStart, Index inEnd) + { + IndexRange range; + range.set(inStart, inEnd); + return range; + } Index startIndex; Index endIndex; @@ -289,7 +304,10 @@ struct FileSystemContents void setDirectory() { range.set(0, 0); } void setFile() { range.set(-1, -1); } - void setType(SlangPathType type) { (type == SLANG_PATH_TYPE_FILE) ? setFile() : setDirectory(); } + void setType(SlangPathType type) + { + (type == SLANG_PATH_TYPE_FILE) ? setFile() : setDirectory(); + } void setDirectoryRange(Index inStartIndex, Index inEndIndex) { @@ -298,33 +316,34 @@ struct FileSystemContents range.set(inStartIndex, inEndIndex); } - Index parentDirectoryIndex = -1; ///< The directory this entry is in. -1 is root. - UnownedStringSlice name; ///< Name of this entry - IndexRange range = IndexRange::make(-1, -1); ///< Default to file + Index parentDirectoryIndex = -1; ///< The directory this entry is in. -1 is root. + UnownedStringSlice name; ///< Name of this entry + IndexRange range = IndexRange::make(-1, -1); ///< Default to file }; - + void clear() { m_pool.clear(); m_entries.clear(); } - + IndexRange getContentsRange(Index index) const { return m_entries[index].range; } - - ConstArrayView<Entry> getContents(Index index) const { return getContents(m_entries[index]); } + + ConstArrayView<Entry> getContents(Index index) const { return getContents(m_entries[index]); } ConstArrayView<Entry> getContents(const Entry& entry) const { - return entry.range.getCount() ? - makeConstArrayView(m_entries.getBuffer() + entry.range.startIndex, entry.range.getCount()) : - makeConstArrayView<Entry>(nullptr, 0); + return entry.range.getCount() ? makeConstArrayView( + m_entries.getBuffer() + entry.range.startIndex, + entry.range.getCount()) + : makeConstArrayView<Entry>(nullptr, 0); } - + void appendPath(Index entryIndex, StringBuilder& buf); SlangResult find(ISlangFileSystemExt* fileSyste, const UnownedStringSlice& path); - FileSystemContents(): - m_pool(StringSlicePool::Style::Default) + FileSystemContents() + : m_pool(StringSlicePool::Style::Default) { clear(); } @@ -334,7 +353,7 @@ struct FileSystemContents FileSystemContents* contents = (FileSystemContents*)userData; Entry entry; - + entry.parentDirectoryIndex = contents->m_currentParent; entry.name = contents->m_pool.addAndGetSlice(name); entry.setType(pathType); @@ -342,10 +361,10 @@ struct FileSystemContents contents->m_entries.add(entry); } - Index m_currentParent = -1; ///< Convenience for adding entries when using enumerate + Index m_currentParent = -1; ///< Convenience for adding entries when using enumerate - StringSlicePool m_pool; ///< Holds strings - List<Entry> m_entries; ///< The entries + StringSlicePool m_pool; ///< Holds strings + List<Entry> m_entries; ///< The entries }; void FileSystemContents::appendPath(Index entryIndex, StringBuilder& buf) @@ -366,7 +385,9 @@ void FileSystemContents::appendPath(Index entryIndex, StringBuilder& buf) buf.append(entry.name); } -SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const UnownedStringSlice& inPath) +SlangResult FileSystemContents::find( + ISlangFileSystemExt* fileSystem, + const UnownedStringSlice& inPath) { clear(); @@ -400,7 +421,7 @@ SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const Unow { Entry directoryEntry; directoryEntry.setDirectory(); - + directoryEntry.name = m_pool.addAndGetSlice(inPath); m_entries.add(directoryEntry); @@ -420,12 +441,12 @@ SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const Unow const auto startIndex = m_entries.getCount(); - const char*const path = currentPath.getLength() ? currentPath.getBuffer() : "."; + const char* const path = currentPath.getLength() ? currentPath.getBuffer() : "."; const auto res = fileSystem->enumeratePathContents(path, _add, this); - + m_entries[i].setDirectoryRange(startIndex, m_entries.getCount()); - + SLANG_RETURN_ON_FAIL(res); } } @@ -436,12 +457,15 @@ SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const Unow /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactContainerUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */SlangResult ArtifactContainerUtil::writeContainer(IArtifact* artifact, const String& defaultFileName, ISlangMutableFileSystem* fileSystem) +/* static */ SlangResult ArtifactContainerUtil::writeContainer( + IArtifact* artifact, + const String& defaultFileName, + ISlangMutableFileSystem* fileSystem) { ArtifactContainerWriter writer(fileSystem); String baseName; - + { const char* name = artifact->getName(); if (name == nullptr || name[0] == 0) @@ -454,9 +478,9 @@ SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const Unow // If it's still not set try generating it. if (baseName.getLength() == 0) { - SLANG_RETURN_ON_FAIL(writer.getBaseName(artifact, baseName)); + SLANG_RETURN_ON_FAIL(writer.getBaseName(artifact, baseName)); } - + SLANG_RETURN_ON_FAIL(writer.writeInDirectory(artifact, baseName)); return SLANG_OK; @@ -472,7 +496,9 @@ static SlangResult _remove(ISlangMutableFileSystem* fileSystem, const String& pa return SLANG_OK; } -/* static */SlangResult ArtifactContainerUtil::writeContainer(IArtifact* artifact, const String& fileName) +/* static */ SlangResult ArtifactContainerUtil::writeContainer( + IArtifact* artifact, + const String& fileName) { auto osFileSystem = OSFileSystem::getMutableSingleton(); @@ -502,7 +528,7 @@ static SlangResult _remove(ISlangMutableFileSystem* fileSystem, const String& pa } else if (ext == toSlice("dir")) { - // We use the special extension "dir" to write out to a directory. + // We use the special extension "dir" to write out to a directory. // This is a little hokey arguably... auto path = Path::getPathWithoutExt(fileName); @@ -517,7 +543,8 @@ static SlangResult _remove(ISlangMutableFileSystem* fileSystem, const String& pa } // In order to write out as a artifact hierarchy we need a file system. If we don't have that - // we only write out the "main" (or root) artifact. All associated/children are typically ignored. + // we only write out the "main" (or root) artifact. All associated/children are typically + // ignored. { // Get the artifact as a blob ComPtr<ISlangBlob> containerBlob; @@ -534,9 +561,12 @@ struct ArtifactContainerReader { SlangResult read(ISlangFileSystemExt* fileSystem, ComPtr<IArtifact>& outArtifact); - /// A directory that contains multiple artifact directories - SlangResult _readContainerDirectory(Index directoryIndex, IArtifact::ContainedKind kind, IArtifact* container); - /// A directory that holds a single + /// A directory that contains multiple artifact directories + SlangResult _readContainerDirectory( + Index directoryIndex, + IArtifact::ContainedKind kind, + IArtifact* container); + /// A directory that holds a single SlangResult _readArtifactDirectory(Index directoryIndex, ComPtr<IArtifact>& outArtifact); SlangResult _readFile(Index fileIndex, ComPtr<IArtifact>& outArtifact); @@ -545,7 +575,9 @@ struct ArtifactContainerReader ISlangFileSystemExt* m_fileSystem; }; -SlangResult ArtifactContainerReader::read(ISlangFileSystemExt* fileSystem, ComPtr<IArtifact>& outArtifact) +SlangResult ArtifactContainerReader::read( + ISlangFileSystemExt* fileSystem, + ComPtr<IArtifact>& outArtifact) { m_fileSystem = fileSystem; m_contents.find(fileSystem, toSlice("")); @@ -556,7 +588,7 @@ SlangResult ArtifactContainerReader::read(ISlangFileSystemExt* fileSystem, ComPt SlangResult ArtifactContainerReader::_readFile(Index fileIndex, ComPtr<IArtifact>& outArtifact) { outArtifact.setNull(); - + const auto& entry = m_contents.m_entries[fileIndex]; SLANG_ASSERT(entry.isFile()); @@ -565,8 +597,8 @@ SlangResult ArtifactContainerReader::_readFile(Index fileIndex, ComPtr<IArtifact auto ext = Path::getPathExt(entry.name); if (ext.getLength() == 0) { - // I guess we'll assume it's an executable for now. We should use some kind of associated information/manifest - // probly + // I guess we'll assume it's an executable for now. We should use some kind of associated + // information/manifest probly desc = ArtifactDesc::make(ArtifactKind::Executable, ArtifactPayload::HostCPU); } else @@ -574,17 +606,15 @@ SlangResult ArtifactContainerReader::_readFile(Index fileIndex, ComPtr<IArtifact desc = ArtifactDescUtil::getDescFromPath(entry.name); } - // Don't know what this is. - if (desc.kind == ArtifactKind::Unknown || - desc.kind == ArtifactKind::Invalid) + // Don't know what this is. + if (desc.kind == ArtifactKind::Unknown || desc.kind == ArtifactKind::Invalid) { return SLANG_OK; } - // We don't have manifest, so for now well assume if the name ends in "-obfuscated" and it's a source map - // it's an obfuscated one - if (desc.kind == ArtifactKind::Json && - desc.payload == ArtifactPayload::SourceMap) + // We don't have manifest, so for now well assume if the name ends in "-obfuscated" and it's a + // source map it's an obfuscated one + if (desc.kind == ArtifactKind::Json && desc.payload == ArtifactPayload::SourceMap) { auto name = Path::getFileNameWithoutExt(entry.name); @@ -600,7 +630,7 @@ SlangResult ArtifactContainerReader::_readFile(Index fileIndex, ComPtr<IArtifact if (entry.name.getLength()) { // We can set the name on the artifact if set - // We know it's 0 terminated, because all names are in the pool + // We know it's 0 terminated, because all names are in the pool // and therefore have to have 0 termination artifact->setName(entry.name.begin()); } @@ -608,17 +638,21 @@ SlangResult ArtifactContainerReader::_readFile(Index fileIndex, ComPtr<IArtifact StringBuilder path; m_contents.appendPath(fileIndex, path); - IExtFileArtifactRepresentation* rep = new ExtFileArtifactRepresentation(path.getUnownedSlice(), m_fileSystem); + IExtFileArtifactRepresentation* rep = + new ExtFileArtifactRepresentation(path.getUnownedSlice(), m_fileSystem); artifact->addRepresentation(rep); - + outArtifact = artifact; return SLANG_OK; } -SlangResult ArtifactContainerReader::_readContainerDirectory(Index directoryIndex, IArtifact::ContainedKind kind, IArtifact* containerArtifact) +SlangResult ArtifactContainerReader::_readContainerDirectory( + Index directoryIndex, + IArtifact::ContainedKind kind, + IArtifact* containerArtifact) { // This directory only contains other directories which are artifacts - // Files are ignored + // Files are ignored auto indexRange = m_contents.getContentsRange(directoryIndex); @@ -635,14 +669,16 @@ SlangResult ArtifactContainerReader::_readContainerDirectory(Index directoryInde ComPtr<IArtifact> artifact; SLANG_RETURN_ON_FAIL(_readArtifactDirectory(i, artifact)); - + if (artifact) { switch (kind) { - case IArtifact::ContainedKind::Associated: containerArtifact->addAssociated(artifact); break; - case IArtifact::ContainedKind::Children: containerArtifact->addChild(artifact); break; - default: SLANG_ASSERT(!"Can't add artifact to this kind"); return SLANG_FAIL; + case IArtifact::ContainedKind::Associated: + containerArtifact->addAssociated(artifact); + break; + case IArtifact::ContainedKind::Children: containerArtifact->addChild(artifact); break; + default: SLANG_ASSERT(!"Can't add artifact to this kind"); return SLANG_FAIL; } } } @@ -650,7 +686,9 @@ SlangResult ArtifactContainerReader::_readContainerDirectory(Index directoryInde return SLANG_OK; } -SlangResult ArtifactContainerReader::_readArtifactDirectory(Index directoryIndex, ComPtr<IArtifact>& outArtifact) +SlangResult ArtifactContainerReader::_readArtifactDirectory( + Index directoryIndex, + ComPtr<IArtifact>& outArtifact) { auto indexRange = m_contents.getContentsRange(directoryIndex); @@ -667,7 +705,7 @@ SlangResult ArtifactContainerReader::_readArtifactDirectory(Index directoryIndex { ComPtr<IArtifact> readArtifact; SLANG_RETURN_ON_FAIL(_readFile(i, readArtifact)); - + if (readArtifact) { if (artifact) @@ -697,7 +735,8 @@ SlangResult ArtifactContainerReader::_readArtifactDirectory(Index directoryIndex // If we have children/associated we can assume it's a container if (childrenIndex >= 0 || associatedIndex >= 0) { - artifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::Unknown)); + artifact = ArtifactUtil::createArtifact( + ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::Unknown)); artifact->setName(m_contents.m_entries[directoryIndex].name.begin()); } else @@ -709,26 +748,32 @@ SlangResult ArtifactContainerReader::_readArtifactDirectory(Index directoryIndex if (childrenIndex >= 0) { - SLANG_RETURN_ON_FAIL(_readContainerDirectory(childrenIndex, IArtifact::ContainedKind::Children, artifact)); + SLANG_RETURN_ON_FAIL( + _readContainerDirectory(childrenIndex, IArtifact::ContainedKind::Children, artifact)); } if (associatedIndex >= 0) { - SLANG_RETURN_ON_FAIL(_readContainerDirectory(associatedIndex, IArtifact::ContainedKind::Associated, artifact)); + SLANG_RETURN_ON_FAIL(_readContainerDirectory( + associatedIndex, + IArtifact::ContainedKind::Associated, + artifact)); } outArtifact = artifact; return SLANG_OK; } -SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr<IArtifact>& outArtifact) +SlangResult ArtifactContainerUtil::readContainer( + IArtifact* artifact, + ComPtr<IArtifact>& outArtifact) { auto desc = artifact->getDesc(); ComPtr<ISlangMutableFileSystem> fileSystem; - + switch (desc.kind) { - case ArtifactKind::Zip: + case ArtifactKind::Zip: { SLANG_RETURN_ON_FAIL(ZipFileSystem::create(fileSystem)); @@ -741,10 +786,11 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr<IAr IArchiveFileSystem* archiveFileSystem = as<IArchiveFileSystem>(fileSystem); SLANG_ASSERT(archiveFileSystem); - SLANG_RETURN_ON_FAIL(archiveFileSystem->loadArchive(blob->getBufferPointer(), blob->getBufferSize())); + SLANG_RETURN_ON_FAIL( + archiveFileSystem->loadArchive(blob->getBufferPointer(), blob->getBufferSize())); break; } - default: + default: { return SLANG_FAIL; } @@ -754,7 +800,9 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr<IAr return SLANG_OK; } -/* static */SlangResult ArtifactContainerUtil::readContainer(ISlangFileSystemExt* fileSystem, ComPtr<IArtifact>& outArtifact) +/* static */ SlangResult ArtifactContainerUtil::readContainer( + ISlangFileSystemExt* fileSystem, + ComPtr<IArtifact>& outArtifact) { SLANG_UNUSED(outArtifact); @@ -764,7 +812,9 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr<IAr return SLANG_OK; } -/* static */SlangResult ArtifactContainerUtil::filter(IArtifact* artifact, ComPtr<IArtifact>& outArtifact) +/* static */ SlangResult ArtifactContainerUtil::filter( + IArtifact* artifact, + ComPtr<IArtifact>& outArtifact) { outArtifact.setNull(); @@ -821,17 +871,15 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr<IAr } } - // We only return the artifact if any of the following are true + // We only return the artifact if any of the following are true // 1) It has a blob representation // 2) It contains children or associated artifacts - if (blob || - dstArtifact->getChildren().count || - dstArtifact->getAssociated().count) + if (blob || dstArtifact->getChildren().count || dstArtifact->getAssociated().count) { outArtifact = dstArtifact; } - + // If we return an artifact or not, this was successful return SLANG_OK; } diff --git a/source/compiler-core/slang-artifact-container-util.h b/source/compiler-core/slang-artifact-container-util.h index eb0a12dfc..83090074e 100644 --- a/source/compiler-core/slang-artifact-container-util.h +++ b/source/compiler-core/slang-artifact-container-util.h @@ -3,43 +3,47 @@ #define SLANG_ARTIFACT_CONTAINER_UTIL_H #include "slang-artifact-representation.h" - #include "slang-com-helper.h" #include "slang-com-ptr.h" namespace Slang { -/* Functionality to save of and read artifact hierarchies via the slang +/* Functionality to save of and read artifact hierarchies via the slang artifact container style. This style treats storage as a file system. -Since this represention, is not directly a file system representation +Since this represention, is not directly a file system representation some conventions are used to associate data, via names etc. -The use of ISlangMutableFileSystem, allows writing this structure, to memory, zip, riff, directory +The use of ISlangMutableFileSystem, allows writing this structure, to memory, zip, riff, directory or other file like representations */ -struct ArtifactContainerUtil +struct ArtifactContainerUtil { - /// Write the container using the specified path. - /// Uses the extension of the path to determine how to write + /// Write the container using the specified path. + /// Uses the extension of the path to determine how to write static SlangResult writeContainer(IArtifact* artifact, const String& path); - /// If there isn't a suitable name on artifact, the filename is used to generate a name. If it's not set - /// a name may be generated. - static SlangResult writeContainer(IArtifact* artifact, const String& defaultFileName, ISlangMutableFileSystem* fileSystem); + /// If there isn't a suitable name on artifact, the filename is used to generate a name. If it's + /// not set a name may be generated. + static SlangResult writeContainer( + IArtifact* artifact, + const String& defaultFileName, + ISlangMutableFileSystem* fileSystem); - static SlangResult readContainer(ISlangFileSystemExt* fileSystem, ComPtr<IArtifact>& outArtifact); + static SlangResult readContainer( + ISlangFileSystemExt* fileSystem, + ComPtr<IArtifact>& outArtifact); - /// Read an artifact that represents a container as an artifact hierarchy + /// Read an artifact that represents a container as an artifact hierarchy static SlangResult readContainer(IArtifact* artifact, ComPtr<IArtifact>& outArtifact); - /// Creates a copy of artifact where - /// * All artifacts are blobs - /// * Any generic containers that are empty are dropped - /// * Any sub artifact that can't be blobed and isn't significant is ignored - /// - /// A future improvement would be to take a function to also control what makes it to the output + /// Creates a copy of artifact where + /// * All artifacts are blobs + /// * Any generic containers that are empty are dropped + /// * Any sub artifact that can't be blobed and isn't significant is ignored + /// + /// A future improvement would be to take a function to also control what makes it to the output static SlangResult filter(IArtifact* artifact, ComPtr<IArtifact>& outArtifact); }; diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index 7c2622f70..078398400 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -1,16 +1,16 @@ // slang-artifact-desc-util.cpp #include "slang-artifact-desc-util.h" -#include "slang-artifact-representation.h" - -#include "slang-artifact-impl.h" - -#include "../core/slang-type-text-util.h" #include "../core/slang-io.h" +#include "../core/slang-type-text-util.h" +#include "slang-artifact-impl.h" +#include "slang-artifact-representation.h" -namespace Slang { +namespace Slang +{ -namespace { // anonymous +namespace +{ // anonymous struct HierarchicalEnumEntry { @@ -61,7 +61,7 @@ static bool _isHierarchicalEnumOk(ConstArrayView<HierarchicalEnumEntry> entries, return true; } -template <typename T> +template<typename T> struct HierarchicalEnumTable { HierarchicalEnumTable(ConstArrayView<HierarchicalEnumEntry> entries) @@ -86,7 +86,7 @@ struct HierarchicalEnumTable m_names[value] = UnownedStringSlice(entry.name); } - // TODO(JS): NOTE! If we wanted to use parent to indicate if a value was *invalid* + // TODO(JS): NOTE! If we wanted to use parent to indicate if a value was *invalid* // we would want the Parent of Base to be Base. // // Base parent should be invalid @@ -95,17 +95,10 @@ struct HierarchicalEnumTable SLANG_ASSERT(getParent(T::Invalid) == T::Invalid); } - T getParent(T kind) const - { - return (kind >= T::CountOf) ? - T::Invalid : - m_parents[Index(kind)]; - } + T getParent(T kind) const { return (kind >= T::CountOf) ? T::Invalid : m_parents[Index(kind)]; } UnownedStringSlice getName(T kind) const { - return (kind >= T::CountOf) ? - UnownedStringSlice() : - m_names[Index(kind)]; + return (kind >= T::CountOf) ? UnownedStringSlice() : m_names[Index(kind)]; } bool isDerivedFrom(T type, T base) const @@ -132,25 +125,34 @@ protected: UnownedStringSlice m_names[Count(T::CountOf)]; }; -} // anonymous +} // namespace // Macro utils to create "enum hierarchy" tables -#define SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_ENTRY_MACRO) \ -static ConstArrayView<HierarchicalEnumEntry> _getEntries##ENUM_TYPE() \ -{ \ - static const HierarchicalEnumEntry values[] = { ENUM_TYPE_MACRO(ENUM_ENTRY_MACRO) }; \ - return makeConstArrayView(values); \ -} - -#define SLANG_HIERARCHICAL_ENUM(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ -SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ -\ -static const HierarchicalEnumTable<ENUM_TYPE> g_table##ENUM_TYPE(_getEntries##ENUM_TYPE()); \ -\ -ENUM_TYPE getParent(ENUM_TYPE kind) { return g_table##ENUM_TYPE.getParent(kind); } \ -UnownedStringSlice getName(ENUM_TYPE kind) { return g_table##ENUM_TYPE.getName(kind); } \ -bool isDerivedFrom(ENUM_TYPE kind, ENUM_TYPE base) { return g_table##ENUM_TYPE.isDerivedFrom(kind, base); } +#define SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_ENTRY_MACRO) \ + static ConstArrayView<HierarchicalEnumEntry> _getEntries##ENUM_TYPE() \ + { \ + static const HierarchicalEnumEntry values[] = {ENUM_TYPE_MACRO(ENUM_ENTRY_MACRO)}; \ + return makeConstArrayView(values); \ + } + +#define SLANG_HIERARCHICAL_ENUM(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ + SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ + \ + static const HierarchicalEnumTable<ENUM_TYPE> g_table##ENUM_TYPE(_getEntries##ENUM_TYPE()); \ + \ + ENUM_TYPE getParent(ENUM_TYPE kind) \ + { \ + return g_table##ENUM_TYPE.getParent(kind); \ + } \ + UnownedStringSlice getName(ENUM_TYPE kind) \ + { \ + return g_table##ENUM_TYPE.getName(kind); \ + } \ + bool isDerivedFrom(ENUM_TYPE kind, ENUM_TYPE base) \ + { \ + return g_table##ENUM_TYPE.isDerivedFrom(kind, base); \ + } /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactKind !!!!!!!!!!!!!!!!!!!!!!! */ @@ -245,117 +247,129 @@ SLANG_HIERARCHICAL_ENUM(ArtifactPayload, SLANG_ARTIFACT_PAYLOAD, SLANG_ARTIFACT_ x(CodeLike, Base) \ x(Kernel, CodeLike) \ x(Host, CodeLike) \ - x(Obfuscated, Base) + x(Obfuscated, Base) // clang-format on -#define SLANG_ARTIFACT_STYLE_ENTRY(TYPE, PARENT) { Index(ArtifactStyle::TYPE), Index(ArtifactStyle::PARENT), #TYPE }, +#define SLANG_ARTIFACT_STYLE_ENTRY(TYPE, PARENT) \ + {Index(ArtifactStyle::TYPE), Index(ArtifactStyle::PARENT), #TYPE}, SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYLE_ENTRY) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDescUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */ArtifactDesc ArtifactDescUtil::makeDescForCompileTarget(SlangCompileTarget target) +/* static */ ArtifactDesc ArtifactDescUtil::makeDescForCompileTarget(SlangCompileTarget target) { switch (target) { - case SLANG_TARGET_UNKNOWN: return Desc::make(Kind::Unknown, Payload::None, Style::Unknown, 0); - case SLANG_TARGET_NONE: return Desc::make(Kind::None, Payload::None, Style::Unknown, 0); - case SLANG_GLSL: + case SLANG_TARGET_UNKNOWN: return Desc::make(Kind::Unknown, Payload::None, Style::Unknown, 0); + case SLANG_TARGET_NONE: return Desc::make(Kind::None, Payload::None, Style::Unknown, 0); + case SLANG_GLSL: { // For the moment we Desc::make all just map to GLSL, but we could use flags // or some other mechanism to distinguish the types return Desc::make(Kind::Source, Payload::GLSL, Style::Kernel, 0); } - case SLANG_HLSL: return Desc::make(Kind::Source, Payload::HLSL, Style::Kernel, 0); - case SLANG_SPIRV: return Desc::make(Kind::ObjectCode, Payload::SPIRV, Style::Kernel, 0); - case SLANG_SPIRV_ASM: return Desc::make(Kind::Assembly, Payload::SPIRV, Style::Kernel, 0); - case SLANG_DXBC: return Desc::make(Kind::ObjectCode, Payload::DXBC, Style::Kernel, 0); - case SLANG_DXBC_ASM: return Desc::make(Kind::Assembly, Payload::DXBC, Style::Kernel, 0); - case SLANG_DXIL: return Desc::make(Kind::ObjectCode, Payload::DXIL, Style::Kernel, 0); - case SLANG_DXIL_ASM: return Desc::make(Kind::Assembly, Payload::DXIL, Style::Kernel, 0); - case SLANG_C_SOURCE: return Desc::make(Kind::Source, Payload::C, Style::Kernel, 0); - case SLANG_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Kernel, 0); - case SLANG_HOST_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0); - case SLANG_CPP_PYTORCH_BINDING: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0); - case SLANG_HOST_EXECUTABLE: return Desc::make(Kind::Executable, Payload::HostCPU, Style::Host, 0); - case SLANG_HOST_SHARED_LIBRARY: return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Host, 0); - case SLANG_SHADER_SHARED_LIBRARY: return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Kernel, 0); - case SLANG_SHADER_HOST_CALLABLE: return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Kernel, 0); - case SLANG_CUDA_SOURCE: return Desc::make(Kind::Source, Payload::CUDA, Style::Kernel, 0); - // TODO(JS): - // Not entirely clear how best to represent PTX here. We could mark as 'Assembly'. Saying it is - // 'Executable' implies it is Binary (which PTX isn't). Executable also implies 'complete for executation', - // irrespective of it being text. - case SLANG_PTX: return Desc::make(Kind::ObjectCode, Payload::PTX, Style::Kernel, 0); - case SLANG_OBJECT_CODE: return Desc::make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0); - case SLANG_HOST_HOST_CALLABLE: return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Host, 0); - case SLANG_METAL: return Desc::make(Kind::Source, Payload::Metal, Style::Kernel, 0); - case SLANG_METAL_LIB: return Desc::make(Kind::ObjectCode, Payload::MetalAIR, Style::Kernel, 0); - case SLANG_METAL_LIB_ASM: return Desc::make(Kind::Assembly, Payload::MetalAIR, Style::Kernel, 0); - case SLANG_WGSL: return Desc::make(Kind::Source, Payload::WGSL, Style::Kernel, 0); - case SLANG_WGSL_SPIRV_ASM: return Desc::make(Kind::Assembly, Payload::WGSL_SPIRV, Style::Kernel, 0); - case SLANG_WGSL_SPIRV: return Desc::make(Kind::ObjectCode, Payload::WGSL_SPIRV, Style::Kernel, 0); - default: break; + case SLANG_HLSL: return Desc::make(Kind::Source, Payload::HLSL, Style::Kernel, 0); + case SLANG_SPIRV: return Desc::make(Kind::ObjectCode, Payload::SPIRV, Style::Kernel, 0); + case SLANG_SPIRV_ASM: return Desc::make(Kind::Assembly, Payload::SPIRV, Style::Kernel, 0); + case SLANG_DXBC: return Desc::make(Kind::ObjectCode, Payload::DXBC, Style::Kernel, 0); + case SLANG_DXBC_ASM: return Desc::make(Kind::Assembly, Payload::DXBC, Style::Kernel, 0); + case SLANG_DXIL: return Desc::make(Kind::ObjectCode, Payload::DXIL, Style::Kernel, 0); + case SLANG_DXIL_ASM: return Desc::make(Kind::Assembly, Payload::DXIL, Style::Kernel, 0); + case SLANG_C_SOURCE: return Desc::make(Kind::Source, Payload::C, Style::Kernel, 0); + case SLANG_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Kernel, 0); + case SLANG_HOST_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0); + case SLANG_CPP_PYTORCH_BINDING: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0); + case SLANG_HOST_EXECUTABLE: + return Desc::make(Kind::Executable, Payload::HostCPU, Style::Host, 0); + case SLANG_HOST_SHARED_LIBRARY: + return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Host, 0); + case SLANG_SHADER_SHARED_LIBRARY: + return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Kernel, 0); + case SLANG_SHADER_HOST_CALLABLE: + return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Kernel, 0); + case SLANG_CUDA_SOURCE: + return Desc::make(Kind::Source, Payload::CUDA, Style::Kernel, 0); + // TODO(JS): + // Not entirely clear how best to represent PTX here. We could mark as 'Assembly'. + // Saying it is 'Executable' implies it is Binary (which PTX isn't). Executable also + // implies 'complete for executation', irrespective of it being text. + case SLANG_PTX: return Desc::make(Kind::ObjectCode, Payload::PTX, Style::Kernel, 0); + case SLANG_OBJECT_CODE: return Desc::make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0); + case SLANG_HOST_HOST_CALLABLE: + return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Host, 0); + case SLANG_METAL: return Desc::make(Kind::Source, Payload::Metal, Style::Kernel, 0); + case SLANG_METAL_LIB: return Desc::make(Kind::ObjectCode, Payload::MetalAIR, Style::Kernel, 0); + case SLANG_METAL_LIB_ASM: + return Desc::make(Kind::Assembly, Payload::MetalAIR, Style::Kernel, 0); + case SLANG_WGSL: return Desc::make(Kind::Source, Payload::WGSL, Style::Kernel, 0); + case SLANG_WGSL_SPIRV_ASM: + return Desc::make(Kind::Assembly, Payload::WGSL_SPIRV, Style::Kernel, 0); + case SLANG_WGSL_SPIRV: + return Desc::make(Kind::ObjectCode, Payload::WGSL_SPIRV, Style::Kernel, 0); + default: break; } SLANG_UNEXPECTED("Unhandled type"); } -/* static */ArtifactPayload ArtifactDescUtil::getPayloadForSourceLanaguage(SlangSourceLanguage language) +/* static */ ArtifactPayload ArtifactDescUtil::getPayloadForSourceLanaguage( + SlangSourceLanguage language) { switch (language) { - default: - case SLANG_SOURCE_LANGUAGE_UNKNOWN: return Payload::Unknown; - case SLANG_SOURCE_LANGUAGE_SLANG: return Payload::Slang; - case SLANG_SOURCE_LANGUAGE_HLSL: return Payload::HLSL; - case SLANG_SOURCE_LANGUAGE_GLSL: return Payload::GLSL; - case SLANG_SOURCE_LANGUAGE_C: return Payload::C; - case SLANG_SOURCE_LANGUAGE_CPP: return Payload::Cpp; - case SLANG_SOURCE_LANGUAGE_CUDA: return Payload::CUDA; + default: + case SLANG_SOURCE_LANGUAGE_UNKNOWN: return Payload::Unknown; + case SLANG_SOURCE_LANGUAGE_SLANG: return Payload::Slang; + case SLANG_SOURCE_LANGUAGE_HLSL: return Payload::HLSL; + case SLANG_SOURCE_LANGUAGE_GLSL: return Payload::GLSL; + case SLANG_SOURCE_LANGUAGE_C: return Payload::C; + case SLANG_SOURCE_LANGUAGE_CPP: return Payload::Cpp; + case SLANG_SOURCE_LANGUAGE_CUDA: return Payload::CUDA; } } -/* static */ArtifactDesc ArtifactDescUtil::makeDescForSourceLanguage(SlangSourceLanguage language) +/* static */ ArtifactDesc ArtifactDescUtil::makeDescForSourceLanguage(SlangSourceLanguage language) { return Desc::make(Kind::Source, getPayloadForSourceLanaguage(language), Style::Unknown, 0); } -/* static */SlangCompileTarget ArtifactDescUtil::getCompileTargetFromDesc(const ArtifactDesc& desc) +/* static */ SlangCompileTarget ArtifactDescUtil::getCompileTargetFromDesc(const ArtifactDesc& desc) { switch (desc.kind) { - case ArtifactKind::None: return SLANG_TARGET_NONE; - case ArtifactKind::Source: + case ArtifactKind::None: return SLANG_TARGET_NONE; + case ArtifactKind::Source: { switch (desc.payload) { - case Payload::HLSL: return SLANG_HLSL; - case Payload::GLSL: return SLANG_GLSL; - case Payload::C: return SLANG_C_SOURCE; - case Payload::Cpp: return (desc.style == Style::Host) ? SLANG_HOST_CPP_SOURCE : SLANG_CPP_SOURCE; - case Payload::CUDA: return SLANG_CUDA_SOURCE; - case Payload::Metal: return SLANG_METAL; - case Payload::WGSL: return SLANG_WGSL; - default: break; + case Payload::HLSL: return SLANG_HLSL; + case Payload::GLSL: return SLANG_GLSL; + case Payload::C: return SLANG_C_SOURCE; + case Payload::Cpp: + return (desc.style == Style::Host) ? SLANG_HOST_CPP_SOURCE : SLANG_CPP_SOURCE; + case Payload::CUDA: return SLANG_CUDA_SOURCE; + case Payload::Metal: return SLANG_METAL; + case Payload::WGSL: return SLANG_WGSL; + default: break; } break; } - case ArtifactKind::Assembly: + case ArtifactKind::Assembly: { switch (desc.payload) { - case Payload::SPIRV: return SLANG_SPIRV_ASM; - case Payload::DXIL: return SLANG_DXIL_ASM; - case Payload::DXBC: return SLANG_DXBC_ASM; - case Payload::PTX: return SLANG_PTX; - case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; - case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV_ASM; - default: break; + case Payload::SPIRV: return SLANG_SPIRV_ASM; + case Payload::DXIL: return SLANG_DXIL_ASM; + case Payload::DXBC: return SLANG_DXBC_ASM; + case Payload::PTX: return SLANG_PTX; + case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; + case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV_ASM; + default: break; } } - default: break; + default: break; } if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) @@ -364,24 +378,28 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL { switch (desc.kind) { - case Kind::Executable: return SLANG_HOST_EXECUTABLE; - case Kind::SharedLibrary: return desc.style == ArtifactStyle::Host ? SLANG_HOST_SHARED_LIBRARY : SLANG_SHADER_SHARED_LIBRARY; - case Kind::HostCallable: return desc.style == ArtifactStyle::Host ? SLANG_HOST_HOST_CALLABLE : SLANG_SHADER_HOST_CALLABLE; - case Kind::ObjectCode: return SLANG_OBJECT_CODE; - default: break; + case Kind::Executable: return SLANG_HOST_EXECUTABLE; + case Kind::SharedLibrary: + return desc.style == ArtifactStyle::Host ? SLANG_HOST_SHARED_LIBRARY + : SLANG_SHADER_SHARED_LIBRARY; + case Kind::HostCallable: + return desc.style == ArtifactStyle::Host ? SLANG_HOST_HOST_CALLABLE + : SLANG_SHADER_HOST_CALLABLE; + case Kind::ObjectCode: return SLANG_OBJECT_CODE; + default: break; } } else { switch (desc.payload) { - case Payload::SPIRV: return SLANG_SPIRV; - case Payload::DXIL: return SLANG_DXIL; - case Payload::DXBC: return SLANG_DXBC; - case Payload::PTX: return SLANG_PTX; - case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; - case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV; - default: break; + case Payload::SPIRV: return SLANG_SPIRV; + case Payload::DXIL: return SLANG_DXIL; + case Payload::DXBC: return SLANG_DXBC; + case Payload::PTX: return SLANG_PTX; + case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; + case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV; + default: break; } } } @@ -390,35 +408,31 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL } -namespace { // anonymous +namespace +{ // anonymous struct KindExtension { ArtifactKind kind; UnownedStringSlice ext; }; -} // anonymous +} // namespace -#define SLANG_KIND_EXTENSION(kind, ext) \ - { ArtifactKind::kind, toSlice(ext) }, +#define SLANG_KIND_EXTENSION(kind, ext) {ArtifactKind::kind, toSlice(ext)}, -static const KindExtension g_cpuKindExts[] = -{ +static const KindExtension g_cpuKindExts[] = { #if SLANG_WINDOWS_FAMILY - SLANG_KIND_EXTENSION(Library, "lib") - SLANG_KIND_EXTENSION(ObjectCode, "obj") - SLANG_KIND_EXTENSION(Executable, "exe") - SLANG_KIND_EXTENSION(SharedLibrary, "dll") -#else - SLANG_KIND_EXTENSION(Library, "a") - SLANG_KIND_EXTENSION(ObjectCode, "o") - SLANG_KIND_EXTENSION(Executable, "") + SLANG_KIND_EXTENSION(Library, "lib") SLANG_KIND_EXTENSION(ObjectCode, "obj") + SLANG_KIND_EXTENSION(Executable, "exe") SLANG_KIND_EXTENSION(SharedLibrary, "dll") +#else + SLANG_KIND_EXTENSION(Library, "a") SLANG_KIND_EXTENSION(ObjectCode, "o") + SLANG_KIND_EXTENSION(Executable, "") #if __CYGWIN__ - SLANG_KIND_EXTENSION(SharedLibrary, "dll") + SLANG_KIND_EXTENSION(SharedLibrary, "dll") #elif SLANG_APPLE_FAMILY - SLANG_KIND_EXTENSION(SharedLibrary, "dylib") + SLANG_KIND_EXTENSION(SharedLibrary, "dylib") #else - SLANG_KIND_EXTENSION(SharedLibrary, "so") + SLANG_KIND_EXTENSION(SharedLibrary, "so") #endif #endif @@ -426,10 +440,11 @@ static const KindExtension g_cpuKindExts[] = /* static */ bool ArtifactDescUtil::isCpuBinary(const ArtifactDesc& desc) { - return isDerivedFrom(desc.kind, ArtifactKind::CompileBinary) && isDerivedFrom(desc.payload, ArtifactPayload::CPULike); + return isDerivedFrom(desc.kind, ArtifactKind::CompileBinary) && + isDerivedFrom(desc.payload, ArtifactPayload::CPULike); } -/* static */bool ArtifactDescUtil::isText(const ArtifactDesc& desc) +/* static */ bool ArtifactDescUtil::isText(const ArtifactDesc& desc) { // If it's derived from text... if (isDerivedFrom(desc.kind, ArtifactKind::Text)) @@ -447,33 +462,33 @@ static const KindExtension g_cpuKindExts[] = return false; } -/* static */bool ArtifactDescUtil::isGpuUsable(const ArtifactDesc& desc) +/* static */ bool ArtifactDescUtil::isGpuUsable(const ArtifactDesc& desc) { if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) { return isDerivedFrom(desc.payload, ArtifactPayload::KernelLike); } - // PTX is a kind of special case, it's an 'assembly' (low level text represention) that can be passed - // to CUDA runtime + // PTX is a kind of special case, it's an 'assembly' (low level text represention) that can be + // passed to CUDA runtime return desc.kind == ArtifactKind::Assembly && desc.payload == ArtifactPayload::PTX; } -/* static */bool ArtifactDescUtil::isKindBinaryLinkable(Kind kind) +/* static */ bool ArtifactDescUtil::isKindBinaryLinkable(Kind kind) { switch (kind) { - case Kind::Library: - case Kind::ObjectCode: + case Kind::Library: + case Kind::ObjectCode: { return true; } - default: break; + default: break; } return false; } -/* static */bool ArtifactDescUtil::isLinkable(const ArtifactDesc& desc) +/* static */ bool ArtifactDescUtil::isLinkable(const ArtifactDesc& desc) { // If is a container with compile results *assume* that result is linkable if (isDerivedFrom(desc.kind, ArtifactKind::Container) && @@ -483,7 +498,7 @@ static const KindExtension g_cpuKindExts[] = } // if it's a compile binary or a container - if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) + if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) { if (isDerivedFrom(desc.payload, ArtifactPayload::KernelLike)) { @@ -498,8 +513,7 @@ static const KindExtension g_cpuKindExts[] = else if (isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) { // If kind is exe or shared library, linking will arguably not work - if (desc.kind == ArtifactKind::SharedLibrary || - desc.kind == ArtifactKind::Executable) + if (desc.kind == ArtifactKind::SharedLibrary || desc.kind == ArtifactKind::Executable) { return false; } @@ -515,7 +529,7 @@ static const KindExtension g_cpuKindExts[] = return false; } -/* static */bool ArtifactDescUtil::isCpuLikeTarget(const ArtifactDesc& desc) +/* static */ bool ArtifactDescUtil::isCpuLikeTarget(const ArtifactDesc& desc) { if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) { @@ -530,10 +544,9 @@ static const KindExtension g_cpuKindExts[] = return false; } -/* static */ArtifactDesc ArtifactDescUtil::getDescFromExtension(const UnownedStringSlice& slice) +/* static */ ArtifactDesc ArtifactDescUtil::getDescFromExtension(const UnownedStringSlice& slice) { - if (slice == "slang-module" || - slice == "slang-lib") + if (slice == "slang-module" || slice == "slang-lib") { return ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR); } @@ -577,7 +590,7 @@ static const KindExtension g_cpuKindExts[] = return ArtifactDesc::make(ArtifactKind::Assembly, ArtifactPayload::HostCPU); } - // TODO(JS): Unfortunately map extension is also used from output for linkage from + // TODO(JS): Unfortunately map extension is also used from output for linkage from // Visual Studio. It's used here for source map. if (slice == toSlice("map")) { @@ -604,7 +617,7 @@ static const KindExtension g_cpuKindExts[] = return makeDescForCompileTarget(target); } -/* static */ArtifactDesc ArtifactDescUtil::getDescFromPath(const UnownedStringSlice& slice) +/* static */ ArtifactDesc ArtifactDescUtil::getDescFromPath(const UnownedStringSlice& slice) { auto extension = Path::getPathExt(slice); return getDescFromExtension(extension); @@ -628,36 +641,36 @@ static UnownedStringSlice _getPayloadExtension(ArtifactPayload payload) typedef ArtifactPayload Payload; switch (payload) { - /* Source types */ - case Payload::HLSL: return toSlice("hlsl"); - case Payload::GLSL: return toSlice("glsl"); + /* Source types */ + case Payload::HLSL: return toSlice("hlsl"); + case Payload::GLSL: return toSlice("glsl"); - case Payload::Cpp: return toSlice("cpp"); - case Payload::C: return toSlice("c"); + case Payload::Cpp: return toSlice("cpp"); + case Payload::C: return toSlice("c"); - case Payload::Metal: return toSlice("metal"); + case Payload::Metal: return toSlice("metal"); - case Payload::CUDA: return toSlice("cu"); + case Payload::CUDA: return toSlice("cu"); - case Payload::Slang: return toSlice("slang"); + case Payload::Slang: return toSlice("slang"); - /* Binary types */ - case Payload::DXIL: return toSlice("dxil"); - case Payload::DXBC: return toSlice("dxbc"); - case Payload::SPIRV: return toSlice("spv"); + /* Binary types */ + case Payload::DXIL: return toSlice("dxil"); + case Payload::DXBC: return toSlice("dxbc"); + case Payload::SPIRV: return toSlice("spv"); - case Payload::PTX: return toSlice("ptx"); + case Payload::PTX: return toSlice("ptx"); - case Payload::LLVMIR: return toSlice("llvm-ir"); + case Payload::LLVMIR: return toSlice("llvm-ir"); - case Payload::SlangIR: return toSlice("slang-ir"); - - case Payload::MetalAIR: return toSlice("metallib"); + case Payload::SlangIR: return toSlice("slang-ir"); - case Payload::PdbDebugInfo: return toSlice("pdb"); - case Payload::SourceMap: return toSlice("map"); + case Payload::MetalAIR: return toSlice("metallib"); - default: break; + case Payload::PdbDebugInfo: return toSlice("pdb"); + case Payload::SourceMap: return toSlice("map"); + + default: break; } return UnownedStringSlice(); } @@ -666,7 +679,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S { switch (desc.kind) { - case ArtifactKind::Library: + case ArtifactKind::Library: { // Special cases if (desc.payload == Payload::SlangIR) @@ -680,30 +693,30 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S out << toSlice("metallib"); return SLANG_OK; } - + break; } - case ArtifactKind::Zip: + case ArtifactKind::Zip: { out << toSlice("zip"); return SLANG_OK; } - case ArtifactKind::RiffContainer: + case ArtifactKind::RiffContainer: { out << toSlice("riff"); return SLANG_OK; } - case ArtifactKind::RiffLz4Container: + case ArtifactKind::RiffLz4Container: { out << toSlice("riff-lz4"); return SLANG_OK; } - case ArtifactKind::RiffDeflateContainer: + case ArtifactKind::RiffDeflateContainer: { out << toSlice("riff-deflate"); return SLANG_OK; } - case ArtifactKind::Assembly: + case ArtifactKind::Assembly: { // Special case PTX, because it is assembly if (desc.payload == Payload::PTX) @@ -724,7 +737,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S out << toSlice("-asm"); return SLANG_OK; } - case ArtifactKind::Source: + case ArtifactKind::Source: { auto ext = _getPayloadExtension(desc.payload); if (ext.begin() != nullptr) @@ -732,10 +745,10 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S out << ext; return SLANG_OK; } - // Don't know the extension for that + // Don't know the extension for that return SLANG_E_NOT_FOUND; } - case ArtifactKind::Json: + case ArtifactKind::Json: { auto ext = _getPayloadExtension(desc.payload); if (ext.begin() != nullptr) @@ -743,8 +756,8 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S // TODO(JS): // Do we need to alter the extension or the name if it's an // obfuscated map? - //if (isDerivedFrom(desc.style, ArtifactStyle::Obfuscated)) - //{ + // if (isDerivedFrom(desc.style, ArtifactStyle::Obfuscated)) + //{ //} out << ext; @@ -755,7 +768,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S out << "json"; return SLANG_OK; } - case ArtifactKind::CompileBinary: + case ArtifactKind::CompileBinary: { if (isDerivedFrom(desc.payload, ArtifactPayload::SlangIR) || isDerivedFrom(desc.payload, ArtifactPayload::SlangAST)) @@ -765,7 +778,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S } break; } - default: break; + default: break; } if (ArtifactDescUtil::isGpuUsable(desc)) @@ -778,21 +791,26 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S } } - if (ArtifactDescUtil::isCpuLikeTarget(desc) && !isDerivedFrom(desc.payload, ArtifactPayload::Source)) + if (ArtifactDescUtil::isCpuLikeTarget(desc) && + !isDerivedFrom(desc.payload, ArtifactPayload::Source)) { return appendCpuExtensionForKind(desc.kind, out); } - + return SLANG_E_NOT_FOUND; } -/* static */String ArtifactDescUtil::getBaseNameFromPath(const ArtifactDesc& desc, const UnownedStringSlice& path) +/* static */ String ArtifactDescUtil::getBaseNameFromPath( + const ArtifactDesc& desc, + const UnownedStringSlice& path) { const String name = Path::getFileName(path); return getBaseNameFromName(desc, name.getUnownedSlice()); } -/* static */String ArtifactDescUtil::getBaseNameFromName(const ArtifactDesc& desc, const UnownedStringSlice& inName) +/* static */ String ArtifactDescUtil::getBaseNameFromName( + const ArtifactDesc& desc, + const UnownedStringSlice& inName) { String name(inName); @@ -801,8 +819,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S { // Strip lib prefix if (isCpuBinary(desc) && - (desc.kind == ArtifactKind::Library || - desc.kind == ArtifactKind::SharedLibrary)) + (desc.kind == ArtifactKind::Library || desc.kind == ArtifactKind::SharedLibrary)) { // If it starts with lib strip it if (name.startsWith("lib")) @@ -816,12 +833,11 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S // Strip any extension { StringBuilder descExt; - if (SLANG_SUCCEEDED(appendDefaultExtension(desc, descExt)) && - descExt.getLength()) + if (SLANG_SUCCEEDED(appendDefaultExtension(desc, descExt)) && descExt.getLength()) { - // TODO(JS): + // TODO(JS): // It has an extension. We could check if they are the same - // but if they are not that might be fine, because of case insensitivity + // but if they are not that might be fine, because of case insensitivity // or perhaps there are multiple valid extensions. So for now we just strip // and don't bother confirming with something like.. // if (Path::getPathExt(name) == descExt)) @@ -833,19 +849,24 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S return name; } -/* static */String ArtifactDescUtil::getBaseName(const ArtifactDesc& desc, IPathArtifactRepresentation* pathRep) +/* static */ String ArtifactDescUtil::getBaseName( + const ArtifactDesc& desc, + IPathArtifactRepresentation* pathRep) { UnownedStringSlice path(pathRep->getPath()); return getBaseNameFromPath(desc, path); } -/* static */SlangResult ArtifactDescUtil::hasDefinedNameForDesc(const ArtifactDesc& desc) +/* static */ SlangResult ArtifactDescUtil::hasDefinedNameForDesc(const ArtifactDesc& desc) { StringBuilder buf; return SLANG_SUCCEEDED(appendDefaultExtension(desc, buf)); } -/* static */SlangResult ArtifactDescUtil::calcNameForDesc(const ArtifactDesc& desc, const UnownedStringSlice& inBaseName, StringBuilder& outName) +/* static */ SlangResult ArtifactDescUtil::calcNameForDesc( + const ArtifactDesc& desc, + const UnownedStringSlice& inBaseName, + StringBuilder& outName) { UnownedStringSlice baseName(inBaseName); @@ -857,8 +878,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S // Prefix if (isCpuBinary(desc) && - (desc.kind == ArtifactKind::SharedLibrary || - desc.kind == ArtifactKind::Library)) + (desc.kind == ArtifactKind::SharedLibrary || desc.kind == ArtifactKind::Library)) { const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY; if (isSharedLibraryPrefixPlatform) @@ -889,7 +909,10 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S return SLANG_OK; } -/* static */SlangResult ArtifactDescUtil::calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath) +/* static */ SlangResult ArtifactDescUtil::calcPathForDesc( + const ArtifactDesc& desc, + const UnownedStringSlice& basePath, + StringBuilder& outPath) { outPath.clear(); @@ -914,18 +937,17 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S } } -/* static */bool ArtifactDescUtil::isDisassembly(const ArtifactDesc& from, const ArtifactDesc& to) +/* static */ bool ArtifactDescUtil::isDisassembly(const ArtifactDesc& from, const ArtifactDesc& to) { // From must be a binary like type if (!isDerivedFrom(from.kind, ArtifactKind::CompileBinary)) { return false; } - - + + // Target must be assembly, and the payload be the same type - if (!(to.kind == ArtifactKind::Assembly && - to.payload == from.payload)) + if (!(to.kind == ArtifactKind::Assembly && to.payload == from.payload)) { return false; } @@ -934,15 +956,14 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S // Check the payload seems like something plausible to 'disassemble' if (!(isDerivedFrom(payload, ArtifactPayload::KernelLike) || - isDerivedFrom(payload, ArtifactPayload::CPULike) || - isDerivedFrom(payload, ArtifactPayload::GeneralIR))) + isDerivedFrom(payload, ArtifactPayload::CPULike) || + isDerivedFrom(payload, ArtifactPayload::GeneralIR))) { return false; } // If the flags or style are different, then it's something more than just disassembly - if (!(from.style == to.style && - from.flags == to.flags)) + if (!(from.style == to.style && from.flags == to.flags)) { return false; } @@ -950,13 +971,13 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S return true; } -/* static */void ArtifactDescUtil::appendText(const ArtifactDesc& desc, StringBuilder& out) +/* static */ void ArtifactDescUtil::appendText(const ArtifactDesc& desc, StringBuilder& out) { out << getName(desc.kind) << "/" << getName(desc.payload) << "/" << getName(desc.style); // TODO(JS): Output flags? None currently used } -/* static */String ArtifactDescUtil::getText(const ArtifactDesc& desc) +/* static */ String ArtifactDescUtil::getText(const ArtifactDesc& desc) { StringBuilder buf; appendText(desc, buf); diff --git a/source/compiler-core/slang-artifact-desc-util.h b/source/compiler-core/slang-artifact-desc-util.h index 879732bb1..0c513474b 100644 --- a/source/compiler-core/slang-artifact-desc-util.h +++ b/source/compiler-core/slang-artifact-desc-util.h @@ -8,25 +8,25 @@ namespace Slang { - /// Get the parent kind +/// Get the parent kind ArtifactKind getParent(ArtifactKind kind); - /// Returns true if kind is derived from base +/// Returns true if kind is derived from base bool isDerivedFrom(ArtifactKind kind, ArtifactKind base); - /// Get the name for the kind +/// Get the name for the kind UnownedStringSlice getName(ArtifactKind kind); - /// Get the parent payload -ArtifactPayload getParent(ArtifactPayload payload); - /// Returns true if payload is derived from base +/// Get the parent payload +ArtifactPayload getParent(ArtifactPayload payload); +/// Returns true if payload is derived from base bool isDerivedFrom(ArtifactPayload payload, ArtifactPayload base); - /// Get the name for the payload +/// Get the name for the payload UnownedStringSlice getName(ArtifactPayload payload); - /// Get the parent style +/// Get the parent style ArtifactStyle getParent(ArtifactStyle style); - /// Returns true if style is derived from base +/// Returns true if style is derived from base bool isDerivedFrom(ArtifactStyle style, ArtifactStyle base); - /// Get the name for the style +/// Get the name for the style UnownedStringSlice getName(ArtifactStyle style); struct ArtifactDescUtil @@ -35,89 +35,95 @@ struct ArtifactDescUtil typedef ArtifactKind Kind; typedef ArtifactStyle Style; typedef ArtifactDesc Desc; - - /// Returns true if the kind is binary linkable + + /// Returns true if the kind is binary linkable static bool isKindBinaryLinkable(Kind kind); - /// True if is a CPU target - either + /// True if is a CPU target - either static bool isCpuLikeTarget(const ArtifactDesc& desc); - /// True if is a CPU binary + /// True if is a CPU binary static bool isCpuBinary(const ArtifactDesc& desc); - /// True if is a GPU usable (can be passed to a driver/API and be used) + /// True if is a GPU usable (can be passed to a driver/API and be used) static bool isGpuUsable(const ArtifactDesc& desc); - /// True if the desc holds textual information + /// True if the desc holds textual information static bool isText(const ArtifactDesc& desc); - /// True if artifact appears to be linkable + /// True if artifact appears to be linkable static bool isLinkable(const ArtifactDesc& desc); - /// Try to determine the desc from just a file extension (passed without .) + /// Try to determine the desc from just a file extension (passed without .) static ArtifactDesc getDescFromExtension(const UnownedStringSlice& slice); - /// Try to determine the desc from a path + /// Try to determine the desc from a path static ArtifactDesc getDescFromPath(const UnownedStringSlice& slice); - /// Appends the default file extension for the artifact type. + /// Appends the default file extension for the artifact type. static SlangResult appendDefaultExtension(const ArtifactDesc& desc, StringBuilder& out); - /// Get the extension for CPU/Host for a kind + /// Get the extension for CPU/Host for a kind static SlangResult appendCpuExtensionForKind(Kind kind, StringBuilder& out); - /// Given a desc and a path returns the base name (stripped of prefix and extension) + /// Given a desc and a path returns the base name (stripped of prefix and extension) static String getBaseNameFromPath(const ArtifactDesc& desc, const UnownedStringSlice& path); - /// Given a desc and a name returns the base name (stripped of prefix and extension) + /// Given a desc and a name returns the base name (stripped of prefix and extension) static String getBaseNameFromName(const ArtifactDesc& desc, const UnownedStringSlice& path); - /// Get the base name of the fileRep - /// If no base name is found will return an empty slice + /// Get the base name of the fileRep + /// If no base name is found will return an empty slice static String getBaseName(const ArtifactDesc& desc, IPathArtifactRepresentation* fileRep); - /// Given a desc and a basePath returns a suitable path for a entity of specified desc - static SlangResult calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath); + /// Given a desc and a basePath returns a suitable path for a entity of specified desc + static SlangResult calcPathForDesc( + const ArtifactDesc& desc, + const UnownedStringSlice& basePath, + StringBuilder& outPath); - /// Given a desc and a baseName works out the the output file name - static SlangResult calcNameForDesc(const ArtifactDesc& desc, const UnownedStringSlice& baseName, StringBuilder& outName); + /// Given a desc and a baseName works out the the output file name + static SlangResult calcNameForDesc( + const ArtifactDesc& desc, + const UnownedStringSlice& baseName, + StringBuilder& outName); - /// Returns true if there is a defined name extension/type for this desc + /// Returns true if there is a defined name extension/type for this desc static SlangResult hasDefinedNameForDesc(const ArtifactDesc& desc); - /// Given a target returns the ArtifactDesc + /// Given a target returns the ArtifactDesc static ArtifactDesc makeDescForCompileTarget(SlangCompileTarget target); - /// Get the payload for the specified language + /// Get the payload for the specified language static ArtifactPayload getPayloadForSourceLanaguage(SlangSourceLanguage language); - /// Given a source language return a desc + /// Given a source language return a desc static ArtifactDesc makeDescForSourceLanguage(SlangSourceLanguage language); - /// Returns the closest compile target for desc. Will return - /// SLANG_TARGET_UNKNOWN if not known + /// Returns the closest compile target for desc. Will return + /// SLANG_TARGET_UNKNOWN if not known static SlangCompileTarget getCompileTargetFromDesc(const ArtifactDesc& desc); - /// Make ArtifactDesc from target + /// Make ArtifactDesc from target static bool isDescDerivedFrom(const ArtifactDesc& desc, const ArtifactDesc& from); - /// True if `to` is disassembly of `from` + /// True if `to` is disassembly of `from` static bool isDisassembly(const ArtifactDesc& from, const ArtifactDesc& to); - /// Append the desc as text to out + /// Append the desc as text to out static void appendText(const ArtifactDesc& desc, StringBuilder& out); - /// Given an artifact desc return a description as a string + /// Given an artifact desc return a description as a string static String getText(const ArtifactDesc& desc); - }; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -inline /* static */bool ArtifactDescUtil::isDescDerivedFrom(const ArtifactDesc& desc, const ArtifactDesc& from) +inline /* static */ bool ArtifactDescUtil::isDescDerivedFrom( + const ArtifactDesc& desc, + const ArtifactDesc& from) { - // TODO(JS): Currently this ignores flags in desc. That may or may not be right + // TODO(JS): Currently this ignores flags in desc. That may or may not be right // long term. - return isDerivedFrom(desc.kind, from.kind) && - isDerivedFrom(desc.payload, from.payload) && - isDerivedFrom(desc.style, from.style); + return isDerivedFrom(desc.kind, from.kind) && isDerivedFrom(desc.payload, from.payload) && + isDerivedFrom(desc.style, from.style); } } // namespace Slang diff --git a/source/compiler-core/slang-artifact-diagnostic-util.cpp b/source/compiler-core/slang-artifact-diagnostic-util.cpp index 38e5c5fd8..bf1f0474b 100644 --- a/source/compiler-core/slang-artifact-diagnostic-util.cpp +++ b/source/compiler-core/slang-artifact-diagnostic-util.cpp @@ -4,22 +4,26 @@ #include "../core/slang-char-util.h" #include "../core/slang-string-util.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnosticsUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */UnownedStringSlice ArtifactDiagnosticUtil::getSeverityText(Severity severity) +/* static */ UnownedStringSlice ArtifactDiagnosticUtil::getSeverityText(Severity severity) { switch (severity) { - default: return UnownedStringSlice::fromLiteral("Unknown"); - case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); - case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); - case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); + default: return UnownedStringSlice::fromLiteral("Unknown"); + case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); + case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); + case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); } } -/* static */SlangResult ArtifactDiagnosticUtil::splitPathLocation(SliceAllocator& allocator, const UnownedStringSlice& pathLocation, ArtifactDiagnostic& outDiagnostic) +/* static */ SlangResult ArtifactDiagnosticUtil::splitPathLocation( + SliceAllocator& allocator, + const UnownedStringSlice& pathLocation, + ArtifactDiagnostic& outDiagnostic) { const Index lineStartIndex = pathLocation.lastIndexOf('('); if (lineStartIndex >= 0) @@ -37,8 +41,8 @@ namespace Slang { UnownedStringSlice slices[2]; const Index numSlices = StringUtil::split(locationSlice, ',', 2, slices); - // NOTE! FXC actually outputs a range of columns in the form of START-END in the column position - // We don't need to parse here, because we only care about the line number + // NOTE! FXC actually outputs a range of columns in the form of START-END in the column + // position We don't need to parse here, because we only care about the line number Int lineNumber = 0; if (numSlices > 0) @@ -57,7 +61,10 @@ namespace Slang { return SLANG_OK; } -/* static */SlangResult ArtifactDiagnosticUtil::splitColonDelimitedLine(const UnownedStringSlice& line, Int pathIndex, List<UnownedStringSlice>& outSlices) +/* static */ SlangResult ArtifactDiagnosticUtil::splitColonDelimitedLine( + const UnownedStringSlice& line, + Int pathIndex, + List<UnownedStringSlice>& outSlices) { StringUtil::split(line, ':', outSlices); @@ -69,7 +76,8 @@ namespace Slang { if (pathStart.getLength() == 1 && CharUtil::isAlpha(pathStart[0])) { // Splice back together - outSlices[pathIndex] = UnownedStringSlice(outSlices[pathIndex].begin(), outSlices[pathIndex + 1].end()); + outSlices[pathIndex] = + UnownedStringSlice(outSlices[pathIndex].begin(), outSlices[pathIndex + 1].end()); outSlices.removeAt(pathIndex + 1); } } @@ -77,7 +85,12 @@ namespace Slang { return SLANG_OK; } -/* static */SlangResult ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(SliceAllocator& allocator, const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, IArtifactDiagnostics* diagnostics) +/* static */ SlangResult ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics( + SliceAllocator& allocator, + const UnownedStringSlice& inText, + Int pathIndex, + LineParser lineParser, + IArtifactDiagnostics* diagnostics) { List<UnownedStringSlice> splitLine; @@ -106,7 +119,9 @@ namespace Slang { return SLANG_OK; } -/* static */void ArtifactDiagnosticUtil::maybeAddNote(const UnownedStringSlice& in, IArtifactDiagnostics* diagnostics) +/* static */ void ArtifactDiagnosticUtil::maybeAddNote( + const UnownedStringSlice& in, + IArtifactDiagnostics* diagnostics) { // Don't bother adding an empty line if (in.trim().getLength() == 0) diff --git a/source/compiler-core/slang-artifact-diagnostic-util.h b/source/compiler-core/slang-artifact-diagnostic-util.h index fe158ce38..2ccd13820 100644 --- a/source/compiler-core/slang-artifact-diagnostic-util.h +++ b/source/compiler-core/slang-artifact-diagnostic-util.h @@ -2,10 +2,8 @@ #ifndef SLANG_ARTIFACT_DIAGNOSTIC_UTIL_H #define SLANG_ARTIFACT_DIAGNOSTIC_UTIL_H -#include "slang-artifact.h" - #include "slang-artifact-associated.h" - +#include "slang-artifact.h" #include "slang-slice-allocator.h" namespace Slang @@ -18,16 +16,32 @@ struct ArtifactDiagnosticUtil /// Given severity return as text static UnownedStringSlice getSeverityText(Severity severity); - /// Given a path, that holds line number and potentially column number in () after path, writes result into outDiagnostic - static SlangResult splitPathLocation(SliceAllocator& allocator, const UnownedStringSlice& pathLocation, ArtifactDiagnostic& outDiagnostic); - - /// Split the line (separated by :), where a path is at pathIndex - static SlangResult splitColonDelimitedLine(const UnownedStringSlice& line, Int pathIndex, List<UnownedStringSlice>& outSlices); - - typedef SlangResult(*LineParser)(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic); + /// Given a path, that holds line number and potentially column number in () after path, writes + /// result into outDiagnostic + static SlangResult splitPathLocation( + SliceAllocator& allocator, + const UnownedStringSlice& pathLocation, + ArtifactDiagnostic& outDiagnostic); + + /// Split the line (separated by :), where a path is at pathIndex + static SlangResult splitColonDelimitedLine( + const UnownedStringSlice& line, + Int pathIndex, + List<UnownedStringSlice>& outSlices); + + typedef SlangResult (*LineParser)( + SliceAllocator& allocator, + const UnownedStringSlice& line, + List<UnownedStringSlice>& lineSlices, + ArtifactDiagnostic& outDiagnostic); /// Given diagnostics in inText that are colon delimited, use lineParser to do per line parsing. - static SlangResult parseColonDelimitedDiagnostics(SliceAllocator& allocator, const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, IArtifactDiagnostics* diagnostics); + static SlangResult parseColonDelimitedDiagnostics( + SliceAllocator& allocator, + const UnownedStringSlice& inText, + Int pathIndex, + LineParser lineParser, + IArtifactDiagnostics* diagnostics); /// Maybe add a note static void maybeAddNote(const UnownedStringSlice& in, IArtifactDiagnostics* diagnostics); diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp index 6fc96dc44..b19a9bd6e 100644 --- a/source/compiler-core/slang-artifact-handler-impl.cpp +++ b/source/compiler-core/slang-artifact-handler-impl.cpp @@ -1,340 +1,369 @@ // slang-artifact-handler-impl.cpp #include "slang-artifact-handler-impl.h" -#include "slang-artifact-impl.h" -#include "slang-artifact-representation-impl.h" - -#include "slang-artifact-desc-util.h" - -#include "slang-artifact-helper.h" -#include "slang-artifact-util.h" - #include "../core/slang-castable.h" - -#include "slang-slice-allocator.h" - #include "../core/slang-file-system.h" #include "../core/slang-io.h" #include "../core/slang-shared-library.h" - -#include "slang-source-map.h" - +#include "slang-artifact-desc-util.h" +#include "slang-artifact-helper.h" +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" #include "slang-json-source-map-util.h" +#include "slang-slice-allocator.h" +#include "slang-source-map.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */DefaultArtifactHandler DefaultArtifactHandler::g_singleton; +/* static */ DefaultArtifactHandler DefaultArtifactHandler::g_singleton; SlangResult DefaultArtifactHandler::queryInterface(SlangUUID const& uuid, void** outObject) { - if ([[maybe_unused]] auto ptr = getInterface(uuid)) - { + if ([[maybe_unused]] auto ptr = getInterface(uuid)) + { SLANG_ASSERT(ptr == this); - addRef(); - *outObject = static_cast<IArtifactHandler*>(this); - return SLANG_OK; - } - return SLANG_E_NO_INTERFACE; + addRef(); + *outObject = static_cast<IArtifactHandler*>(this); + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; } void* DefaultArtifactHandler::castAs(const Guid& guid) { - if (auto ptr = getInterface(guid)) - { - return ptr; - } - return getObject(guid); + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); } void* DefaultArtifactHandler::getInterface(const Guid& uuid) { - if (uuid == ISlangUnknown::getTypeGuid() || - uuid == ICastable::getTypeGuid() || - uuid == IArtifactHandler::getTypeGuid()) - { - return static_cast<IArtifactHandler*>(this); - } - - return nullptr; + if (uuid == ISlangUnknown::getTypeGuid() || uuid == ICastable::getTypeGuid() || + uuid == IArtifactHandler::getTypeGuid()) + { + return static_cast<IArtifactHandler*>(this); + } + + return nullptr; } void* DefaultArtifactHandler::getObject(const Guid& uuid) { - SLANG_UNUSED(uuid); - return nullptr; + SLANG_UNUSED(uuid); + return nullptr; } -SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable) +SlangResult DefaultArtifactHandler::_addRepresentation( + IArtifact* artifact, + ArtifactKeep keep, + ISlangUnknown* rep, + ICastable** outCastable) { - SLANG_ASSERT(rep); - - // See if it implements ICastable - { - ComPtr<ICastable> castable; - if (SLANG_SUCCEEDED(rep->queryInterface(SLANG_IID_PPV_ARGS(castable.writeRef()))) && castable) - { - return _addRepresentation(artifact, keep, castable, outCastable); - } - } - - // We have to wrap - ComPtr<IUnknownCastableAdapter> adapter(new UnknownCastableAdapter(rep)); - return _addRepresentation(artifact, keep, adapter, outCastable); + SLANG_ASSERT(rep); + + // See if it implements ICastable + { + ComPtr<ICastable> castable; + if (SLANG_SUCCEEDED(rep->queryInterface(SLANG_IID_PPV_ARGS(castable.writeRef()))) && + castable) + { + return _addRepresentation(artifact, keep, castable, outCastable); + } + } + + // We have to wrap + ComPtr<IUnknownCastableAdapter> adapter(new UnknownCastableAdapter(rep)); + return _addRepresentation(artifact, keep, adapter, outCastable); } -SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable) +SlangResult DefaultArtifactHandler::_addRepresentation( + IArtifact* artifact, + ArtifactKeep keep, + ICastable* castable, + ICastable** outCastable) { - SLANG_ASSERT(castable); + SLANG_ASSERT(castable); - if (canKeep(keep)) - { - artifact->addRepresentation(castable); - } + if (canKeep(keep)) + { + artifact->addRepresentation(castable); + } - castable->addRef(); - *outCastable = castable; - return SLANG_OK; + castable->addRef(); + *outCastable = castable; + return SLANG_OK; } SlangResult DefaultArtifactHandler::expandChildren(IArtifact* container) { - // First check if it has already been expanded - SlangResult res = container->getExpandChildrenResult(); - if (res != SLANG_E_UNINITIALIZED) - { - // It's already expanded - return res; - } - - // For the generic container type, we just expand as empty - const auto desc = container->getDesc(); + // First check if it has already been expanded + SlangResult res = container->getExpandChildrenResult(); + if (res != SLANG_E_UNINITIALIZED) + { + // It's already expanded + return res; + } + + // For the generic container type, we just expand as empty + const auto desc = container->getDesc(); if (desc.kind == ArtifactKind::Container) { // If it's just a generic container, we can assume it's expanded, and be done return SLANG_OK; } - if (isDerivedFrom(desc.kind, ArtifactKind::Container)) - { + if (isDerivedFrom(desc.kind, ArtifactKind::Container)) + { // TODO(JS): // Proper implementation should (for example) be able to expand a Zip file etc. // For now we just set that there are no children, and be done - container->setChildren(nullptr, 0); - return SLANG_E_NOT_IMPLEMENTED; - } + container->setChildren(nullptr, 0); + return SLANG_E_NOT_IMPLEMENTED; + } // We can't expand non container like types, so we just make sure it's empty container->setChildren(nullptr, 0); - return SLANG_OK; + return SLANG_OK; } -static SlangResult _loadSourceMap(IArtifact* artifact, ArtifactKeep intermediateKeep, SourceMap& outSourceMap) +static SlangResult _loadSourceMap( + IArtifact* artifact, + ArtifactKeep intermediateKeep, + SourceMap& outSourceMap) { - const auto desc = artifact->getDesc(); - if (isDerivedFrom(desc.kind, ArtifactKind::Json) && - isDerivedFrom(desc.payload, ArtifactPayload::SourceMap)) - { - ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(artifact->loadBlob(intermediateKeep, blob.writeRef())); - - SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::read(blob, outSourceMap)); - return SLANG_OK; - } - - return SLANG_FAIL; + const auto desc = artifact->getDesc(); + if (isDerivedFrom(desc.kind, ArtifactKind::Json) && + isDerivedFrom(desc.payload, ArtifactPayload::SourceMap)) + { + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(artifact->loadBlob(intermediateKeep, blob.writeRef())); + + SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::read(blob, outSourceMap)); + return SLANG_OK; + } + + return SLANG_FAIL; } -SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) +SlangResult DefaultArtifactHandler::getOrCreateRepresentation( + IArtifact* artifact, + const Guid& guid, + ArtifactKeep keep, + ICastable** outCastable) { - const auto reps = artifact->getRepresentations(); - - // See if we already have a rep of this type - for (ICastable* rep : reps) - { - if (rep->castAs(guid)) - { - rep->addRef(); - *outCastable = rep; - return SLANG_OK; - } - } - - // We can ask each representation if they can do the conversion to the type, if they can we just use that - for (ICastable* castable : reps) - { - if (auto rep = as<IArtifactRepresentation>(castable)) - { - ComPtr<ICastable> created; - if (SLANG_SUCCEEDED(rep->createRepresentation(guid, created.writeRef()))) - { - SLANG_ASSERT(created); - // Add the rep - return _addRepresentation(artifact, keep, created, outCastable); - } - } - } - - // Special cases - if (guid == SourceMap::getTypeGuid()) - { - // Blob -> SourceMap - ComPtr<IBoxValue<SourceMap>> sourceMap(new BoxValue<SourceMap>); - SLANG_RETURN_ON_FAIL(_loadSourceMap(artifact, getIntermediateKeep(keep), sourceMap->get())); - return _addRepresentation(artifact, keep, sourceMap, outCastable); - } - else if (guid == ISlangSharedLibrary::getTypeGuid()) - { - ComPtr<ISlangSharedLibrary> sharedLib; - SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, sharedLib.writeRef())); - return _addRepresentation(artifact, keep, sharedLib, outCastable); - } - else if (guid == IOSFileArtifactRepresentation::getTypeGuid()) - { - ComPtr<IOSFileArtifactRepresentation> fileRep; - SLANG_RETURN_ON_FAIL(_createOSFile(artifact, getIntermediateKeep(keep), fileRep.writeRef())); - return _addRepresentation(artifact, keep, fileRep, outCastable); - } - - // Handle known conversion to blobs - if (guid == ISlangBlob::getTypeGuid()) - { - if (auto sourceMap = findRepresentation<SourceMap>(artifact)) - { - // SourceMap -> Blob - ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::write(*sourceMap, blob)); - // Add the rep - return _addRepresentation(artifact, keep, blob, outCastable); - } - } - - return SLANG_E_NOT_AVAILABLE; + const auto reps = artifact->getRepresentations(); + + // See if we already have a rep of this type + for (ICastable* rep : reps) + { + if (rep->castAs(guid)) + { + rep->addRef(); + *outCastable = rep; + return SLANG_OK; + } + } + + // We can ask each representation if they can do the conversion to the type, if they can we just + // use that + for (ICastable* castable : reps) + { + if (auto rep = as<IArtifactRepresentation>(castable)) + { + ComPtr<ICastable> created; + if (SLANG_SUCCEEDED(rep->createRepresentation(guid, created.writeRef()))) + { + SLANG_ASSERT(created); + // Add the rep + return _addRepresentation(artifact, keep, created, outCastable); + } + } + } + + // Special cases + if (guid == SourceMap::getTypeGuid()) + { + // Blob -> SourceMap + ComPtr<IBoxValue<SourceMap>> sourceMap(new BoxValue<SourceMap>); + SLANG_RETURN_ON_FAIL(_loadSourceMap(artifact, getIntermediateKeep(keep), sourceMap->get())); + return _addRepresentation(artifact, keep, sourceMap, outCastable); + } + else if (guid == ISlangSharedLibrary::getTypeGuid()) + { + ComPtr<ISlangSharedLibrary> sharedLib; + SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, sharedLib.writeRef())); + return _addRepresentation(artifact, keep, sharedLib, outCastable); + } + else if (guid == IOSFileArtifactRepresentation::getTypeGuid()) + { + ComPtr<IOSFileArtifactRepresentation> fileRep; + SLANG_RETURN_ON_FAIL( + _createOSFile(artifact, getIntermediateKeep(keep), fileRep.writeRef())); + return _addRepresentation(artifact, keep, fileRep, outCastable); + } + + // Handle known conversion to blobs + if (guid == ISlangBlob::getTypeGuid()) + { + if (auto sourceMap = findRepresentation<SourceMap>(artifact)) + { + // SourceMap -> Blob + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::write(*sourceMap, blob)); + // Add the rep + return _addRepresentation(artifact, keep, blob, outCastable); + } + } + + return SLANG_E_NOT_AVAILABLE; } -SlangResult DefaultArtifactHandler::_createOSFile(IArtifact* artifact, ArtifactKeep keep, IOSFileArtifactRepresentation** outFileRep) +SlangResult DefaultArtifactHandler::_createOSFile( + IArtifact* artifact, + ArtifactKeep keep, + IOSFileArtifactRepresentation** outFileRep) { - // Look if we have an IExtFile representation, as we might already have a OS file associated with that - if (auto extRep = findRepresentation<IExtFileArtifactRepresentation>(artifact)) - { - auto system = extRep->getFileSystem(); - - String path; - switch (system->getOSPathKind()) - { - case OSPathKind::Direct: - { - path = UnownedStringSlice(extRep->getPath()); - break; - } - case OSPathKind::OperatingSystem: - { - ComPtr<ISlangBlob> osPathBlob; - if (SLANG_SUCCEEDED(system->getPath(PathKind::OperatingSystem, extRep->getPath(), osPathBlob.writeRef()))) - { - path = StringUtil::getString(osPathBlob); - } - break; - } - default: break; - } - - if (path.getLength()) - { - auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Reference, path.getUnownedSlice() , nullptr); - // As a sanity check make sure it exists! - if (fileRep->exists()) - { - *outFileRep = fileRep.detach(); - return SLANG_OK; - } - } - } - - // Okay looks like we will need to generate a temporary file - auto helper = DefaultArtifactHelper::getSingleton(); - - // If we are going to access as a file we need to be able to write it, and to do that we need a blob - ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(artifact->loadBlob(getIntermediateKeep(keep), blob.writeRef())); - - // Find some name associated - auto name = ArtifactUtil::findName(artifact); - if (name.getLength() == 0) - { - name = toSlice("unknown"); - } - - // Okay we need to store as a temporary. Get a lock file. - ComPtr<IOSFileArtifactRepresentation> lockFile; - SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(name), lockFile.writeRef())); - - // Now we need the appropriate name for this item - ComPtr<ISlangBlob> pathBlob; - SLANG_RETURN_ON_FAIL(helper->calcArtifactPath(artifact, lockFile->getPath(), pathBlob.writeRef())); - - const auto path = StringUtil::getSlice(pathBlob); - - // Write the contents - SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); - if(artifact->getDesc().kind == ArtifactKind::Executable) + // Look if we have an IExtFile representation, as we might already have a OS file associated + // with that + if (auto extRep = findRepresentation<IExtFileArtifactRepresentation>(artifact)) + { + auto system = extRep->getFileSystem(); + + String path; + switch (system->getOSPathKind()) + { + case OSPathKind::Direct: + { + path = UnownedStringSlice(extRep->getPath()); + break; + } + case OSPathKind::OperatingSystem: + { + ComPtr<ISlangBlob> osPathBlob; + if (SLANG_SUCCEEDED(system->getPath( + PathKind::OperatingSystem, + extRep->getPath(), + osPathBlob.writeRef()))) + { + path = StringUtil::getString(osPathBlob); + } + break; + } + default: break; + } + + if (path.getLength()) + { + auto fileRep = OSFileArtifactRepresentation::create( + IOSFileArtifactRepresentation::Kind::Reference, + path.getUnownedSlice(), + nullptr); + // As a sanity check make sure it exists! + if (fileRep->exists()) + { + *outFileRep = fileRep.detach(); + return SLANG_OK; + } + } + } + + // Okay looks like we will need to generate a temporary file + auto helper = DefaultArtifactHelper::getSingleton(); + + // If we are going to access as a file we need to be able to write it, and to do that we need a + // blob + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(artifact->loadBlob(getIntermediateKeep(keep), blob.writeRef())); + + // Find some name associated + auto name = ArtifactUtil::findName(artifact); + if (name.getLength() == 0) + { + name = toSlice("unknown"); + } + + // Okay we need to store as a temporary. Get a lock file. + ComPtr<IOSFileArtifactRepresentation> lockFile; + SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(name), lockFile.writeRef())); + + // Now we need the appropriate name for this item + ComPtr<ISlangBlob> pathBlob; + SLANG_RETURN_ON_FAIL( + helper->calcArtifactPath(artifact, lockFile->getPath(), pathBlob.writeRef())); + + const auto path = StringUtil::getSlice(pathBlob); + + // Write the contents + SLANG_RETURN_ON_FAIL( + File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); + if (artifact->getDesc().kind == ArtifactKind::Executable) { SLANG_RETURN_ON_FAIL(File::makeExecutable(path)); } - ComPtr<IOSFileArtifactRepresentation> fileRep; - - // TODO(JS): This path comparison is perhaps not perfect, in that it assumes the path is not changed - // in any way. For example an impl of calcArtifactPath that changed slashes or used a canonical path - // might mean the lock file and the rep have the same path. - // As it stands calcArtifactPath impl doesn't do that, but that is perhaps somewhatfragile - - // If the paths are identical, we can just use the lock file for the rep - if (UnownedStringSlice(lockFile->getPath()) == path) - { - fileRep.swap(lockFile); - } - else - { - // Create a new rep that references the lock file - fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Owned, path, lockFile); - } - - // Return the file - *outFileRep = fileRep.detach(); - return SLANG_OK; + ComPtr<IOSFileArtifactRepresentation> fileRep; + + // TODO(JS): This path comparison is perhaps not perfect, in that it assumes the path is not + // changed in any way. For example an impl of calcArtifactPath that changed slashes or used a + // canonical path might mean the lock file and the rep have the same path. As it stands + // calcArtifactPath impl doesn't do that, but that is perhaps somewhatfragile + + // If the paths are identical, we can just use the lock file for the rep + if (UnownedStringSlice(lockFile->getPath()) == path) + { + fileRep.swap(lockFile); + } + else + { + // Create a new rep that references the lock file + fileRep = new OSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind::Owned, + path, + lockFile); + } + + // Return the file + *outFileRep = fileRep.detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ISlangSharedLibrary** outSharedLibrary) +SlangResult DefaultArtifactHandler::_loadSharedLibrary( + IArtifact* artifact, + ISlangSharedLibrary** outSharedLibrary) { - // If it is 'shared library' for a CPU like thing, we can try and load it - const auto desc = artifact->getDesc(); - if ((isDerivedFrom(desc.kind, ArtifactKind::HostCallable) || - isDerivedFrom(desc.kind, ArtifactKind::SharedLibrary)) && - isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) - { - // Get as a file represenation on the OS file system - ComPtr<IOSFileArtifactRepresentation> fileRep; - - // We want to keep the file representation, otherwise every request, could produce a new file - // and that seems like a bad idea. - SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); - - // Try loading the shared library - SharedLibrary::Handle handle; - if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(fileRep->getPath(), handle))) - { - return SLANG_FAIL; - } - - // Output - *outSharedLibrary = ScopeSharedLibrary::create(handle, fileRep).detach(); - return SLANG_OK; - } - - return SLANG_FAIL; + // If it is 'shared library' for a CPU like thing, we can try and load it + const auto desc = artifact->getDesc(); + if ((isDerivedFrom(desc.kind, ArtifactKind::HostCallable) || + isDerivedFrom(desc.kind, ArtifactKind::SharedLibrary)) && + isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) + { + // Get as a file represenation on the OS file system + ComPtr<IOSFileArtifactRepresentation> fileRep; + + // We want to keep the file representation, otherwise every request, could produce a new + // file and that seems like a bad idea. + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); + + // Try loading the shared library + SharedLibrary::Handle handle; + if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(fileRep->getPath(), handle))) + { + return SLANG_FAIL; + } + + // Output + *outSharedLibrary = ScopeSharedLibrary::create(handle, fileRep).detach(); + return SLANG_OK; + } + + return SLANG_FAIL; } } // namespace Slang diff --git a/source/compiler-core/slang-artifact-handler-impl.h b/source/compiler-core/slang-artifact-handler-impl.h index c1cd25980..675dcd5f2 100644 --- a/source/compiler-core/slang-artifact-handler-impl.h +++ b/source/compiler-core/slang-artifact-handler-impl.h @@ -2,10 +2,9 @@ #ifndef SLANG_ARTIFACT_HANDLER_IMPL_H #define SLANG_ARTIFACT_HANDLER_IMPL_H -#include "slang-artifact.h" -#include "slang-artifact-representation.h" - #include "../core/slang-com-object.h" +#include "slang-artifact-representation.h" +#include "slang-artifact.h" namespace Slang { @@ -13,30 +12,46 @@ namespace Slang class DefaultArtifactHandler : public ComBaseObject, public IArtifactHandler { public: - SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; - - // ICastable - SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - - // IArtifactHandler - SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifact* container) SLANG_OVERRIDE; - SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) SLANG_OVERRIDE; - - static IArtifactHandler* getSingleton() { return &g_singleton; } -protected: + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) + SLANG_OVERRIDE; - SlangResult _loadSharedLibrary(IArtifact* artifact, ISlangSharedLibrary** outSharedLibrary); - SlangResult _createOSFile(IArtifact* artifact, ArtifactKeep intermediateKeep, IOSFileArtifactRepresentation** outFileRep); + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - void* getInterface(const Guid& uuid); - void* getObject(const Guid& uuid); + // IArtifactHandler + SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifact* container) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation( + IArtifact* artifact, + const Guid& guid, + ArtifactKeep keep, + ICastable** outCastable) SLANG_OVERRIDE; - SlangResult _addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable); - SlangResult _addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable); - - static DefaultArtifactHandler g_singleton; + static IArtifactHandler* getSingleton() { return &g_singleton; } + +protected: + SlangResult _loadSharedLibrary(IArtifact* artifact, ISlangSharedLibrary** outSharedLibrary); + SlangResult _createOSFile( + IArtifact* artifact, + ArtifactKeep intermediateKeep, + IOSFileArtifactRepresentation** outFileRep); + + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + SlangResult _addRepresentation( + IArtifact* artifact, + ArtifactKeep keep, + ISlangUnknown* rep, + ICastable** outCastable); + SlangResult _addRepresentation( + IArtifact* artifact, + ArtifactKeep keep, + ICastable* castable, + ICastable** outCastable); + + static DefaultArtifactHandler g_singleton; }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-helper.cpp b/source/compiler-core/slang-artifact-helper.cpp index 7f1bf1ea2..dc4d6638d 100644 --- a/source/compiler-core/slang-artifact-helper.cpp +++ b/source/compiler-core/slang-artifact-helper.cpp @@ -1,141 +1,191 @@ // slang-artifact-helper.cpp #include "slang-artifact-helper.h" -#include "slang-artifact-impl.h" -#include "slang-artifact-representation-impl.h" - -#include "slang-artifact-desc-util.h" -#include "slang-artifact-util.h" - #include "../compiler-core/slang-slice-allocator.h" - #include "../core/slang-castable.h" - #include "../core/slang-file-system.h" #include "../core/slang-io.h" #include "../core/slang-shared-library.h" +#include "slang-artifact-desc-util.h" +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHelper !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */DefaultArtifactHelper DefaultArtifactHelper::g_singleton; +/* static */ DefaultArtifactHelper DefaultArtifactHelper::g_singleton; SlangResult DefaultArtifactHelper::queryInterface(SlangUUID const& uuid, void** outObject) { - if (auto intf = getInterface(uuid)) - { - *outObject = intf; - return SLANG_OK; - } - return SLANG_E_NO_INTERFACE; + if (auto intf = getInterface(uuid)) + { + *outObject = intf; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; } void* DefaultArtifactHelper::castAs(const Guid& guid) { - if (auto ptr = getInterface(guid)) - { - return ptr; - } - return getObject(guid); + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); } void* DefaultArtifactHelper::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == IArtifactHelper::getTypeGuid()) - { - return static_cast<IArtifactHelper*>(this); - } - return nullptr; + if (guid == ISlangUnknown::getTypeGuid() || guid == IArtifactHelper::getTypeGuid()) + { + return static_cast<IArtifactHelper*>(this); + } + return nullptr; } void* DefaultArtifactHelper::getObject(const Guid& guid) { - SLANG_UNUSED(guid); - return nullptr; + SLANG_UNUSED(guid); + return nullptr; } -SlangResult DefaultArtifactHelper::createArtifact(const ArtifactDesc& desc, const char* inName, IArtifact** outArtifact) +SlangResult DefaultArtifactHelper::createArtifact( + const ArtifactDesc& desc, + const char* inName, + IArtifact** outArtifact) { - *outArtifact = inName ? - Artifact::create(desc, UnownedStringSlice(inName)).detach() : - Artifact::create(desc).detach(); + *outArtifact = inName ? Artifact::create(desc, UnownedStringSlice(inName)).detach() + : Artifact::create(desc).detach(); - return SLANG_OK; + return SLANG_OK; } -ArtifactKind DefaultArtifactHelper::getKindParent(ArtifactKind kind) { return getParent(kind); } -UnownedStringSlice DefaultArtifactHelper::getKindName(ArtifactKind kind) { return getName(kind); } -bool DefaultArtifactHelper::isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) { return isDerivedFrom(kind, base); } +ArtifactKind DefaultArtifactHelper::getKindParent(ArtifactKind kind) +{ + return getParent(kind); +} +UnownedStringSlice DefaultArtifactHelper::getKindName(ArtifactKind kind) +{ + return getName(kind); +} +bool DefaultArtifactHelper::isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) +{ + return isDerivedFrom(kind, base); +} -ArtifactPayload DefaultArtifactHelper::getPayloadParent(ArtifactPayload payload) { return getParent(payload); } -UnownedStringSlice DefaultArtifactHelper::getPayloadName(ArtifactPayload payload) { return getName(payload); } -bool DefaultArtifactHelper::isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) { return isDerivedFrom(payload, base); } +ArtifactPayload DefaultArtifactHelper::getPayloadParent(ArtifactPayload payload) +{ + return getParent(payload); +} +UnownedStringSlice DefaultArtifactHelper::getPayloadName(ArtifactPayload payload) +{ + return getName(payload); +} +bool DefaultArtifactHelper::isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) +{ + return isDerivedFrom(payload, base); +} -ArtifactStyle DefaultArtifactHelper::getStyleParent(ArtifactStyle style) { return getParent(style); } -UnownedStringSlice DefaultArtifactHelper::getStyleName(ArtifactStyle style) { return getName(style); } -bool DefaultArtifactHelper::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) { return isDerivedFrom(style, base); } +ArtifactStyle DefaultArtifactHelper::getStyleParent(ArtifactStyle style) +{ + return getParent(style); +} +UnownedStringSlice DefaultArtifactHelper::getStyleName(ArtifactStyle style) +{ + return getName(style); +} +bool DefaultArtifactHelper::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) +{ + return isDerivedFrom(style, base); +} -SlangResult DefaultArtifactHelper::createLockFile(const CharSlice& inNameBase, IOSFileArtifactRepresentation** outLockFile) +SlangResult DefaultArtifactHelper::createLockFile( + const CharSlice& inNameBase, + IOSFileArtifactRepresentation** outLockFile) { - const UnownedStringSlice nameBase = inNameBase.count ? asStringSlice(inNameBase) : UnownedStringSlice("unknown"); - String lockPath; - SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, lockPath)); - *outLockFile = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Lock, lockPath.getUnownedSlice(), nullptr).detach(); - return SLANG_OK; + const UnownedStringSlice nameBase = + inNameBase.count ? asStringSlice(inNameBase) : UnownedStringSlice("unknown"); + String lockPath; + SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, lockPath)); + *outLockFile = OSFileArtifactRepresentation::create( + IOSFileArtifactRepresentation::Kind::Lock, + lockPath.getUnownedSlice(), + nullptr) + .detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHelper::calcArtifactDescPath(const ArtifactDesc& desc, const char* inBasePath, ISlangBlob** outPath) +SlangResult DefaultArtifactHelper::calcArtifactDescPath( + const ArtifactDesc& desc, + const char* inBasePath, + ISlangBlob** outPath) { - UnownedStringSlice basePath(inBasePath); - StringBuilder path; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path)); - *outPath = StringBlob::moveCreate(path).detach(); - return SLANG_OK; + UnownedStringSlice basePath(inBasePath); + StringBuilder path; + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path)); + *outPath = StringBlob::moveCreate(path).detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHelper::calcArtifactPath(IArtifact* artifact, const char* inBasePath, ISlangBlob** outPath) +SlangResult DefaultArtifactHelper::calcArtifactPath( + IArtifact* artifact, + const char* inBasePath, + ISlangBlob** outPath) { - UnownedStringSlice basePath(inBasePath); - StringBuilder path; - SLANG_RETURN_ON_FAIL(ArtifactUtil::calcPath(artifact, basePath, path)); - *outPath = StringBlob::moveCreate(path).detach(); - return SLANG_OK; + UnownedStringSlice basePath(inBasePath); + StringBuilder path; + SLANG_RETURN_ON_FAIL(ArtifactUtil::calcPath(artifact, basePath, path)); + *outPath = StringBlob::moveCreate(path).detach(); + return SLANG_OK; } ArtifactDesc DefaultArtifactHelper::makeDescForCompileTarget(SlangCompileTarget target) { - return ArtifactDescUtil::makeDescForCompileTarget(target); + return ArtifactDescUtil::makeDescForCompileTarget(target); } void DefaultArtifactHelper::getCastable(ISlangUnknown* unk, ICastable** outCastable) { - *outCastable = CastableUtil::getCastable(unk).detach(); + *outCastable = CastableUtil::getCastable(unk).detach(); } SlangResult DefaultArtifactHelper::createOSFileArtifactRepresentation( - IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) + IOSFileArtifactRepresentation::Kind kind, + const CharSlice& path, + IOSFileArtifactRepresentation* lockFile, + IOSFileArtifactRepresentation** outRep) { - *outRep = OSFileArtifactRepresentation::create(kind, asStringSlice(path), lockFile).detach(); - return SLANG_OK; + *outRep = OSFileArtifactRepresentation::create(kind, asStringSlice(path), lockFile).detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHelper::createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) +SlangResult DefaultArtifactHelper::createExtFileArtifactRepresentation( + const CharSlice& path, + ISlangFileSystemExt* system, + IExtFileArtifactRepresentation** outRep) { - *outRep = ExtFileArtifactRepresentation::create(asStringSlice(path), system).detach(); - return SLANG_OK; + *outRep = ExtFileArtifactRepresentation::create(asStringSlice(path), system).detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHelper::createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& path, IArtifact** outArtifact) +SlangResult DefaultArtifactHelper::createOSFileArtifact( + const ArtifactDesc& desc, + const CharSlice& path, + IArtifact** outArtifact) { - auto artifact = Artifact::create(desc); + auto artifact = Artifact::create(desc); + + auto fileRep = new OSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind::Reference, + asStringSlice(path), + nullptr); + artifact->addRepresentation(fileRep); - auto fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Reference, asStringSlice(path), nullptr); - artifact->addRepresentation(fileRep); - - *outArtifact = artifact.detach(); - return SLANG_OK; + *outArtifact = artifact.detach(); + return SLANG_OK; } } // namespace Slang diff --git a/source/compiler-core/slang-artifact-helper.h b/source/compiler-core/slang-artifact-helper.h index a0d4d6b75..530a36de9 100644 --- a/source/compiler-core/slang-artifact-helper.h +++ b/source/compiler-core/slang-artifact-helper.h @@ -2,116 +2,165 @@ #ifndef SLANG_ARTIFACT_HELPER_H #define SLANG_ARTIFACT_HELPER_H -#include "slang-artifact.h" -#include "slang-artifact-representation.h" - #include "../core/slang-com-object.h" +#include "slang-artifact-representation.h" +#include "slang-artifact.h" namespace Slang { class IArtifactHelper : public ICastable { - SLANG_COM_INTERFACE(0x882b25d7, 0xe300, 0x4b20, { 0xbe, 0xb, 0x26, 0xd2, 0x52, 0x3e, 0x70, 0x20 }) - - /// Create an artifact - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) = 0; - - /// Get the parent to a kind - virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) = 0; - /// Get the name of a kind - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) = 0; - /// Returns true if kind is derived from base - virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) = 0; - - /// Get the parent payload for payload - virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) = 0; - /// Get the payload name text - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) = 0; - /// Returns true if payload is derived from base - virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) = 0; - - /// Get the parent type of a style - virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) = 0; - /// Get text name for a style - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) = 0; - /// Returns true if style is derived from base - virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0; - - /// Create a lock file, the path of which can be used to generate other temporary files - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const CharSlice& nameBase, IOSFileArtifactRepresentation** outLockFile) = 0; - - /// Given a desc and a basePath returns a suitable name - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0; - - /// Given an artifact and a basePath returns a suitable name - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(IArtifact* , const char* basePath, ISlangBlob** outPath) = 0; - - /// Given a compile target return the equivalent desc - virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescForCompileTarget(SlangCompileTarget target) = 0; - - /// Given an interface returns as a castable interface. This might just cast unk into ICastable, or wrap it such that it uses the castable interface - virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) = 0; - - /// Create a file rep - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( - IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) = 0; + SLANG_COM_INTERFACE(0x882b25d7, 0xe300, 0x4b20, {0xbe, 0xb, 0x26, 0xd2, 0x52, 0x3e, 0x70, 0x20}) + + /// Create an artifact + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) = 0; + + /// Get the parent to a kind + virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) = 0; + /// Get the name of a kind + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) = 0; + /// Returns true if kind is derived from base + virtual SLANG_NO_THROW bool SLANG_MCALL + isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) = 0; + + /// Get the parent payload for payload + virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL + getPayloadParent(ArtifactPayload payload) = 0; + /// Get the payload name text + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL + getPayloadName(ArtifactPayload payload) = 0; + /// Returns true if payload is derived from base + virtual SLANG_NO_THROW bool SLANG_MCALL + isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) = 0; + + /// Get the parent type of a style + virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) = 0; + /// Get text name for a style + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) = 0; + /// Returns true if style is derived from base + virtual SLANG_NO_THROW bool SLANG_MCALL + isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0; + + /// Create a lock file, the path of which can be used to generate other temporary files + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createLockFile(const CharSlice& nameBase, IOSFileArtifactRepresentation** outLockFile) = 0; + + /// Given a desc and a basePath returns a suitable name + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0; + + /// Given an artifact and a basePath returns a suitable name + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + calcArtifactPath(IArtifact*, const char* basePath, ISlangBlob** outPath) = 0; + + /// Given a compile target return the equivalent desc + virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL + makeDescForCompileTarget(SlangCompileTarget target) = 0; + + /// Given an interface returns as a castable interface. This might just cast unk into ICastable, + /// or wrap it such that it uses the castable interface + virtual SLANG_NO_THROW void SLANG_MCALL + getCastable(ISlangUnknown* unk, ICastable** outCastable) = 0; + + /// Create a file rep + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind kind, + const CharSlice& path, + IOSFileArtifactRepresentation* lockFile, + IOSFileArtifactRepresentation** outRep) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation( + const CharSlice& path, + ISlangFileSystemExt* system, + IExtFileArtifactRepresentation** outRep) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact( + const ArtifactDesc& desc, + const CharSlice& slice, + IArtifact** outArtifact) = 0; }; class DefaultArtifactHelper : public IArtifactHelper { public: - // ISlangUnknown - SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; - - // ICastable - SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - - // IArtifactHelper - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) SLANG_OVERRIDE; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) SLANG_OVERRIDE; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) SLANG_OVERRIDE; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const CharSlice& nameBase, IOSFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(IArtifact*, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescForCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( - IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) SLANG_OVERRIDE; - - static IArtifactHelper* getSingleton() { return &g_singleton; } + // ISlangUnknown + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) + SLANG_OVERRIDE; + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IArtifactHelper + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact( + const ArtifactDesc& desc, + const char* name, + IArtifact** outArtifact) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) + SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile( + const CharSlice& nameBase, + IOSFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath( + const ArtifactDesc& desc, + const char* basePath, + ISlangBlob** outPath) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + calcArtifactPath(IArtifact*, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL + makeDescForCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) + SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind kind, + const CharSlice& path, + IOSFileArtifactRepresentation* lockFile, + IOSFileArtifactRepresentation** outRep) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation( + const CharSlice& path, + ISlangFileSystemExt* system, + IExtFileArtifactRepresentation** outRep) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact( + const ArtifactDesc& desc, + const CharSlice& slice, + IArtifact** outArtifact) SLANG_OVERRIDE; + + static IArtifactHelper* getSingleton() { return &g_singleton; } protected: - void* getInterface(const Guid& guid); - void* getObject(const Guid& guid); + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); - static DefaultArtifactHelper g_singleton; + static DefaultArtifactHelper g_singleton; }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp index d13421880..bb7584510 100644 --- a/source/compiler-core/slang-artifact-impl.cpp +++ b/source/compiler-core/slang-artifact-impl.cpp @@ -1,29 +1,27 @@ // slang-artifact-impl.cpp #include "slang-artifact-impl.h" -#include "slang-artifact-representation.h" - -#include "slang-artifact-util.h" +#include "../core/slang-castable.h" #include "slang-artifact-desc-util.h" - #include "slang-artifact-handler-impl.h" - +#include "slang-artifact-representation.h" +#include "slang-artifact-util.h" #include "slang-slice-allocator.h" -#include "../core/slang-castable.h" - -namespace Slang { +namespace Slang +{ -namespace { // anonymous +namespace +{ // anonymous /* Get a view as a slice of *raw* pointers */ -template <typename T> +template<typename T> SLANG_FORCE_INLINE ConstArrayView<T*> _getRawView(const List<ComPtr<T>>& in) { - return makeConstArrayView((T*const*)in.getBuffer(), in.getCount()); + return makeConstArrayView((T* const*)in.getBuffer(), in.getCount()); } -} // anonymous +} // namespace /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Artifact !!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -38,8 +36,7 @@ void* Artifact::castAs(const Guid& guid) void* Artifact::getInterface(const Guid& uuid) { - if (uuid == ISlangUnknown::getTypeGuid() || - uuid == ICastable::getTypeGuid() || + if (uuid == ISlangUnknown::getTypeGuid() || uuid == ICastable::getTypeGuid() || uuid == IArtifact::getTypeGuid()) { return static_cast<IArtifact*>(this); @@ -96,7 +93,11 @@ SlangResult Artifact::requireFile(Keep keep, IOSFileArtifactRepresentation** out auto handler = _getHandler(); ComPtr<ICastable> castable; - SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, IOSFileArtifactRepresentation::getTypeGuid(), keep, castable.writeRef())); + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation( + this, + IOSFileArtifactRepresentation::getTypeGuid(), + keep, + castable.writeRef())); auto fileRep = as<IOSFileArtifactRepresentation>(castable); fileRep->addRef(); @@ -110,8 +111,12 @@ SlangResult Artifact::loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** auto handler = _getHandler(); ComPtr<ICastable> castable; - SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, ISlangSharedLibrary::getTypeGuid(), keep, castable.writeRef())); - + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation( + this, + ISlangSharedLibrary::getTypeGuid(), + keep, + castable.writeRef())); + auto lib = as<ISlangSharedLibrary>(castable); lib->addRef(); @@ -133,10 +138,10 @@ void Artifact::clear(IArtifact::ContainedKind kind) { switch (kind) { - case ContainedKind::Associated: m_associated.clear(); break; - case ContainedKind::Representation: m_representations.clear(); break; - case ContainedKind::Children: m_children.clear(); break; - default: break; + case ContainedKind::Associated: m_associated.clear(); break; + case ContainedKind::Representation: m_representations.clear(); break; + case ContainedKind::Children: m_children.clear(); break; + default: break; } } @@ -144,14 +149,17 @@ void Artifact::removeAt(ContainedKind kind, Index i) { switch (kind) { - case ContainedKind::Associated: m_associated.removeAt(i); break; - case ContainedKind::Representation: m_representations.removeAt(i); break; - case ContainedKind::Children: m_children.removeAt(i); break; - default: break; + case ContainedKind::Associated: m_associated.removeAt(i); break; + case ContainedKind::Representation: m_representations.removeAt(i); break; + case ContainedKind::Children: m_children.removeAt(i); break; + default: break; } } -SlangResult Artifact::getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) +SlangResult Artifact::getOrCreateRepresentation( + const Guid& typeGuid, + ArtifactKeep keep, + ICastable** outCastable) { auto handler = _getHandler(); return handler->getOrCreateRepresentation(this, typeGuid, keep, outCastable); @@ -162,7 +170,11 @@ SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) auto handler = _getHandler(); ComPtr<ICastable> castable; - SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, ISlangBlob::getTypeGuid(), keep, castable.writeRef())); + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation( + this, + ISlangBlob::getTypeGuid(), + keep, + castable.writeRef())); ISlangBlob* blob = as<ISlangBlob>(castable); blob->addRef(); @@ -205,9 +217,10 @@ void* Artifact::findRepresentation(ContainedKind kind, const Guid& guid) { switch (kind) { - case ContainedKind::Associated: return _findRepresentation(_getRawView(m_associated), guid); - case ContainedKind::Representation: return _findRepresentation(_getRawView(m_representations), guid); - case ContainedKind::Children: + case ContainedKind::Associated: return _findRepresentation(_getRawView(m_associated), guid); + case ContainedKind::Representation: + return _findRepresentation(_getRawView(m_representations), guid); + case ContainedKind::Children: { _requireChildren(); return _findRepresentation(_getRawView(m_children), guid); @@ -240,7 +253,9 @@ void Artifact::addRepresentationUnknown(ISlangUnknown* unk) SLANG_ASSERT(unk); { - const auto view = makeConstArrayView((ISlangUnknown*const*)m_representations.getBuffer(), m_representations.getCount()); + const auto view = makeConstArrayView( + (ISlangUnknown* const*)m_representations.getBuffer(), + m_representations.getCount()); if (view.indexOf(unk) >= 0) { SLANG_ASSERT_FAILURE("Already have this representation"); @@ -270,7 +285,7 @@ Slice<ICastable*> Artifact::getRepresentations() return SliceUtil::asSlice(m_representations); } -void Artifact::setChildren(IArtifact*const* children, Count count) +void Artifact::setChildren(IArtifact* const* children, Count count) { m_expandResult = SLANG_OK; diff --git a/source/compiler-core/slang-artifact-impl.h b/source/compiler-core/slang-artifact-impl.h index 22547d3ef..a307a9d6d 100644 --- a/source/compiler-core/slang-artifact-impl.h +++ b/source/compiler-core/slang-artifact-impl.h @@ -2,34 +2,36 @@ #ifndef SLANG_ARTIFACT_IMPL_H #define SLANG_ARTIFACT_IMPL_H +#include "../core/slang-com-object.h" #include "slang-artifact.h" - #include "slang-com-helper.h" #include "slang-com-ptr.h" -#include "../core/slang-com-object.h" - namespace Slang { /* Discussion: -Another issue occurs around wanting to hold multiple kernels within a container. The problem here is that although through the desc -we can identify what target a kernel is for, there is no way of telling what stage it is for. +Another issue occurs around wanting to hold multiple kernels within a container. The problem here is +that although through the desc we can identify what target a kernel is for, there is no way of +telling what stage it is for. -When discussing the idea of a shader cache, one idea was to use a ISlangFileSystem (which could actually be a zip, or directory or in memory rep) -as the main structure. Within this it can contain kernels, and then a json manifest can describe what each of these actually are. +When discussing the idea of a shader cache, one idea was to use a ISlangFileSystem (which could +actually be a zip, or directory or in memory rep) as the main structure. Within this it can contain +kernels, and then a json manifest can describe what each of these actually are. -This all 'works', in that we can add an element of ISlangFileSystem with a desc of Container. Code that uses this can then go through the process -of finding, and getting the blob, and find from the manifest what it means. That does sound a little tedious though. Perhaps we just have an interface -that handles this detail, such that we search for that first. That interface is just attached to the artifact as an element. +This all 'works', in that we can add an element of ISlangFileSystem with a desc of Container. Code +that uses this can then go through the process of finding, and getting the blob, and find from the +manifest what it means. That does sound a little tedious though. Perhaps we just have an interface +that handles this detail, such that we search for that first. That interface is just attached to the +artifact as an element. */ class Artifact : public ComBaseObject, public IArtifact { public: SLANG_COM_BASE_IUNKNOWN_ALL - + /// ICastable virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; @@ -37,47 +39,71 @@ public: virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } virtual SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); } - virtual SLANG_NO_THROW void SLANG_MCALL setName(const char* name) SLANG_OVERRIDE { m_name = name; } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE + { + return m_name.getBuffer(); + } + virtual SLANG_NO_THROW void SLANG_MCALL setName(const char* name) SLANG_OVERRIDE + { + m_name = name; + } virtual SLANG_NO_THROW void SLANG_MCALL addAssociated(IArtifact* artifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getAssociated() SLANG_OVERRIDE; - + virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(ICastable* castable) SLANG_OVERRIDE; - virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) + SLANG_OVERRIDE; virtual SLANG_NO_THROW Slice<ICastable*> SLANG_MCALL getRepresentations() SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation( + const Guid& typeGuid, + ArtifactKeep keep, + ICastable** outCastable) SLANG_OVERRIDE; virtual SLANG_NO_THROW IArtifactHandler* SLANG_MCALL getHandler() SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setHandler(IArtifactHandler* handler) SLANG_OVERRIDE; virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getChildren() SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() SLANG_OVERRIDE { return m_expandResult; } - virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact*const* children, Count count) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() SLANG_OVERRIDE + { + return m_expandResult; + } + virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact* const* children, Count count) + SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren() SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL addChild(IArtifact* artifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW void* SLANG_MCALL findRepresentation(ContainedKind kind, const Guid& unk) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void* SLANG_MCALL findRepresentation(ContainedKind kind, const Guid& unk) + SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL clear(ContainedKind kind) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL removeAt(ContainedKind kind, Index i) SLANG_OVERRIDE; - static ComPtr<IArtifact> create(const Desc& desc) { return ComPtr<IArtifact>(new Artifact(desc)); } - static ComPtr<IArtifact> create(const Desc& desc, const UnownedStringSlice& name) { return ComPtr<IArtifact>(new Artifact(desc, name)); } - -protected: + static ComPtr<IArtifact> create(const Desc& desc) + { + return ComPtr<IArtifact>(new Artifact(desc)); + } + static ComPtr<IArtifact> create(const Desc& desc, const UnownedStringSlice& name) + { + return ComPtr<IArtifact>(new Artifact(desc, name)); + } +protected: /// Ctor - Artifact(const Desc& desc, const UnownedStringSlice& name) : - m_desc(desc), - m_name(name) - {} - Artifact(const Desc& desc) : - m_desc(desc) - {} + Artifact(const Desc& desc, const UnownedStringSlice& name) + : m_desc(desc), m_name(name) + { + } + Artifact(const Desc& desc) + : m_desc(desc) + { + } IArtifactHandler* _getHandler(); void _requireChildren(); @@ -85,15 +111,16 @@ protected: void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - Desc m_desc; ///< Description of the artifact - String m_name; ///< Name of this artifact + Desc m_desc; ///< Description of the artifact + String m_name; ///< Name of this artifact SlangResult m_expandResult = SLANG_E_UNINITIALIZED; - ComPtr<IArtifactHandler> m_handler; ///< The handler. Can be nullptr and then default handler is used. + ComPtr<IArtifactHandler> + m_handler; ///< The handler. Can be nullptr and then default handler is used. - List<ComPtr<ICastable>> m_representations; ///< All the representation of this artifact - List<ComPtr<IArtifact>> m_associated; ///< All the items associated with this artifact - List<ComPtr<IArtifact>> m_children; ///< All the child artifacts owned + List<ComPtr<ICastable>> m_representations; ///< All the representation of this artifact + List<ComPtr<IArtifact>> m_associated; ///< All the items associated with this artifact + List<ComPtr<IArtifact>> m_children; ///< All the child artifacts owned }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp index 85563fe61..648e4d8c1 100644 --- a/source/compiler-core/slang-artifact-representation-impl.cpp +++ b/source/compiler-core/slang-artifact-representation-impl.cpp @@ -1,24 +1,21 @@ // slang-artifact-representation-impl.cpp #include "slang-artifact-representation-impl.h" +#include "../core/slang-array-view.h" +#include "../core/slang-castable.h" #include "../core/slang-file-system.h" - -#include "../core/slang-type-text-util.h" #include "../core/slang-io.h" -#include "../core/slang-array-view.h" - +#include "../core/slang-type-text-util.h" #include "slang-artifact-util.h" -#include "../core/slang-castable.h" - -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ExtFileArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* ExtFileArtifactRepresentation::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid() || guid == IPathArtifactRepresentation::getTypeGuid() || guid == IExtFileArtifactRepresentation::getTypeGuid()) @@ -43,7 +40,9 @@ void* ExtFileArtifactRepresentation::castAs(const Guid& guid) return getObject(guid); } -SlangResult ExtFileArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) +SlangResult ExtFileArtifactRepresentation::createRepresentation( + const Guid& typeGuid, + ICastable** outCastable) { // We can convert into a blob only, and only if we have a path // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general. @@ -72,7 +71,9 @@ const char* ExtFileArtifactRepresentation::getUniqueIdentity() if (m_uniqueIdentity.getLength() == 0) { ComPtr<ISlangBlob> uniqueIdentityBlob; - if (SLANG_FAILED(m_fileSystem->getFileUniqueIdentity(m_path.getBuffer(), uniqueIdentityBlob.writeRef()))) + if (SLANG_FAILED(m_fileSystem->getFileUniqueIdentity( + m_path.getBuffer(), + uniqueIdentityBlob.writeRef()))) { return nullptr; } @@ -82,12 +83,12 @@ const char* ExtFileArtifactRepresentation::getUniqueIdentity() return m_uniqueIdentity.getLength() ? m_uniqueIdentity.getBuffer() : nullptr; } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SourceBlobWithPathArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SourceBlobWithPathArtifactRepresentation + * !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* SourceBlobWithPathInfoArtifactRepresentation::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid() || guid == IPathArtifactRepresentation::getTypeGuid()) { @@ -111,7 +112,9 @@ void* SourceBlobWithPathInfoArtifactRepresentation::castAs(const Guid& guid) return getObject(guid); } -SlangResult SourceBlobWithPathInfoArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) +SlangResult SourceBlobWithPathInfoArtifactRepresentation::createRepresentation( + const Guid& typeGuid, + ICastable** outCastable) { // We can convert into a blob only. if (typeGuid != ISlangBlob::getTypeGuid()) @@ -132,8 +135,7 @@ SlangResult SourceBlobWithPathInfoArtifactRepresentation::createRepresentation(c void* OSFileArtifactRepresentation::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid() || guid == IPathArtifactRepresentation::getTypeGuid() || guid == IOSFileArtifactRepresentation::getTypeGuid()) @@ -149,7 +151,7 @@ void* OSFileArtifactRepresentation::getObject(const Guid& guid) return nullptr; } -/* static */ISlangMutableFileSystem* OSFileArtifactRepresentation::_getFileSystem() +/* static */ ISlangMutableFileSystem* OSFileArtifactRepresentation::_getFileSystem() { return OSFileSystem::getMutableSingleton(); } @@ -163,12 +165,13 @@ void* OSFileArtifactRepresentation::castAs(const Guid& guid) return getObject(guid); } -SlangResult OSFileArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) +SlangResult OSFileArtifactRepresentation::createRepresentation( + const Guid& typeGuid, + ICastable** outCastable) { // We can convert into a blob only, and only if we have a path // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general. - if (typeGuid != ISlangBlob::getTypeGuid() || - m_kind == Kind::NameOnly) + if (typeGuid != ISlangBlob::getTypeGuid() || m_kind == Kind::NameOnly) { return SLANG_E_NOT_AVAILABLE; } @@ -185,9 +188,9 @@ SlangResult OSFileArtifactRepresentation::createRepresentation(const Guid& typeG bool OSFileArtifactRepresentation::exists() { // TODO(JS): - // If it's a name only it's hard to know what exists should do. It can't *check* because it relies on the 'system' doing - // the actual location. We could ask the IArtifactUtil, and that could change the behavior. - // For now we just assume it does. + // If it's a name only it's hard to know what exists should do. It can't *check* because it + // relies on the 'system' doing the actual location. We could ask the IArtifactUtil, and that + // could change the behavior. For now we just assume it does. if (m_kind == Kind::NameOnly) { return true; @@ -209,7 +212,9 @@ const char* OSFileArtifactRepresentation::getUniqueIdentity() auto fileSystem = _getFileSystem(); ComPtr<ISlangBlob> uniqueIdentityBlob; - if (SLANG_FAILED(fileSystem->getFileUniqueIdentity(m_path.getBuffer(), uniqueIdentityBlob.writeRef()))) + if (SLANG_FAILED(fileSystem->getFileUniqueIdentity( + m_path.getBuffer(), + uniqueIdentityBlob.writeRef()))) { return nullptr; } @@ -236,11 +241,12 @@ OSFileArtifactRepresentation::~OSFileArtifactRepresentation() } } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! + */ void* ObjectArtifactRepresentation::castAs(const Guid& guid) { - + if (auto ptr = getInterface(guid)) { return ptr; @@ -250,8 +256,7 @@ void* ObjectArtifactRepresentation::castAs(const Guid& guid) void* ObjectArtifactRepresentation::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid()) { return static_cast<IArtifactRepresentation*>(this); diff --git a/source/compiler-core/slang-artifact-representation-impl.h b/source/compiler-core/slang-artifact-representation-impl.h index 034084950..5e28d42f3 100644 --- a/source/compiler-core/slang-artifact-representation-impl.h +++ b/source/compiler-core/slang-artifact-representation-impl.h @@ -2,14 +2,11 @@ #ifndef SLANG_ARTIFACT_REPRESENTATION_IMPL_H #define SLANG_ARTIFACT_REPRESENTATION_IMPL_H +#include "../core/slang-com-object.h" +#include "../core/slang-memory-arena.h" #include "slang-artifact-representation.h" - #include "slang-com-helper.h" #include "slang-com-ptr.h" - -#include "../core/slang-com-object.h" -#include "../core/slang-memory-arena.h" - #include "slang-source-loc.h" namespace Slang @@ -27,29 +24,43 @@ public: SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IArtifactRepresentation - SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; // IPathArtifactRepresentation - virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } - virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return SLANG_PATH_TYPE_FILE; } + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE + { + return m_path.getBuffer(); + } + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE + { + return SLANG_PATH_TYPE_FILE; + } virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() SLANG_OVERRIDE; // IOSFileArtifactRepresentation virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() SLANG_OVERRIDE { return m_kind; } virtual SLANG_NO_THROW void SLANG_MCALL disown() SLANG_OVERRIDE; - virtual SLANG_NO_THROW IOSFileArtifactRepresentation* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; } + virtual SLANG_NO_THROW IOSFileArtifactRepresentation* SLANG_MCALL getLockFile() SLANG_OVERRIDE + { + return m_lockFile; + } - OSFileArtifactRepresentation(Kind kind, const UnownedStringSlice& path, IOSFileArtifactRepresentation* lockFile): - m_kind(kind), - m_lockFile(lockFile), - m_path(path) + OSFileArtifactRepresentation( + Kind kind, + const UnownedStringSlice& path, + IOSFileArtifactRepresentation* lockFile) + : m_kind(kind), m_lockFile(lockFile), m_path(path) { } ~OSFileArtifactRepresentation(); - static ComPtr<IOSFileArtifactRepresentation> create(Kind kind, const UnownedStringSlice& path, IOSFileArtifactRepresentation* lockFile) + static ComPtr<IOSFileArtifactRepresentation> create( + Kind kind, + const UnownedStringSlice& path, + IOSFileArtifactRepresentation* lockFile) { return ComPtr<IOSFileArtifactRepresentation>(new ThisType(kind, path, lockFile)); } @@ -58,7 +69,7 @@ protected: void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - /// True if the file is owned + /// True if the file is owned bool _isOwned() const { return Index(m_kind) >= Index(Kind::Owned); } static ISlangMutableFileSystem* _getFileSystem(); @@ -82,24 +93,35 @@ public: SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IArtifactRepresentation - SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; // IPathArtifactRepresentation - virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } - virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return SLANG_PATH_TYPE_FILE; } + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE + { + return m_path.getBuffer(); + } + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE + { + return SLANG_PATH_TYPE_FILE; + } virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() SLANG_OVERRIDE; - + // IExtFileArtifactRepresentation - virtual SLANG_NO_THROW ISlangFileSystemExt* SLANG_MCALL getFileSystem() SLANG_OVERRIDE { return m_fileSystem; } + virtual SLANG_NO_THROW ISlangFileSystemExt* SLANG_MCALL getFileSystem() SLANG_OVERRIDE + { + return m_fileSystem; + } - ExtFileArtifactRepresentation(const UnownedStringSlice& path, ISlangFileSystemExt* fileSystem) : - m_path(path), - m_fileSystem(fileSystem) + ExtFileArtifactRepresentation(const UnownedStringSlice& path, ISlangFileSystemExt* fileSystem) + : m_path(path), m_fileSystem(fileSystem) { } - static ComPtr<IExtFileArtifactRepresentation> create(const UnownedStringSlice& path, ISlangFileSystemExt* fileSystem) + static ComPtr<IExtFileArtifactRepresentation> create( + const UnownedStringSlice& path, + ISlangFileSystemExt* fileSystem) { return ComPtr<IExtFileArtifactRepresentation>(new ThisType(path, fileSystem)); } @@ -113,7 +135,8 @@ protected: ComPtr<ISlangFileSystemExt> m_fileSystem; }; -class SourceBlobWithPathInfoArtifactRepresentation : public ComBaseObject, public IPathArtifactRepresentation +class SourceBlobWithPathInfoArtifactRepresentation : public ComBaseObject, + public IPathArtifactRepresentation { public: typedef SourceBlobWithPathInfoArtifactRepresentation ThisType; @@ -124,21 +147,32 @@ public: SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IArtifactRepresentation - SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE { return false; } // IPathArtifactRepresentation - virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_pathInfo.getName().getBuffer(); } - virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return SLANG_PATH_TYPE_FILE; } - virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() SLANG_OVERRIDE { return m_pathInfo.hasUniqueIdentity() ? m_pathInfo.uniqueIdentity.getBuffer() : nullptr; } + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE + { + return m_pathInfo.getName().getBuffer(); + } + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE + { + return SLANG_PATH_TYPE_FILE; + } + virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() SLANG_OVERRIDE + { + return m_pathInfo.hasUniqueIdentity() ? m_pathInfo.uniqueIdentity.getBuffer() : nullptr; + } - SourceBlobWithPathInfoArtifactRepresentation(const PathInfo& pathInfo, ISlangBlob* sourceBlob) : - m_pathInfo(pathInfo), - m_blob(sourceBlob) + SourceBlobWithPathInfoArtifactRepresentation(const PathInfo& pathInfo, ISlangBlob* sourceBlob) + : m_pathInfo(pathInfo), m_blob(sourceBlob) { } - static ComPtr<IPathArtifactRepresentation> create(const PathInfo& pathInfo, ISlangBlob* sourceBlob) + static ComPtr<IPathArtifactRepresentation> create( + const PathInfo& pathInfo, + ISlangBlob* sourceBlob) { return ComPtr<IPathArtifactRepresentation>(new ThisType(pathInfo, sourceBlob)); } @@ -151,34 +185,40 @@ protected: ComPtr<ISlangBlob> m_blob; }; -/* This allows wrapping any object to be an artifact representation. +/* This allows wrapping any object to be an artifact representation. -NOTE! Only allows casting from a single guid. Passing a RefObject across an ABI boundary remains risky! +NOTE! Only allows casting from a single guid. Passing a RefObject across an ABI boundary remains +risky! */ class ObjectArtifactRepresentation : public ComBaseObject, public IArtifactRepresentation { public: - SLANG_CLASS_GUID(0xb9d5af57, 0x725b, 0x45f8, { 0xac, 0xed, 0x18, 0xf4, 0xa8, 0x4b, 0xf4, 0x73 }) + SLANG_CLASS_GUID(0xb9d5af57, 0x725b, 0x45f8, {0xac, 0xed, 0x18, 0xf4, 0xa8, 0x4b, 0xf4, 0x73}) SLANG_COM_BASE_IUNKNOWN_ALL // ICastable SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IArtifactRepresentation - SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& guid, ICastable** outCastable) SLANG_OVERRIDE { SLANG_UNUSED(guid); SLANG_UNUSED(outCastable); return SLANG_E_NOT_AVAILABLE; } + SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& guid, ICastable** outCastable) SLANG_OVERRIDE + { + SLANG_UNUSED(guid); + SLANG_UNUSED(outCastable); + return SLANG_E_NOT_AVAILABLE; + } SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE { return m_object; } - ObjectArtifactRepresentation(const Guid& typeGuid, RefObject* obj): - m_typeGuid(typeGuid), - m_object(obj) + ObjectArtifactRepresentation(const Guid& typeGuid, RefObject* obj) + : m_typeGuid(typeGuid), m_object(obj) { } void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - - Guid m_typeGuid; ///< Will return m_object if a cast to m_typeGuid is given - RefPtr<RefObject> m_object; ///< The object + + Guid m_typeGuid; ///< Will return m_object if a cast to m_typeGuid is given + RefPtr<RefObject> m_object; ///< The object }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-representation.h b/source/compiler-core/slang-artifact-representation.h index 3e7659058..719571806 100644 --- a/source/compiler-core/slang-artifact-representation.h +++ b/source/compiler-core/slang-artifact-representation.h @@ -10,49 +10,65 @@ namespace Slang /* Base interface for types that have a path. */ class IPathArtifactRepresentation : public IArtifactRepresentation { - SLANG_COM_INTERFACE(0xcb1c188c, 0x7e48, 0x43eb, { 0xb0, 0x9a, 0xa1, 0x6e, 0xef, 0xd4, 0x9b, 0xef }); + SLANG_COM_INTERFACE( + 0xcb1c188c, + 0x7e48, + 0x43eb, + {0xb0, 0x9a, 0xa1, 0x6e, 0xef, 0xd4, 0x9b, 0xef}); - /// The path + /// The path virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0; - /// Get type + /// Get type virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() = 0; - /// Returns the unique identity. If a unique identity is not supported - /// or available will return nullptr. + /// Returns the unique identity. If a unique identity is not supported + /// or available will return nullptr. virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() = 0; }; /* Represents a path to a file held on an ISlangFileSystem. */ class IExtFileArtifactRepresentation : public IPathArtifactRepresentation { - SLANG_COM_INTERFACE(0xacd65576, 0xb09d, 0x4ac9, { 0xa5, 0x93, 0xeb, 0xf8, 0x9b, 0xd7, 0x11, 0xfd }); + SLANG_COM_INTERFACE( + 0xacd65576, + 0xb09d, + 0x4ac9, + {0xa5, 0x93, 0xeb, 0xf8, 0x9b, 0xd7, 0x11, 0xfd}); - /// File system that holds the item along the path. + /// File system that holds the item along the path. virtual SLANG_NO_THROW ISlangFileSystemExt* SLANG_MCALL getFileSystem() = 0; }; -/* +/* A representation as a file on the OS file system. */ class IOSFileArtifactRepresentation : public IPathArtifactRepresentation { public: - SLANG_COM_INTERFACE(0xc7d7d3a4, 0x8683, 0x44b5, { 0x87, 0x96, 0xdf, 0xba, 0x9b, 0xc3, 0xf1, 0x7b }); + SLANG_COM_INTERFACE( + 0xc7d7d3a4, + 0x8683, + 0x44b5, + {0x87, 0x96, 0xdf, 0xba, 0x9b, 0xc3, 0xf1, 0x7b}); /* Determines ownership and other characteristics of the OS 'file' */ enum class Kind { - Reference, ///< References a file on the file system - NameOnly, ///< Typically used for items that can be found by the 'system'. The path is just a name, and cannot typically be loaded as a blob. - Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope - Lock, ///< An owned type, indicates potentially in part may only exist to 'lock' a path for a temporary file. Other files might exists based on the 'lock' path. + Reference, ///< References a file on the file system + NameOnly, ///< Typically used for items that can be found by the 'system'. The path is just + ///< a name, and cannot typically be loaded as a blob. + Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope + Lock, ///< An owned type, indicates potentially in part may only exist to 'lock' a path for + ///< a temporary file. Other files might exists based on the 'lock' path. CountOf, }; - /// The the kind of file. - virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() = 0; - /// Makes the file no longer owned. Only applicable for Owned/Lock and they will become 'Reference' + /// The the kind of file. + virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() = 0; + /// Makes the file no longer owned. Only applicable for Owned/Lock and they will become + /// 'Reference' virtual SLANG_NO_THROW void SLANG_MCALL disown() = 0; - /// Gets the 'lock file' if any associated with this file. Returns nullptr if there isn't one. - /// If this file is based on a 'lock file', the lock file must stay in scope at least as long as this does. + /// Gets the 'lock file' if any associated with this file. Returns nullptr if there isn't one. + /// If this file is based on a 'lock file', the lock file must stay in scope at least as long as + /// this does. virtual SLANG_NO_THROW IOSFileArtifactRepresentation* SLANG_MCALL getLockFile() = 0; }; diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index e03f02e1e..703f8fddb 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -1,15 +1,14 @@ // slang-artifact-util.cpp #include "slang-artifact-util.h" -#include "slang-artifact-impl.h" -#include "slang-artifact-representation-impl.h" - -#include "slang-artifact-desc-util.h" - #include "../core/slang-castable.h" #include "../core/slang-io.h" +#include "slang-artifact-desc-util.h" +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" -namespace Slang { +namespace Slang +{ static bool _checkSelf(ArtifactUtil::FindStyle findStyle) { @@ -23,36 +22,39 @@ static bool _checkChildren(ArtifactUtil::FindStyle findStyle) static bool _checkRecursive(ArtifactUtil::FindStyle findStyle) { - return findStyle == ArtifactUtil::FindStyle::Recursive || - findStyle == ArtifactUtil::FindStyle::ChildrenRecursive; + return findStyle == ArtifactUtil::FindStyle::Recursive || + findStyle == ArtifactUtil::FindStyle::ChildrenRecursive; } - + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */ComPtr<IArtifact> ArtifactUtil::createArtifact(const ArtifactDesc& desc, const char* name) +/* static */ ComPtr<IArtifact> ArtifactUtil::createArtifact( + const ArtifactDesc& desc, + const char* name) { auto artifact = createArtifact(desc); artifact->setName(name); return artifact; } -/* static */ComPtr<IArtifact> ArtifactUtil::createArtifact(const ArtifactDesc& desc) +/* static */ ComPtr<IArtifact> ArtifactUtil::createArtifact(const ArtifactDesc& desc) { return Artifact::create(desc); } -/* static */ComPtr<IArtifact> ArtifactUtil::createArtifactForCompileTarget(SlangCompileTarget target) +/* static */ ComPtr<IArtifact> ArtifactUtil::createArtifactForCompileTarget( + SlangCompileTarget target) { auto desc = ArtifactDescUtil::makeDescForCompileTarget(target); return createArtifact(desc); } -/* static */bool ArtifactUtil::isSignificant(IArtifact* artifact) +/* static */ bool ArtifactUtil::isSignificant(IArtifact* artifact) { return isSignificant(artifact->getDesc()); } -/* static */bool ArtifactUtil::isSignificant(const ArtifactDesc& desc) +/* static */ bool ArtifactUtil::isSignificant(const ArtifactDesc& desc) { // Containers are not significant as of themselves, they may contain something tho if (isDerivedFrom(desc.kind, ArtifactKind::Container)) @@ -61,16 +63,14 @@ static bool _checkRecursive(ArtifactUtil::FindStyle findStyle) } // If it has no payload.. we are done - if (desc.payload == ArtifactPayload::None || - desc.payload == ArtifactPayload::Invalid) + if (desc.payload == ArtifactPayload::None || desc.payload == ArtifactPayload::Invalid) { return false; } // If it's binary like or assembly/source we it's significant if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary) || - desc.kind == ArtifactKind::Assembly || - desc.kind == ArtifactKind::Source) + desc.kind == ArtifactKind::Assembly || desc.kind == ArtifactKind::Source) { return true; } @@ -93,15 +93,19 @@ static bool _checkRecursive(ArtifactUtil::FindStyle findStyle) } -/* static */bool ArtifactUtil::isSignificant(IArtifact* artifact, void* data) +/* static */ bool ArtifactUtil::isSignificant(IArtifact* artifact, void* data) { SLANG_UNUSED(data); return isSignificant(artifact->getDesc()); } -/* static */IArtifact* ArtifactUtil::findSignificant(IArtifact* artifact) -{ - return findArtifactByPredicate(artifact, FindStyle::SelfOrChildren, &ArtifactUtil::isSignificant, nullptr); +/* static */ IArtifact* ArtifactUtil::findSignificant(IArtifact* artifact) +{ + return findArtifactByPredicate( + artifact, + FindStyle::SelfOrChildren, + &ArtifactUtil::isSignificant, + nullptr); } UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) @@ -122,7 +126,7 @@ UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) { if (auto pathRep = as<IPathArtifactRepresentation>(rep)) { - if (pathRep->getPathType() == SLANG_PATH_TYPE_FILE && + if (pathRep->getPathType() == SLANG_PATH_TYPE_FILE && (bestRep == nullptr || as<IExtFileArtifactRepresentation>(rep))) { bestRep = pathRep; @@ -130,11 +134,12 @@ UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) } } - const UnownedStringSlice name = bestRep ? UnownedStringSlice(bestRep->getPath()) : UnownedStringSlice(); + const UnownedStringSlice name = + bestRep ? UnownedStringSlice(bestRep->getPath()) : UnownedStringSlice(); return name.getLength() ? name : UnownedStringSlice(); } -/* static */UnownedStringSlice ArtifactUtil::inferExtension(IArtifact* artifact) +/* static */ UnownedStringSlice ArtifactUtil::inferExtension(IArtifact* artifact) { const UnownedStringSlice path = findPath(artifact); if (path.getLength()) @@ -148,14 +153,17 @@ UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) return UnownedStringSlice(); } -/* static */UnownedStringSlice ArtifactUtil::findName(IArtifact* artifact) +/* static */ UnownedStringSlice ArtifactUtil::findName(IArtifact* artifact) { const UnownedStringSlice path = findPath(artifact); const Index pos = Path::findLastSeparatorIndex(path); return (pos >= 0) ? path.tail(pos + 1) : path; } -static SlangResult _calcInferred(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath) +static SlangResult _calcInferred( + IArtifact* artifact, + const UnownedStringSlice& basePath, + StringBuilder& outPath) { auto ext = ArtifactUtil::inferExtension(artifact); @@ -175,7 +183,10 @@ static SlangResult _calcInferred(IArtifact* artifact, const UnownedStringSlice& return SLANG_OK; } -/* static */SlangResult ArtifactUtil::calcPath(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath) +/* static */ SlangResult ArtifactUtil::calcPath( + IArtifact* artifact, + const UnownedStringSlice& basePath, + StringBuilder& outPath) { if (ArtifactDescUtil::hasDefinedNameForDesc(artifact->getDesc())) { @@ -187,7 +198,10 @@ static SlangResult _calcInferred(IArtifact* artifact, const UnownedStringSlice& } } -/* static */SlangResult ArtifactUtil::calcName(IArtifact* artifact, const UnownedStringSlice& baseName, StringBuilder& outName) +/* static */ SlangResult ArtifactUtil::calcName( + IArtifact* artifact, + const UnownedStringSlice& baseName, + StringBuilder& outName) { if (ArtifactDescUtil::hasDefinedNameForDesc(artifact->getDesc())) { @@ -223,22 +237,39 @@ static bool _isName(IArtifact* artifact, void* data) return ::strcmp(name, artifactName) == 0; } -/* static */IArtifact* ArtifactUtil::findArtifactByDerivedDesc(IArtifact* artifact, FindStyle findStyle, const ArtifactDesc& desc) +/* static */ IArtifact* ArtifactUtil::findArtifactByDerivedDesc( + IArtifact* artifact, + FindStyle findStyle, + const ArtifactDesc& desc) { - return findArtifactByPredicate(artifact, findStyle, _isByDerivedDesc, &const_cast<ArtifactDesc&>(desc)); + return findArtifactByPredicate( + artifact, + findStyle, + _isByDerivedDesc, + &const_cast<ArtifactDesc&>(desc)); } -/* static */IArtifact* ArtifactUtil::findArtifactByName(IArtifact* artifact, FindStyle findStyle, const char* name) +/* static */ IArtifact* ArtifactUtil::findArtifactByName( + IArtifact* artifact, + FindStyle findStyle, + const char* name) { return findArtifactByPredicate(artifact, findStyle, _isName, const_cast<char*>(name)); } -/* static */IArtifact* ArtifactUtil::findArtifactByDesc(IArtifact* artifact, FindStyle findStyle, const ArtifactDesc& desc) +/* static */ IArtifact* ArtifactUtil::findArtifactByDesc( + IArtifact* artifact, + FindStyle findStyle, + const ArtifactDesc& desc) { return findArtifactByPredicate(artifact, findStyle, _isDesc, &const_cast<ArtifactDesc&>(desc)); } -/* static */IArtifact* ArtifactUtil::findArtifactByPredicate(IArtifact* artifact, FindStyle findStyle, FindFunc func, void* data) +/* static */ IArtifact* ArtifactUtil::findArtifactByPredicate( + IArtifact* artifact, + FindStyle findStyle, + FindFunc func, + void* data) { if (_checkSelf(findStyle) && func(artifact, data)) { @@ -250,7 +281,7 @@ static bool _isName(IArtifact* artifact, void* data) return nullptr; } - // Expand the children so we can search them + // Expand the children so we can search them artifact->expandChildren(); auto children = artifact->getChildren(); @@ -268,38 +299,45 @@ static bool _isName(IArtifact* artifact, void* data) } } - // If it's recursive, we check all the children of children + // If it's recursive, we check all the children of children if (_checkRecursive(findStyle)) { for (auto child : children) { - if (auto found = findArtifactByPredicate(child, FindStyle::ChildrenRecursive, func, data)) + if (auto found = + findArtifactByPredicate(child, FindStyle::ChildrenRecursive, func, data)) { return found; } } } - + return nullptr; } -/* static */void ArtifactUtil::addAssociated(IArtifact* artifact, IArtifactPostEmitMetadata* metadata) +/* static */ void ArtifactUtil::addAssociated( + IArtifact* artifact, + IArtifactPostEmitMetadata* metadata) { if (metadata) { - auto metadataArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::PostEmitMetadata)); + auto metadataArtifact = ArtifactUtil::createArtifact( + ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::PostEmitMetadata)); metadataArtifact->addRepresentation(metadata); artifact->addAssociated(metadataArtifact); } } -/* static */void ArtifactUtil::addAssociated(IArtifact* artifact, IArtifactDiagnostics* diagnostics) +/* static */ void ArtifactUtil::addAssociated( + IArtifact* artifact, + IArtifactDiagnostics* diagnostics) { if (diagnostics) { - auto diagnosticsArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::Diagnostics)); + auto diagnosticsArtifact = ArtifactUtil::createArtifact( + ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::Diagnostics)); diagnosticsArtifact->addRepresentation(diagnostics); - artifact->addAssociated(diagnosticsArtifact); + artifact->addAssociated(diagnosticsArtifact); } } diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h index 5341f309b..538affcdb 100644 --- a/source/compiler-core/slang-artifact-util.h +++ b/source/compiler-core/slang-artifact-util.h @@ -2,10 +2,9 @@ #ifndef SLANG_ARTIFACT_UTIL_H #define SLANG_ARTIFACT_UTIL_H -#include "slang-artifact.h" -#include "slang-artifact-representation.h" #include "slang-artifact-associated.h" - +#include "slang-artifact-representation.h" +#include "slang-artifact.h" #include "slang-com-ptr.h" namespace Slang @@ -17,63 +16,86 @@ struct ArtifactUtil enum class FindStyle : uint8_t { - Self, ///< Just on self - SelfOrChildren, ///< Self, or if container just the children - Recursive, ///< On self plus any children recursively - Children, ///< Only on children - ChildrenRecursive, ///< Only on children recursively + Self, ///< Just on self + SelfOrChildren, ///< Self, or if container just the children + Recursive, ///< On self plus any children recursively + Children, ///< Only on children + ChildrenRecursive, ///< Only on children recursively }; - /// Find an artifact that matches desc allowing derivations. Flags is ignored - static IArtifact* findArtifactByDerivedDesc(IArtifact* artifact, FindStyle findStyle, const ArtifactDesc& desc); - /// Find an artifact that predicate matches - static IArtifact* findArtifactByPredicate(IArtifact* artifact, FindStyle findStyle, FindFunc func, void* data); - /// Find by name - static IArtifact* findArtifactByName(IArtifact* artifact, FindStyle findStyle, const char* name); - /// Find by desc exactly - static IArtifact* findArtifactByDesc(IArtifact* artifact, FindStyle findStyle, const ArtifactDesc& desc); - - /// Creates an empty artifact for a type + /// Find an artifact that matches desc allowing derivations. Flags is ignored + static IArtifact* findArtifactByDerivedDesc( + IArtifact* artifact, + FindStyle findStyle, + const ArtifactDesc& desc); + /// Find an artifact that predicate matches + static IArtifact* findArtifactByPredicate( + IArtifact* artifact, + FindStyle findStyle, + FindFunc func, + void* data); + /// Find by name + static IArtifact* findArtifactByName( + IArtifact* artifact, + FindStyle findStyle, + const char* name); + /// Find by desc exactly + static IArtifact* findArtifactByDesc( + IArtifact* artifact, + FindStyle findStyle, + const ArtifactDesc& desc); + + /// Creates an empty artifact for a type static ComPtr<IArtifact> createArtifactForCompileTarget(SlangCompileTarget target); - /// Create an artifact + /// Create an artifact static ComPtr<IArtifact> createArtifact(const ArtifactDesc& desc, const char* name); static ComPtr<IArtifact> createArtifact(const ArtifactDesc& desc); - /// True if is significant + /// True if is significant static bool isSignificant(IArtifact* artifact); - /// True if is significant + /// True if is significant static bool isSignificant(const ArtifactDesc& desc); - /// Returns true if an artifact is 'significant'. - /// The data parameter is unused and just used to make work as FindFunc + /// Returns true if an artifact is 'significant'. + /// The data parameter is unused and just used to make work as FindFunc static bool isSignificant(IArtifact* artifact, void* data); - /// Find a significant artifact + /// Find a significant artifact static IArtifact* findSignificant(IArtifact* artifact); - /// Find the path/name associated with the artifact. - /// The path is *not* necessarily the path on the file system. The order of search is - /// * If the artifact has a name return that - /// * If the artifact has a IPathFileArtifactRepresentation (that isn't temporary) return it's path - /// * If not found return an empty slice + /// Find the path/name associated with the artifact. + /// The path is *not* necessarily the path on the file system. The order of search is + /// * If the artifact has a name return that + /// * If the artifact has a IPathFileArtifactRepresentation (that isn't temporary) return it's + /// path + /// * If not found return an empty slice static UnownedStringSlice findPath(IArtifact* artifact); - /// Find a name + /// Find a name static UnownedStringSlice findName(IArtifact* artifact); - /// Sometimes we have artifacts that don't specify a payload type - perhaps because they can be interpretted in different ways - /// This function uses the associated name and file representations to infer a extension. If none is found returns an empty slice. + /// Sometimes we have artifacts that don't specify a payload type - perhaps because they can be + /// interpretted in different ways This function uses the associated name and file + /// representations to infer a extension. If none is found returns an empty slice. static UnownedStringSlice inferExtension(IArtifact* artifact); - /// Given a desc and a basePath returns a suitable path for a entity of specified desc - static SlangResult calcPath(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath); + /// Given a desc and a basePath returns a suitable path for a entity of specified desc + static SlangResult calcPath( + IArtifact* artifact, + const UnownedStringSlice& basePath, + StringBuilder& outPath); - /// Given a desc and a baseName works out the the output file name - static SlangResult calcName(IArtifact* artifact, const UnownedStringSlice& baseName, StringBuilder& outName); + /// Given a desc and a baseName works out the the output file name + static SlangResult calcName( + IArtifact* artifact, + const UnownedStringSlice& baseName, + StringBuilder& outName); - /// Convenience function that adds metadata to artifact. If metadata is nullptr nothing is added. + /// Convenience function that adds metadata to artifact. If metadata is nullptr nothing is + /// added. static void addAssociated(IArtifact* artifact, IArtifactPostEmitMetadata* metadata); - /// Convenience function that adds diagnostics to artifact. If diagnostics is nullptr nothing is added. + /// Convenience function that adds diagnostics to artifact. If diagnostics is nullptr nothing is + /// added. static void addAssociated(IArtifact* artifact, IArtifactDiagnostics* diagnostics); }; diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index d3784ca0a..46e8831ff 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -10,32 +10,39 @@ namespace Slang { -/* Simplest slice types. We can't use UnownedStringSlice etc, because they implement functionality in libraries, -and we want to use these types in headers. -If we wanted a C implementation it would be easy to use a macro to generate the functionality */ +/* Simplest slice types. We can't use UnownedStringSlice etc, because they implement functionality +in libraries, and we want to use these types in headers. If we wanted a C implementation it would be +easy to use a macro to generate the functionality */ -template <typename T> +template<typename T> struct Slice { const T* begin() const { return data; } const T* end() const { return data + count; } - const T& operator[](Index index) const { SLANG_ASSERT(index >= 0 && index < count); return data[index]; } + const T& operator[](Index index) const + { + SLANG_ASSERT(index >= 0 && index < count); + return data[index]; + } - Slice() :count(0), data(nullptr) {} - Slice(const T* inData, Count inCount) : - data(inData), - count(inCount) - {} + Slice() + : count(0), data(nullptr) + { + } + Slice(const T* inData, Count inCount) + : data(inData), count(inCount) + { + } const T* data; Count count; }; -template <typename T> -SLANG_FORCE_INLINE Slice<T> makeSlice(const T* inData, Count inCount) -{ - return Slice<T>(inData, inCount); +template<typename T> +SLANG_FORCE_INLINE Slice<T> makeSlice(const T* inData, Count inCount) +{ + return Slice<T>(inData, inCount); } struct CharSlice : public Slice<char> @@ -43,13 +50,26 @@ struct CharSlice : public Slice<char> typedef CharSlice ThisType; typedef Slice<char> Super; - bool operator==(const ThisType& rhs) const { return count == rhs.count && (data == rhs.data || ::memcmp(data, rhs.data, count) == 0); } + bool operator==(const ThisType& rhs) const + { + return count == rhs.count && (data == rhs.data || ::memcmp(data, rhs.data, count) == 0); + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - explicit CharSlice(const char* in) :Super(in, ::strlen(in)) {} - CharSlice(const char* in, Count inCount) :Super(in, inCount) {} - CharSlice() :Super(nullptr, 0) {} - explicit CharSlice(const String& s) :CharSlice(s.begin(), s.getLength()){}; + explicit CharSlice(const char* in) + : Super(in, ::strlen(in)) + { + } + CharSlice(const char* in, Count inCount) + : Super(in, inCount) + { + } + CharSlice() + : Super(nullptr, 0) + { + } + explicit CharSlice(const String& s) + : CharSlice(s.begin(), s.getLength()){}; }; static_assert(std::is_trivially_copyable_v<CharSlice>); @@ -61,17 +81,28 @@ struct TerminatedCharSlice : public CharSlice SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const { return Super::operator==(rhs); } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Make convertable to char* - SLANG_FORCE_INLINE operator const char* () const { return data; } + /// Make convertable to char* + SLANG_FORCE_INLINE operator const char*() const { return data; } - explicit TerminatedCharSlice(const char* in) :Super(in) {} - TerminatedCharSlice(const char* in, Count inCount) :Super(in, inCount) { SLANG_ASSERT(in[inCount] == 0); } - TerminatedCharSlice() :Super("", 0) {} + explicit TerminatedCharSlice(const char* in) + : Super(in) + { + } + TerminatedCharSlice(const char* in, Count inCount) + : Super(in, inCount) + { + SLANG_ASSERT(in[inCount] == 0); + } + TerminatedCharSlice() + : Super("", 0) + { + } }; static_assert(std::is_trivially_copyable_v<TerminatedCharSlice>); -/* As a rule of thumb, if we can define some aspect in a hierarchy then we should do so at the highest level. -If some aspect can apply to multiple items identically we move that to a separate enum. +/* As a rule of thumb, if we can define some aspect in a hierarchy then we should do so at the +highest level. If some aspect can apply to multiple items identically we move that to a separate +enum. NOTE! New Kinds must be added at the end. Values can be deprecated, or disabled @@ -80,43 +111,43 @@ but never removed, without breaking binary compatability. Any change requires a change to SLANG_ARTIFACT_KIND */ enum class ArtifactKind : uint8_t -{ - Invalid, ///< Invalid - Base, ///< Base kind of all valid kinds - - None, ///< Doesn't contain anything - Unknown, ///< Unknown - - BinaryFormat, ///< A generic binary format. - - Container, ///< Container like types - Zip, ///< Zip container - RiffContainer, ///< Riff container - RiffLz4Container, ///< Riff container using Lz4 compression - RiffDeflateContainer, ///< Riff container using deflate compression - - Text, ///< Representation is text. Encoding is utf8, unless prefixed with 'encoding'. - - Source, ///< Source (Source type is in payload) - Assembly, ///< Assembly (Type is in payload) - HumanText, ///< Text for human consumption - - CompileBinary, ///< Kinds which are 'binary like' - can be executed, linked with and so forth. - - ObjectCode, ///< Object file - Library, ///< Library (collection of object code) - Executable, ///< Executable - SharedLibrary, ///< Shared library - can be dynamically linked - HostCallable, ///< Code can be executed directly on the host - - Instance, ///< Primary representation is an interface/class instance - - Json, ///< It's JSON +{ + Invalid, ///< Invalid + Base, ///< Base kind of all valid kinds + + None, ///< Doesn't contain anything + Unknown, ///< Unknown + + BinaryFormat, ///< A generic binary format. + + Container, ///< Container like types + Zip, ///< Zip container + RiffContainer, ///< Riff container + RiffLz4Container, ///< Riff container using Lz4 compression + RiffDeflateContainer, ///< Riff container using deflate compression + + Text, ///< Representation is text. Encoding is utf8, unless prefixed with 'encoding'. + + Source, ///< Source (Source type is in payload) + Assembly, ///< Assembly (Type is in payload) + HumanText, ///< Text for human consumption + + CompileBinary, ///< Kinds which are 'binary like' - can be executed, linked with and so forth. + + ObjectCode, ///< Object file + Library, ///< Library (collection of object code) + Executable, ///< Executable + SharedLibrary, ///< Shared library - can be dynamically linked + HostCallable, ///< Code can be executed directly on the host + + Instance, ///< Primary representation is an interface/class instance + + Json, ///< It's JSON CountOf, }; -/* Payload. +/* Payload. SlangIR and LLVMIR can be GPU or CPU orientated, so put in own category. @@ -128,69 +159,69 @@ Any change requires a change to SLANG_ARTIFACT_PAYLOAD */ enum class ArtifactPayload : uint8_t { - Invalid, ///< Is invalid - indicates some kind of problem - Base, ///< The base of the hierarchy - - None, ///< Doesn't have a payload - Unknown, ///< Unknown but probably valid - - Source, ///< Source code - - C, ///< C source - Cpp, ///< C++ source - HLSL, ///< HLSL source - GLSL, ///< GLSL source - CUDA, ///< CUDA source - Metal, ///< Metal source - Slang, ///< Slang source - WGSL, ///< WGSL source - - KernelLike, ///< GPU Kernel like - - DXIL, ///< DXIL - DXBC, ///< DXBC - SPIRV, ///< SPIR-V - PTX, ///< PTX. NOTE! PTX is a text format, but is handable to CUDA API. - MetalAIR, ///< Metal AIR - CuBin, ///< CUDA binary - WGSL_SPIRV, ///< SPIR-V derived via WebGPU shading language - - CPULike, ///< CPU code - - UnknownCPU, ///< CPU code for unknown/undetermined type - X86, ///< X86 - X86_64, ///< X86_64 - Aarch, ///< 32 bit arm - Aarch64, ///< Aarch64 - HostCPU, ///< HostCPU - UniversalCPU, ///< CPU code for multiple CPU types - - GeneralIR, ///< General purpose IR representation (IR) - - SlangIR, ///< Slang IR - LLVMIR, ///< LLVM IR - - AST, ///< Abstract syntax tree (AST) - - SlangAST, ///< Slang AST + Invalid, ///< Is invalid - indicates some kind of problem + Base, ///< The base of the hierarchy + + None, ///< Doesn't have a payload + Unknown, ///< Unknown but probably valid + + Source, ///< Source code + + C, ///< C source + Cpp, ///< C++ source + HLSL, ///< HLSL source + GLSL, ///< GLSL source + CUDA, ///< CUDA source + Metal, ///< Metal source + Slang, ///< Slang source + WGSL, ///< WGSL source + + KernelLike, ///< GPU Kernel like + + DXIL, ///< DXIL + DXBC, ///< DXBC + SPIRV, ///< SPIR-V + PTX, ///< PTX. NOTE! PTX is a text format, but is handable to CUDA API. + MetalAIR, ///< Metal AIR + CuBin, ///< CUDA binary + WGSL_SPIRV, ///< SPIR-V derived via WebGPU shading language + + CPULike, ///< CPU code + + UnknownCPU, ///< CPU code for unknown/undetermined type + X86, ///< X86 + X86_64, ///< X86_64 + Aarch, ///< 32 bit arm + Aarch64, ///< Aarch64 + HostCPU, ///< HostCPU + UniversalCPU, ///< CPU code for multiple CPU types + + GeneralIR, ///< General purpose IR representation (IR) + + SlangIR, ///< Slang IR + LLVMIR, ///< LLVM IR + + AST, ///< Abstract syntax tree (AST) + + SlangAST, ///< Slang AST CompileResults, ///< Payload is a collection of compilation results - Metadata, ///< Metadata + Metadata, ///< Metadata - DebugInfo, ///< Debugging information - Diagnostics, ///< Diagnostics information + DebugInfo, ///< Debugging information + Diagnostics, ///< Diagnostics information - Miscellaneous, ///< Category for miscellaneous payloads (like Log/Lock) + Miscellaneous, ///< Category for miscellaneous payloads (like Log/Lock) - Log, ///< Log file - Lock, ///< Typically some kind of 'lock' file. Contents is typically not important. + Log, ///< Log file + Lock, ///< Typically some kind of 'lock' file. Contents is typically not important. - PdbDebugInfo, ///< PDB debug info + PdbDebugInfo, ///< PDB debug info - SourceMap, ///< A source map + SourceMap, ///< A source map - PostEmitMetadata, ///< Metadata from post emit (binding information) + PostEmitMetadata, ///< Metadata from post emit (binding information) CountOf, }; @@ -205,18 +236,18 @@ Any change requires a change to SLANG_ARTIFACT_STYLE */ enum class ArtifactStyle : uint8_t { - Invalid, ///< Invalid style (indicating an error) + Invalid, ///< Invalid style (indicating an error) Base, - - None, ///< A style is not applicable - Unknown, ///< Unknown + None, ///< A style is not applicable + + Unknown, ///< Unknown - CodeLike, ///< For styles that are 'code like' such as 'kernel' or 'host'. + CodeLike, ///< For styles that are 'code like' such as 'kernel' or 'host'. - Kernel, ///< Compiled as `GPU kernel` style. - Host, ///< Compiled in `host` style - Obfuscated, ///< Holds something specific to obfuscation, such as an obfuscated source map + Kernel, ///< Compiled as `GPU kernel` style. + Host, ///< Compiled in `host` style + Obfuscated, ///< Holds something specific to obfuscation, such as an obfuscated source map CountOf, }; @@ -242,21 +273,35 @@ public: typedef ArtifactPayload Payload; typedef ArtifactStyle Style; typedef ArtifactFlags Flags; - + typedef uint32_t PackedBacking; enum class Packed : PackedBacking; - - /// Get in packed format + + /// Get in packed format inline Packed getPacked() const; - bool operator==(const ThisType& rhs) const { return kind == rhs.kind && payload == rhs.payload && style == rhs.style && flags == rhs.flags; } + bool operator==(const ThisType& rhs) const + { + return kind == rhs.kind && payload == rhs.payload && style == rhs.style && + flags == rhs.flags; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Construct from the elements - static ThisType make(Kind inKind, Payload inPayload, Style inStyle = Style::Unknown, Flags flags = 0) { return ThisType{ inKind, inPayload, inStyle, flags }; } - static ThisType make(Kind inKind, Payload inPayload, const ThisType& base) { return ThisType{ inKind, inPayload, base.style, base.flags }; } + /// Construct from the elements + static ThisType make( + Kind inKind, + Payload inPayload, + Style inStyle = Style::Unknown, + Flags flags = 0) + { + return ThisType{inKind, inPayload, inStyle, flags}; + } + static ThisType make(Kind inKind, Payload inPayload, const ThisType& base) + { + return ThisType{inKind, inPayload, base.style, base.flags}; + } - /// Construct from the packed format + /// Construct from the packed format inline static ThisType make(Packed inPacked); Kind kind; @@ -269,14 +314,11 @@ public: inline ArtifactDesc::Packed ArtifactDesc::getPacked() const { typedef PackedBacking IntType; - return Packed((IntType(kind) << 24) | - (IntType(payload) << 16) | - (IntType(style) << 8) | - flags); + return Packed((IntType(kind) << 24) | (IntType(payload) << 16) | (IntType(style) << 8) | flags); } // -------------------------------------------------------------------------- -inline /* static */ArtifactDesc ArtifactDesc::make(Packed inPacked) +inline /* static */ ArtifactDesc ArtifactDesc::make(Packed inPacked) { const PackedBacking packed = PackedBacking(inPacked); @@ -295,43 +337,53 @@ class IPathArtifactRepresentation; class IArtifactRepresentation; -// Controls what items can be kept. +// Controls what items can be kept. enum class ArtifactKeep { - No, ///< Don't keep the item - Yes, ///< Yes keep the final item - All, ///< Keep the final item and any intermediataries + No, ///< Don't keep the item + Yes, ///< Yes keep the final item + All, ///< Keep the final item and any intermediataries }; /// True if can keep an intermediate item -SLANG_INLINE bool canKeepIntermediate(ArtifactKeep keep) { return keep == ArtifactKeep::All; } +SLANG_INLINE bool canKeepIntermediate(ArtifactKeep keep) +{ + return keep == ArtifactKeep::All; +} /// True if can keep -SLANG_INLINE bool canKeep(ArtifactKeep keep) { return Index(keep) >= Index(ArtifactKeep::Yes); } +SLANG_INLINE bool canKeep(ArtifactKeep keep) +{ + return Index(keep) >= Index(ArtifactKeep::Yes); +} /// Returns the keep type for an intermediate -SLANG_INLINE ArtifactKeep getIntermediateKeep(ArtifactKeep keep) { return (keep == ArtifactKeep::All) ? ArtifactKeep::All : ArtifactKeep::No; } +SLANG_INLINE ArtifactKeep getIntermediateKeep(ArtifactKeep keep) +{ + return (keep == ArtifactKeep::All) ? ArtifactKeep::All : ArtifactKeep::No; +} /* Forward define */ class IArtifactHandler; -/* The IArtifact interface is designed to represent some Artifact of compilation. It could be input to or output from a compilation. +/* The IArtifact interface is designed to represent some Artifact of compilation. It could be input +to or output from a compilation. An abstraction is desirable here, because depending on the compiler the artifact/s could be * A file on the file system * A blob * Multiple files -* Some other (perhaps multiple) in memory representations -* A name +* Some other (perhaps multiple) in memory representations +* A name -The artifact uses the Blob as the canonical in memory representation. +The artifact uses the Blob as the canonical in memory representation. Some downstream compilers require the artifact to be available as a file system file, or to produce artifacts that are files. The IArtifact type allows to abstract away this difference, including the -ability to turn an in memory representation into a temporary file on the file system. +ability to turn an in memory representation into a temporary file on the file system. -The mechanism also allows for 'Containers' which allow for Artifacts to contain other Artifacts (amongst other things). -Those artifacts may be other files. For example a downstream compilation that produces results as well as temporary -files could be a Container containing artifacts for +The mechanism also allows for 'Containers' which allow for Artifacts to contain other Artifacts +(amongst other things). Those artifacts may be other files. For example a downstream compilation +that produces results as well as temporary files could be a Container containing artifacts for * Diagnostics * Temporary files (of known and unknown types) @@ -344,20 +396,26 @@ There are several types of ways to associate data with an artifact: * An associated artifact * A child artifact -A `representation` has to wholly represent the artifact. That representation could be a blob, a file on the file system, -an in memory representation. There are two classes of `Representation` - ones that can be turned into blobs (and therefore -derive from IArtifactRepresentation) and ones that are in of themselves a representation (such as a blob or or ISlangSharedLibrary). +A `representation` has to wholly represent the artifact. That representation could be a blob, a file +on the file system, an in memory representation. There are two classes of `Representation` - ones +that can be turned into blobs (and therefore derive from IArtifactRepresentation) and ones that are +in of themselves a representation (such as a blob or or ISlangSharedLibrary). -`Associated artifacts` hold information that is associated with the artifact. It could be part -of the representation, or useful for the implementation of a representation. Could also be considered as a kind of side channel -to associate arbitrary data including temporary data with an artifact. +`Associated artifacts` hold information that is associated with the artifact. It could be part +of the representation, or useful for the implementation of a representation. Could also be +considered as a kind of side channel to associate arbitrary data including temporary data with an +artifact. A `child artifact` belongs to the artifact, within the hierarchy of artifacts. */ class IArtifact : public ICastable { public: - SLANG_COM_INTERFACE(0xf90acdb0, 0x9a4a, 0x414e, { 0x85, 0x45, 0x8b, 0x26, 0xc9, 0x2d, 0x94, 0x42 }) + SLANG_COM_INTERFACE( + 0xf90acdb0, + 0x9a4a, + 0x414e, + {0x85, 0x45, 0x8b, 0x26, 0xc9, 0x2d, 0x94, 0x42}) enum class ContainedKind { @@ -374,90 +432,100 @@ public: typedef ArtifactFlags Flags; typedef ArtifactKeep Keep; - - /// Get the Desc defining the contents of the artifact + + /// Get the Desc defining the contents of the artifact virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() = 0; - /// Returns true if the artifact in principal exists + /// Returns true if the artifact in principal exists virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; - /// Load as a blob + /// Load as a blob virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) = 0; - - /// Require artifact is available as a file. - /// NOTE! May need to serialize and write as a temporary file. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) = 0; - /// Load the artifact as a shared library - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) = 0; + /// Require artifact is available as a file. + /// NOTE! May need to serialize and write as a temporary file. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) = 0; - /// Get the name of the artifact. This can be empty. + /// Load the artifact as a shared library + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) = 0; + + /// Get the name of the artifact. This can be empty. virtual SLANG_NO_THROW const char* SLANG_MCALL getName() = 0; - /// Set the name associated with the artifact + /// Set the name associated with the artifact virtual SLANG_NO_THROW void SLANG_MCALL setName(const char* name) = 0; - /// Add associated artifacts with this artifact + /// Add associated artifacts with this artifact virtual SLANG_NO_THROW void SLANG_MCALL addAssociated(IArtifact* artifact) = 0; - /// Get the list of associated items + /// Get the list of associated items virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getAssociated() = 0; - - /// Add a representation + + /// Add a representation virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(ICastable* castable) = 0; - /// Add a representation that doesn't derive from IArtifactRepresentation + /// Add a representation that doesn't derive from IArtifactRepresentation virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) = 0; - /// Get all the representations + /// Get all the representations virtual SLANG_NO_THROW Slice<ICastable*> SLANG_MCALL getRepresentations() = 0; - /// Given a typeGuid representing the desired type get or create the representation. - /// If found outCastable holds an entity that *must* be castable to typeGuid - /// Use the keep parameter to determine if the representation should be cached on the artifact/s or not. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) = 0; - - /// Get the handler used for this artifact. If nullptr means the default handler will be used. + /// Given a typeGuid representing the desired type get or create the representation. + /// If found outCastable holds an entity that *must* be castable to typeGuid + /// Use the keep parameter to determine if the representation should be cached on the artifact/s + /// or not. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) = 0; + + /// Get the handler used for this artifact. If nullptr means the default handler will be used. virtual SLANG_NO_THROW IArtifactHandler* SLANG_MCALL getHandler() = 0; - /// Set the handler associated with this artifact. Setting nullptr will use the default handler. + /// Set the handler associated with this artifact. Setting nullptr will use the default handler. virtual SLANG_NO_THROW void SLANG_MCALL setHandler(IArtifactHandler* handler) = 0; - /// Returns the result of expansion. Will return SLANG_E_UNINITIALIZED if expansion hasn't happened + /// Returns the result of expansion. Will return SLANG_E_UNINITIALIZED if expansion hasn't + /// happened virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() = 0; - /// Sets all of the children, will set the expansion state to SLANG_OK - virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact*const* children, Count count) = 0; - /// Will be called implicitly on access to children + /// Sets all of the children, will set the expansion state to SLANG_OK + virtual SLANG_NO_THROW void SLANG_MCALL + setChildren(IArtifact* const* children, Count count) = 0; + /// Will be called implicitly on access to children virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren() = 0; - /// Add the artifact to the list + /// Add the artifact to the list virtual SLANG_NO_THROW void SLANG_MCALL addChild(IArtifact* artifact) = 0; - /// Get the children, will only remain valid if no mutation of children list + /// Get the children, will only remain valid if no mutation of children list virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getChildren() = 0; - /// Find a represention from the specified list - virtual SLANG_NO_THROW void* SLANG_MCALL findRepresentation(ContainedKind kind, const Guid& guid) = 0; - /// Clear all of the contained kind + /// Find a represention from the specified list + virtual SLANG_NO_THROW void* SLANG_MCALL + findRepresentation(ContainedKind kind, const Guid& guid) = 0; + /// Clear all of the contained kind virtual SLANG_NO_THROW void SLANG_MCALL clear(ContainedKind kind) = 0; - /// Remove entry at index for the specified kind + /// Remove entry at index for the specified kind virtual SLANG_NO_THROW void SLANG_MCALL removeAt(ContainedKind kind, Index i) = 0; }; -template <typename T> +template<typename T> SLANG_FORCE_INLINE T* findRepresentation(IArtifact* artifact) { - return reinterpret_cast<T*>(artifact->findRepresentation(IArtifact::ContainedKind::Representation, T::getTypeGuid())); + return reinterpret_cast<T*>( + artifact->findRepresentation(IArtifact::ContainedKind::Representation, T::getTypeGuid())); } -template <typename T> +template<typename T> SLANG_FORCE_INLINE T* findAssociatedRepresentation(IArtifact* artifact) { - return reinterpret_cast<T*>(artifact->findRepresentation(IArtifact::ContainedKind::Associated, T::getTypeGuid())); + return reinterpret_cast<T*>( + artifact->findRepresentation(IArtifact::ContainedKind::Associated, T::getTypeGuid())); } -template <typename T> +template<typename T> SLANG_FORCE_INLINE T* findChildRepresentation(IArtifact* artifact) { - return reinterpret_cast<T*>(artifact->findRepresentation(IArtifact::ContainedKind::Children, T::getTypeGuid())); + return reinterpret_cast<T*>( + artifact->findRepresentation(IArtifact::ContainedKind::Children, T::getTypeGuid())); } -/* The IArtifactRepresentation interface represents a single representation that can be part of an artifact. It's special in so far -as +/* The IArtifactRepresentation interface represents a single representation that can be part of an +artifact. It's special in so far as * IArtifactRepresentation can be queried for it's underlying object class * Can determine if the representation exists (for example if it's on the file system) @@ -465,26 +533,35 @@ as */ class IArtifactRepresentation : public ICastable { - SLANG_COM_INTERFACE(0xa3790eb, 0x22b9, 0x430e, { 0xbf, 0xc6, 0x24, 0x6c, 0x5b, 0x5c, 0xcd, 0x0 }) + SLANG_COM_INTERFACE(0xa3790eb, 0x22b9, 0x430e, {0xbf, 0xc6, 0x24, 0x6c, 0x5b, 0x5c, 0xcd, 0x0}) - /// Create a representation of the specified typeGuid interface. - /// Calling castAs on the castable will return the specific type - /// Returns SLANG_E_NOT_IMPLEMENTED if an implementation doesn't implement - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) = 0; + /// Create a representation of the specified typeGuid interface. + /// Calling castAs on the castable will return the specific type + /// Returns SLANG_E_NOT_IMPLEMENTED if an implementation doesn't implement + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& typeGuid, ICastable** outCastable) = 0; - /// Returns true if this representation exists and is available for use. + /// Returns true if this representation exists and is available for use. virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; }; /* Handler provides functionality external to the artifact */ class IArtifactHandler : public ICastable { - SLANG_COM_INTERFACE(0x6a646f57, 0xb3ac, 0x4c6a, { 0xb6, 0xf1, 0x33, 0xb6, 0xef, 0x60, 0xa6, 0xae }); + SLANG_COM_INTERFACE( + 0x6a646f57, + 0xb3ac, + 0x4c6a, + {0xb6, 0xf1, 0x33, 0xb6, 0xef, 0x60, 0xa6, 0xae}); - /// Given an artifact expands children + /// Given an artifact expands children virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifact* container) = 0; - /// Given an artifact gets or creates a representation. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) = 0; + /// Given an artifact gets or creates a representation. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation( + IArtifact* artifact, + const Guid& guid, + ArtifactKeep keep, + ICastable** outCastable) = 0; }; } // namespace Slang diff --git a/source/compiler-core/slang-command-line-args.cpp b/source/compiler-core/slang-command-line-args.cpp index b69836030..451ea406c 100644 --- a/source/compiler-core/slang-command-line-args.cpp +++ b/source/compiler-core/slang-command-line-args.cpp @@ -6,9 +6,10 @@ #include "../core/slang-type-text-util.h" #include "slang-core-diagnostics.h" -namespace Slang { +namespace Slang +{ -void CommandLineArgs::setArgs(const char*const* args, size_t argCount) +void CommandLineArgs::setArgs(const char* const* args, size_t argCount) { m_args.clear(); @@ -17,7 +18,7 @@ void CommandLineArgs::setArgs(const char*const* args, size_t argCount) const SourceLoc startLoc = sourceManager->getNextRangeStart(); StringBuilder buf; - + auto escapeHandler = Process::getEscapeHandler(); for (size_t i = 0; i < argCount; ++i) @@ -39,14 +40,16 @@ void CommandLineArgs::setArgs(const char*const* args, size_t argCount) buf << " "; } - SourceFile* sourceFile = sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), buf.produceString()); - SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr, SourceLoc::fromRaw(0)); + SourceFile* sourceFile = + sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), buf.produceString()); + SourceView* sourceView = + sourceManager->createSourceView(sourceFile, nullptr, SourceLoc::fromRaw(0)); SLANG_UNUSED(sourceView); SLANG_ASSERT(sourceView->getRange().begin == startLoc); } -bool CommandLineArgs::hasArgs(const char*const* args, Index count) const +bool CommandLineArgs::hasArgs(const char* const* args, Index count) const { if (m_args.getCount() != count) { @@ -164,12 +167,16 @@ Index DownstreamArgs::addName(const String& name) if (index < 0) { index = m_entries.getCount(); - m_entries.add(Entry{name, CommandLineArgs(m_context) }); + m_entries.add(Entry{name, CommandLineArgs(m_context)}); } return index; } -Index DownstreamArgs::_findOrAddName(SourceLoc loc, const UnownedStringSlice& name, Flags flags, DiagnosticSink* sink) +Index DownstreamArgs::_findOrAddName( + SourceLoc loc, + const UnownedStringSlice& name, + Flags flags, + DiagnosticSink* sink) { if (name.getLength() <= 0) { @@ -225,7 +232,10 @@ const CommandLineArgs& DownstreamArgs::getArgsByName(const char* name) const return m_entries[index].args; } -SlangResult DownstreamArgs::stripDownstreamArgs(CommandLineArgs& ioArgs, Flags flags, DiagnosticSink* sink) +SlangResult DownstreamArgs::stripDownstreamArgs( + CommandLineArgs& ioArgs, + Flags flags, + DiagnosticSink* sink) { CommandLineReader reader(&ioArgs, sink); @@ -237,7 +247,8 @@ SlangResult DownstreamArgs::stripDownstreamArgs(CommandLineArgs& ioArgs, Flags f { if (arg.value.endsWith("...")) { - const UnownedStringSlice name = arg.value.getUnownedSlice().subString(2, arg.value.getLength() - 5); + const UnownedStringSlice name = + arg.value.getUnownedSlice().subString(2, arg.value.getLength() - 5); const Index nameIndex = _findOrAddName(arg.loc, name, flags, sink); if (nameIndex < 0) { @@ -283,7 +294,9 @@ SlangResult DownstreamArgs::stripDownstreamArgs(CommandLineArgs& ioArgs, Flags f CommandLineArgs& args = getArgsAt(nameIndex); // Copy the values in the range - args.m_args.addRange(ioArgs.m_args.getBuffer() + startIndex + 1, index - (startIndex + 1)); + args.m_args.addRange( + ioArgs.m_args.getBuffer() + startIndex + 1, + index - (startIndex + 1)); // If we aren't at the end, we must be pointing to -X., so skip that index += Index(index < count); diff --git a/source/compiler-core/slang-command-line-args.h b/source/compiler-core/slang-command-line-args.h index 0c11a3c46..388847f5c 100644 --- a/source/compiler-core/slang-command-line-args.h +++ b/source/compiler-core/slang-command-line-args.h @@ -5,33 +5,34 @@ // the name of types, variables, etc. in the AST. #include "../core/slang-basic.h" - -#include "slang-source-loc.h" #include "slang-diagnostic-sink.h" +#include "slang-source-loc.h" -namespace Slang { +namespace Slang +{ struct CommandLineArg { - String value; ///< The value of the arg - SourceLoc loc; ///< The location of the arg + String value; ///< The value of the arg + SourceLoc loc; ///< The location of the arg }; -/* This type ends up being really just a container for the sourceManager that has the CommandLine specific SourceLocs. -That it would perhaps be better to just have SourceManager derive from RefObject, and then we could remove this -type. */ +/* This type ends up being really just a container for the sourceManager that has the CommandLine +specific SourceLocs. That it would perhaps be better to just have SourceManager derive from +RefObject, and then we could remove this type. */ class CommandLineContext : public RefObject { -public: - /// Get the source manager +public: + /// Get the source manager SourceManager* getSourceManager() { return &m_sourceManager; } CommandLineContext(ISlangFileSystemExt* fileSystemExt = nullptr) { m_sourceManager.initialize(nullptr, fileSystemExt); // Make range start from high value, so can be differentiated from other uses - // That this doesn't not assume exclusive use of this range - just that in normal use scenarios - // there is no confusion, and using the wrong source manager, will typically report nothing is found. + // That this doesn't not assume exclusive use of this range - just that in normal use + // scenarios there is no confusion, and using the wrong source manager, will typically + // report nothing is found. m_sourceManager.allocateSourceRange(~(~SourceLoc::RawValue(0) >> 1)); } @@ -49,26 +50,26 @@ struct CommandLineArgs const Arg* begin() const { return m_args.begin(); } const Arg* end() const { return m_args.end(); } - /// NOTE! Should NOT include the executable name - void setArgs(const char*const* args, size_t argCount); + /// NOTE! Should NOT include the executable name + void setArgs(const char* const* args, size_t argCount); - /// True if has args in same order - bool hasArgs(const char*const* args, Index count) const; + /// True if has args in same order + bool hasArgs(const char* const* args, Index count) const; - /// Add an arg + /// Add an arg void add(const Arg& arg) { m_args.add(arg); } - /// Ctor with a context - CommandLineArgs(CommandLineContext* context): - m_context(context) + /// Ctor with a context + CommandLineArgs(CommandLineContext* context) + : m_context(context) { } - /// Default Ctor + /// Default Ctor CommandLineArgs() {} - //String m_executablePath; ///< Can be optionally be set - List<Arg> m_args; ///< The args - RefPtr<CommandLineContext> m_context; ///< The context, which mainly has source manager + // String m_executablePath; ///< Can be optionally be set + List<Arg> m_args; ///< The args + RefPtr<CommandLineContext> m_context; ///< The context, which mainly has source manager String serialize(); void deserialize(String content); @@ -76,45 +77,83 @@ struct CommandLineArgs struct CommandLineReader { - /// Peek the current location - SourceLoc peekLoc() const { return m_index < m_args->getArgCount() ? (*m_args)[m_index].loc : SourceLoc(); } - /// Peek the current arg - const CommandLineArg& peekArg() const { SLANG_ASSERT(hasArg()); return (*m_args)[m_index]; } + /// Peek the current location + SourceLoc peekLoc() const + { + return m_index < m_args->getArgCount() ? (*m_args)[m_index].loc : SourceLoc(); + } + /// Peek the current arg + const CommandLineArg& peekArg() const + { + SLANG_ASSERT(hasArg()); + return (*m_args)[m_index]; + } - /// Peek the string value at that position - const String& peekValue() const { SLANG_ASSERT(hasArg()); return (*m_args)[m_index].value; } + /// Peek the string value at that position + const String& peekValue() const + { + SLANG_ASSERT(hasArg()); + return (*m_args)[m_index].value; + } - /// Get the arg and advance - CommandLineArg getArgAndAdvance() { CommandLineArg arg(peekArg()); advance(); return arg; } + /// Get the arg and advance + CommandLineArg getArgAndAdvance() + { + CommandLineArg arg(peekArg()); + advance(); + return arg; + } - const String& getValueAndAdvance() { const String& value = peekValue(); advance(); return value; } + const String& getValueAndAdvance() + { + const String& value = peekValue(); + advance(); + return value; + } - /// True if at end + /// True if at end bool atEnd() const { return m_index >= m_args->getArgCount(); } - /// True if has a current arg + /// True if has a current arg bool hasArg() const { return !atEnd(); } - /// Advance to next arg - void advance() { SLANG_ASSERT(m_index < m_args->getArgCount()); m_index++; } - /// Removes arg at current position - void removeArg() { SLANG_ASSERT(hasArg()); m_args->m_args.removeAt(m_index); } + /// Advance to next arg + void advance() + { + SLANG_ASSERT(m_index < m_args->getArgCount()); + m_index++; + } + /// Removes arg at current position + void removeArg() + { + SLANG_ASSERT(hasArg()); + m_args->m_args.removeAt(m_index); + } - /// Get the value from the arg previous to the current position. Will assert if there isn't one. - String getPreviousValue() const; + /// Get the value from the arg previous to the current position. Will assert if there isn't one. + String getPreviousValue() const; - /// If there is an arg outArg is set and advanced - /// Note, this *assumes* the previous arg is the option that initated this + /// If there is an arg outArg is set and advanced + /// Note, this *assumes* the previous arg is the option that initated this SlangResult expectArg(String& outArg); SlangResult expectArg(CommandLineArg& outArg); - /// Get the current index + /// Get the current index Index getIndex() const { return m_index; } - /// Set the current index - void setIndex(Index index) { SLANG_ASSERT(index >= 0 && index <= m_args->getArgCount()); m_index = index; } + /// Set the current index + void setIndex(Index index) + { + SLANG_ASSERT(index >= 0 && index <= m_args->getArgCount()); + m_index = index; + } - void init(CommandLineArgs* args, DiagnosticSink* sink) { m_args = args; m_sink = sink; m_index = 0; } + void init(CommandLineArgs* args, DiagnosticSink* sink) + { + m_args = args; + m_sink = sink; + m_index = 0; + } - /// Set up reader with args + /// Set up reader with args CommandLineReader(CommandLineArgs* args, DiagnosticSink* sink) { init(args, sink); } CommandLineReader() = default; @@ -136,39 +175,48 @@ struct DownstreamArgs struct Entry { - String name; ///< The name of the 'tool' that these args are associated with - CommandLineArgs args; ///< The args to be passed to the tool + String name; ///< The name of the 'tool' that these args are associated with + CommandLineArgs args; ///< The args to be passed to the tool }; - /// Add a name, returns the index + /// Add a name, returns the index Index addName(const String& name); - /// Find the index of a name. Returns < 0 if not found. - Index findName(const String& name) const { return m_entries.findFirstIndex([&](const Entry& entry) -> bool { return entry.name == name; }); } + /// Find the index of a name. Returns < 0 if not found. + Index findName(const String& name) const + { + return m_entries.findFirstIndex( + [&](const Entry& entry) -> bool { return entry.name == name; }); + } - /// Get the args at the nameIndex + /// Get the args at the nameIndex CommandLineArgs& getArgsAt(Index nameIndex) { return m_entries[nameIndex].args; } - /// Get args by name - will assert if name isn't found + /// Get args by name - will assert if name isn't found CommandLineArgs& getArgsByName(const char* name); const CommandLineArgs& getArgsByName(const char* name) const; - /// Looks for '-X' expressions, removing them from ioArgs and putting in appropriate args + /// Looks for '-X' expressions, removing them from ioArgs and putting in appropriate args SlangResult stripDownstreamArgs(CommandLineArgs& ioArgs, Flags flags, DiagnosticSink* sink); - /// Get the context used + /// Get the context used CommandLineContext* getContext() const { return m_context; } - /// Ctor + /// Ctor DownstreamArgs(CommandLineContext* context); - /// Default ctor - for convenience, should really use with context normally + /// Default ctor - for convenience, should really use with context normally DownstreamArgs() {} - List<Entry> m_entries; ///< All of the entries + List<Entry> m_entries; ///< All of the entries protected: - Index _findOrAddName(SourceLoc loc, const UnownedStringSlice& name, Flags flags, DiagnosticSink* sink); - - RefPtr<CommandLineContext> m_context; ///< The context that is being used (primarily for loc tracking) across all entries/args + Index _findOrAddName( + SourceLoc loc, + const UnownedStringSlice& name, + Flags flags, + DiagnosticSink* sink); + + RefPtr<CommandLineContext> m_context; ///< The context that is being used (primarily for loc + ///< tracking) across all entries/args }; diff --git a/source/compiler-core/slang-core-diagnostics.cpp b/source/compiler-core/slang-core-diagnostics.cpp index 7aa6c5c14..4fbae6873 100644 --- a/source/compiler-core/slang-core-diagnostics.cpp +++ b/source/compiler-core/slang-core-diagnostics.cpp @@ -1,18 +1,19 @@ // slang-core-diagnostics.cpp #include "slang-core-diagnostics.h" -namespace Slang { +namespace Slang +{ namespace MiscDiagnostics { -#define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, #name, messageFormat }; +#define DIAGNOSTIC(id, severity, name, messageFormat) \ + const DiagnosticInfo name = {id, Severity::severity, #name, messageFormat}; #include "slang-misc-diagnostic-defs.h" #undef DIAGNOSTIC -} +} // namespace MiscDiagnostics -static const DiagnosticInfo* const kMiscDiagnostics[] = -{ -#define DIAGNOSTIC(id, severity, name, messageFormat) &MiscDiagnostics::name, +static const DiagnosticInfo* const kMiscDiagnostics[] = { +#define DIAGNOSTIC(id, severity, name, messageFormat) &MiscDiagnostics::name, #include "slang-misc-diagnostic-defs.h" #undef DIAGNOSTIC }; @@ -20,14 +21,14 @@ static const DiagnosticInfo* const kMiscDiagnostics[] = namespace LexerDiagnostics { -#define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, #name, messageFormat }; +#define DIAGNOSTIC(id, severity, name, messageFormat) \ + const DiagnosticInfo name = {id, Severity::severity, #name, messageFormat}; #include "slang-lexer-diagnostic-defs.h" #undef DIAGNOSTIC -} +} // namespace LexerDiagnostics -static const DiagnosticInfo* const kLexerDiagnostics[] = -{ -#define DIAGNOSTIC(id, severity, name, messageFormat) &LexerDiagnostics::name, +static const DiagnosticInfo* const kLexerDiagnostics[] = { +#define DIAGNOSTIC(id, severity, name, messageFormat) &LexerDiagnostics::name, #include "slang-lexer-diagnostic-defs.h" #undef DIAGNOSTIC }; diff --git a/source/compiler-core/slang-core-diagnostics.h b/source/compiler-core/slang-core-diagnostics.h index fd1906fae..815a042c0 100644 --- a/source/compiler-core/slang-core-diagnostics.h +++ b/source/compiler-core/slang-core-diagnostics.h @@ -3,11 +3,9 @@ #include "../core/slang-basic.h" #include "../core/slang-writer.h" - -#include "slang-source-loc.h" #include "slang-diagnostic-sink.h" +#include "slang-source-loc.h" #include "slang-token.h" - #include "slang.h" namespace Slang @@ -19,14 +17,14 @@ namespace MiscDiagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) extern const DiagnosticInfo name; #include "slang-misc-diagnostic-defs.h" -} +} // namespace MiscDiagnostics namespace LexerDiagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) extern const DiagnosticInfo name; #include "slang-lexer-diagnostic-defs.h" -} +} // namespace LexerDiagnostics -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-diagnostic-sink.cpp b/source/compiler-core/slang-diagnostic-sink.cpp index a4cbce22f..537892f08 100644 --- a/source/compiler-core/slang-diagnostic-sink.cpp +++ b/source/compiler-core/slang-diagnostic-sink.cpp @@ -1,16 +1,16 @@ // slang-diagnostic-sink.cpp #include "slang-diagnostic-sink.h" -#include "slang-name.h" -#include "slang-core-diagnostics.h" -#include "slang-name-convention-util.h" - -#include "../core/slang-memory-arena.h" +#include "../core/slang-char-util.h" #include "../core/slang-dictionary.h" +#include "../core/slang-memory-arena.h" #include "../core/slang-string-util.h" -#include "../core/slang-char-util.h" +#include "slang-core-diagnostics.h" +#include "slang-name-convention-util.h" +#include "slang-name.h" -namespace Slang { +namespace Slang +{ void printDiagnosticArg(StringBuilder& sb, char const* str) { @@ -75,10 +75,14 @@ SourceLoc getDiagnosticPos(Token const& token) } // Take the format string for a diagnostic message, along with its arguments, and turn it into a -static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int argCount, DiagnosticArg const* args) +static void formatDiagnosticMessage( + StringBuilder& sb, + char const* format, + int argCount, + DiagnosticArg const* args) { char const* spanBegin = format; - for(;;) + for (;;) { char const* spanEnd = spanBegin; while (int c = *spanEnd) @@ -97,21 +101,28 @@ static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int a int d = *spanEnd++; switch (d) { - // A double dollar sign `$$` is used to emit a single `$` - case '$': - sb.append('$'); - break; + // A double dollar sign `$$` is used to emit a single `$` + case '$': sb.append('$'); break; // A single digit means to emit the corresponding argument. // TODO: support more than 10 arguments, and add options // to control formatting, etc. - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { int index = d - '0'; if (index >= argCount) { - // TODO(tfoley): figure out what a good policy will be for "panic" situations like this + // TODO(tfoley): figure out what a good policy will be for "panic" situations + // like this SLANG_INVALID_OPERATION("too few arguments for diagnostic message"); } else @@ -122,16 +133,18 @@ static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int a } break; - default: - SLANG_INVALID_OPERATION("invalid diagnostic message format"); - break; + default: SLANG_INVALID_OPERATION("invalid diagnostic message format"); break; } spanBegin = spanEnd; } } -static void formatDiagnostic(const HumaneSourceLoc& humaneLoc, Diagnostic const& diagnostic, DiagnosticSink::Flags flags, StringBuilder& outBuilder) +static void formatDiagnostic( + const HumaneSourceLoc& humaneLoc, + Diagnostic const& diagnostic, + DiagnosticSink::Flags flags, + StringBuilder& outBuilder) { if (flags & DiagnosticSink::Flag::HumaneLoc) { @@ -161,7 +174,7 @@ static void formatDiagnostic(const HumaneSourceLoc& humaneLoc, Diagnostic const& static void _replaceTabWithSpaces(const UnownedStringSlice& slice, Int tabSize, StringBuilder& out) { const char* start = slice.begin(); - const char*const end = slice.end(); + const char* const end = slice.end(); const Index startLength = out.getLength(); @@ -211,12 +224,14 @@ static void _replaceTabWithSpaces(const UnownedStringSlice& slice, Int tabSize, // Given multi-line text, and a position within the text (as a pointer into the memory of text) // extract the line that contains pos -static UnownedStringSlice _extractLineContainingPosition(const UnownedStringSlice& text, const char* pos) +static UnownedStringSlice _extractLineContainingPosition( + const UnownedStringSlice& text, + const char* pos) { SLANG_ASSERT(text.isMemoryContained(pos)); - const char*const contentStart = text.begin(); - const char*const contentEnd = text.end(); + const char* const contentStart = text.begin(); + const char* const contentEnd = text.end(); // We want to determine the start of the line, and the end of the line const char* start = pos; @@ -251,7 +266,11 @@ static void _reduceLength(Index startIndex, const UnownedStringSlice& prefix, St ioBuf = buf; } -static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sourceView, SourceLoc sourceLoc, StringBuilder& sb) +static void _sourceLocationNoteDiagnostic( + DiagnosticSink* sink, + SourceView* sourceView, + SourceLoc sourceLoc, + StringBuilder& sb) { SourceFile* sourceFile = sourceView->getSourceFile(); if (!sourceFile) @@ -262,8 +281,9 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour UnownedStringSlice content = sourceFile->getContent(); // Make sure the offset is within content. - // This is important because it's possible to have a 'SourceFile' that doesn't contain any content - // (for example when reconstructed via serialization with just line offsets, the actual source text 'content' isn't available). + // This is important because it's possible to have a 'SourceFile' that doesn't contain any + // content (for example when reconstructed via serialization with just line offsets, the actual + // source text 'content' isn't available). const int offset = sourceView->getRange().getOffset(sourceLoc); if (offset < 0 || offset >= content.getLength()) { @@ -271,7 +291,7 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour } // Work out the position of the SourceLoc in the source - const char*const pos = content.begin() + offset; + const char* const pos = content.begin() + offset; UnownedStringSlice line = _extractLineContainingPosition(content, pos); @@ -287,7 +307,7 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour // First work out the sourceLine _replaceTabWithSpaces(line, tabSize, sourceLine); - + // Now the caretLine which appears underneath the sourceLine { // Produce the text up to the caret position (at pos), taking into account tabs @@ -321,9 +341,9 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour const UnownedStringSlice spaces = UnownedStringSlice::fromLiteral(" "); SLANG_ASSERT(ellipsis.getLength() == spaces.getLength()); - // We use the caretLine length if we have a lexer, because it will have underscores such that it's end is the end of - // the item at issue. - // If we don't have the lexer, we guesstimate using 1/4 of the maximum length + // We use the caretLine length if we have a lexer, because it will have underscores such + // that it's end is the end of the item at issue. If we don't have the lexer, we + // guesstimate using 1/4 of the maximum length const Index endIndex = lexer ? caretLine.getLength() : (caretIndex + (maxLength / 4)); if (endIndex > maxLength) @@ -344,9 +364,8 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour } } - // We could have handling here for if the line is too long, that we surround the important section - // will ellipsis for example. - // For now we just output. + // We could have handling here for if the line is too long, that we surround the important + // section will ellipsis for example. For now we just output. sb << sourceLine << "\n"; sb << caretLine << "\n"; @@ -354,7 +373,10 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour // Output the length of the token at `sourceLoc`. This is used by language server. static void _tokenLengthNoteDiagnostic( - DiagnosticSink* sink, SourceView* sourceView, SourceLoc sourceLoc, StringBuilder& sb) + DiagnosticSink* sink, + SourceView* sourceView, + SourceLoc sourceLoc, + StringBuilder& sb) { SourceFile* sourceFile = sourceView->getSourceFile(); if (!sourceFile) @@ -394,10 +416,7 @@ static void _tokenLengthNoteDiagnostic( } } -static void formatDiagnostic( - DiagnosticSink* sink, - Diagnostic const& diagnostic, - StringBuilder& sb) +static void formatDiagnostic(DiagnosticSink* sink, Diagnostic const& diagnostic, StringBuilder& sb) { auto sourceManager = sink->getSourceManager(); @@ -413,15 +432,19 @@ static void formatDiagnostic( humaneLoc = sourceView->getHumaneLoc(sourceLoc); } } - + formatDiagnostic(humaneLoc, diagnostic, sink->getFlags(), sb); { SourceView* currentView = sourceView; - while (currentView && currentView->getInitiatingSourceLoc().isValid() && currentView->getSourceFile()->getPathInfo().type == PathInfo::Type::TokenPaste) + while (currentView && currentView->getInitiatingSourceLoc().isValid() && + currentView->getSourceFile()->getPathInfo().type == PathInfo::Type::TokenPaste) { - SourceView* initiatingView = sourceManager ? sourceManager->findSourceView(currentView->getInitiatingSourceLoc()) : nullptr; + SourceView* initiatingView = + sourceManager + ? sourceManager->findSourceView(currentView->getInitiatingSourceLoc()) + : nullptr; if (initiatingView == nullptr) { break; @@ -441,8 +464,10 @@ static void formatDiagnostic( initiationDiagnostic.severity = diagnosticInfo.severity; // TODO(JS): - // Not 100% clear what the best sourceLoc type is most useful here - we will go with default for now - HumaneSourceLoc pasteHumaneLoc = initiatingView->getHumaneLoc(sourceView->getInitiatingSourceLoc()); + // Not 100% clear what the best sourceLoc type is most useful here - we will go + // with default for now + HumaneSourceLoc pasteHumaneLoc = + initiatingView->getHumaneLoc(sourceView->getInitiatingSourceLoc()); // Okay we should output where the token paste took place formatDiagnostic(pasteHumaneLoc, initiationDiagnostic, sink->getFlags(), sb); @@ -459,7 +484,8 @@ static void formatDiagnostic( _tokenLengthNoteDiagnostic(sink, sourceView, sourceLoc, sb); } - if (sourceView && sink->isFlagSet(DiagnosticSink::Flag::SourceLocationLine) && diagnostic.loc.isValid()) + if (sourceView && sink->isFlagSet(DiagnosticSink::Flag::SourceLocationLine) && + diagnostic.loc.isValid()) { _sourceLocationNoteDiagnostic(sink, sourceView, sourceLoc, sb); } @@ -473,9 +499,8 @@ static void formatDiagnostic( // Only output if it's actually different if (actualHumaneLoc.pathInfo.foundPath != humaneLoc.pathInfo.foundPath || - actualHumaneLoc.line != humaneLoc.line || - actualHumaneLoc.column != humaneLoc.column) - { + actualHumaneLoc.line != humaneLoc.line || actualHumaneLoc.column != humaneLoc.column) + { formatDiagnostic(actualHumaneLoc, diagnostic, sink->getFlags(), sb); } } @@ -533,7 +558,8 @@ SlangResult DiagnosticSink::getBlobIfNeeded(ISlangBlob** outBlob) { // If the client doesn't want an output blob, there is nothing to do. // - if (!outBlob) return SLANG_OK; + if (!outBlob) + return SLANG_OK; // For outputBuffer to be valid and hold diagnostics, writer must not be set SLANG_ASSERT(writer == nullptr); @@ -550,7 +576,9 @@ SlangResult DiagnosticSink::getBlobIfNeeded(ISlangBlob** outBlob) return SLANG_OK; } -bool DiagnosticSink::diagnoseImpl(DiagnosticInfo const& info, const UnownedStringSlice& formattedMessage) +bool DiagnosticSink::diagnoseImpl( + DiagnosticInfo const& info, + const UnownedStringSlice& formattedMessage) { if (info.severity >= Severity::Error) { @@ -600,7 +628,11 @@ Severity DiagnosticSink::getEffectiveMessageSeverity(DiagnosticInfo const& info) return effectiveSeverity; } -bool DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo info, int argCount, DiagnosticArg const* args) +bool DiagnosticSink::diagnoseImpl( + SourceLoc const& pos, + DiagnosticInfo info, + int argCount, + DiagnosticArg const* args) { // Override the severity in the 'info' structure to pass it further into formatDiagnostics info.severity = getEffectiveMessageSeverity(info); @@ -626,16 +658,12 @@ bool DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo info, int return diagnoseImpl(info, messageBuilder.getUnownedSlice()); } -void DiagnosticSink::diagnoseRaw( - Severity severity, - char const* message) +void DiagnosticSink::diagnoseRaw(Severity severity, char const* message) { return diagnoseRaw(severity, UnownedStringSlice(message)); } -void DiagnosticSink::diagnoseRaw( - Severity severity, - const UnownedStringSlice& message) +void DiagnosticSink::diagnoseRaw(Severity severity, const UnownedStringSlice& message) { if (severity >= Severity::Error) { @@ -643,7 +671,7 @@ void DiagnosticSink::diagnoseRaw( } // Did the client supply a callback for us to use? - if(writer) + if (writer) { // If so, pass the error string along to them. writer->write(message.begin(), message.getLength()); @@ -667,7 +695,10 @@ void DiagnosticSink::diagnoseRaw( } } -void DiagnosticSink::overrideDiagnosticSeverity(int diagnosticId, Severity overrideSeverity, const DiagnosticInfo* info) +void DiagnosticSink::overrideDiagnosticSeverity( + int diagnosticId, + Severity overrideSeverity, + const DiagnosticInfo* info) { if (info) { @@ -685,7 +716,8 @@ void DiagnosticSink::overrideDiagnosticSeverity(int diagnosticId, Severity overr m_severityOverrides[diagnosticId] = overrideSeverity; } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticLookup !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticLookup + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ Index DiagnosticsLookup::_findDiagnosticIndexByExactName(const UnownedStringSlice& slice) const { @@ -715,7 +747,8 @@ const DiagnosticInfo* DiagnosticsLookup::getDiagnosticById(Int id) const return indexPtr ? m_diagnostics[*indexPtr] : nullptr; } -const DiagnosticInfo* DiagnosticsLookup::findDiagnosticByExactName(const UnownedStringSlice& slice) const +const DiagnosticInfo* DiagnosticsLookup::findDiagnosticByExactName( + const UnownedStringSlice& slice) const { const Index* indexPtr = m_nameMap.tryGetValue(slice); return indexPtr ? m_diagnostics[*indexPtr] : nullptr; @@ -726,9 +759,9 @@ const DiagnosticInfo* DiagnosticsLookup::findDiagnosticByName(const UnownedStrin const auto convention = NameConventionUtil::inferConventionFromText(slice); switch (convention) { - case NameConvention::Invalid: return nullptr; - case NameConvention::LowerCamel: return findDiagnosticByExactName(slice); - default: break; + case NameConvention::Invalid: return nullptr; + case NameConvention::LowerCamel: return findDiagnosticByExactName(slice); + default: break; } StringBuilder buf; @@ -747,11 +780,11 @@ Index DiagnosticsLookup::add(const DiagnosticInfo* info) _addName(info->name, diagnosticIndex); m_idMap.addIfNotExists(info->id, diagnosticIndex); - + return diagnosticIndex; } -void DiagnosticsLookup::add(const DiagnosticInfo*const* infos, Index infosCount) +void DiagnosticsLookup::add(const DiagnosticInfo* const* infos, Index infosCount) { for (Index i = 0; i < infosCount; ++i) { @@ -759,19 +792,21 @@ void DiagnosticsLookup::add(const DiagnosticInfo*const* infos, Index infosCount) } } -DiagnosticsLookup::DiagnosticsLookup(): - m_arena(kArenaInitialSize) +DiagnosticsLookup::DiagnosticsLookup() + : m_arena(kArenaInitialSize) { } -DiagnosticsLookup::DiagnosticsLookup(const DiagnosticInfo*const* diagnostics, Index diagnosticsCount) : - m_arena(kArenaInitialSize) +DiagnosticsLookup::DiagnosticsLookup( + const DiagnosticInfo* const* diagnostics, + Index diagnosticsCount) + : m_arena(kArenaInitialSize) { // TODO: We should eventually have a more formal system for associating individual // diagnostics, or groups of diagnostics, with user-exposed names for use when // enabling/disabling warnings (or turning warnings into errors, etc.). // - // For now we build a map from diagnostic name to it's entry. + // For now we build a map from diagnostic name to it's entry. add(diagnostics, diagnosticsCount); } diff --git a/source/compiler-core/slang-diagnostic-sink.h b/source/compiler-core/slang-diagnostic-sink.h index 38a31752f..9a4116855 100644 --- a/source/compiler-core/slang-diagnostic-sink.h +++ b/source/compiler-core/slang-diagnostic-sink.h @@ -2,12 +2,10 @@ #define SLANG_DIAGNOSTIC_SINK_H #include "../core/slang-basic.h" -#include "../core/slang-writer.h" #include "../core/slang-memory-arena.h" - +#include "../core/slang-writer.h" #include "slang-source-loc.h" #include "slang-token.h" - #include "slang.h" namespace Slang @@ -24,25 +22,27 @@ enum class Severity }; // Make sure that the slang.h severity constants match those defined here -static_assert(SLANG_SEVERITY_DISABLED == int(Severity::Disable), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_NOTE == int(Severity::Note), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_WARNING == int(Severity::Warning), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_ERROR == int(Severity::Error), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_FATAL == int(Severity::Fatal), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_INTERNAL == int(Severity::Internal), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_DISABLED == int(Severity::Disable), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_NOTE == int(Severity::Note), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_WARNING == int(Severity::Warning), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_ERROR == int(Severity::Error), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_FATAL == int(Severity::Fatal), "mismatched Severity enum values"); +static_assert( + SLANG_SEVERITY_INTERNAL == int(Severity::Internal), + "mismatched Severity enum values"); // TODO(tfoley): move this into a source file... inline const char* getSeverityName(Severity severity) { switch (severity) { - case Severity::Disable: return "ignored"; - case Severity::Note: return "note"; - case Severity::Warning: return "warning"; - case Severity::Error: return "error"; - case Severity::Fatal: return "fatal error"; - case Severity::Internal: return "internal error"; - default: return "unknown error"; + case Severity::Disable: return "ignored"; + case Severity::Note: return "note"; + case Severity::Warning: return "warning"; + case Severity::Error: return "error"; + case Severity::Fatal: return "fatal error"; + case Severity::Internal: return "internal error"; + default: return "unknown error"; } } @@ -52,7 +52,7 @@ struct DiagnosticInfo { int id; Severity severity; - char const* name; ///< Unique name + char const* name; ///< Unique name char const* messageFormat; }; @@ -64,15 +64,8 @@ public: int ErrorID; Severity severity; - Diagnostic() - { - ErrorID = -1; - } - Diagnostic( - const String & msg, - int id, - const SourceLoc & pos, - Severity severity) + Diagnostic() { ErrorID = -1; } + Diagnostic(const String& msg, int id, const SourceLoc& pos, Severity severity) : severity(severity) { Message = msg; @@ -105,14 +98,17 @@ void printDiagnosticArg(StringBuilder& sb, IRInst* irObject); class Modifier; void printDiagnosticArg(StringBuilder& sb, Modifier* modifier); - + template<typename T> void printDiagnosticArg(StringBuilder& sb, RefPtr<T> ptr) { printDiagnosticArg(sb, ptr.Ptr()); } -inline SourceLoc getDiagnosticPos(SourceLoc const& pos) { return pos; } +inline SourceLoc getDiagnosticPos(SourceLoc const& pos) +{ + return pos; +} SourceLoc getDiagnosticPos(Token const& token); @@ -136,39 +132,43 @@ struct DiagnosticArg template<typename T> DiagnosticArg(T const& arg) - : data((void*)&arg) - , printFunc(&Helper<T>::printFunc) - {} + : data((void*)&arg), printFunc(&Helper<T>::printFunc) + { + } }; class DiagnosticSink { public: - /// Flags to control some aspects of Diagnostic sink behavior + /// Flags to control some aspects of Diagnostic sink behavior typedef uint32_t Flags; - struct Flag + struct Flag { - enum Enum: Flags + enum Enum : Flags { - VerbosePath = 0x1, ///< Will display a more verbose path (if available) - such as a canonical or absolute path - SourceLocationLine = 0x2, ///< If set will display the location line if source is available - HumaneLoc = 0x4, ///< If set will display humane locs (filename/line number) information - TreatWarningsAsErrors = 0x8, ///< If set will turn all Warning type messages (after overrides) into Error type messages - LanguageServer = 0x10, ///< If set will format message in a way that is suitable for language server + VerbosePath = 0x1, ///< Will display a more verbose path (if available) - such as a + ///< canonical or absolute path + SourceLocationLine = + 0x2, ///< If set will display the location line if source is available + HumaneLoc = 0x4, ///< If set will display humane locs (filename/line number) information + TreatWarningsAsErrors = 0x8, ///< If set will turn all Warning type messages (after + ///< overrides) into Error type messages + LanguageServer = + 0x10, ///< If set will format message in a way that is suitable for language server }; }; - /// Used by diagnostic sink to be able to underline tokens. If not defined on the DiagnosticSink, - /// will only display a caret at the SourceLoc - typedef UnownedStringSlice(*SourceLocationLexer)(const UnownedStringSlice& text); + /// Used by diagnostic sink to be able to underline tokens. If not defined on the + /// DiagnosticSink, will only display a caret at the SourceLoc + typedef UnownedStringSlice (*SourceLocationLexer)(const UnownedStringSlice& text); - /// Get the total amount of errors that have taken place on this DiagnosticSink + /// Get the total amount of errors that have taken place on this DiagnosticSink SLANG_FORCE_INLINE int getErrorCount() { return m_errorCount; } template<typename P, typename... Args> - bool diagnose(P const& pos, DiagnosticInfo const& info, Args const&... args ) + bool diagnose(P const& pos, DiagnosticInfo const& info, Args const&... args) { - DiagnosticArg as[] = { DiagnosticArg(args)... }; + DiagnosticArg as[] = {DiagnosticArg(args)...}; return diagnoseImpl(getDiagnosticPos(pos), info, sizeof...(args), as); } @@ -179,10 +179,10 @@ public: return diagnoseImpl(getDiagnosticPos(pos), info, 0, nullptr); } - // Useful for notes on existing diagnostics, where it would be redundant to display the same line again. - // (Ideally we would print the error/warning and notes in one call...) + // Useful for notes on existing diagnostics, where it would be redundant to display the same + // line again. (Ideally we would print the error/warning and notes in one call...) template<typename P, typename... Args> - bool diagnoseWithoutSourceView(P const& pos, DiagnosticInfo const& info, Args const&... args ) + bool diagnoseWithoutSourceView(P const& pos, DiagnosticInfo const& info, Args const&... args) { const auto fs = this->getFlags(); this->resetFlag(Flag::SourceLocationLine); @@ -193,83 +193,92 @@ public: return result; } - // Add a diagnostic with raw text - // (used when we get errors from a downstream compiler) + // Add a diagnostic with raw text + // (used when we get errors from a downstream compiler) void diagnoseRaw(Severity severity, char const* message); void diagnoseRaw(Severity severity, const UnownedStringSlice& message); - /// During propagation of an exception for an internal - /// error, note that this source location was involved + /// During propagation of an exception for an internal + /// error, note that this source location was involved void noteInternalErrorLoc(SourceLoc const& loc); - /// Create a blob containing diagnostics if there were any errors. - /// *note* only works if writer is not set, the blob is created from outputBuffer + /// Create a blob containing diagnostics if there were any errors. + /// *note* only works if writer is not set, the blob is created from outputBuffer SlangResult getBlobIfNeeded(ISlangBlob** outBlob); - /// Get the source manager used + /// Get the source manager used SourceManager* getSourceManager() const { return m_sourceManager; } - /// Set the source manager used for lookup of source locs + /// Set the source manager used for lookup of source locs void setSourceManager(SourceManager* inSourceManager) { m_sourceManager = inSourceManager; } - /// Set the flags - void setFlags(Flags flags) { m_flags = flags; } - /// Get the flags + /// Set the flags + void setFlags(Flags flags) { m_flags = flags; } + /// Get the flags Flags getFlags() const { return m_flags; } - /// Set a flag + /// Set a flag void setFlag(Flag::Enum flag) { m_flags |= Flags(flag); } - /// Reset a flag + /// Reset a flag void resetFlag(Flag::Enum flag) { m_flags &= ~Flags(flag); } - /// Test if flag is set + /// Test if flag is set bool isFlagSet(Flag::Enum flag) { return (m_flags & Flags(flag)) != 0; } - /// Sets an override on the severity of a specific diagnostic message (by numeric identifier) - /// info can be set to nullptr if only to override - void overrideDiagnosticSeverity(int diagnosticId, Severity overrideSeverity, const DiagnosticInfo* info = nullptr); + /// Sets an override on the severity of a specific diagnostic message (by numeric identifier) + /// info can be set to nullptr if only to override + void overrideDiagnosticSeverity( + int diagnosticId, + Severity overrideSeverity, + const DiagnosticInfo* info = nullptr); - /// Get the (optional) diagnostic sink lexer. This is used to - /// improve quality of highlighting a locations token. If not set, will just have a single - /// character caret at location + /// Get the (optional) diagnostic sink lexer. This is used to + /// improve quality of highlighting a locations token. If not set, will just have a single + /// character caret at location SourceLocationLexer getSourceLocationLexer() const { return m_sourceLocationLexer; } - /// Set the maximum length (in chars) of a source line displayed. Set to 0 for no limit + /// Set the maximum length (in chars) of a source line displayed. Set to 0 for no limit void setSourceLineMaxLength(Index length) { m_sourceLineMaxLength = length; } Index getSourceLineMaxLength() const { return m_sourceLineMaxLength; } - /// The parent sink is another sink that will receive diagnostics from this sink. + /// The parent sink is another sink that will receive diagnostics from this sink. void setParentSink(DiagnosticSink* parentSink) { m_parentSink = parentSink; } DiagnosticSink* getParentSink() const { return m_parentSink; } - /// Reset state. - /// Resets error counts. Resets the output buffer. + /// Reset state. + /// Resets error counts. Resets the output buffer. void reset(); - /// Initialize state. + /// Initialize state. void init(SourceManager* sourceManager, SourceLocationLexer sourceLocationLexer); - /// Ctor - DiagnosticSink(SourceManager* sourceManager, SourceLocationLexer sourceLocationLexer) { init(sourceManager, sourceLocationLexer); } - /// Default Ctor - DiagnosticSink(): - m_sourceManager(nullptr), - m_sourceLocationLexer(nullptr) + /// Ctor + DiagnosticSink(SourceManager* sourceManager, SourceLocationLexer sourceLocationLexer) + { + init(sourceManager, sourceLocationLexer); + } + /// Default Ctor + DiagnosticSink() + : m_sourceManager(nullptr), m_sourceLocationLexer(nullptr) { } // Public members - /// The outputBuffer will contain any diagnostics *iff* the writer is *not* set + /// The outputBuffer will contain any diagnostics *iff* the writer is *not* set StringBuilder outputBuffer; - /// If a writer is set output will *not* be written to the outputBuffer + /// If a writer is set output will *not* be written to the outputBuffer ISlangWriter* writer = nullptr; protected: // Returns true if a diagnostic is actually written. - bool diagnoseImpl(SourceLoc const& pos, DiagnosticInfo info, int argCount, DiagnosticArg const* args); + bool diagnoseImpl( + SourceLoc const& pos, + DiagnosticInfo info, + int argCount, + DiagnosticArg const* args); bool diagnoseImpl(DiagnosticInfo const& info, const UnownedStringSlice& formattedMessage); Severity getEffectiveMessageSeverity(DiagnosticInfo const& info); - /// If set all diagnostics (as formatted by *this* sink, will be routed to the parent). + /// If set all diagnostics (as formatted by *this* sink, will be routed to the parent). DiagnosticSink* m_parentSink = nullptr; int m_errorCount = 0; @@ -277,7 +286,7 @@ protected: /// If 0, then there is no limit, otherwise max amount of chars of the source line location /// We don't know the size of a terminal in general, but for now we'll guess 120. - Index m_sourceLineMaxLength = 120; + Index m_sourceLineMaxLength = 120; Flags m_flags = 0; @@ -285,26 +294,27 @@ protected: SourceManager* m_sourceManager = nullptr; SourceLocationLexer m_sourceLocationLexer; - + // Configuration that allows the user to control the severity of certain diagnostic messages Dictionary<int, Severity> m_severityOverrides; }; - /// An `ISlangWriter` that writes directly to a diagnostic sink. +/// An `ISlangWriter` that writes directly to a diagnostic sink. class DiagnosticSinkWriter : public AppendBufferWriter { public: typedef AppendBufferWriter Super; DiagnosticSinkWriter(DiagnosticSink* sink) - : Super(WriterFlag::IsStatic) - , m_sink(sink) - {} + : Super(WriterFlag::IsStatic), m_sink(sink) + { + } // ISlangWriter - SLANG_NO_THROW virtual SlangResult SLANG_MCALL write(const char* chars, size_t numChars) SLANG_OVERRIDE + SLANG_NO_THROW virtual SlangResult SLANG_MCALL write(const char* chars, size_t numChars) + SLANG_OVERRIDE { - m_sink->diagnoseRaw(Severity::Note, UnownedStringSlice(chars, chars+numChars)); + m_sink->diagnoseRaw(Severity::Note, UnownedStringSlice(chars, chars + numChars)); return SLANG_OK; } @@ -317,36 +327,36 @@ class DiagnosticsLookup : public RefObject public: static const Index kArenaInitialSize = 65536; - /// Will take into account the slice name could be using different conventions + /// Will take into account the slice name could be using different conventions const DiagnosticInfo* findDiagnosticByName(const UnownedStringSlice& slice) const; - /// The name must be as defined in the diagnostics exactly, typically lower camel + /// The name must be as defined in the diagnostics exactly, typically lower camel const DiagnosticInfo* findDiagnosticByExactName(const UnownedStringSlice& slice) const; - /// Get a diagnostic by it's id. - /// NOTE! That it is possible for multiple diagnostics to have the same id. This will return - /// the first added + /// Get a diagnostic by it's id. + /// NOTE! That it is possible for multiple diagnostics to have the same id. This will return + /// the first added const DiagnosticInfo* getDiagnosticById(Int id) const; - /// info must stay in scope + /// info must stay in scope Index add(const DiagnosticInfo* info); - /// Infos referenced must remain in scope - void add(const DiagnosticInfo*const* infos, Index infosCount); + /// Infos referenced must remain in scope + void add(const DiagnosticInfo* const* infos, Index infosCount); - /// NOTE! Name must stay in scope as long as the diagnostics lookup. - /// If not possible add it to the arena to keep in scope. + /// NOTE! Name must stay in scope as long as the diagnostics lookup. + /// If not possible add it to the arena to keep in scope. void addAlias(const char* name, const char* diagnosticName); - /// Get the diagnostics held in this lookup + /// Get the diagnostics held in this lookup const List<const DiagnosticInfo*>& getDiagnostics() const { return m_diagnostics; } - /// Get the associated arena + /// Get the associated arena MemoryArena& getArena() { return m_arena; } - /// NOTE! diagnostics must stay in scope for lifetime of lookup - DiagnosticsLookup(const DiagnosticInfo*const* diagnostics, Index diagnosticsCount); + /// NOTE! diagnostics must stay in scope for lifetime of lookup + DiagnosticsLookup(const DiagnosticInfo* const* diagnostics, Index diagnosticsCount); DiagnosticsLookup(); -protected: +protected: void _addName(const char* name, Index diagnosticIndex); Index _findDiagnosticIndexByExactName(const UnownedStringSlice& slice) const; @@ -360,6 +370,6 @@ protected: MemoryArena m_arena; }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-doc-extractor.cpp b/source/compiler-core/slang-doc-extractor.cpp index 9a625f3e0..d8a27822f 100644 --- a/source/compiler-core/slang-doc-extractor.cpp +++ b/source/compiler-core/slang-doc-extractor.cpp @@ -3,23 +3,28 @@ #include "../core/slang-string-util.h" -namespace Slang { +namespace Slang +{ /* TODO(JS): -* If Decls hand SourceRange, then we could use the range to simplify getting the Post markup, as will be trivial to get to the 'end' +* If Decls hand SourceRange, then we could use the range to simplify getting the Post markup, as +will be trivial to get to the 'end' * Need to handle preceeding * in some markup styles -* If we want to be able to disable markup we need a mechanism to do this. Probably define source ranges. +* If we want to be able to disable markup we need a mechanism to do this. Probably define source +ranges. * Need a way to take the extracted markup and produce suitable markdown ** This will need to display the decoration appropriately */ -/* static */UnownedStringSlice DocMarkupExtractor::removeStart(MarkupType type, const UnownedStringSlice& comment) +/* static */ UnownedStringSlice DocMarkupExtractor::removeStart( + MarkupType type, + const UnownedStringSlice& comment) { switch (type) { - case MarkupType::BlockBefore: + case MarkupType::BlockBefore: { if (comment.startsWith(UnownedStringSlice::fromLiteral("/**")) || comment.startsWith(UnownedStringSlice::fromLiteral("/*!"))) @@ -28,10 +33,10 @@ namespace Slang { return comment.tail(3); } return comment; - } - case MarkupType::BlockAfter: + } + case MarkupType::BlockAfter: { - + if (comment.startsWith(UnownedStringSlice::fromLiteral("/**<")) || comment.startsWith(UnownedStringSlice::fromLiteral("/*!<"))) { @@ -40,7 +45,7 @@ namespace Slang { } return comment; } - case MarkupType::OrdinaryBlockBefore: + case MarkupType::OrdinaryBlockBefore: { if (comment.startsWith(UnownedStringSlice::fromLiteral("/*"))) { @@ -49,29 +54,34 @@ namespace Slang { } return comment; } - case MarkupType::LineBangBefore: + case MarkupType::LineBangBefore: { - return comment.startsWith(UnownedStringSlice::fromLiteral("//!")) ? comment.tail(3) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("//!")) ? comment.tail(3) + : comment; } - case MarkupType::LineSlashBefore: + case MarkupType::LineSlashBefore: { - return comment.startsWith(UnownedStringSlice::fromLiteral("///")) ? comment.tail(3) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("///")) ? comment.tail(3) + : comment; } - case MarkupType::OrdinaryLineBefore: - case MarkupType::OrdinaryLineAfter: + case MarkupType::OrdinaryLineBefore: + case MarkupType::OrdinaryLineAfter: { - return comment.startsWith(UnownedStringSlice::fromLiteral("//")) ? comment.tail(2) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("//")) ? comment.tail(2) + : comment; } - case MarkupType::LineBangAfter: + case MarkupType::LineBangAfter: { /// //!< Can be multiple lines - return comment.startsWith(UnownedStringSlice::fromLiteral("//!<")) ? comment.tail(4) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("//!<")) ? comment.tail(4) + : comment; } - case MarkupType::LineSlashAfter: + case MarkupType::LineSlashAfter: { - return comment.startsWith(UnownedStringSlice::fromLiteral("///<")) ? comment.tail(4) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("///<")) ? comment.tail(4) + : comment; } - default: break; + default: break; } return comment; } @@ -106,37 +116,37 @@ static Index _findTokenIndex(SourceLoc loc, const Token* toks, Index numToks) return -1; } -/* static */DocMarkupExtractor::MarkupFlags DocMarkupExtractor::getFlags(MarkupType type) +/* static */ DocMarkupExtractor::MarkupFlags DocMarkupExtractor::getFlags(MarkupType type) { switch (type) { - default: - case MarkupType::None: return 0; - case MarkupType::BlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock; - case MarkupType::BlockAfter: return MarkupFlag::After | MarkupFlag::IsBlock; - case MarkupType::OrdinaryBlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock; - - case MarkupType::LineBangBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; - case MarkupType::LineSlashBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; - case MarkupType::OrdinaryLineBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; - - case MarkupType::LineBangAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; - case MarkupType::LineSlashAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; - case MarkupType::OrdinaryLineAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; - + default: + case MarkupType::None: return 0; + case MarkupType::BlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock; + case MarkupType::BlockAfter: return MarkupFlag::After | MarkupFlag::IsBlock; + case MarkupType::OrdinaryBlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock; + + case MarkupType::LineBangBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; + case MarkupType::LineSlashBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; + case MarkupType::OrdinaryLineBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; + + case MarkupType::LineBangAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; + case MarkupType::LineSlashAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; + case MarkupType::OrdinaryLineAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; } } -/* static */DocMarkupExtractor::MarkupType DocMarkupExtractor::findMarkupType(const Token& tok) +/* static */ DocMarkupExtractor::MarkupType DocMarkupExtractor::findMarkupType(const Token& tok) { switch (tok.type) { - case TokenType::BlockComment: + case TokenType::BlockComment: { UnownedStringSlice slice = tok.getContent(); if (slice.getLength() >= 3 && (slice[2] == '!' || slice[2] == '*')) { - return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::BlockAfter : MarkupType::BlockBefore; + return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::BlockAfter + : MarkupType::BlockBefore; } else { @@ -144,25 +154,28 @@ static Index _findTokenIndex(SourceLoc loc, const Token* toks, Index numToks) } break; } - case TokenType::LineComment: + case TokenType::LineComment: { UnownedStringSlice slice = tok.getContent(); if (slice.getLength() >= 3) { if (slice[2] == '!') { - return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::LineBangAfter : MarkupType::LineBangBefore; + return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::LineBangAfter + : MarkupType::LineBangBefore; } else if (slice[2] == '/') { - return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::LineSlashAfter : MarkupType::LineSlashBefore; + return (slice.getLength() >= 4 && slice[3] == '<') + ? MarkupType::LineSlashAfter + : MarkupType::LineSlashBefore; } } return (tok.flags & TokenFlag::AtStartOfLine) != 0 ? MarkupType::OrdinaryLineBefore : MarkupType::OrdinaryLineAfter; break; } - default: break; + default: break; } return MarkupType::None; } @@ -172,7 +185,8 @@ static Index _calcWhitespaceIndent(const UnownedStringSlice& line) // TODO(JS): For now we ignore tabs and just work out indentation based on spaces/assume ASCII Index indent = 0; const Index count = line.getLength(); - for (; indent < count && line[indent] == ' '; indent++); + for (; indent < count && line[indent] == ' '; indent++) + ; return indent; } @@ -182,7 +196,10 @@ static Index _calcIndent(const UnownedStringSlice& line) return line.getLength(); } -static void _appendUnindenttedLine(const UnownedStringSlice& line, Index maxIndent, StringBuilder& out) +static void _appendUnindenttedLine( + const UnownedStringSlice& line, + Index maxIndent, + StringBuilder& out) { Index indent = _calcWhitespaceIndent(line); @@ -196,19 +213,22 @@ static void _appendUnindenttedLine(const UnownedStringSlice& line, Index maxInde out.append(line.tail(indent)); } -SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const FoundMarkup& foundMarkup, StringBuilder& out) +SlangResult DocMarkupExtractor::_extractMarkup( + const FindInfo& info, + const FoundMarkup& foundMarkup, + StringBuilder& out) { SourceView* sourceView = info.sourceView; SourceFile* sourceFile = sourceView->getSourceFile(); // Here we want to produce the text that is implied by the markup tokens. // We want to removing surrounding markup, and to also keep appropriate indentation - + switch (foundMarkup.type) { - case MarkupType::BlockBefore: - case MarkupType::BlockAfter: - case MarkupType::OrdinaryBlockBefore: + case MarkupType::BlockBefore: + case MarkupType::BlockAfter: + case MarkupType::OrdinaryBlockBefore: { // We should only have a single line SLANG_ASSERT(foundMarkup.range.getCount() == 1); @@ -239,9 +259,10 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found { if (startLine.isMemoryContained(line.begin())) { - // For now we'll ignore tabs, and that the indent amount is, the amount of *byte* - // NOTE! This is only appropriate for ASCII without tabs. - maxIndent = _calcIndent(UnownedStringSlice(startLine.begin(), line.begin())); + // For now we'll ignore tabs, and that the indent amount is, the amount of + // *byte* NOTE! This is only appropriate for ASCII without tabs. + maxIndent = + _calcIndent(UnownedStringSlice(startLine.begin(), line.begin())); // Let's strip the start stuff line = removeStart(foundMarkup.type, line); @@ -250,7 +271,8 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found if (i == linesCount - 1) { - SLANG_ASSERT(line.tail(line.getLength() - 2) == UnownedStringSlice::fromLiteral("*/")); + SLANG_ASSERT( + line.tail(line.getLength() - 2) == UnownedStringSlice::fromLiteral("*/")); // Remove the */ at the end of the line line = line.head(line.getLength() - 2); } @@ -263,9 +285,10 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found { unindentedLine.append(line); } - + // If the first or last line are all white space, just ignore them - if ((i == linesCount - 1 || i == 0) && unindentedLine.getUnownedSlice().trim().getLength() == 0) + if ((i == linesCount - 1 || i == 0) && + unindentedLine.getUnownedSlice().trim().getLength() == 0) { continue; } @@ -276,18 +299,19 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found break; } - case MarkupType::OrdinaryLineBefore: - case MarkupType::OrdinaryLineAfter: - case MarkupType::LineBangBefore: - case MarkupType::LineSlashBefore: - case MarkupType::LineBangAfter: - case MarkupType::LineSlashAfter: + case MarkupType::OrdinaryLineBefore: + case MarkupType::OrdinaryLineAfter: + case MarkupType::LineBangBefore: + case MarkupType::LineSlashBefore: + case MarkupType::LineBangAfter: + case MarkupType::LineSlashAfter: { - // Holds the lines extracted, they may have some white space indenting (like the space at the start of //) + // Holds the lines extracted, they may have some white space indenting (like the space + // at the start of //) List<UnownedStringSlice> lines; const auto& range = foundMarkup.range; - for (Index i = range.start; i < range.end; ++ i) + for (Index i = range.start; i < range.end; ++i) { const auto& tok = info.tokenList->m_tokens[i]; UnownedStringSlice line = tok.getContent(); @@ -322,7 +346,7 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found break; } - default: return SLANG_FAIL; + default: return SLANG_FAIL; } return SLANG_OK; @@ -344,22 +368,24 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio switch (tok.type) { - case TokenType::LBrace: - case TokenType::LBracket: - case TokenType::LParent: - case TokenType::OpLess: + case TokenType::LBrace: + case TokenType::LBracket: + case TokenType::LParent: + case TokenType::OpLess: { openCount += direction; - if (openCount < 0) return -1; + if (openCount < 0) + return -1; break; } - case TokenType::RBracket: + case TokenType::RBracket: { openCount -= direction; - if (openCount < 0) return -1; + if (openCount < 0) + return -1; break; } - case TokenType::OpGreater: + case TokenType::OpGreater: { if (location == Location::AfterGenericParam && openCount == 0) { @@ -367,11 +393,12 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } openCount -= direction; - if (openCount < 0) return -1; + if (openCount < 0) + return -1; break; } - case TokenType::RParent: + case TokenType::RParent: { if (openCount == 0 && location == Location::AfterParam) { @@ -379,10 +406,11 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } openCount -= direction; - if (openCount < 0) return -1; + if (openCount < 0) + return -1; break; } - case TokenType::RBrace: + case TokenType::RBrace: { // If we haven't hit a candidate yet before hitting } it's not going to work if (location == Location::Before || location == Location::AfterEnumCase) @@ -391,8 +419,8 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } break; } - case TokenType::BlockComment: - case TokenType::LineComment: + case TokenType::BlockComment: + case TokenType::LineComment: { if (openCount == 0) { @@ -407,7 +435,8 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio { return i; } - // If we are looking for enum cases, and the markup is after, we'll assume this is it + // If we are looking for enum cases, and the markup is after, we'll assume this + // is it if (isAfter(location) && isAfter(markupType)) { return i; @@ -415,11 +444,12 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } break; } - case TokenType::Comma: + case TokenType::Comma: { if (openCount == 0) - { - if (location == Location::AfterParam || location == Location::AfterEnumCase || location == Location::AfterGenericParam) + { + if (location == Location::AfterParam || location == Location::AfterEnumCase || + location == Location::AfterGenericParam) { return i + 1; } @@ -432,7 +462,7 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio break; } - case TokenType::Semicolon: + case TokenType::Semicolon: { // If we haven't hit a candidate yet it's not going to work if (location == Location::Before) @@ -445,14 +475,18 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } break; } - default: break; + default: break; } } return -1; } -/* static */bool DocMarkupExtractor::_isTokenOnLineIndex(SourceView* sourceView, MarkupType type, const Token& tok, Index lineIndex) +/* static */ bool DocMarkupExtractor::_isTokenOnLineIndex( + SourceView* sourceView, + MarkupType type, + const Token& tok, + Index lineIndex) { SourceFile* sourceFile = sourceView->getSourceFile(); const int offset = sourceView->getRange().getOffset(tok.loc); @@ -462,7 +496,8 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio if (flags & MarkupFlag::IsBlock) { // Either the start or the end of the block have to be on the specified line - return sourceFile->isOffsetOnLine(offset, lineIndex) || sourceFile->isOffsetOnLine(offset + tok.charsCount, lineIndex); + return sourceFile->isOffsetOnLine(offset, lineIndex) || + sourceFile->isOffsetOnLine(offset + tok.charsCount, lineIndex); } else { @@ -471,12 +506,15 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } } -SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location location, FoundMarkup& out) +SlangResult DocMarkupExtractor::_findMarkup( + const FindInfo& info, + Location location, + FoundMarkup& out) { out.reset(); const auto& toks = info.tokenList->m_tokens; - + // The starting token index Index startIndex = _findStartIndex(info, location); if (startIndex <= 0) @@ -490,7 +528,7 @@ SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location locat // Let's lookup the line index where this occurred const int startOffset = sourceView->getRange().getOffset(toks[startIndex].loc); - // The line index that the markoff starts from + // The line index that the markoff starts from Index lineIndex = sourceFile->calcLineIndexFromOffset(startOffset); if (lineIndex < 0) { @@ -498,12 +536,13 @@ SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location locat } const Index searchDirection = isBefore(location) ? -1 : 1; - + // Get the type and flags const MarkupType type = findMarkupType(toks[startIndex]); const MarkupFlags flags = getFlags(type); - const MarkupFlag::Enum requiredFlag = isBefore(location) ? MarkupFlag::Before : MarkupFlag::After; + const MarkupFlag::Enum requiredFlag = + isBefore(location) ? MarkupFlag::Before : MarkupFlag::After; if ((flags & requiredFlag) == 0) { return SLANG_E_NOT_FOUND; @@ -567,14 +606,19 @@ SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location locat // Okay we've found the markup out.type = type; out.location = location; - out.range = IndexRange{ startIndex, endIndex }; + out.range = IndexRange{startIndex, endIndex}; SLANG_ASSERT(out.range.getCount() > 0); return SLANG_OK; } -SlangResult DocMarkupExtractor::_findFirstMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out, Index& outIndex) +SlangResult DocMarkupExtractor::_findFirstMarkup( + const FindInfo& info, + const Location* locs, + Index locCount, + FoundMarkup& out, + Index& outIndex) { Index i = 0; for (; i < locCount; ++i) @@ -589,7 +633,11 @@ SlangResult DocMarkupExtractor::_findFirstMarkup(const FindInfo& info, const Loc return SLANG_E_NOT_FOUND; } -SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out) +SlangResult DocMarkupExtractor::_findMarkup( + const FindInfo& info, + const Location* locs, + Index locCount, + FoundMarkup& out) { Index foundIndex; SLANG_RETURN_ON_FAIL(_findFirstMarkup(info, locs, locCount, out, foundIndex)); @@ -611,53 +659,59 @@ SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, const Location } -SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, SearchStyle searchStyle, FoundMarkup& out) +SlangResult DocMarkupExtractor::_findMarkup( + const FindInfo& info, + SearchStyle searchStyle, + FoundMarkup& out) { switch (searchStyle) { - default: - case SearchStyle::None: + default: + case SearchStyle::None: { return SLANG_E_NOT_FOUND; } - case SearchStyle::EnumCase: + case SearchStyle::EnumCase: { - Location locs[] = { Location::Before, Location::AfterEnumCase }; + Location locs[] = {Location::Before, Location::AfterEnumCase}; return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out); } - case SearchStyle::Param: + case SearchStyle::Param: { - Location locs[] = { Location::Before, Location::AfterParam }; + Location locs[] = {Location::Before, Location::AfterParam}; return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out); } - case SearchStyle::Before: + case SearchStyle::Before: { return _findMarkup(info, Location::Before, out); } - case SearchStyle::Function: + case SearchStyle::Function: { return _findMarkup(info, Location::Before, out); } - case SearchStyle::Attribute: + case SearchStyle::Attribute: { FindInfo newInfo = info; newInfo.tokenIndex -= 2; return _findMarkup(newInfo, Location::Before, out); } - case SearchStyle::Variable: + case SearchStyle::Variable: { - Location locs[] = { Location::Before, Location::AfterSemicolon }; + Location locs[] = {Location::Before, Location::AfterSemicolon}; return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out); } - case SearchStyle::GenericParam: + case SearchStyle::GenericParam: { - Location locs[] = { Location::Before, Location::AfterGenericParam }; + Location locs[] = {Location::Before, Location::AfterGenericParam}; return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out); } } } -static void _calcLineVisibility(SourceView* sourceView, const TokenList& toks, List<MarkupVisibility>& outLineVisibility) +static void _calcLineVisibility( + SourceView* sourceView, + const TokenList& toks, + List<MarkupVisibility>& outLineVisibility) { SourceFile* sourceFile = sourceView->getSourceFile(); const auto& lineOffsets = sourceFile->getLineBreakOffsets(); @@ -713,21 +767,27 @@ static void _calcLineVisibility(SourceView* sourceView, const TokenList& toks, L } // Fill in the remaining - for (Index i = lastLine; i < outLineVisibility.getCount(); ++ i) + for (Index i = lastLine; i < outLineVisibility.getCount(); ++i) { outLineVisibility[i] = lastVisibility; } } -SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inputCount, SourceManager* sourceManager, DiagnosticSink* sink, List<SourceView*>& outViews, List<SearchItemOutput>& out) +SlangResult DocMarkupExtractor::extract( + const SearchItemInput* inputs, + Index inputCount, + SourceManager* sourceManager, + DiagnosticSink* sink, + List<SourceView*>& outViews, + List<SearchItemOutput>& out) { struct Entry { - Index viewIndex; ///< The view/file index this loc is found in - SourceLoc::RawValue locOrOffset; ///< Can be a loc or an offset into the file + Index viewIndex; ///< The view/file index this loc is found in + SourceLoc::RawValue locOrOffset; ///< Can be a loc or an offset into the file - SearchStyle searchStyle; ///< The search style when looking for an item - Index inputIndex; ///< The index to this item in the input + SearchStyle searchStyle; ///< The search style when looking for an item + Index inputIndex; ///< The index to this item in the input }; List<Entry> entries; @@ -739,14 +799,15 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp const auto& input = inputs[i]; Entry& entry = entries[i]; entry.inputIndex = i; - entry.viewIndex = -1; //< We don't know what file/view it's in + entry.viewIndex = -1; //< We don't know what file/view it's in entry.locOrOffset = input.sourceLoc.getRaw(); entry.searchStyle = input.searchStyle; } } // Sort them into loc order - entries.sort([](const Entry& a, const Entry& b) -> bool { return a.locOrOffset < b.locOrOffset; }); + entries.sort( + [](const Entry& a, const Entry& b) -> bool { return a.locOrOffset < b.locOrOffset; }); { SourceView* sourceView = nullptr; @@ -774,8 +835,10 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp // We want only one view per SourceFile SourceFile* sourceFile = sourceView->getSourceFile(); - // NOTE! The view found might be different than sourceView. - viewIndex = outViews.findFirstIndex([&](SourceView* currentView) -> bool { return currentView->getSourceFile() == sourceFile; }); + // NOTE! The view found might be different than sourceView. + viewIndex = outViews.findFirstIndex( + [&](SourceView* currentView) -> bool + { return currentView->getSourceFile() == sourceFile; }); if (viewIndex < 0) { @@ -789,12 +852,17 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp // Set the file index entry.viewIndex = viewIndex; - // Set as the offset within the file + // Set as the offset within the file entry.locOrOffset = sourceView->getRange().getOffset(loc); } // Sort into view/file and then offset order - entries.sort([](const Entry& a, const Entry& b) -> bool { return (a.viewIndex < b.viewIndex) || ((a.viewIndex == b.viewIndex) && a.locOrOffset < b.locOrOffset); }); + entries.sort( + [](const Entry& a, const Entry& b) -> bool + { + return (a.viewIndex < b.viewIndex) || + ((a.viewIndex == b.viewIndex) && a.locOrOffset < b.locOrOffset); + }); } { @@ -854,7 +922,8 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp // Get the offset within the source file const uint32_t offset = entry.locOrOffset; - // We need to get the loc in the source views space, so we look up appropriately in the list of tokens (which uses the views loc range) + // We need to get the loc in the source views space, so we look up appropriately in the + // list of tokens (which uses the views loc range) const SourceLoc loc = sourceView->getRange().getSourceLocFromOffset(offset); // Work out the line number @@ -864,7 +933,8 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp dst.visibilty = lineVisibility[lineIndex]; // Okay, lets find the token index with a binary chop - Index tokenIndex = _findTokenIndex(loc, tokens.m_tokens.getBuffer(), tokens.m_tokens.getCount()); + Index tokenIndex = + _findTokenIndex(loc, tokens.m_tokens.getBuffer(), tokens.m_tokens.getCount()); if (tokenIndex >= 0 && lineIndex >= 0) { FindInfo findInfo; @@ -885,7 +955,6 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp // Save the extracted text in the output dst.text = buf; - } else if (res != SLANG_E_NOT_FOUND) { diff --git a/source/compiler-core/slang-doc-extractor.h b/source/compiler-core/slang-doc-extractor.h index 30346ce6f..45575126f 100644 --- a/source/compiler-core/slang-doc-extractor.h +++ b/source/compiler-core/slang-doc-extractor.h @@ -3,25 +3,25 @@ #define SLANG_DOC_EXTRACTOR_H #include "../core/slang-basic.h" - -#include "slang-source-loc.h" #include "slang-lexer.h" +#include "slang-source-loc.h" -namespace Slang { +namespace Slang +{ enum class MarkupVisibility : uint8_t { - Public, ///< Always available - Internal, ///< Can be available in more verbose 'internal' documentation - Hidden, ///< Not generally available + Public, ///< Always available + Internal, ///< Can be available in more verbose 'internal' documentation + Hidden, ///< Not generally available }; -/* Extracts 'markup' from comments in Slang source core. The comments are extracted and associated in declarations. The association -is held in DocMarkup type. The comment style follows the doxygen style */ +/* Extracts 'markup' from comments in Slang source core. The comments are extracted and associated +in declarations. The association is held in DocMarkup type. The comment style follows the doxygen +style */ class DocMarkupExtractor { public: - typedef uint32_t MarkupFlags; struct MarkupFlag { @@ -29,8 +29,8 @@ public: { Before = 0x1, After = 0x2, - IsMultiToken = 0x4, ///< Can use more than one token - IsBlock = 0x8, ///< + IsMultiToken = 0x4, ///< Can use more than one token + IsBlock = 0x8, ///< }; }; @@ -39,20 +39,23 @@ public: { None, - BlockBefore, /// /** */ or /*! */. - LineBangBefore, /// //! Can be multiple lines - LineSlashBefore, /// /// Can be multiple lines + BlockBefore, /// /** */ or /*! */. + LineBangBefore, /// //! Can be multiple lines + LineSlashBefore, /// /// Can be multiple lines OrdinaryBlockBefore, OrdinaryLineBefore, - BlockAfter, /// /*!< */ or /**< */ - LineBangAfter, /// //!< Can be multiple lines - LineSlashAfter, /// ///< Can be multiple lines + BlockAfter, /// /*!< */ or /**< */ + LineBangAfter, /// //!< Can be multiple lines + LineSlashAfter, /// ///< Can be multiple lines OrdinaryLineAfter, - }; - static bool isBefore(MarkupType type) { return Index(type) >= Index(MarkupType::BlockBefore) && Index(type) <= Index(MarkupType::OrdinaryLineBefore); } + static bool isBefore(MarkupType type) + { + return Index(type) >= Index(MarkupType::BlockBefore) && + Index(type) <= Index(MarkupType::OrdinaryLineBefore); + } static bool isAfter(MarkupType type) { return Index(type) >= Index(MarkupType::BlockAfter); } struct IndexRange @@ -65,15 +68,18 @@ public: enum class Location { - None, ///< No defined location + None, ///< No defined location Before, - AfterParam, ///< Can have trailing , or ) - AfterSemicolon, ///< Can have a trailing ; - AfterEnumCase, ///< Can have a , or before } - AfterGenericParam, ///< Can have trailing , or > + AfterParam, ///< Can have trailing , or ) + AfterSemicolon, ///< Can have a trailing ; + AfterEnumCase, ///< Can have a , or before } + AfterGenericParam, ///< Can have trailing , or > }; - static bool isAfter(Location location) { return Index(location) >= Index(Location::AfterParam); } + static bool isAfter(Location location) + { + return Index(location) >= Index(Location::AfterParam); + } static bool isBefore(Location location) { return location == Location::Before; } struct FoundMarkup @@ -82,7 +88,7 @@ public: { location = Location::None; type = MarkupType::None; - range = IndexRange{ 0, 0 }; + range = IndexRange{0, 0}; } Location location = Location::None; @@ -92,50 +98,54 @@ public: enum SearchStyle { - None, ///< Cannot be searched for - EnumCase, ///< An enum case - Param, ///< A parameter in a function/method - Variable, ///< A variable-like declaration - Before, ///< Only allows before - Function, ///< Function/method - GenericParam, ///< Generic parameter - Attribute, ///< Attribute definition + None, ///< Cannot be searched for + EnumCase, ///< An enum case + Param, ///< A parameter in a function/method + Variable, ///< A variable-like declaration + Before, ///< Only allows before + Function, ///< Function/method + GenericParam, ///< Generic parameter + Attribute, ///< Attribute definition }; - /// An input search item + /// An input search item struct SearchItemInput { SourceLoc sourceLoc; - SearchStyle searchStyle; ///< The search style when looking for an item + SearchStyle searchStyle; ///< The search style when looking for an item }; - /// The items will be in source order + /// The items will be in source order struct SearchItemOutput { - Index viewIndex; ///< Index into the array of views on the output - Index inputIndex; ///< The index to this item in the input - String text; ///< The found text - MarkupVisibility visibilty; ///< Visibility of the item + Index viewIndex; ///< Index into the array of views on the output + Index inputIndex; ///< The index to this item in the input + String text; ///< The found text + MarkupVisibility visibilty; ///< Visibility of the item }; struct FindInfo { - SourceView* sourceView; ///< The source view the tokens were generated from - TokenList* tokenList; ///< The token list - Index tokenIndex; ///< The token index location (where searches start from) - Index lineIndex; ///< The line number for the decl + SourceView* sourceView; ///< The source view the tokens were generated from + TokenList* tokenList; ///< The token list + Index tokenIndex; ///< The token index location (where searches start from) + Index lineIndex; ///< The line number for the decl }; - void setSearchInOrdinaryComments(bool val) - { - m_searchInOrindaryComments = val; - } - - /// Extracts 'markup' doc information for the specified input items - /// The output is placed in out - with the items now in the source order *not* the order of the input items - /// The inputIndex on the output holds the input item index - /// The outViews holds the views specified in viewIndex in the output, which may be useful for determining where the documentation was placed in source - SlangResult extract(const SearchItemInput* inputItems, Index inputCount, SourceManager* sourceManager, DiagnosticSink* sink, List<SourceView*>& outViews, List<SearchItemOutput>& out); + void setSearchInOrdinaryComments(bool val) { m_searchInOrindaryComments = val; } + + /// Extracts 'markup' doc information for the specified input items + /// The output is placed in out - with the items now in the source order *not* the order of the + /// input items The inputIndex on the output holds the input item index The outViews holds the + /// views specified in viewIndex in the output, which may be useful for determining where the + /// documentation was placed in source + SlangResult extract( + const SearchItemInput* inputItems, + Index inputCount, + SourceManager* sourceManager, + DiagnosticSink* sink, + List<SourceView*>& outViews, + List<SearchItemOutput>& out); static MarkupFlags getFlags(MarkupType type); static MarkupType findMarkupType(const Token& tok); @@ -145,24 +155,42 @@ protected: /// returns SLANG_E_NOT_FOUND if not found, SLANG_OK on success else an error SlangResult _findMarkup(const FindInfo& info, Location location, FoundMarkup& out); - /// Locations are processed in order, and the first successful used. If found in another location will issue a warning. - /// returns SLANG_E_NOT_FOUND if not found, SLANG_OK on success else an error - SlangResult _findFirstMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out, Index& outIndex); - - SlangResult _findMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out); - - /// Given the decl, the token stream, and the decls tokenIndex, try to find some associated markup + /// Locations are processed in order, and the first successful used. If found in another + /// location will issue a warning. returns SLANG_E_NOT_FOUND if not found, SLANG_OK on success + /// else an error + SlangResult _findFirstMarkup( + const FindInfo& info, + const Location* locs, + Index locCount, + FoundMarkup& out, + Index& outIndex); + + SlangResult _findMarkup( + const FindInfo& info, + const Location* locs, + Index locCount, + FoundMarkup& out); + + /// Given the decl, the token stream, and the decls tokenIndex, try to find some associated + /// markup SlangResult _findMarkup(const FindInfo& info, SearchStyle searchStyle, FoundMarkup& out); /// Given a found markup location extracts the contents of the tokens into out - SlangResult _extractMarkup(const FindInfo& info, const FoundMarkup& foundMarkup, StringBuilder& out); + SlangResult _extractMarkup( + const FindInfo& info, + const FoundMarkup& foundMarkup, + StringBuilder& out); /// Given a location, try to find the first token index that could potentially be markup /// Will return -1 if not found Index _findStartIndex(const FindInfo& info, Location location); /// True if the tok is 'on' lineIndex. Interpretation of 'on' depends on the markup type. - static bool _isTokenOnLineIndex(SourceView* sourceView, MarkupType type, const Token& tok, Index lineIndex); + static bool _isTokenOnLineIndex( + SourceView* sourceView, + MarkupType type, + const Token& tok, + Index lineIndex); DiagnosticSink* m_sink; diff --git a/source/compiler-core/slang-downstream-compiler-set.cpp b/source/compiler-core/slang-downstream-compiler-set.cpp index ee09b994c..151c74b3e 100644 --- a/source/compiler-core/slang-downstream-compiler-set.cpp +++ b/source/compiler-core/slang-downstream-compiler-set.cpp @@ -19,7 +19,7 @@ Index DownstreamCompilerSet::_findIndex(const DownstreamCompilerDesc& desc) cons { const Index count = m_compilers.getCount(); for (Index i = 0; i < count; ++i) - { + { if (m_compilers[i]->getDesc() == desc) { return i; @@ -28,7 +28,8 @@ Index DownstreamCompilerSet::_findIndex(const DownstreamCompilerDesc& desc) cons return -1; } -IDownstreamCompiler* DownstreamCompilerSet::getCompiler(const DownstreamCompilerDesc& compilerDesc) const +IDownstreamCompiler* DownstreamCompilerSet::getCompiler( + const DownstreamCompilerDesc& compilerDesc) const { const Index index = _findIndex(compilerDesc); return index >= 0 ? m_compilers[index] : nullptr; @@ -37,13 +38,14 @@ IDownstreamCompiler* DownstreamCompilerSet::getCompiler(const DownstreamCompiler void DownstreamCompilerSet::getCompilers(List<IDownstreamCompiler*>& outCompilers) const { outCompilers.clear(); - outCompilers.addRange((IDownstreamCompiler*const*)m_compilers.begin(), m_compilers.getCount()); + outCompilers.addRange((IDownstreamCompiler* const*)m_compilers.begin(), m_compilers.getCount()); } bool DownstreamCompilerSet::hasSharedLibrary(ISlangSharedLibrary* lib) { - const Index foundIndex = m_sharedLibraries.findFirstIndex([lib](ISlangSharedLibrary* inLib) -> bool { return lib == inLib; }); - return(foundIndex >= 0); + const Index foundIndex = m_sharedLibraries.findFirstIndex( + [lib](ISlangSharedLibrary* inLib) -> bool { return lib == inLib; }); + return (foundIndex >= 0); } void DownstreamCompilerSet::addSharedLibrary(ISlangSharedLibrary* lib) @@ -94,4 +96,4 @@ void DownstreamCompilerSet::addCompiler(IDownstreamCompiler* compiler) } } -} +} // namespace Slang diff --git a/source/compiler-core/slang-downstream-compiler-set.h b/source/compiler-core/slang-downstream-compiler-set.h index 2a3d1ac01..042fcc9f6 100644 --- a/source/compiler-core/slang-downstream-compiler-set.h +++ b/source/compiler-core/slang-downstream-compiler-set.h @@ -11,23 +11,29 @@ class DownstreamCompilerSet : public RefObject public: typedef RefObject Super; - /// Find all the available compilers + /// Find all the available compilers void getCompilerDescs(List<IDownstreamCompiler::Desc>& outCompilerDescs) const; - /// Returns list of all compilers + /// Returns list of all compilers void getCompilers(List<IDownstreamCompiler*>& outCompilers) const; - /// Get a compiler + /// Get a compiler IDownstreamCompiler* getCompiler(const DownstreamCompilerDesc& compilerDesc) const; - - /// Will replace if there is one with same desc + + /// Will replace if there is one with same desc void addCompiler(IDownstreamCompiler* compiler); - /// Get a default compiler - IDownstreamCompiler* getDefaultCompiler(SlangSourceLanguage sourceLanguage) const { return m_defaultCompilers[int(sourceLanguage)]; } - /// Set the default compiler - void setDefaultCompiler(SlangSourceLanguage sourceLanguage, IDownstreamCompiler* compiler) { m_defaultCompilers[int(sourceLanguage)] = compiler; } + /// Get a default compiler + IDownstreamCompiler* getDefaultCompiler(SlangSourceLanguage sourceLanguage) const + { + return m_defaultCompilers[int(sourceLanguage)]; + } + /// Set the default compiler + void setDefaultCompiler(SlangSourceLanguage sourceLanguage, IDownstreamCompiler* compiler) + { + m_defaultCompilers[int(sourceLanguage)] = compiler; + } - /// True if has a compiler of the specified type + /// True if has a compiler of the specified type bool hasCompiler(SlangPassThrough compilerType) const; void remove(SlangPassThrough compilerType); @@ -51,7 +57,6 @@ public: } protected: - Index _findIndex(const DownstreamCompilerDesc& desc) const; @@ -63,6 +68,6 @@ protected: List<ComPtr<ISlangSharedLibrary>> m_sharedLibraries; }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-downstream-compiler-util.cpp b/source/compiler-core/slang-downstream-compiler-util.cpp index bf4c7cc04..1ab35d4fe 100644 --- a/source/compiler-core/slang-downstream-compiler-util.cpp +++ b/source/compiler-core/slang-downstream-compiler-util.cpp @@ -1,30 +1,28 @@ // slang-downstream-compiler.cpp #include "slang-downstream-compiler-util.h" +#include "../core/slang-blob.h" +#include "../core/slang-char-util.h" #include "../core/slang-common.h" -#include "slang-com-helper.h" -#include "../core/slang-string-util.h" - -#include "../core/slang-type-text-util.h" - #include "../core/slang-io.h" #include "../core/slang-shared-library.h" -#include "../core/slang-blob.h" -#include "../core/slang-char-util.h" +#include "../core/slang-string-util.h" +#include "../core/slang-type-text-util.h" +#include "slang-com-helper.h" #ifdef SLANG_VC -# include "windows/slang-win-visual-studio-util.h" +#include "windows/slang-win-visual-studio-util.h" #endif -#include "slang-visual-studio-compiler-util.h" -#include "slang-gcc-compiler-util.h" -#include "slang-nvrtc-compiler.h" -#include "slang-fxc-compiler.h" #include "slang-dxc-compiler.h" +#include "slang-fxc-compiler.h" +#include "slang-gcc-compiler-util.h" #include "slang-glslang-compiler.h" #include "slang-llvm-compiler.h" #include "slang-metal-compiler.h" +#include "slang-nvrtc-compiler.h" #include "slang-tint-compiler.h" +#include "slang-visual-studio-compiler-util.h" namespace Slang { @@ -46,10 +44,14 @@ struct DownstreamCompilerInfos DownstreamCompilerInfos infos; - infos.infos[int(SLANG_PASS_THROUGH_CLANG)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_GCC)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_LLVM)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_CLANG)] = + Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = + Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_GCC)] = + Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_LLVM)] = + Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); infos.infos[int(SLANG_PASS_THROUGH_NVRTC)] = Info(SourceLanguageFlag::CUDA); @@ -61,16 +63,20 @@ struct DownstreamCompilerInfos return infos; } -/* static */DownstreamCompilerInfos DownstreamCompilerInfos::s_infos = DownstreamCompilerInfos::_calcInfos(); +/* static */ DownstreamCompilerInfos DownstreamCompilerInfos::s_infos = + DownstreamCompilerInfos::_calcInfos(); /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerInfo !!!!!!!!!!!!!!!!!!!!!!*/ -/* static */const DownstreamCompilerInfo& DownstreamCompilerInfo::getInfo(SlangPassThrough compiler) +/* static */ const DownstreamCompilerInfo& DownstreamCompilerInfo::getInfo( + SlangPassThrough compiler) { return DownstreamCompilerInfos::s_infos.infos[int(compiler)]; } -/* static */bool DownstreamCompilerInfo::canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage) +/* static */ bool DownstreamCompilerInfo::canCompile( + SlangPassThrough compiler, + SlangSourceLanguage sourceLanguage) { const auto& info = getInfo(compiler); return (info.sourceLanguageFlags & (SourceLanguageFlags(1) << int(sourceLanguage))) != 0; @@ -91,7 +97,8 @@ static DownstreamCompilerMatchVersion _calcCompiledVersion() matchVersion.type = SLANG_PASS_THROUGH_GCC; matchVersion.matchVersion.set(Index(__GNUC__), Index(__GNUC_MINOR__)); #else - // TODO(JS): Hmmm None is not quite the same as unknown. It works for now, but we might want to have a distinct enum for unknown. + // TODO(JS): Hmmm None is not quite the same as unknown. It works for now, but we might want to + // have a distinct enum for unknown. matchVersion.type = SLANG_PASS_THROUGH_NONE; #endif @@ -105,14 +112,20 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() return s_version; } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const DownstreamCompilerSet* set, MatchType matchType, const DownstreamCompilerDesc& desc) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findCompiler( + const DownstreamCompilerSet* set, + MatchType matchType, + const DownstreamCompilerDesc& desc) { List<IDownstreamCompiler*> compilers; set->getCompilers(compilers); return findCompiler(compilers, matchType, desc); } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<IDownstreamCompiler*>& compilers, MatchType matchType, const DownstreamCompilerDesc& desc) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findCompiler( + const List<IDownstreamCompiler*>& compilers, + MatchType matchType, + const DownstreamCompilerDesc& desc) { if (compilers.getCount() <= 0) { @@ -145,7 +158,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() const Int versionValue = compilerDesc.getVersionValue(); switch (matchType) { - case MatchType::MinGreaterEqual: + case MatchType::MinGreaterEqual: { auto diff = descVersionValue - versionValue; if (diff >= 0 && diff < minVersionDiff) @@ -155,7 +168,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } break; } - case MatchType::MinAbsolute: + case MatchType::MinAbsolute: { auto diff = descVersionValue - versionValue; diff = (diff >= 0) ? diff : -diff; @@ -166,7 +179,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } break; } - case MatchType::Newest: + case MatchType::Newest: { if (versionValue > maxVersionValue) { @@ -182,7 +195,9 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() return (bestIndex >= 0) ? compilers[bestIndex] : nullptr; } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<IDownstreamCompiler*>& compilers, const DownstreamCompilerDesc& desc) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findCompiler( + const List<IDownstreamCompiler*>& compilers, + const DownstreamCompilerDesc& desc) { for (auto compiler : compilers) { @@ -194,15 +209,21 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() return nullptr; } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List<IDownstreamCompiler*>& compilers, SlangPassThrough type, const SemanticVersion& version) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findCompiler( + const List<IDownstreamCompiler*>& compilers, + SlangPassThrough type, + const SemanticVersion& version) { DownstreamCompilerDesc desc; desc.type = type; - desc.version = version; + desc.version = version; return findCompiler(compilers, desc); } -/* static */void DownstreamCompilerUtil::findVersions(const List<IDownstreamCompiler*>& compilers, SlangPassThrough type, List<SemanticVersion>& outVersions) +/* static */ void DownstreamCompilerUtil::findVersions( + const List<IDownstreamCompiler*>& compilers, + SlangPassThrough type, + List<SemanticVersion>& outVersions) { for (auto compiler : compilers) { @@ -215,7 +236,9 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const List<IDownstreamCompiler*>& compilers, const DownstreamCompilerMatchVersion& matchVersion) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler( + const List<IDownstreamCompiler*>& compilers, + const DownstreamCompilerMatchVersion& matchVersion) { List<SemanticVersion> versions; @@ -230,7 +253,10 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } // Okay lets find the best one - auto bestVersion = MatchSemanticVersion::findAnyBest(versions.getBuffer(), versions.getCount(), matchVersion.matchVersion); + auto bestVersion = MatchSemanticVersion::findAnyBest( + versions.getBuffer(), + versions.getCount(), + matchVersion.matchVersion); // If one is found use it if (bestVersion.isSet()) @@ -241,14 +267,13 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() { // TODO(JS): - // NOTE! This may not really be appropriate, because LLVM is *not* interchangable with + // NOTE! This may not really be appropriate, because LLVM is *not* interchangable with // a 'normal' C++ compiler as cannot access standard libraries/headers. // So `slang-llvm` can't be used for 'host' code. - // These compilers should be usable interchangably. The order is important, as the first one that matches will - // be used, so LLVM is used before CLANG or GCC if appropriate - const SlangPassThrough compatiblePassThroughs[] = - { + // These compilers should be usable interchangably. The order is important, as the first one + // that matches will be used, so LLVM is used before CLANG or GCC if appropriate + const SlangPassThrough compatiblePassThroughs[] = { SLANG_PASS_THROUGH_LLVM, SLANG_PASS_THROUGH_CLANG, SLANG_PASS_THROUGH_GCC, @@ -266,7 +291,8 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() if (versions.getCount() > 0) { // Get the latest version (as we have no way to really compare) - auto latestVersion = SemanticVersion::getLatest(versions.getBuffer(), versions.getCount()); + auto latestVersion = + SemanticVersion::getLatest(versions.getBuffer(), versions.getCount()); return findCompiler(compilers, matchVersion.type, latestVersion); } } @@ -276,21 +302,25 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() return nullptr; } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompilerMatchVersion& matchVersion) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler( + const DownstreamCompilerSet* set, + const DownstreamCompilerMatchVersion& matchVersion) { List<IDownstreamCompiler*> compilers; set->getCompilers(compilers); return findClosestCompiler(compilers, matchVersion); } -/* static */void DownstreamCompilerUtil::updateDefault(DownstreamCompilerSet* set, SlangSourceLanguage sourceLanguage) +/* static */ void DownstreamCompilerUtil::updateDefault( + DownstreamCompilerSet* set, + SlangSourceLanguage sourceLanguage) { IDownstreamCompiler* compiler = nullptr; switch (sourceLanguage) { - case SLANG_SOURCE_LANGUAGE_CPP: - case SLANG_SOURCE_LANGUAGE_C: + case SLANG_SOURCE_LANGUAGE_CPP: + case SLANG_SOURCE_LANGUAGE_C: { // Find the compiler closest to the compiler this was compiled with if (!compiler) @@ -299,20 +329,20 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } break; } - case SLANG_SOURCE_LANGUAGE_CUDA: + case SLANG_SOURCE_LANGUAGE_CUDA: { DownstreamCompilerDesc desc; desc.type = SLANG_PASS_THROUGH_NVRTC; compiler = findCompiler(set, MatchType::Newest, desc); break; } - default: break; + default: break; } set->setDefaultCompiler(sourceLanguage, compiler); } -/* static */void DownstreamCompilerUtil::updateDefaults(DownstreamCompilerSet* set) +/* static */ void DownstreamCompilerUtil::updateDefaults(DownstreamCompilerSet* set) { for (Index i = 0; i < Index(SLANG_SOURCE_LANGUAGE_COUNT_OF); ++i) { @@ -320,7 +350,8 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } } -/* static */void DownstreamCompilerUtil::setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]) +/* static */ void DownstreamCompilerUtil::setDefaultLocators( + DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]) { outFuncs[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = &VisualStudioCompilerUtil::locateCompilers; outFuncs[int(SLANG_PASS_THROUGH_CLANG)] = &GCCDownstreamCompilerUtil::locateClangCompilers; @@ -350,7 +381,11 @@ static String _getParentPath(const String& path) } } -static SlangResult _findPaths(const String& path, const char* libraryName, String& outParentPath, String& outLibraryPath) +static SlangResult _findPaths( + const String& path, + const char* libraryName, + String& outParentPath, + String& outLibraryPath) { // Try to determine what the path is by looking up the path type SlangPathType pathType; @@ -372,14 +407,17 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin return SLANG_OK; } - // If this failed the path could be to a shared library, but we may need to convert to the shared library filename first + // If this failed the path could be to a shared library, but we may need to convert to the + // shared library filename first const String sharedLibraryFilePath = SharedLibrary::calcPlatformPath(path.getUnownedSlice()); - if (SLANG_SUCCEEDED(Path::getPathType(sharedLibraryFilePath, &pathType)) && pathType == SLANG_PATH_TYPE_FILE) + if (SLANG_SUCCEEDED(Path::getPathType(sharedLibraryFilePath, &pathType)) && + pathType == SLANG_PATH_TYPE_FILE) { - // We pass in the shared library path, as canonical paths can sometimes only apply to pre-existing objects. + // We pass in the shared library path, as canonical paths can sometimes only apply to + // pre-existing objects. outParentPath = _getParentPath(sharedLibraryFilePath); - // The original path should work as is for the SharedLibrary load. Notably we don't use the sharedLibraryFilePath - // as this is the wrong name to do a SharedLibrary load with. + // The original path should work as is for the SharedLibrary load. Notably we don't use the + // sharedLibraryFilePath as this is the wrong name to do a SharedLibrary load with. outLibraryPath = path; return SLANG_OK; @@ -388,7 +426,12 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin return SLANG_FAIL; } -/* static */SlangResult DownstreamCompilerUtil::loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependentNames, const char* inLibraryName, ComPtr<ISlangSharedLibrary>& outSharedLib) +/* static */ SlangResult DownstreamCompilerUtil::loadSharedLibrary( + const String& path, + ISlangSharedLibraryLoader* loader, + const char* const* dependentNames, + const char* inLibraryName, + ComPtr<ISlangSharedLibrary>& outSharedLib) { String parentPath; String libraryPath; @@ -399,19 +442,21 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin if (SLANG_FAILED(_findPaths(path, inLibraryName, parentPath, libraryPath))) { // We have a few scenarios here. - // 1) The path could be the shared library/dll filename, that will be found through some operating system mechanism - // 2) That the shared library is *NOT* on the filesystem directly (the loader does something different) - // 3) Permissions or some other mechanism stops the lookup from working + // 1) The path could be the shared library/dll filename, that will be found through some + // operating system mechanism 2) That the shared library is *NOT* on the filesystem + // directly (the loader does something different) 3) Permissions or some other mechanism + // stops the lookup from working // We should probably assume that the path means something, else why set it. - // It's probably less likely that it is a directory that we can't detect - as if it's a directory as part of an app - // it's permissions should allow detection, or be made to allow it. + // It's probably less likely that it is a directory that we can't detect - as if it's a + // directory as part of an app it's permissions should allow detection, or be made to + // allow it. // All this being the case we should probably assume that it is the shared library name. libraryPath = path; - // Attempt to get a parent. If there isn't one this will be empty, which will mean it will be ignored, which is probably - // what we want if path is just a shared library name + // Attempt to get a parent. If there isn't one this will be empty, which will mean it + // will be ignored, which is probably what we want if path is just a shared library name parentPath = Path::getParentDirectory(libraryPath); } } @@ -422,7 +467,7 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin // Try to load any dependent libs from the parent path if (dependentNames) { - for (const char*const* cur = dependentNames; *cur; ++cur) + for (const char* const* cur = dependentNames; *cur; ++cur) { const char* dependentName = *cur; ComPtr<ISlangSharedLibrary> lib; @@ -455,7 +500,9 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin } } -/* static */void DownstreamCompilerUtil::appendAsText(const DownstreamCompilerDesc& desc, StringBuilder& out) +/* static */ void DownstreamCompilerUtil::appendAsText( + const DownstreamCompilerDesc& desc, + StringBuilder& out) { out << TypeTextUtil::getPassThroughAsHumanText(desc.type); @@ -469,4 +516,4 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin } } -} +} // namespace Slang diff --git a/source/compiler-core/slang-downstream-compiler-util.h b/source/compiler-core/slang-downstream-compiler-util.h index 84b8edcca..b6efb2e4f 100644 --- a/source/compiler-core/slang-downstream-compiler-util.h +++ b/source/compiler-core/slang-downstream-compiler-util.h @@ -1,13 +1,16 @@ #ifndef SLANG_DOWNSTREAM_COMPILER_UTIL_H #define SLANG_DOWNSTREAM_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" #include "slang-downstream-compiler-set.h" +#include "slang-downstream-compiler.h" namespace Slang { -typedef SlangResult (*DownstreamCompilerLocatorFunc)(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); +typedef SlangResult (*DownstreamCompilerLocatorFunc)( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); struct DownstreamCompilerInfo { @@ -33,31 +36,38 @@ struct DownstreamCompilerInfo /// True if this compiler can compile the specified language static bool canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage); - DownstreamCompilerInfo() : sourceLanguageFlags(0) {} + DownstreamCompilerInfo() + : sourceLanguageFlags(0) + { + } - DownstreamCompilerInfo(SourceLanguageFlags inSourceLanguageFlags) : - sourceLanguageFlags(inSourceLanguageFlags) - {} + DownstreamCompilerInfo(SourceLanguageFlags inSourceLanguageFlags) + : sourceLanguageFlags(inSourceLanguageFlags) + { + } SourceLanguageFlags sourceLanguageFlags; }; -// Combination of a downstream compiler type (pass through) and +// Combination of a downstream compiler type (pass through) and // a match version. struct DownstreamCompilerMatchVersion { - DownstreamCompilerMatchVersion(SlangPassThrough inType, MatchSemanticVersion inMatchVersion) : - type(inType), - matchVersion(inMatchVersion) - {} + DownstreamCompilerMatchVersion(SlangPassThrough inType, MatchSemanticVersion inMatchVersion) + : type(inType), matchVersion(inMatchVersion) + { + } - DownstreamCompilerMatchVersion() :type(SLANG_PASS_THROUGH_NONE) {} + DownstreamCompilerMatchVersion() + : type(SLANG_PASS_THROUGH_NONE) + { + } - SlangPassThrough type; ///< The type of the compiler - MatchSemanticVersion matchVersion; ///< The match version + SlangPassThrough type; ///< The type of the compiler + MatchSemanticVersion matchVersion; ///< The match version }; -struct DownstreamCompilerUtil: public DownstreamCompilerUtilBase +struct DownstreamCompilerUtil : public DownstreamCompilerUtilBase { enum class MatchType { @@ -66,40 +76,66 @@ struct DownstreamCompilerUtil: public DownstreamCompilerUtilBase Newest, }; - /// Find a compiler - static IDownstreamCompiler* findCompiler(const DownstreamCompilerSet* set, MatchType matchType, const DownstreamCompilerDesc& desc); - static IDownstreamCompiler* findCompiler(const List<IDownstreamCompiler*>& compilers, MatchType matchType, const DownstreamCompilerDesc& desc); - - static IDownstreamCompiler* findCompiler(const List<IDownstreamCompiler*>& compilers, SlangPassThrough type, const SemanticVersion& version); - static IDownstreamCompiler* findCompiler(const List<IDownstreamCompiler*>& compilers, const DownstreamCompilerDesc& desc); - - /// Find all the compilers with the version - static void findVersions(const List<IDownstreamCompiler*>& compilers, SlangPassThrough compiler, List<SemanticVersion>& versions); - - - /// Find the compiler closest to the desc - static IDownstreamCompiler* findClosestCompiler(const List<IDownstreamCompiler*>& compilers, const DownstreamCompilerMatchVersion& version); - static IDownstreamCompiler* findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompilerMatchVersion& version); - - /// Get the information on the compiler used to compile this source + /// Find a compiler + static IDownstreamCompiler* findCompiler( + const DownstreamCompilerSet* set, + MatchType matchType, + const DownstreamCompilerDesc& desc); + static IDownstreamCompiler* findCompiler( + const List<IDownstreamCompiler*>& compilers, + MatchType matchType, + const DownstreamCompilerDesc& desc); + + static IDownstreamCompiler* findCompiler( + const List<IDownstreamCompiler*>& compilers, + SlangPassThrough type, + const SemanticVersion& version); + static IDownstreamCompiler* findCompiler( + const List<IDownstreamCompiler*>& compilers, + const DownstreamCompilerDesc& desc); + + /// Find all the compilers with the version + static void findVersions( + const List<IDownstreamCompiler*>& compilers, + SlangPassThrough compiler, + List<SemanticVersion>& versions); + + + /// Find the compiler closest to the desc + static IDownstreamCompiler* findClosestCompiler( + const List<IDownstreamCompiler*>& compilers, + const DownstreamCompilerMatchVersion& version); + static IDownstreamCompiler* findClosestCompiler( + const DownstreamCompilerSet* set, + const DownstreamCompilerMatchVersion& version); + + /// Get the information on the compiler used to compile this source static DownstreamCompilerMatchVersion getCompiledVersion(); static void updateDefault(DownstreamCompilerSet* set, SlangSourceLanguage sourceLanguage); static void updateDefaults(DownstreamCompilerSet* set); - static void setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]); - - /// Attempts to determine what 'path' is and load appropriately. Is it a path to a shared library? Is it a directory holding the libraries? - /// Some downstream shared libraries need other shared libraries to be loaded before the main shared library, such that they are in the same directory - /// otherwise the shared library could come from some unwanted location. - /// dependentNames names shared libraries which should be attempted to be loaded in the path of the main shared library. - /// The list is optional (nullptr can be passed in), and the list is terminated by nullptr. - static SlangResult loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependantNames, const char* libraryName, ComPtr<ISlangSharedLibrary>& outSharedLib); - - /// Append the desc as text + static void setDefaultLocators( + DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]); + + /// Attempts to determine what 'path' is and load appropriately. Is it a path to a shared + /// library? Is it a directory holding the libraries? Some downstream shared libraries need + /// other shared libraries to be loaded before the main shared library, such that they are in + /// the same directory otherwise the shared library could come from some unwanted location. + /// dependentNames names shared libraries which should be attempted to be loaded in the path of + /// the main shared library. The list is optional (nullptr can be passed in), and the list is + /// terminated by nullptr. + static SlangResult loadSharedLibrary( + const String& path, + ISlangSharedLibraryLoader* loader, + const char* const* dependantNames, + const char* libraryName, + ComPtr<ISlangSharedLibrary>& outSharedLib); + + /// Append the desc as text static void appendAsText(const DownstreamCompilerDesc& desc, StringBuilder& out); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index 855319176..190400f55 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -1,37 +1,36 @@ // slang-downstream-compiler.cpp #include "slang-downstream-compiler.h" +#include "../core/slang-blob.h" +#include "../core/slang-castable.h" +#include "../core/slang-char-util.h" #include "../core/slang-common.h" -#include "slang-com-helper.h" -#include "../core/slang-string-util.h" - -#include "../core/slang-type-text-util.h" - #include "../core/slang-io.h" #include "../core/slang-shared-library.h" -#include "../core/slang-blob.h" -#include "../core/slang-char-util.h" - -#include "../core/slang-castable.h" - +#include "../core/slang-string-util.h" +#include "../core/slang-type-text-util.h" +#include "slang-artifact-associated-impl.h" +#include "slang-artifact-desc-util.h" +#include "slang-artifact-helper.h" #include "slang-artifact-impl.h" #include "slang-artifact-representation-impl.h" -#include "slang-artifact-associated-impl.h" #include "slang-artifact-util.h" -#include "slang-artifact-helper.h" -#include "slang-artifact-desc-util.h" +#include "slang-com-helper.h" namespace Slang { /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ -SlangResult DownstreamCompilerBase::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult DownstreamCompilerBase::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { SLANG_UNUSED(from); SLANG_UNUSED(to); SLANG_UNUSED(outArtifact); - + return SLANG_E_NOT_AVAILABLE; } @@ -46,8 +45,7 @@ void* DownstreamCompilerBase::castAs(const Guid& guid) void* DownstreamCompilerBase::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IDownstreamCompiler::getTypeGuid()) { return static_cast<IDownstreamCompiler*>(this); @@ -64,7 +62,9 @@ void* DownstreamCompilerBase::getObject(const Guid& guid) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineDownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!*/ -SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptions, IArtifact** outArtifact) +SlangResult CommandLineDownstreamCompiler::compile( + const CompileOptions& inOptions, + IArtifact** outArtifact) { if (!isVersionCompatible(inOptions)) { @@ -77,11 +77,11 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Copy the command line options CommandLine cmdLine(m_cmdLine); - // Work out the ArtifactDesc + // Work out the ArtifactDesc const auto targetDesc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); auto helper = DefaultArtifactHelper::getSingleton(); - + List<ComPtr<IArtifact>> artifactList; // It may be necessary to produce a temporary file 'lock file'. @@ -93,11 +93,13 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // If no module path is set we will need to generate one if (options.modulePath.count == 0) { - // We could use the path to the source, or use the source name/paths as defined on the artifact - // For now we just go with a lock file based on "slang-generated". - SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(toSlice("slang-generated")), lockFile.writeRef())); + // We could use the path to the source, or use the source name/paths as defined on the + // artifact For now we just go with a lock file based on "slang-generated". + SLANG_RETURN_ON_FAIL( + helper->createLockFile(asCharSlice(toSlice("slang-generated")), lockFile.writeRef())); - auto lockArtifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::Lock, ArtifactStyle::None)); + auto lockArtifact = Artifact::create( + ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::Lock, ArtifactStyle::None)); lockArtifact->addRepresentation(lockFile); artifactList.add(lockArtifact); @@ -108,14 +110,17 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio options.modulePath = SliceUtil::asTerminatedCharSlice(modulePath); } - // Append command line args to the end of cmdLine using the target specific function for the specified options + // Append command line args to the end of cmdLine using the target specific function for the + // specified options SLANG_RETURN_ON_FAIL(calcArgs(options, cmdLine)); - // The 'productArtifact' is the main product produced from the compilation - the executable/sharedlibrary/object etc + // The 'productArtifact' is the main product produced from the compilation - the + // executable/sharedlibrary/object etc ComPtr<IArtifact> productArtifact; { List<ComPtr<IArtifact>> artifacts; - SLANG_RETURN_ON_FAIL(calcCompileProducts(options, DownstreamProductFlag::All, lockFile, artifacts)); + SLANG_RETURN_ON_FAIL( + calcCompileProducts(options, DownstreamProductFlag::All, lockFile, artifacts)); for (IArtifact* artifact : artifacts) { @@ -129,7 +134,7 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio artifactList.add(ComPtr<IArtifact>(artifact)); } } - + SLANG_ASSERT(productArtifact); // Somethings gone wrong if we don't find the main artifact if (!productArtifact) @@ -155,21 +160,22 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio } #endif - // Go through the list of artifacts in the artifactList and check if they exist. - // - // This is useful because `calcCompileProducts` is conservative and may produce artifacts for products that aren't actually - // produced, by the compilation. + // Go through the list of artifacts in the artifactList and check if they exist. + // + // This is useful because `calcCompileProducts` is conservative and may produce artifacts for + // products that aren't actually produced, by the compilation. { - + Count count = artifactList.getCount(); for (Index i = 0; i < count; ++i) { IArtifact* artifact = artifactList[i]; - + if (!artifact->exists()) { // We should find a file rep and if we do we can disown it. Disowning will mean - // when scope is lost the rep won't try and delete the (apparently non existing) backing file. + // when scope is lost the rep won't try and delete the (apparently non existing) + // backing file. if (auto fileRep = findRepresentation<IOSFileArtifactRepresentation>(artifact)) { fileRep->disown(); @@ -189,7 +195,8 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio } } - // Add all of the source artifacts, that are temporary on the file system, such that they can stay in scope for debugging + // Add all of the source artifacts, that are temporary on the file system, such that they can + // stay in scope for debugging for (auto sourceArtifact : options.sourceArtifacts) { if (auto fileRep = findRepresentation<IOSFileArtifactRepresentation>(sourceArtifact)) @@ -205,16 +212,18 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Create the result artifact auto artifact = ArtifactUtil::createArtifact(targetDesc); - // Createa the diagnostics + // Createa the diagnostics auto diagnostics = ArtifactDiagnostics::create(); SLANG_RETURN_ON_FAIL(parseOutput(exeRes, diagnostics)); ArtifactUtil::addAssociated(artifact, diagnostics); - // Find the rep from the 'main' artifact, we'll just use the same representation on the output + // Find the rep from the 'main' artifact, we'll just use the same representation on the output // artifact. Sharing is desirable, because the rep owns the file. - if (auto fileRep = productArtifact ? findRepresentation<IOSFileArtifactRepresentation>(productArtifact) : nullptr) + if (auto fileRep = productArtifact + ? findRepresentation<IOSFileArtifactRepresentation>(productArtifact) + : nullptr) { artifact->addRepresentation(fileRep); } @@ -222,13 +231,17 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Add the artifact list if there is anything in it if (artifactList.getCount()) { - // Holds all of the artifacts that are relatated to the final artifact - such as debug files, ancillary file and lock files - auto artifactContainer = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::Unknown, ArtifactStyle::Unknown)); + // Holds all of the artifacts that are relatated to the final artifact - such as debug + // files, ancillary file and lock files + auto artifactContainer = ArtifactUtil::createArtifact(ArtifactDesc::make( + ArtifactKind::Container, + ArtifactPayload::Unknown, + ArtifactStyle::Unknown)); auto slice = SliceUtil::asSlice(artifactList); artifactContainer->setChildren(slice.data, slice.count); - + artifact->addAssociated(artifactContainer); } @@ -236,4 +249,4 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index 95793eaa3..c0cc868d1 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -2,19 +2,14 @@ #define SLANG_DOWNSTREAM_COMPILER_H #include "../core/slang-common.h" -#include "../core/slang-string.h" - -#include "../core/slang-process-util.h" - +#include "../core/slang-io.h" #include "../core/slang-platform.h" +#include "../core/slang-process-util.h" #include "../core/slang-semantic-version.h" - -#include "../core/slang-io.h" - -#include "slang-com-ptr.h" - -#include "slang-artifact.h" +#include "../core/slang-string.h" #include "slang-artifact-associated.h" +#include "slang-artifact.h" +#include "slang-com-ptr.h" #include <type_traits> @@ -29,43 +24,58 @@ struct DownstreamCompilerDesc typedef DownstreamCompilerDesc ThisType; HashCode getHashCode() const { return combineHash(HashCode(type), version.getHashCode()); } - bool operator==(const ThisType& rhs) const { return type == rhs.type && version == rhs.version; } + bool operator==(const ThisType& rhs) const + { + return type == rhs.type && version == rhs.version; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Get the version as a value + /// Get the version as a value Int getVersionValue() const { return version.m_major * 100 + version.m_minor; } - /// true if has a version set + /// true if has a version set bool hasVersion() const { return version.isSet(); } /// Ctor - explicit DownstreamCompilerDesc(SlangPassThrough inType = SLANG_PASS_THROUGH_NONE, Int inMajorVersion = 0, Int inMinorVersion = 0) :type(inType), version(int(inMajorVersion), int(inMinorVersion)) {} - explicit DownstreamCompilerDesc(SlangPassThrough inType, const SemanticVersion& inVersion) : type(inType), version(inVersion) {} + explicit DownstreamCompilerDesc( + SlangPassThrough inType = SLANG_PASS_THROUGH_NONE, + Int inMajorVersion = 0, + Int inMinorVersion = 0) + : type(inType), version(int(inMajorVersion), int(inMinorVersion)) + { + } + explicit DownstreamCompilerDesc(SlangPassThrough inType, const SemanticVersion& inVersion) + : type(inType), version(inVersion) + { + } - SlangPassThrough type; ///< The type of the compiler - SemanticVersion version; ///< The version of the compiler + SlangPassThrough type; ///< The type of the compiler + SemanticVersion version; ///< The version of the compiler }; -/* Placed at the start of structs that are versioned. -The id uniquely identifies a compatible set of versions. +/* Placed at the start of structs that are versioned. +The id uniquely identifies a compatible set of versions. The size indicates the struct size. It should be considered as a kind of version number. The larger the number for the target the newer the *compatible* version (assuming the identifiers match). -Note that size versioning *only* works, if adding a field *doesn't* use any existing unused "pad" bytes. -This implies that any new members *must* take into account padding/alignment. Any additions that have alignment -*less* than the alignment of struct may need padding. +Note that size versioning *only* works, if adding a field *doesn't* use any existing unused "pad" +bytes. This implies that any new members *must* take into account padding/alignment. Any additions +that have alignment *less* than the alignment of struct may need padding. */ struct VersionedStruct { typedef VersionedStruct ThisType; - VersionedStruct(uint32_t inIdentifier, size_t inSize): - identifier(inIdentifier), - size(uint32_t(inSize)) - {} + VersionedStruct(uint32_t inIdentifier, size_t inSize) + : identifier(inIdentifier), size(uint32_t(inSize)) + { + } - /// True if the versions are identical - bool operator==(const ThisType& rhs) const { return identifier == rhs.identifier && size == rhs.size; } + /// True if the versions are identical + bool operator==(const ThisType& rhs) const + { + return identifier == rhs.identifier && size == rhs.size; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } VersionedStruct(const ThisType& rhs) = default; @@ -75,7 +85,7 @@ struct VersionedStruct uint32_t size; }; -template <typename T> +template<typename T> T getCompatibleVersion(const T* inT) { const VersionedStruct* in = &inT->version; @@ -85,7 +95,7 @@ T getCompatibleVersion(const T* inT) // Note that the struct is passed in by pointer rather than reference, because // we must ensure that it is not sliced. - + // Must match SLANG_ASSERT(T::kVersionIdentifier == in->identifier); @@ -118,13 +128,13 @@ T getCompatibleVersion(const T* inT) return t; } -template <typename T> +template<typename T> bool isVersionCompatible(const VersionedStruct& ver) { return ver.identifier == T::kVersionIdentifier; } -template <typename T> +template<typename T> bool isVersionCompatible(const T& in) { return isVersionCompatible<T>(in.version); @@ -132,20 +142,21 @@ bool isVersionCompatible(const T& in) /* Downstream compile options -NOTE! This type is trafficed across shared library boundaries and *versioned*. +NOTE! This type is trafficed across shared library boundaries and *versioned*. In particular * The struct can only contain types that can be trivially memcpyd (checked by static_assert); -* New fields can only be added to the end of the struct -* New fields must take into account alignment/padding such that they do not share bytes in previous version sizes +* New fields can only be added to the end of the struct +* New fields must take into account alignment/padding such that they do not share bytes in previous +version sizes */ struct DownstreamCompileOptions { typedef DownstreamCompileOptions ThisType; - // A unique identifer for this particular struct kind. If the struct become incompatible + // A unique identifer for this particular struct kind. If the struct become incompatible // a new id should be used to identify a specific style. If the change is only to add members - // to the end, this should be handled via the version size at use sites. + // to the end, this should be handled via the version size at use sites. static const uint32_t kVersionIdentifier = 0x34296897; typedef uint32_t Flags; @@ -153,27 +164,31 @@ struct DownstreamCompileOptions { enum Enum : Flags { - EnableExceptionHandling = 0x01, ///< Enables exception handling support (say as optionally supported by C++) - Verbose = 0x02, ///< Give more verbose diagnostics - EnableSecurityChecks = 0x04, ///< Enable runtime security checks (such as for buffer overruns) - enabling typically decreases performance - EnableFloat16 = 0x08, ///< If set compiles with support for float16/half + EnableExceptionHandling = + 0x01, ///< Enables exception handling support (say as optionally supported by C++) + Verbose = 0x02, ///< Give more verbose diagnostics + EnableSecurityChecks = 0x04, ///< Enable runtime security checks (such as for buffer + ///< overruns) - enabling typically decreases performance + EnableFloat16 = 0x08, ///< If set compiles with support for float16/half }; }; enum class OptimizationLevel : uint8_t { - None, ///< Don't optimize at all. - Default, ///< Default optimization level: balance code quality and compilation time. - High, ///< Optimize aggressively. - Maximal, ///< Include optimizations that may take a very long time, or may involve severe space-vs-speed tradeoffs + None, ///< Don't optimize at all. + Default, ///< Default optimization level: balance code quality and compilation time. + High, ///< Optimize aggressively. + Maximal, ///< Include optimizations that may take a very long time, or may involve severe + ///< space-vs-speed tradeoffs }; enum class DebugInfoType : uint8_t { - None, ///< Don't emit debug information at all. - Minimal, ///< Emit as little debug information as possible, while still supporting stack traces. - Standard, ///< Emit whatever is the standard level of debug information for each target. - Maximal, ///< Emit as much debug information as possible for each target. + None, ///< Don't emit debug information at all. + Minimal, ///< Emit as little debug information as possible, while still supporting stack + ///< traces. + Standard, ///< Emit whatever is the standard level of debug information for each target. + Maximal, ///< Emit as much debug information as possible for each target. }; enum class FloatingPointMode : uint8_t { @@ -192,7 +207,7 @@ struct DownstreamCompileOptions struct Define { - TerminatedCharSlice nameWithSig; ///< If macro takes parameters include in brackets + TerminatedCharSlice nameWithSig; ///< If macro takes parameters include in brackets TerminatedCharSlice value; }; @@ -200,7 +215,7 @@ struct DownstreamCompileOptions { enum class Kind : uint8_t { - CUDASM, ///< What the version is for + CUDASM, ///< What the version is for SPIRV, }; Kind kind; @@ -222,8 +237,9 @@ struct DownstreamCompileOptions PlatformKind platform = PlatformKind::Unknown; - /// The path/name of the output module. Should not have the extension, as that will be added for each of the target types. - /// If not set a module path will be internally generated internally on a command line based compiler + /// The path/name of the output module. Should not have the extension, as that will be added for + /// each of the target types. If not set a module path will be internally generated internally + /// on a command line based compiler TerminatedCharSlice modulePath; Slice<Define> defines; @@ -241,31 +257,32 @@ struct DownstreamCompileOptions /// For compilers/compiles that require an entry point name, else can be empty TerminatedCharSlice entryPointName; - /// Profile name to use, only required for compiles that need to compile against a a specific profiles. - /// Profile names are tied to compilers and targets. + /// Profile name to use, only required for compiles that need to compile against a a specific + /// profiles. Profile names are tied to compilers and targets. TerminatedCharSlice profileName; - /// The stage being compiled for + /// The stage being compiled for SlangStage stage = SLANG_STAGE_NONE; /// Arguments that are specific to a particular compiler implementation. Slice<TerminatedCharSlice> compilerSpecificArguments; - /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will be ignored in those scenarios. + /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will + /// be ignored in those scenarios. ISlangFileSystemExt* fileSystemExt = nullptr; SourceManager* sourceManager = nullptr; - // The debug info format to use. + // The debug info format to use. SlangDebugInfoFormat m_debugInfoFormat = SLANG_DEBUG_INFO_FORMAT_DEFAULT; }; static_assert(std::is_trivially_copyable_v<DownstreamCompileOptions>); -#define SLANG_ALIAS_DEPRECATED_VERSION(name, id, firstField, lastField) \ -struct name##_AliasDeprecated##id \ -{ \ - static const ptrdiff_t kStart = SLANG_OFFSET_OF(name, firstField); \ - static const ptrdiff_t kEnd = SLANG_OFFSET_OF(name, lastField) + sizeof(name::lastField); \ -}; +#define SLANG_ALIAS_DEPRECATED_VERSION(name, id, firstField, lastField) \ + struct name##_AliasDeprecated##id \ + { \ + static const ptrdiff_t kStart = SLANG_OFFSET_OF(name, firstField); \ + static const ptrdiff_t kEnd = SLANG_OFFSET_OF(name, lastField) + sizeof(name::lastField); \ + }; /* Used to indicate what kind of products are expected to be produced for a compilation. */ typedef uint32_t DownstreamProductFlags; @@ -273,25 +290,29 @@ struct DownstreamProductFlag { enum Enum : DownstreamProductFlags { - Debug = 0x1, ///< Used by debugger during execution - Execution = 0x2, ///< Required for execution - Compile = 0x4, ///< A product *required* for compilation - Miscellaneous = 0x8, ///< Anything else + Debug = 0x1, ///< Used by debugger during execution + Execution = 0x2, ///< Required for execution + Compile = 0x4, ///< A product *required* for compilation + Miscellaneous = 0x8, ///< Anything else }; enum Mask : DownstreamProductFlags { - All = 0xf, ///< All the flags + All = 0xf, ///< All the flags }; }; class IDownstreamCompiler : public ICastable { public: - SLANG_COM_INTERFACE(0x167b8ba7, 0xbd41, 0x469a, { 0x92, 0x28, 0xb8, 0x53, 0xc8, 0xea, 0x56, 0x6d }) + SLANG_COM_INTERFACE( + 0x167b8ba7, + 0xbd41, + 0x469a, + {0x92, 0x28, 0xb8, 0x53, 0xc8, 0xea, 0x56, 0x6d}) typedef DownstreamCompilerDesc Desc; typedef DownstreamCompileOptions CompileOptions; - + typedef CompileOptions::OptimizationLevel OptimizationLevel; typedef CompileOptions::DebugInfoType DebugInfoType; typedef CompileOptions::FloatingPointMode FloatingPointMode; @@ -299,40 +320,63 @@ public: typedef CompileOptions::Define Define; typedef CompileOptions::CapabilityVersion CapabilityVersion; - /// Get the desc of this compiler + /// Get the desc of this compiler virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0; - /// Compile using the specified options. The result is in resOut - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) = 0; - /// Returns true if compiler can do a transformation of `from` to `to` Artifact types - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) = 0; - /// Converts an artifact `from` to a desc of `to` and puts the result in outArtifact - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) = 0; - /// Get the version of this compiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) = 0; - /// Validate and return the result - virtual SLANG_NO_THROW SlangResult SLANG_MCALL validate(const uint32_t* contents, int contentsSize) = 0; - - /// True if underlying compiler uses file system to communicate source + /// Compile using the specified options. The result is in resOut + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) = 0; + /// Returns true if compiler can do a transformation of `from` to `to` Artifact types + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) = 0; + /// Converts an artifact `from` to a desc of `to` and puts the result in outArtifact + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) = 0; + /// Get the version of this compiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getVersionString(slang::IBlob** outVersionString) = 0; + /// Validate and return the result + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + validate(const uint32_t* contents, int contentsSize) = 0; + + /// True if underlying compiler uses file system to communicate source virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() = 0; }; class DownstreamCompilerBase : public ComBaseObject, public IDownstreamCompiler { public: - SLANG_COM_BASE_IUNKNOWN_ALL + SLANG_COM_BASE_IUNKNOWN_ALL // ICastable virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IDownstreamCompiler virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE { SLANG_UNUSED(from); SLANG_UNUSED(to); return false; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) SLANG_OVERRIDE { *outVersionString = nullptr; return SLANG_FAIL; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE { SLANG_UNUSED(contents); SLANG_UNUSED(contentsSize); return SLANG_FAIL; } + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE + { + SLANG_UNUSED(from); + SLANG_UNUSED(to); + return false; + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) + SLANG_OVERRIDE + { + *outVersionString = nullptr; + return SLANG_FAIL; + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE + { + SLANG_UNUSED(contents); + SLANG_UNUSED(contentsSize); + return SLANG_FAIL; + } - DownstreamCompilerBase(const Desc& desc): - m_desc(desc) + DownstreamCompilerBase(const Desc& desc) + : m_desc(desc) { } DownstreamCompilerBase() {} @@ -349,36 +393,47 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return true; } // Functions to be implemented for a specific CommandLine - /// Given options determines the paths to products produced (including the 'moduleFilePath'). - /// Note that does *not* guarentee all products were or should be produced. Just aims to include all that could - /// be produced, such that can be removed on completion. - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, IOSFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts) = 0; + /// Given options determines the paths to products produced (including the 'moduleFilePath'). + /// Note that does *not* guarentee all products were or should be produced. Just aims to include + /// all that could be produced, such that can be removed on completion. + virtual SlangResult calcCompileProducts( + const CompileOptions& options, + DownstreamProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List<ComPtr<IArtifact>>& outArtifacts) = 0; virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) = 0; - virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) = 0; + virtual SlangResult parseOutput( + const ExecuteResult& exeResult, + IArtifactDiagnostics* diagnostics) = 0; - CommandLineDownstreamCompiler(const Desc& desc, const ExecutableLocation& exe) : - Super(desc) + CommandLineDownstreamCompiler(const Desc& desc, const ExecutableLocation& exe) + : Super(desc) { m_cmdLine.setExecutableLocation(exe); } - CommandLineDownstreamCompiler(const Desc& desc, const CommandLine& cmdLine) : - Super(desc), - m_cmdLine(cmdLine) - {} + CommandLineDownstreamCompiler(const Desc& desc, const CommandLine& cmdLine) + : Super(desc), m_cmdLine(cmdLine) + { + } - CommandLineDownstreamCompiler(const Desc& desc):Super(desc) {} + CommandLineDownstreamCompiler(const Desc& desc) + : Super(desc) + { + } CommandLine m_cmdLine; }; -/* Only purpose of having base-class here is to make all the DownstreamCompiler types available directly in derived Utils */ +/* Only purpose of having base-class here is to make all the DownstreamCompiler types available + * directly in derived Utils */ struct DownstreamCompilerUtilBase { typedef DownstreamCompileOptions CompileOptions; @@ -392,6 +447,6 @@ struct DownstreamCompilerUtilBase typedef DownstreamProductFlags ProductFlags; }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index 30bf71968..b694c4cf6 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -1,35 +1,28 @@ // slang-dxc-compiler.cpp #include "slang-dxc-compiler.h" -#include "../core/slang-common.h" -#include "slang-com-helper.h" - #include "../core/slang-blob.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-string-slice-pool.h" - +#include "../core/slang-char-util.h" +#include "../core/slang-common.h" #include "../core/slang-io.h" -#include "../core/slang-shared-library.h" #include "../core/slang-semantic-version.h" -#include "../core/slang-char-util.h" - -#include "slang-include-system.h" -#include "slang-source-loc.h" - #include "../core/slang-shared-library.h" - +#include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" #include "slang-artifact-associated-impl.h" -#include "slang-artifact-util.h" -#include "slang-artifact-diagnostic-util.h" #include "slang-artifact-desc-util.h" +#include "slang-artifact-diagnostic-util.h" +#include "slang-artifact-util.h" +#include "slang-com-helper.h" +#include "slang-include-system.h" +#include "slang-source-loc.h" // Enable DXIL by default unless told not to #ifndef SLANG_ENABLE_DXIL_SUPPORT #if SLANG_APPLE_FAMILY -# define SLANG_ENABLE_DXIL_SUPPORT 0 +#define SLANG_ENABLE_DXIL_SUPPORT 0 #else -# define SLANG_ENABLE_DXIL_SUPPORT 1 +#define SLANG_ENABLE_DXIL_SUPPORT 1 #endif #endif @@ -37,15 +30,15 @@ // generate code on Windows. #if SLANG_ENABLE_DXIL_SUPPORT -# ifdef _WIN32 -# include <unknwn.h> -# include <windows.h> -# endif +#ifdef _WIN32 +#include <unknwn.h> +#include <windows.h> +#endif -# include "../../external/dxc/dxcapi.h" +#include "../../external/dxc/dxcapi.h" -# ifndef _WIN32 -# ifdef __uuidof +#ifndef _WIN32 +#ifdef __uuidof // DXC's WinAdapter.h defines __uuidof(T) over types, but the existing // usage in this file is over values (both are accepted on MSVC.) // We also need to decay through Slang::ComPtr, hence the helper struct @@ -59,11 +52,10 @@ struct StripSlangComPtr<Slang::ComPtr<T>> { using type = T; }; -# undef __uuidof -# define __uuidof(x) \ - __emulated_uuidof<StripSlangComPtr<std::decay_t<decltype(x)>>::type>() -# endif -# endif +#undef __uuidof +#define __uuidof(x) __emulated_uuidof<StripSlangComPtr<std::decay_t<decltype(x)>>::type>() +#endif +#endif #endif namespace Slang @@ -71,11 +63,15 @@ namespace Slang #if SLANG_ENABLE_DXIL_SUPPORT -static UnownedStringSlice _getSlice(IDxcBlob* blob) { return StringUtil::getSlice((ISlangBlob*)blob); } +static UnownedStringSlice _getSlice(IDxcBlob* blob) +{ + return StringUtil::getSlice((ISlangBlob*)blob); +} // IDxcIncludeHandler // 7f61fc7d-950d-467f-b3e3-3c02fb49187c -static const Guid IID_IDxcIncludeHandler = { 0x7f61fc7d, 0x950d, 0x467f, { 0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c } }; +static const Guid IID_IDxcIncludeHandler = + {0x7f61fc7d, 0x950d, 0x467f, {0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c}}; static UnownedStringSlice _addName(const UnownedStringSlice& inSlice, StringSlicePool& pool) { @@ -89,10 +85,10 @@ static UnownedStringSlice _addName(const UnownedStringSlice& inSlice, StringSlic const Index length = slice.getLength(); buf << slice; - for (Index i = 0; ; ++i) + for (Index i = 0;; ++i) { buf.reduceLength(length); - + if (i > 0) { buf << "_" << i; @@ -131,8 +127,8 @@ public: // Implement IDxcIncludeHandler virtual HRESULT SLANG_MCALL LoadSource(LPCWSTR inFilename, IDxcBlob** outSource) SLANG_OVERRIDE { - // Hmm DXC does something a bit odd - when it sees a path, it just passes that in with ./ in front!! - // NOTE! It doesn't make any difference if it is "" or <> quoted. + // Hmm DXC does something a bit odd - when it sees a path, it just passes that in with ./ in + // front!! NOTE! It doesn't make any difference if it is "" or <> quoted. // So we just do a work around where we strip if we see a path starting with ./ String filePath = String::fromWString(inFilename); @@ -141,9 +137,9 @@ public: if (filePath.startsWith("./")) { const String remaining = filePath.getUnownedSlice().tail(2); - - // Okay if we strip ./ and what we have is absolute, then it's the absolute path that we care about, - // otherwise we just leave as is. + + // Okay if we strip ./ and what we have is absolute, then it's the absolute path that we + // care about, otherwise we just leave as is. if (Path::isAbsolute(remaining)) { filePath = remaining; @@ -160,13 +156,15 @@ public: return res; } - DxcIncludeHandler(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager = nullptr) : - m_system(searchDirectories, fileSystemExt, sourceManager) + DxcIncludeHandler( + SearchDirectoryList* searchDirectories, + ISlangFileSystemExt* fileSystemExt, + SourceManager* sourceManager = nullptr) + : m_system(searchDirectories, fileSystemExt, sourceManager) { } protected: - // Used by QueryInterface for casting ISlangUnknown* getInterface(const Guid& guid) { @@ -176,7 +174,7 @@ protected: } return nullptr; } - + IncludeSystem m_system; }; @@ -186,11 +184,15 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) + SLANG_OVERRIDE; /// Must be called before use SlangResult init(ISlangSharedLibrary* library); @@ -198,13 +200,12 @@ public: DXCDownstreamCompiler() {} protected: - DxcCreateInstanceProc m_createInstance = nullptr; - /// The commit hash associated with the DXC dll used - /// If 0 length, no hash was found - String m_commitHash; - /// The commit count. 0 if not set + /// The commit hash associated with the DXC dll used + /// If 0 length, no hash was found + String m_commitHash; + /// The commit count. 0 if not set uint32_t m_commitCount = 0; ComPtr<ISlangSharedLibrary> m_sharedLibrary; @@ -231,10 +232,13 @@ SlangResult DXCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_FAIL; } - // Must be able to create the compiler. We inly do this here, because we want to get the compiler - // version. + // Must be able to create the compiler. We inly do this here, because we want to get the + // compiler version. ComPtr<IDxcCompiler> dxcCompiler; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef())); + SLANG_RETURN_ON_FAIL(m_createInstance( + CLSID_DxcCompiler, + __uuidof(dxcCompiler), + (LPVOID*)dxcCompiler.writeRef())); uint32_t major = 0; uint32_t minor = 0; @@ -277,12 +281,13 @@ SlangResult DXCDownstreamCompiler::init(ISlangSharedLibrary* library) StringBuilder buf; semanticVersion.append(buf); - if (customVersionString.startsWith(buf) && + if (customVersionString.startsWith(buf) && customVersionString.getLength() > buf.getLength() + 2 && customVersionString[buf.getLength()] == '.') { // Get the patch slice - UnownedStringSlice patchSlice = StringUtil::getAtInSplit(customVersionString.getUnownedSlice(), '.', 2); + UnownedStringSlice patchSlice = + StringUtil::getAtInSplit(customVersionString.getUnownedSlice(), '.', 2); Int patchValue; if (SLANG_SUCCEEDED(StringUtil::parseInt(patchSlice, patchValue)) && patchValue > 0) @@ -298,7 +303,11 @@ SlangResult DXCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, IArtifactDiagnostics::Diagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + List<UnownedStringSlice>& lineSlices, + IArtifactDiagnostics::Diagnostic& outDiagnostic) { /* tests/diagnostics/syntax-error-intrinsic.slang:14:2: error: expected expression */ if (lineSlices.getCount() < 5) @@ -310,8 +319,8 @@ static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const Unowned SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[1], outDiagnostic.location.line)); - //Int lineCol; - //SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[2], lineCol)); + // Int lineCol; + // SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[2], lineCol)); UnownedStringSlice severitySlice = lineSlices[3].trim(); @@ -326,7 +335,10 @@ static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const Unowned return SLANG_OK; } -static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtifactDiagnostics* diagnostics, ComPtr<IDxcBlob>& outBlob) +static SlangResult _handleOperationResult( + IDxcOperationResult* dxcResult, + IArtifactDiagnostics* diagnostics, + ComPtr<IDxcBlob>& outBlob) { // Retrieve result. HRESULT resultCode = S_OK; @@ -355,7 +367,12 @@ static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtif SliceAllocator allocator; List<IArtifactDiagnostics::Diagnostic> parsedDiagnostics; - SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(allocator, diagnosticsSlice, 0, _parseDiagnosticLine, diagnostics); + SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics( + allocator, + diagnosticsSlice, + 0, + _parseDiagnosticLine, + diagnostics); SLANG_UNUSED(diagnosticParseRes); SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes)); @@ -365,7 +382,8 @@ static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtif // If it failed, make sure we have an error in the diagnostics if (SLANG_FAILED(resultCode)) { - // In case the parsing failed, we still have an error -> so require there is one in the diagnostics + // In case the parsing failed, we still have an error -> so require there is one in the + // diagnostics diagnostics->requireErrorDiagnostic(); } else @@ -380,7 +398,7 @@ static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtif SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArtifact** outArtifact) { - if (!isVersionCompatible(inOptions)) + if (!isVersionCompatible(inOptions)) { // Not possible to compile with this version of the interface. return SLANG_E_NOT_IMPLEMENTED; @@ -389,7 +407,8 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt CompileOptions options = getCompatibleVersion(&inOptions); // This compiler can only deal at most, a single source code artifact - // Should be okay to link together multiple libraries without any source artifacts (assuming that means source code) + // Should be okay to link together multiple libraries without any source artifacts (assuming + // that means source code) if (options.sourceArtifacts.count > 1) { return SLANG_FAIL; @@ -401,7 +420,8 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt if (hasSource) { - if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_HLSL || options.targetType != SLANG_DXIL) + if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_HLSL || + options.targetType != SLANG_DXIL) { SLANG_ASSERT(!"Can only compile HLSL to DXIL"); return SLANG_FAIL; @@ -425,9 +445,13 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt } ComPtr<IDxcCompiler> dxcCompiler; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef())); + SLANG_RETURN_ON_FAIL(m_createInstance( + CLSID_DxcCompiler, + __uuidof(dxcCompiler), + (LPVOID*)dxcCompiler.writeRef())); ComPtr<IDxcLibrary> dxcLibrary; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); + SLANG_RETURN_ON_FAIL( + m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); ComPtr<IDxcBlobEncoding> dxcSourceBlob = nullptr; ComPtr<ISlangBlob> sourceBlob; @@ -464,45 +488,36 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt switch (options.matrixLayout) { - default: - break; + default: break; - case SLANG_MATRIX_LAYOUT_ROW_MAJOR: - args.add(L"-Zpr"); - break; + case SLANG_MATRIX_LAYOUT_ROW_MAJOR: args.add(L"-Zpr"); break; } switch (options.floatingPointMode) { - default: - break; + default: break; - case FloatingPointMode::Precise: - args.add(L"-Gis"); // "force IEEE strictness" - break; + case FloatingPointMode::Precise: + args.add(L"-Gis"); // "force IEEE strictness" + break; } - switch (options.optimizationLevel) { - default: - break; + default: break; - case OptimizationLevel::None: args.add(L"-Od"); break; - case OptimizationLevel::Default: args.add(L"-O1"); break; - case OptimizationLevel::High: args.add(L"-O2"); break; - case OptimizationLevel::Maximal: args.add(L"-O3"); break; + case OptimizationLevel::None: args.add(L"-Od"); break; + case OptimizationLevel::Default: args.add(L"-O1"); break; + case OptimizationLevel::High: args.add(L"-O2"); break; + case OptimizationLevel::Maximal: args.add(L"-O3"); break; } switch (options.debugInfoType) { - case DebugInfoType::None: - break; + case DebugInfoType::None: break; - default: - args.add(L"-Zi"); - break; + default: args.add(L"-Zi"); break; } // Slang strives to produce correct code, and by default @@ -556,9 +571,9 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt searchDirectories.searchDirectories.add(asString(includePath)); } - // TODO(JS): - // We don't want to enable HLSL2021 on DXC by default even if it's available because it has - // changes that break things. Such as with operator ?:. So for now we disable. +// TODO(JS): +// We don't want to enable HLSL2021 on DXC by default even if it's available because it has +// changes that break things. Such as with operator ?:. So for now we disable. #if 0 // TODO(JS): Enable in a better way perhaps? { @@ -586,27 +601,33 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt sourcePath = ArtifactUtil::findPath(sourceArtifact); OSString wideSourcePath = sourcePath.toWString(); - DxcIncludeHandler includeHandler(&searchDirectories, options.fileSystemExt, options.sourceManager); + DxcIncludeHandler includeHandler( + &searchDirectories, + options.fileSystemExt, + options.sourceManager); - SLANG_RETURN_ON_FAIL(dxcCompiler->Compile(dxcSourceBlob, + SLANG_RETURN_ON_FAIL(dxcCompiler->Compile( + dxcSourceBlob, wideSourcePath.begin(), wideEntryPointName.begin(), wideProfileName.begin(), args.getBuffer(), UINT32(args.getCount()), - nullptr, // `#define`s - 0, // `#define` count - &includeHandler, // `#include` handler + nullptr, // `#define`s + 0, // `#define` count + &includeHandler, // `#include` handler dxcOperationResult.writeRef())); - SLANG_RETURN_ON_FAIL(_handleOperationResult(dxcOperationResult, diagnostics, dxcResultBlob)); + SLANG_RETURN_ON_FAIL( + _handleOperationResult(dxcOperationResult, diagnostics, dxcResultBlob)); } // If we have libraries then we need to link... if (libraries.getCount()) { ComPtr<IDxcLinker> linker; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLinker, __uuidof(linker), (void**)linker.writeRef())); + SLANG_RETURN_ON_FAIL( + m_createInstance(CLSID_DxcLinker, __uuidof(linker), (void**)linker.writeRef())); StringSlicePool pool(StringSlicePool::Style::Default); @@ -648,22 +669,30 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt SLANG_ASSERT(libraryNames.getCount() == librariesCount); List<const wchar_t*> linkLibraryNames; - + linkLibraryNames.setCount(librariesCount); - + for (Index i = 0; i < librariesCount; ++i) { linkLibraryNames[i] = libraryNames[i].begin(); // Register the library - SLANG_RETURN_ON_FAIL(linker->RegisterLibrary(linkLibraryNames[i], (IDxcBlob*)libraryBlobs[i].get())); + SLANG_RETURN_ON_FAIL( + linker->RegisterLibrary(linkLibraryNames[i], (IDxcBlob*)libraryBlobs[i].get())); } // Use the original profile name wideProfileName = asString(options.profileName).toWString(); ComPtr<IDxcOperationResult> linkDxcResult; - SLANG_RETURN_ON_FAIL(linker->Link(wideEntryPointName.begin(), wideProfileName.begin(), linkLibraryNames.getBuffer(), UINT32(librariesCount), nullptr, 0, linkDxcResult.writeRef())); + SLANG_RETURN_ON_FAIL(linker->Link( + wideEntryPointName.begin(), + wideProfileName.begin(), + linkLibraryNames.getBuffer(), + UINT32(librariesCount), + nullptr, + 0, + linkDxcResult.writeRef())); ComPtr<IDxcBlob> linkedBlob; SLANG_RETURN_ON_FAIL(_handleOperationResult(linkDxcResult, diagnostics, linkedBlob)); @@ -696,9 +725,15 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt ComPtr<IDxcBlob> pdbBlob; ComPtr<IDxcBlobWide> nameBlob; - if (SLANG_SUCCEEDED(dxcResult->GetOutput(DXC_OUT_PDB, __uuidof(pdbBlob), (void**)pdbBlob.writeRef(), nameBlob.writeRef()))) + if (SLANG_SUCCEEDED(dxcResult->GetOutput( + DXC_OUT_PDB, + __uuidof(pdbBlob), + (void**)pdbBlob.writeRef(), + nameBlob.writeRef()))) { - auto pdbArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactDesc::Kind::BinaryFormat, ArtifactDesc::Payload::PdbDebugInfo)); + auto pdbArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make( + ArtifactDesc::Kind::BinaryFormat, + ArtifactDesc::Payload::PdbDebugInfo)); if (nameBlob) { @@ -707,7 +742,8 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt const auto name = String::fromWString(wideName); if (name.getLength()) { - // Set the name on the artifact. This is the name that must be used for the PDB to be loadable as a file by other tooling. + // Set the name on the artifact. This is the name that must be used for + // the PDB to be loadable as a file by other tooling. pdbArtifact->setName(name.getBuffer()); } } @@ -730,7 +766,10 @@ bool DXCDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactD return ArtifactDescUtil::isDisassembly(from, to) && from.payload == ArtifactPayload::DXIL; } -SlangResult DXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult DXCDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { // Can only disassemble blobs that are DXIL if (!canConvert(from->getDesc(), to)) @@ -742,13 +781,21 @@ SlangResult DXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::No, dxilBlob.writeRef())); ComPtr<IDxcCompiler> dxcCompiler; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef())); + SLANG_RETURN_ON_FAIL(m_createInstance( + CLSID_DxcCompiler, + __uuidof(dxcCompiler), + (LPVOID*)dxcCompiler.writeRef())); ComPtr<IDxcLibrary> dxcLibrary; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); + SLANG_RETURN_ON_FAIL( + m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); // Create blob from the input data ComPtr<IDxcBlobEncoding> dxcSourceBlob; - SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned((LPBYTE)dxilBlob->getBufferPointer(), (UINT32)dxilBlob->getBufferSize(), 0, dxcSourceBlob.writeRef())); + SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned( + (LPBYTE)dxilBlob->getBufferPointer(), + (UINT32)dxilBlob->getBufferSize(), + 0, + dxcSourceBlob.writeRef())); ComPtr<IDxcBlobEncoding> dxcResultBlob; SLANG_RETURN_ON_FAIL(dxcCompiler->Disassemble(dxcSourceBlob, dxcResultBlob.writeRef())); @@ -770,26 +817,36 @@ SlangResult DXCDownstreamCompiler::getVersionString(slang::IBlob** outVersionStr m_desc.version.append(versionString); if (m_commitHash.getLength()) - { + { versionString << "#" << m_commitHash; } else { // If we don't have the commitHash, we use the library timestamp, to uniquely identify. - versionString << " " << SharedLibraryUtils::getSharedLibraryTimestamp(reinterpret_cast<void*>(m_createInstance)); + versionString << " " + << SharedLibraryUtils::getSharedLibraryTimestamp( + reinterpret_cast<void*>(m_createInstance)); } *outVersionString = StringBlob::moveCreate(versionString).detach(); return SLANG_OK; } -/* static */SlangResult DXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult DXCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { ComPtr<ISlangSharedLibrary> library; - const char* dependentNames[] = {"dxil", nullptr } ; - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, dependentNames, "dxcompiler", library)); - + const char* dependentNames[] = {"dxil", nullptr}; + SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary( + path, + loader, + dependentNames, + "dxcompiler", + library)); + SLANG_ASSERT(library); if (!library) { @@ -806,7 +863,10 @@ SlangResult DXCDownstreamCompiler::getVersionString(slang::IBlob** outVersionStr #else // SLANG_ENABLE_DXIL_SUPPORT -/* static */SlangResult DXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult DXCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(path); SLANG_UNUSED(loader); @@ -816,4 +876,4 @@ SlangResult DXCDownstreamCompiler::getVersionString(slang::IBlob** outVersionStr #endif // SLANG_ENABLE_DXIL_SUPPORT -} +} // namespace Slang diff --git a/source/compiler-core/slang-dxc-compiler.h b/source/compiler-core/slang-dxc-compiler.h index 4c915fb19..ee1d93c48 100644 --- a/source/compiler-core/slang-dxc-compiler.h +++ b/source/compiler-core/slang-dxc-compiler.h @@ -1,18 +1,20 @@ #ifndef SLANG_DXC_COMPILER_UTIL_H #define SLANG_DXC_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { struct DXCDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp index e4a9f25c7..0c571c10b 100644 --- a/source/compiler-core/slang-fxc-compiler.cpp +++ b/source/compiler-core/slang-fxc-compiler.cpp @@ -3,43 +3,36 @@ #if SLANG_ENABLE_DXBC_SUPPORT -#include "../core/slang-common.h" -#include "slang-com-helper.h" - #include "../core/slang-blob.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-string-slice-pool.h" - +#include "../core/slang-char-util.h" +#include "../core/slang-common.h" #include "../core/slang-io.h" -#include "../core/slang-shared-library.h" #include "../core/slang-semantic-version.h" -#include "../core/slang-char-util.h" - -#include "slang-include-system.h" -#include "slang-source-loc.h" - +#include "../core/slang-shared-library.h" +#include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" #include "slang-artifact-associated-impl.h" #include "slang-artifact-desc-util.h" #include "slang-artifact-diagnostic-util.h" - -#include "../core/slang-shared-library.h" +#include "slang-com-helper.h" +#include "slang-include-system.h" +#include "slang-source-loc.h" // Enable calling through to `fxc` or `dxc` to // generate code on Windows. #ifdef _WIN32 -# include <windows.h> -# include <d3dcompiler.h> +#include <d3dcompiler.h> +#include <windows.h> #endif // Some of the `D3DCOMPILE_*` constants aren't available in all // versions of `d3dcompiler.h`, so we define them here just in case #ifndef D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES -# define D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES (1 << 20) +#define D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES (1 << 20) #endif #ifndef D3DCOMPILE_ALL_RESOURCES_BOUND -# define D3DCOMPILE_ALL_RESOURCES_BOUND (1 << 21) +#define D3DCOMPILE_ALL_RESOURCES_BOUND (1 << 21) #endif #endif // SLANG_ENABLE_DXBC_SUPPORT @@ -49,25 +42,35 @@ namespace Slang #if SLANG_ENABLE_DXBC_SUPPORT -static UnownedStringSlice _getSlice(ID3DBlob* blob) { return StringUtil::getSlice((ISlangBlob*)blob); } +static UnownedStringSlice _getSlice(ID3DBlob* blob) +{ + return StringUtil::getSlice((ISlangBlob*)blob); +} struct FxcIncludeHandler : ID3DInclude { - STDMETHOD(Open)(D3D_INCLUDE_TYPE includeType, LPCSTR fileName, LPCVOID parentData, LPCVOID* outData, UINT* outSize) override + STDMETHOD(Open) + (D3D_INCLUDE_TYPE includeType, + LPCSTR fileName, + LPCVOID parentData, + LPCVOID* outData, + UINT* outSize) override { SLANG_UNUSED(includeType); // NOTE! The pParentData means the *text* of any previous include. - // In order to work out what *path* that came from, we need to seach which source file it came from, and - // use it's path + // In order to work out what *path* that came from, we need to seach which source file it + // came from, and use it's path - // Assume the root pathInfo initially + // Assume the root pathInfo initially PathInfo includedFromPathInfo = m_rootPathInfo; // Lets try and find the parent source if there is any if (parentData) { - SourceFile* foundSourceFile = m_system.getSourceManager()->findSourceFileByContentRecursively((const char*)parentData); + SourceFile* foundSourceFile = + m_system.getSourceManager()->findSourceFileByContentRecursively( + (const char*)parentData); if (foundSourceFile) { includedFromPathInfo = foundSourceFile->getPathInfo(); @@ -78,7 +81,8 @@ struct FxcIncludeHandler : ID3DInclude PathInfo pathInfo; ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(m_system.findAndLoadFile(path, includedFromPathInfo.foundPath, pathInfo, blob)); + SLANG_RETURN_ON_FAIL( + m_system.findAndLoadFile(path, includedFromPathInfo.foundPath, pathInfo, blob)); // Return the data *outData = blob->getBufferPointer(); @@ -92,8 +96,11 @@ struct FxcIncludeHandler : ID3DInclude SLANG_UNUSED(pData); return S_OK; } - FxcIncludeHandler(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager) : - m_system(searchDirectories, fileSystemExt, sourceManager) + FxcIncludeHandler( + SearchDirectoryList* searchDirectories, + ISlangFileSystemExt* fileSystemExt, + SourceManager* sourceManager) + : m_system(searchDirectories, fileSystemExt, sourceManager) { } @@ -107,22 +114,24 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - /// Must be called before use + /// Must be called before use SlangResult init(ISlangSharedLibrary* library); FXCDownstreamCompiler() {} - -protected: +protected: pD3DCompile m_compile = nullptr; pD3DDisassemble m_disassemble = nullptr; - ComPtr<ISlangSharedLibrary> m_sharedLibrary; + ComPtr<ISlangSharedLibrary> m_sharedLibrary; }; SlangResult FXCDownstreamCompiler::init(ISlangSharedLibrary* library) @@ -143,21 +152,29 @@ SlangResult FXCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + List<UnownedStringSlice>& lineSlices, + ArtifactDiagnostic& outDiagnostic) { - /* tests/diagnostics/syntax-error-intrinsic.slang(14,2): error X3000: syntax error: unexpected token '@' */ + /* tests/diagnostics/syntax-error-intrinsic.slang(14,2): error X3000: syntax error: unexpected + * token '@' */ if (lineSlices.getCount() < 3) { return SLANG_FAIL; } - SLANG_RETURN_ON_FAIL(ArtifactDiagnosticUtil::splitPathLocation(allocator, lineSlices[0], outDiagnostic)); + SLANG_RETURN_ON_FAIL( + ArtifactDiagnosticUtil::splitPathLocation(allocator, lineSlices[0], outDiagnostic)); { const UnownedStringSlice severityAndCodeSlice = lineSlices[1].trim(); - const UnownedStringSlice severitySlice = StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 0); + const UnownedStringSlice severitySlice = + StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 0); - outDiagnostic.code = allocator.allocate(StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 1)); + outDiagnostic.code = + allocator.allocate(StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 1)); outDiagnostic.severity = ArtifactDiagnostic::Severity::Error; if (severitySlice == "warning") @@ -212,10 +229,13 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt // Use the default fileSystemExt is not set ID3DInclude* includeHandler = nullptr; - FxcIncludeHandler fxcIncludeHandlerStorage(&searchDirectories, options.fileSystemExt, options.sourceManager); + FxcIncludeHandler fxcIncludeHandlerStorage( + &searchDirectories, + options.fileSystemExt, + options.sourceManager); if (options.fileSystemExt) { - + if (sourcePath.getLength() > 0) { fxcIncludeHandlerStorage.m_rootPathInfo = PathInfo::makePath(sourcePath); @@ -235,7 +255,7 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt dxMacro.Definition = define.value; dxMacrosStorage.add(dxMacro); } - D3D_SHADER_MACRO nullTerminator = { 0, 0 }; + D3D_SHADER_MACRO nullTerminator = {0, 0}; dxMacrosStorage.add(nullTerminator); dxMacros = dxMacrosStorage.getBuffer(); @@ -245,12 +265,9 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt switch (options.floatingPointMode) { - default: - break; + default: break; - case FloatingPointMode::Precise: - flags |= D3DCOMPILE_IEEE_STRICTNESS; - break; + case FloatingPointMode::Precise: flags |= D3DCOMPILE_IEEE_STRICTNESS; break; } flags |= D3DCOMPILE_ENABLE_STRICTNESS; @@ -258,23 +275,19 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt switch (options.optimizationLevel) { - default: - break; + default: break; - case OptimizationLevel::None: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0; break; - case OptimizationLevel::Default: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL1; break; - case OptimizationLevel::High: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL2; break; - case OptimizationLevel::Maximal: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; break; + case OptimizationLevel::None: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0; break; + case OptimizationLevel::Default: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL1; break; + case OptimizationLevel::High: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL2; break; + case OptimizationLevel::Maximal: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; break; } switch (options.debugInfoType) { - case DebugInfoType::None: - break; + case DebugInfoType::None: break; - default: - flags |= D3DCOMPILE_DEBUG; - break; + default: flags |= D3DCOMPILE_DEBUG; break; } ComPtr<ISlangBlob> sourceBlob; @@ -307,7 +320,12 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt UnownedStringSlice diagnosticText = _getSlice(diagnosticsBlob); diagnostics->setRaw(asCharSlice(diagnosticText)); - SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(allocator, diagnosticText, 0, _parseDiagnosticLine, diagnostics); + SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics( + allocator, + diagnosticText, + 0, + _parseDiagnosticLine, + diagnostics); SLANG_UNUSED(diagnosticParseRes); SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes)); } @@ -338,7 +356,10 @@ bool FXCDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactD return ArtifactDescUtil::isDisassembly(from, to) && from.payload == ArtifactPayload::DXBC; } -SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult FXCDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { if (!canConvert(from->getDesc(), to)) { @@ -349,22 +370,31 @@ SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::No, dxbcBlob.writeRef())); ComPtr<ID3DBlob> disassemblyBlob; - SLANG_RETURN_ON_FAIL(m_disassemble(dxbcBlob->getBufferPointer(), dxbcBlob->getBufferSize(), 0, nullptr, disassemblyBlob.writeRef())); + SLANG_RETURN_ON_FAIL(m_disassemble( + dxbcBlob->getBufferPointer(), + dxbcBlob->getBufferSize(), + 0, + nullptr, + disassemblyBlob.writeRef())); auto artifact = ArtifactUtil::createArtifact(to); // ISlangBlob is compatible with ID3DBlob artifact->addRepresentationUnknown((ISlangBlob*)disassemblyBlob.get()); - *outArtifact= artifact.detach(); + *outArtifact = artifact.detach(); return SLANG_OK; } -/* static */SlangResult FXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult FXCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { ComPtr<ISlangSharedLibrary> library; const char* const libName = "d3dcompiler_47"; - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, libName, library)); + SLANG_RETURN_ON_FAIL( + DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, libName, library)); SLANG_ASSERT(library); if (!library) @@ -383,7 +413,10 @@ SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& #else // SLANG_ENABLE_DXBC_SUPPORT -/* static */SlangResult FXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult FXCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(path); SLANG_UNUSED(loader); @@ -393,4 +426,4 @@ SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& #endif // else SLANG_ENABLE_DXBC_SUPPORT -} +} // namespace Slang diff --git a/source/compiler-core/slang-fxc-compiler.h b/source/compiler-core/slang-fxc-compiler.h index 856d2fc0e..9ab072de0 100644 --- a/source/compiler-core/slang-fxc-compiler.h +++ b/source/compiler-core/slang-fxc-compiler.h @@ -1,18 +1,20 @@ #ifndef SLANG_FXC_COMPILER_UTIL_H #define SLANG_FXC_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { struct FXCDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index 875f7bea1..67ee6f8b3 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -1,19 +1,17 @@ // slang-gcc-compiler-util.cpp #include "slang-gcc-compiler-util.h" +#include "../core/slang-char-util.h" #include "../core/slang-common.h" -#include "slang-com-helper.h" -#include "../core/slang-string-util.h" - #include "../core/slang-io.h" #include "../core/slang-shared-library.h" -#include "../core/slang-char-util.h" #include "../core/slang-string-slice-pool.h" - +#include "../core/slang-string-util.h" #include "slang-artifact-desc-util.h" #include "slang-artifact-diagnostic-util.h" -#include "slang-artifact-util.h" #include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" +#include "slang-com-helper.h" namespace Slang { @@ -44,7 +42,10 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return len; } -/* static */SlangResult GCCDownstreamCompilerUtil::parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompilerDesc& outDesc) +/* static */ SlangResult GCCDownstreamCompilerUtil::parseVersion( + const UnownedStringSlice& text, + const UnownedStringSlice& prefix, + DownstreamCompilerDesc& outDesc) { List<UnownedStringSlice> lines; StringUtil::calcLines(text, lines); @@ -57,7 +58,8 @@ static Index _findVersionEnd(const UnownedStringSlice& in) continue; } - const UnownedStringSlice remainingSlice = UnownedStringSlice(line.begin() + prefixIndex + prefix.getLength(), line.end()).trim(); + const UnownedStringSlice remainingSlice = + UnownedStringSlice(line.begin() + prefixIndex + prefix.getLength(), line.end()).trim(); const Index versionEndIndex = _findVersionEnd(remainingSlice); if (versionEndIndex < 0) @@ -65,9 +67,11 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return SLANG_FAIL; } - const UnownedStringSlice versionSlice(remainingSlice.begin(), remainingSlice.begin() + versionEndIndex); + const UnownedStringSlice versionSlice( + remainingSlice.begin(), + remainingSlice.begin() + versionEndIndex); - // Version is in format 0.0.0 + // Version is in format 0.0.0 List<UnownedStringSlice> split; StringUtil::split(versionSlice, '.', split); List<Int> digits; @@ -91,7 +95,9 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return SLANG_FAIL; } -SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe, DownstreamCompilerDesc& outDesc) +SlangResult GCCDownstreamCompilerUtil::calcVersion( + const ExecutableLocation& exe, + DownstreamCompilerDesc& outDesc) { CommandLine cmdLine; cmdLine.setExecutableLocation(exe); @@ -102,16 +108,14 @@ SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe // Note we now have builds that add other words in front of the version // such as "Ubuntu clang version" - const UnownedStringSlice prefixes[] = - { + const UnownedStringSlice prefixes[] = { UnownedStringSlice::fromLiteral("clang version"), UnownedStringSlice::fromLiteral("gcc version"), UnownedStringSlice::fromLiteral("Apple LLVM version"), UnownedStringSlice::fromLiteral("Apple metal version"), }; - const SlangPassThrough types[] = - { + const SlangPassThrough types[] = { SLANG_PASS_THROUGH_CLANG, SLANG_PASS_THROUGH_GCC, SLANG_PASS_THROUGH_CLANG, @@ -125,7 +129,8 @@ SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe // Set the type outDesc.type = types[i]; // Extract the version - if (SLANG_SUCCEEDED(parseVersion(exeRes.standardError.getUnownedSlice(), prefixes[i], outDesc))) + if (SLANG_SUCCEEDED( + parseVersion(exeRes.standardError.getUnownedSlice(), prefixes[i], outDesc))) { return SLANG_OK; } @@ -134,7 +139,9 @@ SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe return SLANG_FAIL; } -static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnostic::Severity& outSeverity) +static SlangResult _parseSeverity( + const UnownedStringSlice& in, + ArtifactDiagnostic::Severity& outSeverity) { typedef ArtifactDiagnostic::Severity Severity; @@ -157,28 +164,33 @@ static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnost return SLANG_OK; } -namespace { // anonymous +namespace +{ // anonymous enum class LineParseResult { - Single, ///< It's a single line - Start, ///< Line was the start of a message - Continuation, ///< Not totally clear, add to previous line if nothing else hit - Ignore, ///< Ignore the line + Single, ///< It's a single line + Start, ///< Line was the start of a message + Continuation, ///< Not totally clear, add to previous line if nothing else hit + Ignore, ///< Ignore the line }; - -} // anonymous - -static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedStringSlice& line, LineParseResult& outLineParseResult, ArtifactDiagnostic& outDiagnostic) + +} // namespace + +static SlangResult _parseGCCFamilyLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + LineParseResult& outLineParseResult, + ArtifactDiagnostic& outDiagnostic) { typedef ArtifactDiagnostic Diagnostic; typedef Diagnostic::Severity Severity; - + // Set to default case outLineParseResult = LineParseResult::Ignore; /* example error output from different scenarios */ - + /* tests/cpp-compiler/c-compile-error.c: In function 'int main(int, char**)': tests/cpp-compiler/c-compile-error.c:8:13: error: 'b' was not declared in this scope @@ -189,25 +201,26 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS ^ */ - /* /tmp/ccS0JCWe.o:c-compile-link-error.c:(.rdata$.refptr.thing[.refptr.thing]+0x0): undefined reference to `thing' - collect2: error: ld returned 1 exit status*/ + /* /tmp/ccS0JCWe.o:c-compile-link-error.c:(.rdata$.refptr.thing[.refptr.thing]+0x0): undefined + reference to `thing' collect2: error: ld returned 1 exit status*/ /* - clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated] - Undefined symbols for architecture x86_64: + clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated + [-Wdeprecated] Undefined symbols for architecture x86_64: "_thing", referenced from: _main in c-compile-link-error-a83ace.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) */ - /* /tmp/c-compile-link-error-ccf151.o: In function `main': - c-compile-link-error.c:(.text+0x19): undefined reference to `thing' - clang: error: linker command failed with exit code 1 (use -v to see invocation) - */ + /* /tmp/c-compile-link-error-ccf151.o: In function `main': + c-compile-link-error.c:(.text+0x19): undefined reference to `thing' + clang: error: linker command failed with exit code 1 (use -v to see invocation) + */ - /* /tmp/c-compile-link-error-301c8c.o: In function `main': - /home/travis/build/shader-slang/slang/tests/cpp-compiler/c-compile-link-error.c:10: undefined reference to `thing' - clang-7: error: linker command failed with exit code 1 (use -v to see invocation)*/ + /* /tmp/c-compile-link-error-301c8c.o: In function `main': + /home/travis/build/shader-slang/slang/tests/cpp-compiler/c-compile-link-error.c:10: undefined + reference to `thing' clang-7: error: linker command failed with exit code 1 (use -v to see + invocation)*/ /* /path/slang-cpp-prelude.h:4:10: fatal error: ../slang.h: No such file or directory #include "slang.h" @@ -221,7 +234,8 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS List<UnownedStringSlice> split; StringUtil::split(line, ':', split); - // On windows we can have paths that are a: etc... if we detect this we can combine 0 - 1 to be 1. + // On windows we can have paths that are a: etc... if we detect this we can combine 0 - 1 to + // be 1. if (split.getCount() > 1 && split[0].getLength() == 1) { const char c = split[0][0]; @@ -328,7 +342,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS outDiagnostic.severity = Diagnostic::Severity::Error; outDiagnostic.stage = Diagnostic::Stage::Link; outDiagnostic.text = allocator.allocate(split[3]); - + outLineParseResult = LineParseResult::Start; return SLANG_OK; } @@ -353,55 +367,60 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* diagnostics) +/* static */ SlangResult GCCDownstreamCompilerUtil::parseOutput( + const ExecuteResult& exeRes, + IArtifactDiagnostics* diagnostics) { LineParseResult prevLineResult = LineParseResult::Ignore; - + SliceAllocator allocator; diagnostics->reset(); diagnostics->setRaw(SliceUtil::asCharSlice(exeRes.standardError)); - // We hold in workDiagnostics so as it is more convenient to append to the last with a continuation - // also means we don't hold the allocations of building up continuations, just the results when finally allocated at the end + // We hold in workDiagnostics so as it is more convenient to append to the last with a + // continuation also means we don't hold the allocations of building up continuations, just the + // results when finally allocated at the end List<ArtifactDiagnostic> workDiagnostics; for (auto line : LineParser(exeRes.standardError.getUnownedSlice())) { ArtifactDiagnostic diagnostic; - + LineParseResult lineRes; - + SLANG_RETURN_ON_FAIL(_parseGCCFamilyLine(allocator, line, lineRes, diagnostic)); - + switch (lineRes) { - case LineParseResult::Start: + case LineParseResult::Start: { // It's start of a new message workDiagnostics.add(diagnostic); prevLineResult = LineParseResult::Start; break; } - case LineParseResult::Single: + case LineParseResult::Single: { // It's a single message, without anything following workDiagnostics.add(diagnostic); prevLineResult = LineParseResult::Ignore; break; } - case LineParseResult::Continuation: + case LineParseResult::Continuation: { - if (prevLineResult == LineParseResult::Start || prevLineResult == LineParseResult::Continuation) + if (prevLineResult == LineParseResult::Start || + prevLineResult == LineParseResult::Continuation) { if (workDiagnostics.getCount() > 0) { auto& last = workDiagnostics.getLast(); - // TODO(JS): Note that this is somewhat wasteful as every time we append we just allocate more memory - // to hold the result. - // If we had an allocator dedicated to 'text' we could perhaps just append to the end of the last allocation - // + // TODO(JS): Note that this is somewhat wasteful as every time we append we + // just allocate more memory to hold the result. If we had an allocator + // dedicated to 'text' we could perhaps just append to the end of the last + // allocation + // // We are now in a continuation, add to the last StringBuilder buf; buf.append(asStringSlice(last.text)); @@ -414,12 +433,12 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS } break; } - case LineParseResult::Ignore: + case LineParseResult::Ignore: { prevLineResult = lineRes; break; } - default: return SLANG_FAIL; + default: return SLANG_FAIL; } } @@ -428,7 +447,8 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS diagnostics->add(diagnostic); } - if (diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error) || exeRes.resultCode != 0) + if (diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error) || + exeRes.resultCode != 0) { diagnostics->setResult(SLANG_FAIL); } @@ -436,7 +456,11 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts) +/* static */ SlangResult GCCDownstreamCompilerUtil::calcCompileProducts( + const CompileOptions& options, + ProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List<ComPtr<IArtifact>>& outArtifacts) { SLANG_ASSERT(options.modulePath.count); @@ -446,9 +470,13 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS { StringBuilder builder; const auto desc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, asStringSlice(options.modulePath), builder)); + SLANG_RETURN_ON_FAIL( + ArtifactDescUtil::calcPathForDesc(desc, asStringSlice(options.modulePath), builder)); - auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Owned, builder.getUnownedSlice(), lockFile); + auto fileRep = OSFileArtifactRepresentation::create( + IOSFileArtifactRepresentation::Kind::Owned, + builder.getUnownedSlice(), + lockFile); auto artifact = ArtifactUtil::createArtifact(desc); artifact->addRepresentation(fileRep); @@ -458,12 +486,16 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) +/* static */ SlangResult GCCDownstreamCompilerUtil::calcArgs( + const CompileOptions& options, + CommandLine& cmdLine) { SLANG_ASSERT(options.modulePath.count); - PlatformKind platformKind = (options.platform == PlatformKind::Unknown) ? PlatformUtil::getPlatformKind() : options.platform; - + PlatformKind platformKind = (options.platform == PlatformKind::Unknown) + ? PlatformUtil::getPlatformKind() + : options.platform; + const auto targetDesc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP) @@ -473,7 +505,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // C++17 since we share headers with slang itself (which uses c++17) cmdLine.addArg("-std=c++17"); } - + if (targetDesc.payload == ArtifactDesc::Payload::MetalAIR) { cmdLine.addArg("-std=metal3.1"); @@ -484,44 +516,44 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // speaking UB, and GCC 10+ is happy to take advantage of this, stop it. cmdLine.addArg("-fno-strict-aliasing"); - // TODO(JS): Here we always set -m32 on x86. It could be argued it is only necessary when creating a shared library - // but if we create an object file, we don't know what to choose because we don't know what final usage is. - // It could also be argued that the platformKind could define the actual desired target - but as it stands - // we only have a target of 'Linux' (as opposed to Win32/64). Really it implies we need an arch enumeration too. + // TODO(JS): Here we always set -m32 on x86. It could be argued it is only necessary when + // creating a shared library but if we create an object file, we don't know what to choose + // because we don't know what final usage is. It could also be argued that the platformKind + // could define the actual desired target - but as it stands we only have a target of 'Linux' + // (as opposed to Win32/64). Really it implies we need an arch enumeration too. // - // For now we just make X86 binaries try and produce x86 compatible binaries as fixes the immediate problems. + // For now we just make X86 binaries try and produce x86 compatible binaries as fixes the + // immediate problems. #if SLANG_PROCESSOR_X86 - /* Used to specify the processor more broadly. For a x86 binary we need to make sure we build x86 builds - even when on an x64 system. - -m32 - -m64*/ + /* Used to specify the processor more broadly. For a x86 binary we need to make sure we build + x86 builds even when on an x64 system. -m32 -m64*/ cmdLine.addArg("-m32"); #endif switch (options.optimizationLevel) { - case OptimizationLevel::None: + case OptimizationLevel::None: { // No optimization cmdLine.addArg("-O0"); break; } - case OptimizationLevel::Default: + case OptimizationLevel::Default: { cmdLine.addArg("-Os"); break; } - case OptimizationLevel::High: + case OptimizationLevel::High: { cmdLine.addArg("-O2"); break; } - case OptimizationLevel::Maximal: + case OptimizationLevel::Maximal: { cmdLine.addArg("-O4"); break; } - default: break; + default: break; } if (options.debugInfoType != DebugInfoType::None) @@ -536,31 +568,35 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS switch (options.floatingPointMode) { - case FloatingPointMode::Default: break; - case FloatingPointMode::Precise: + case FloatingPointMode::Default: break; + case FloatingPointMode::Precise: { - //cmdLine.addArg("-fno-unsafe-math-optimizations"); + // cmdLine.addArg("-fno-unsafe-math-optimizations"); break; } - case FloatingPointMode::Fast: + case FloatingPointMode::Fast: { // We could enable SSE with -mfpmath=sse - // But that would only make sense on a x64/x86 type processor and only if that feature is present (it is on all x64) + // But that would only make sense on a x64/x86 type processor and only if that feature + // is present (it is on all x64) cmdLine.addArg("-ffast-math"); break; } } - StringBuilder moduleFilePath; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(targetDesc, asStringSlice(options.modulePath), moduleFilePath)); - + StringBuilder moduleFilePath; + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc( + targetDesc, + asStringSlice(options.modulePath), + moduleFilePath)); + cmdLine.addArg("-o"); cmdLine.addArg(moduleFilePath); switch (options.targetType) { - case SLANG_SHADER_SHARED_LIBRARY: - case SLANG_HOST_SHARED_LIBRARY: + case SLANG_SHADER_SHARED_LIBRARY: + case SLANG_HOST_SHARED_LIBRARY: { // Shared library cmdLine.addArg("-shared"); @@ -572,18 +608,18 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS } break; } - case SLANG_HOST_EXECUTABLE: + case SLANG_HOST_EXECUTABLE: { cmdLine.addArg("-rdynamic"); break; } - case SLANG_OBJECT_CODE: + case SLANG_OBJECT_CODE: { // Don't link, just produce object file cmdLine.addArg("-c"); break; } - default: break; + default: break; } // Add defines @@ -611,8 +647,8 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // Link options if (0) // && options.targetType != TargetType::Object) { - //linkOptions << "-Wl,"; - //cmdLine.addArg(linkOptions); + // linkOptions << "-Wl,"; + // cmdLine.addArg(linkOptions); } if (options.targetType == SLANG_SHADER_SHARED_LIBRARY) @@ -632,7 +668,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS { ComPtr<IOSFileArtifactRepresentation> fileRep; - // TODO(JS): + // TODO(JS): // Do we want to keep the file on the file system? It's probably reasonable to do so. SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); cmdLine.addArg(fileRep->getPath()); @@ -640,10 +676,9 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // Add the library paths - if (options.libraryPaths.count && - (options.targetType == SLANG_HOST_EXECUTABLE)) + if (options.libraryPaths.count && (options.targetType == SLANG_HOST_EXECUTABLE)) { - if(PlatformUtil::isFamily(PlatformFamily::Apple, platformKind)) + if (PlatformUtil::isFamily(PlatformFamily::Apple, platformKind)) cmdLine.addArg("-Wl,-rpath,@loader_path,-rpath,@loader_path/../lib"); else cmdLine.addArg("-Wl,-rpath,$ORIGIN,-rpath,$ORIGIN/../lib"); @@ -661,7 +696,8 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS { const auto artifactDesc = artifact->getDesc(); // If it's a library for CPU types, try and use it - if (ArtifactDescUtil::isCpuBinary(artifactDesc) && artifactDesc.kind == ArtifactKind::Library) + if (ArtifactDescUtil::isCpuBinary(artifactDesc) && + artifactDesc.kind == ArtifactKind::Library) { ComPtr<IOSFileArtifactRepresentation> fileRep; @@ -670,12 +706,15 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS const UnownedStringSlice path(fileRep->getPath()); libPathPool.add(Path::getParentDirectory(path)); - - cmdLine.addPrefixPathArg("-l", ArtifactDescUtil::getBaseNameFromPath(artifact->getDesc(), path)); + + cmdLine.addPrefixPathArg( + "-l", + ArtifactDescUtil::getBaseNameFromPath(artifact->getDesc(), path)); } } - if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP && !PlatformUtil::isFamily(PlatformFamily::Windows, platformKind)) + if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP && + !PlatformUtil::isFamily(PlatformFamily::Windows, platformKind)) { // Make STD libs available cmdLine.addArg("-lstdc++"); @@ -695,7 +734,9 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::createCompiler(const ExecutableLocation& exe, ComPtr<IDownstreamCompiler>& outCompiler) +/* static */ SlangResult GCCDownstreamCompilerUtil::createCompiler( + const ExecutableLocation& exe, + ComPtr<IDownstreamCompiler>& outCompiler) { DownstreamCompilerDesc desc; SLANG_RETURN_ON_FAIL(GCCDownstreamCompilerUtil::calcVersion(exe, desc)); @@ -708,7 +749,10 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::locateGCCCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult GCCDownstreamCompilerUtil::locateGCCCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(loader); @@ -717,10 +761,10 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS { // A downstream compiler for Slang must currently support C++17 - such that // the prelude and generated code works. - // + // // The first version of gcc that supports stable `-std=c++17` is 9.0 // https://gcc.gnu.org/projects/cxx-status.html - + auto desc = compiler->getDesc(); if (desc.version.m_major < 9) { @@ -733,7 +777,10 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::locateClangCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult GCCDownstreamCompilerUtil::locateClangCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(loader); @@ -745,4 +792,4 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-gcc-compiler-util.h b/source/compiler-core/slang-gcc-compiler-util.h index 6afb39ec6..e15701f94 100644 --- a/source/compiler-core/slang-gcc-compiler-util.h +++ b/source/compiler-core/slang-gcc-compiler-util.h @@ -9,30 +9,46 @@ namespace Slang /* Utility for processing input and output of gcc-like compilers, including clang */ struct GCCDownstreamCompilerUtil : public DownstreamCompilerUtilBase { - /// Extracts version number into desc from text (assumes gcc/clang -v layout with a line with version) - static SlangResult parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompilerDesc& outDesc); + /// Extracts version number into desc from text (assumes gcc/clang -v layout with a line with + /// version) + static SlangResult parseVersion( + const UnownedStringSlice& text, + const UnownedStringSlice& prefix, + DownstreamCompilerDesc& outDesc); - /// Runs the exe, and extracts the version info into outDesc + /// Runs the exe, and extracts the version info into outDesc static SlangResult calcVersion(const ExecutableLocation& exe, DownstreamCompilerDesc& outDesc); - /// Calculate gcc family compilers (including clang) cmdLine arguments from options + /// Calculate gcc family compilers (including clang) cmdLine arguments from options static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine); - /// Parse ExecuteResult into diagnostics + /// Parse ExecuteResult into diagnostics static SlangResult parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* diagnostics); - /// Given options, calculate paths to products/files produced for a compilation - static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts); + /// Given options, calculate paths to products/files produced for a compilation + static SlangResult calcCompileProducts( + const CompileOptions& options, + ProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List<ComPtr<IArtifact>>& outArtifacts); - /// Given the exe location, creates a DownstreamCompiler. - /// Note! Invoke/s the compiler to determine the compiler version number. - static SlangResult createCompiler(const ExecutableLocation& exe, ComPtr<IDownstreamCompiler>& outCompiler); + /// Given the exe location, creates a DownstreamCompiler. + /// Note! Invoke/s the compiler to determine the compiler version number. + static SlangResult createCompiler( + const ExecutableLocation& exe, + ComPtr<IDownstreamCompiler>& outCompiler); - /// Finds GCC compiler/s and adds them to the set - static SlangResult locateGCCCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + /// Finds GCC compiler/s and adds them to the set + static SlangResult locateGCCCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); - /// Finds clang compiler/s and adds them to the set - static SlangResult locateClangCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + /// Finds clang compiler/s and adds them to the set + static SlangResult locateClangCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; class GCCDownstreamCompiler : public CommandLineDownstreamCompiler @@ -42,13 +58,31 @@ public: typedef GCCDownstreamCompilerUtil Util; // CommandLineCPPCompiler impl - just forwards to the Util - virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } - virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE { return Util::parseOutput(exeResult, diagnostics); } - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, IOSFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts) SLANG_OVERRIDE { return Util::calcCompileProducts(options, flags, lockFile, outArtifacts); } + virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE + { + return Util::calcArgs(options, cmdLine); + } + virtual SlangResult parseOutput( + const ExecuteResult& exeResult, + IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE + { + return Util::parseOutput(exeResult, diagnostics); + } + virtual SlangResult calcCompileProducts( + const CompileOptions& options, + DownstreamProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List<ComPtr<IArtifact>>& outArtifacts) SLANG_OVERRIDE + { + return Util::calcCompileProducts(options, flags, lockFile, outArtifacts); + } - GCCDownstreamCompiler(const Desc& desc):Super(desc) {} + GCCDownstreamCompiler(const Desc& desc) + : Super(desc) + { + } }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp index 54635873a..fd80c7581 100644 --- a/source/compiler-core/slang-glslang-compiler.cpp +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -1,35 +1,28 @@ // slang-glslang-compiler.cpp #include "slang-glslang-compiler.h" -#include "../core/slang-common.h" -#include "slang-com-helper.h" - #include "../core/slang-blob.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-string-slice-pool.h" - +#include "../core/slang-char-util.h" +#include "../core/slang-common.h" #include "../core/slang-io.h" -#include "../core/slang-shared-library.h" #include "../core/slang-semantic-version.h" -#include "../core/slang-char-util.h" - +#include "../core/slang-shared-library.h" +#include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" #include "slang-artifact-associated-impl.h" #include "slang-artifact-desc-util.h" - +#include "slang-com-helper.h" #include "slang-include-system.h" #include "slang-source-loc.h" -#include "../core/slang-shared-library.h" - // Enable calling through to `glslang` on // all platforms. #ifndef SLANG_ENABLE_GLSLANG_SUPPORT -# define SLANG_ENABLE_GLSLANG_SUPPORT 1 +#define SLANG_ENABLE_GLSLANG_SUPPORT 1 #endif #if SLANG_ENABLE_GLSLANG_SUPPORT -# include "../slang-glslang/slang-glslang.h" +#include "../slang-glslang/slang-glslang.h" #endif namespace Slang @@ -43,24 +36,31 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE; - /// Must be called before use + /// Must be called before use SlangResult init(ISlangSharedLibrary* library); - GlslangDownstreamCompiler(SlangPassThrough compilerType) : m_compilerType(compilerType) {} - -protected: + GlslangDownstreamCompiler(SlangPassThrough compilerType) + : m_compilerType(compilerType) + { + } +protected: SlangResult _invoke(glslang_CompileRequest_1_2& request); - glslang_CompileFunc_1_0 m_compile_1_0 = nullptr; - glslang_CompileFunc_1_1 m_compile_1_1 = nullptr; + glslang_CompileFunc_1_0 m_compile_1_0 = nullptr; + glslang_CompileFunc_1_1 m_compile_1_1 = nullptr; glslang_CompileFunc_1_2 m_compile_1_2 = nullptr; glslang_ValidateSPIRVFunc m_validate = nullptr; @@ -135,7 +135,11 @@ SlangResult GlslangDownstreamCompiler::_invoke(glslang_CompileRequest_1_2& reque return err ? SLANG_FAIL : SLANG_OK; } -static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List<UnownedStringSlice>& lineSlices, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + List<UnownedStringSlice>& lineSlices, + ArtifactDiagnostic& outDiagnostic) { /* ERROR: tests/diagnostics/syntax-error-intrinsic.slang:13: '@' : unexpected token */ @@ -160,7 +164,9 @@ static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const Unowned return SLANG_OK; } -SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& inOptions, IArtifact** outArtifact) +SlangResult GlslangDownstreamCompiler::compile( + const CompileOptions& inOptions, + IArtifact** outArtifact) { if (!isVersionCompatible(inOptions)) { @@ -186,14 +192,10 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& inOptions, StringBuilder diagnosticOutput; auto diagnosticOutputFunc = [](void const* data, size_t size, void* userData) - { - (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); - }; + { (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); }; List<uint8_t> spirv; auto outputFunc = [](void const* data, size_t size, void* userData) - { - ((List<uint8_t>*)userData)->addRange((uint8_t*)data, size); - }; + { ((List<uint8_t>*)userData)->addRange((uint8_t*)data, size); }; ComPtr<ISlangBlob> sourceBlob; SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef())); @@ -206,15 +208,9 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& inOptions, switch (options.sourceLanguage) { - case SLANG_SOURCE_LANGUAGE_GLSL: - request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV; - break; - case SLANG_SOURCE_LANGUAGE_SPIRV: - request.action = GLSLANG_ACTION_OPTIMIZE_SPIRV; - break; - default: - SLANG_ASSERT(!"Can only handle GLSL or SPIR-V as input."); - return SLANG_FAIL; + case SLANG_SOURCE_LANGUAGE_GLSL: request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV; break; + case SLANG_SOURCE_LANGUAGE_SPIRV: request.action = GLSLANG_ACTION_OPTIMIZE_SPIRV; break; + default: SLANG_ASSERT(!"Can only handle GLSL or SPIR-V as input."); return SLANG_FAIL; } request.sourcePath = sourcePath.getBuffer(); @@ -270,7 +266,12 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& inOptions, SliceAllocator allocator; - SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(allocator, diagnosticOutput.getUnownedSlice(), 1, _parseDiagnosticLine, diagnostics); + SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics( + allocator, + diagnosticOutput.getUnownedSlice(), + 1, + _parseDiagnosticLine, + diagnostics); SLANG_UNUSED(diagnosticParseRes); diagnostics->requireErrorDiagnostic(); @@ -301,12 +302,15 @@ SlangResult GlslangDownstreamCompiler::validate(const uint32_t* contents, int co bool GlslangDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) { // Can only disassemble blobs that are SPIR-V - return ArtifactDescUtil::isDisassembly(from, to) && ( - (from.payload == ArtifactPayload::SPIRV) || - (from.payload == ArtifactPayload::WGSL_SPIRV)); + return ArtifactDescUtil::isDisassembly(from, to) && + ((from.payload == ArtifactPayload::SPIRV) || + (from.payload == ArtifactPayload::WGSL_SPIRV)); } -SlangResult GlslangDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult GlslangDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { if (!canConvert(from->getDesc(), to)) { @@ -317,11 +321,9 @@ SlangResult GlslangDownstreamCompiler::convert(IArtifact* from, const ArtifactDe SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::No, blob.writeRef())); StringBuilder builder; - + auto outputFunc = [](void const* data, size_t size, void* userData) - { - (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); - }; + { (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); }; glslang_CompileRequest_1_2 request; memset(&request, 0, sizeof(request)); @@ -366,14 +368,18 @@ SlangResult GlslangDownstreamCompiler::getVersionString(slang::IBlob** outVersio { return SLANG_FAIL; } - + auto timestampString = String(timestamp); ComPtr<ISlangBlob> version = StringBlob::create(timestampString.getBuffer()); *outVersionString = version.detach(); return SLANG_OK; } -static SlangResult locateGlslangSpirvDownstreamCompiler(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set, SlangPassThrough compilerType) +static SlangResult locateGlslangSpirvDownstreamCompiler( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set, + SlangPassThrough compilerType) { ComPtr<ISlangSharedLibrary> library; @@ -381,18 +387,23 @@ static SlangResult locateGlslangSpirvDownstreamCompiler(const String& path, ISla // On unix systems we need to ensure pthread is loaded first. // TODO(JS): // There is an argument that this should be performed through the loader.... - // NOTE! We don't currently load through a dependent library, as it is *assumed* something as core as 'ptheads' - // isn't going to be distributed with the shader compiler. + // NOTE! We don't currently load through a dependent library, as it is *assumed* something as + // core as 'ptheads' isn't going to be distributed with the shader compiler. ComPtr<ISlangSharedLibrary> pthreadLibrary; DefaultSharedLibraryLoader::load(loader, path, "pthread", pthreadLibrary.writeRef()); if (!pthreadLibrary.get()) { - DefaultSharedLibraryLoader::load(loader, path, "libpthread.so.0", pthreadLibrary.writeRef()); + DefaultSharedLibraryLoader::load( + loader, + path, + "libpthread.so.0", + pthreadLibrary.writeRef()); } #endif - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-glslang", library)); + SLANG_RETURN_ON_FAIL( + DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-glslang", library)); SLANG_ASSERT(library); if (!library) @@ -408,24 +419,36 @@ static SlangResult locateGlslangSpirvDownstreamCompiler(const String& path, ISla return SLANG_OK; } -SlangResult GlslangDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +SlangResult GlslangDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { return locateGlslangSpirvDownstreamCompiler(path, loader, set, SLANG_PASS_THROUGH_GLSLANG); } -SlangResult SpirvOptDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +SlangResult SpirvOptDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { return locateGlslangSpirvDownstreamCompiler(path, loader, set, SLANG_PASS_THROUGH_SPIRV_OPT); } -SlangResult SpirvDisDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +SlangResult SpirvDisDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { return locateGlslangSpirvDownstreamCompiler(path, loader, set, SLANG_PASS_THROUGH_SPIRV_DIS); } #else // SLANG_ENABLE_GLSLANG_SUPPORT -/* static */SlangResult GlslangDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult GlslangDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(path); SLANG_UNUSED(loader); @@ -435,4 +458,4 @@ SlangResult SpirvDisDownstreamCompilerUtil::locateCompilers(const String& path, #endif // SLANG_ENABLE_GLSLANG_SUPPORT -} +} // namespace Slang diff --git a/source/compiler-core/slang-glslang-compiler.h b/source/compiler-core/slang-glslang-compiler.h index 577bcaacc..73cc61135 100644 --- a/source/compiler-core/slang-glslang-compiler.h +++ b/source/compiler-core/slang-glslang-compiler.h @@ -1,29 +1,37 @@ #ifndef SLANG_GLSLANG_COMPILER_UTIL_H #define SLANG_GLSLANG_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { struct GlslangDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; struct SpirvOptDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; struct SpirvDisDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-include-system.cpp b/source/compiler-core/slang-include-system.cpp index 1b768d506..4ee742136 100644 --- a/source/compiler-core/slang-include-system.cpp +++ b/source/compiler-core/slang-include-system.cpp @@ -1,26 +1,31 @@ // slang-include-system.cpp #include "slang-include-system.h" +#include "../core/slang-file-system.h" #include "../core/slang-io.h" #include "../core/slang-string-util.h" - -#include "../core/slang-file-system.h" - -#include "slang-slice-allocator.h" #include "slang-artifact-impl.h" #include "slang-artifact-representation-impl.h" +#include "slang-slice-allocator.h" namespace Slang { -IncludeSystem::IncludeSystem(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager) : - m_searchDirectories(searchDirectories), - m_fileSystemExt(fileSystemExt), - m_sourceManager(sourceManager) +IncludeSystem::IncludeSystem( + SearchDirectoryList* searchDirectories, + ISlangFileSystemExt* fileSystemExt, + SourceManager* sourceManager) + : m_searchDirectories(searchDirectories) + , m_fileSystemExt(fileSystemExt) + , m_sourceManager(sourceManager) { } -SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fromPath, const String& path, PathInfo& outPathInfo) +SlangResult IncludeSystem::findFile( + SlangPathType fromPathType, + const String& fromPath, + const String& path, + PathInfo& outPathInfo) { String combinedPath; @@ -33,7 +38,11 @@ SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fr { // Get relative path ComPtr<ISlangBlob> combinedPathBlob; - SLANG_RETURN_ON_FAIL(m_fileSystemExt->calcCombinedPath(fromPathType, fromPath.begin(), path.begin(), combinedPathBlob.writeRef())); + SLANG_RETURN_ON_FAIL(m_fileSystemExt->calcCombinedPath( + fromPathType, + fromPath.begin(), + path.begin(), + combinedPathBlob.writeRef())); combinedPath = StringUtil::getString(combinedPathBlob); if (combinedPath.getLength() <= 0) { @@ -51,7 +60,9 @@ SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fr // Get the uniqueIdentity ComPtr<ISlangBlob> uniqueIdentityBlob; - SLANG_RETURN_ON_FAIL(m_fileSystemExt->getFileUniqueIdentity(combinedPath.begin(), uniqueIdentityBlob.writeRef())); + SLANG_RETURN_ON_FAIL(m_fileSystemExt->getFileUniqueIdentity( + combinedPath.begin(), + uniqueIdentityBlob.writeRef())); // If the rel path exists -> a uniqueIdentity MUST exists too String uniqueIdentity(StringUtil::getString(uniqueIdentityBlob)); @@ -68,14 +79,20 @@ SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fr String IncludeSystem::simplifyPath(const String& path) { ComPtr<ISlangBlob> simplifiedPath; - if (SLANG_FAILED(m_fileSystemExt->getPath(PathKind::Simplified, path.getBuffer(), simplifiedPath.writeRef()))) + if (SLANG_FAILED(m_fileSystemExt->getPath( + PathKind::Simplified, + path.getBuffer(), + simplifiedPath.writeRef()))) { return path; } return StringUtil::getString(simplifiedPath); } -SlangResult IncludeSystem::findFile(String const& pathToInclude, String const& pathIncludedFrom, PathInfo& outPathInfo) +SlangResult IncludeSystem::findFile( + String const& pathToInclude, + String const& pathIncludedFrom, + PathInfo& outPathInfo) { outPathInfo.type = PathInfo::Type::Unknown; @@ -84,12 +101,17 @@ SlangResult IncludeSystem::findFile(String const& pathToInclude, String const& p { // We pass in "" as the from path, so ensure no from path is taken into account // and to allow easy identification that this is in effect absolute - return findFile(SLANG_PATH_TYPE_DIRECTORY, UnownedStringSlice::fromLiteral(""), pathToInclude, outPathInfo); + return findFile( + SLANG_PATH_TYPE_DIRECTORY, + UnownedStringSlice::fromLiteral(""), + pathToInclude, + outPathInfo); } // Try just relative to current path { - SlangResult res = findFile(SLANG_PATH_TYPE_FILE, pathIncludedFrom, pathToInclude, outPathInfo); + SlangResult res = + findFile(SLANG_PATH_TYPE_FILE, pathIncludedFrom, pathToInclude, outPathInfo); // It either succeeded or wasn't found, anything else is a failure passed back if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND) { @@ -102,7 +124,8 @@ SlangResult IncludeSystem::findFile(String const& pathToInclude, String const& p { for (auto& dir : sd->searchDirectories) { - SlangResult res = findFile(SLANG_PATH_TYPE_DIRECTORY, dir.path, pathToInclude, outPathInfo); + SlangResult res = + findFile(SLANG_PATH_TYPE_DIRECTORY, dir.path, pathToInclude, outPathInfo); if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND) { return res; @@ -113,7 +136,10 @@ SlangResult IncludeSystem::findFile(String const& pathToInclude, String const& p return SLANG_E_NOT_FOUND; } -SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob>& outBlob, SourceFile*& outSourceFile) +SlangResult IncludeSystem::loadFile( + const PathInfo& pathInfo, + ComPtr<ISlangBlob>& outBlob, + SourceFile*& outSourceFile) { if (m_sourceManager) { @@ -124,7 +150,9 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob> if (!outSourceFile) { ComPtr<ISlangBlob> foundSourceBlob; - if (SLANG_FAILED(m_fileSystemExt->loadFile(pathInfo.foundPath.getBuffer(), foundSourceBlob.writeRef()))) + if (SLANG_FAILED(m_fileSystemExt->loadFile( + pathInfo.foundPath.getBuffer(), + foundSourceBlob.writeRef()))) { return SLANG_E_CANNOT_OPEN; } @@ -144,7 +172,9 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob> } ComPtr<ISlangBlob> foundSourceBlob; - if (SLANG_FAILED(m_fileSystemExt->loadFile(pathInfo.foundPath.getBuffer(), foundSourceBlob.writeRef()))) + if (SLANG_FAILED(m_fileSystemExt->loadFile( + pathInfo.foundPath.getBuffer(), + foundSourceBlob.writeRef()))) { return SLANG_E_CANNOT_OPEN; } @@ -163,7 +193,11 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob> } } -SlangResult IncludeSystem::findAndLoadFile(const String& pathToInclude, const String& pathIncludedFrom, PathInfo& outPathInfo, ComPtr<ISlangBlob>& outBlob) +SlangResult IncludeSystem::findAndLoadFile( + const String& pathToInclude, + const String& pathIncludedFrom, + PathInfo& outPathInfo, + ComPtr<ISlangBlob>& outBlob) { SLANG_RETURN_ON_FAIL(findFile(pathToInclude, pathIncludedFrom, outPathInfo)); SLANG_RETURN_ON_FAIL(loadFile(outPathInfo, outBlob)); diff --git a/source/compiler-core/slang-include-system.h b/source/compiler-core/slang-include-system.h index cc89985dd..dbe3793bf 100644 --- a/source/compiler-core/slang-include-system.h +++ b/source/compiler-core/slang-include-system.h @@ -14,7 +14,8 @@ struct SearchDirectory SearchDirectory(SearchDirectory const& other) = default; SearchDirectory(String const& path) : path(path) - {} + { + } SearchDirectory& operator=(SearchDirectory const& other) = default; String path; @@ -24,42 +25,60 @@ struct SearchDirectory struct SearchDirectoryList { // A parent list that should also be searched - SearchDirectoryList* parent = nullptr; + SearchDirectoryList* parent = nullptr; // Directories to be searched - List<SearchDirectory> searchDirectories; + List<SearchDirectory> searchDirectories; }; -/* A helper class that builds basic include handling on top of searchDirectories/fileSystemExt and optionally a sourceManager */ +/* A helper class that builds basic include handling on top of searchDirectories/fileSystemExt and + * optionally a sourceManager */ struct IncludeSystem { - SlangResult findFile(const String& pathToInclude, const String& pathIncludedFrom, PathInfo& outPathInfo); - SlangResult findFile(SlangPathType fromPathType, const String& fromPath, const String& path, PathInfo& outPathInfo); + SlangResult findFile( + const String& pathToInclude, + const String& pathIncludedFrom, + PathInfo& outPathInfo); + SlangResult findFile( + SlangPathType fromPathType, + const String& fromPath, + const String& path, + PathInfo& outPathInfo); String simplifyPath(const String& path); - SlangResult loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob>& outBlob, SourceFile*& outSourceFile); + SlangResult loadFile( + const PathInfo& pathInfo, + ComPtr<ISlangBlob>& outBlob, + SourceFile*& outSourceFile); inline SlangResult loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob>& outBlob) { SourceFile* sourceFile; return loadFile(pathInfo, outBlob, sourceFile); } - SlangResult findAndLoadFile(const String& pathToInclude, const String& pathIncludedFrom, PathInfo& outPathInfo, ComPtr<ISlangBlob>& outBlob); + SlangResult findAndLoadFile( + const String& pathToInclude, + const String& pathIncludedFrom, + PathInfo& outPathInfo, + ComPtr<ISlangBlob>& outBlob); SearchDirectoryList* getSearchDirectoryList() const { return m_searchDirectories; } ISlangFileSystemExt* getFileSystem() const { return m_fileSystemExt; } SourceManager* getSourceManager() const { return m_sourceManager; } - /// Ctor + /// Ctor IncludeSystem() = default; - IncludeSystem(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager = nullptr); + IncludeSystem( + SearchDirectoryList* searchDirectories, + ISlangFileSystemExt* fileSystemExt, + SourceManager* sourceManager = nullptr); protected: - SearchDirectoryList* m_searchDirectories; ISlangFileSystemExt* m_fileSystemExt; - SourceManager* m_sourceManager; ///< If not set, will not look up the content in the source manager + SourceManager* + m_sourceManager; ///< If not set, will not look up the content in the source manager }; -} +} // namespace Slang -#endif // SLANG_INCLUDE_HANDLER_H +#endif // SLANG_INCLUDE_HANDLER_H diff --git a/source/compiler-core/slang-json-diagnostic-defs.h b/source/compiler-core/slang-json-diagnostic-defs.h index 576f14beb..2bc4c6a81 100644 --- a/source/compiler-core/slang-json-diagnostic-defs.h +++ b/source/compiler-core/slang-json-diagnostic-defs.h @@ -14,7 +14,7 @@ // for any arguments. #ifndef DIAGNOSTIC -#error Need to #define DIAGNOSTIC(...) before including +#error Need to #define DIAGNOSTIC(...) before including #define DIAGNOSTIC(id, severity, name, messageFormat) /* */ #endif @@ -40,7 +40,11 @@ DIAGNOSTIC(20009, Error, unableToConvertField, "unable to convert field '$0' in DIAGNOSTIC(20010, Error, fieldNotFound, "field '$0' not found in type '$1'") DIAGNOSTIC(20011, Error, fieldNotDefinedOnType, "field '$0' not defined on type '$1'") DIAGNOSTIC(20011, Error, fieldRequiredOnType, "field '$0' required on '$1'") -DIAGNOSTIC(20012, Error, tooManyElementsForArray, "too many elements ($0) for array array. Max allowed is $1") +DIAGNOSTIC( + 20012, + Error, + tooManyElementsForArray, + "too many elements ($0) for array array. Max allowed is $1") // // 3xxxx JSON-RPC diff --git a/source/compiler-core/slang-json-diagnostics.cpp b/source/compiler-core/slang-json-diagnostics.cpp index 1d35e8faf..1dc30572e 100644 --- a/source/compiler-core/slang-json-diagnostics.cpp +++ b/source/compiler-core/slang-json-diagnostics.cpp @@ -1,18 +1,19 @@ // slang-json-diagnostics.cpp #include "slang-json-diagnostics.h" -namespace Slang { +namespace Slang +{ namespace JSONDiagnostics { -#define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, #name, messageFormat }; +#define DIAGNOSTIC(id, severity, name, messageFormat) \ + const DiagnosticInfo name = {id, Severity::severity, #name, messageFormat}; #include "slang-json-diagnostic-defs.h" #undef DIAGNOSTIC -} +} // namespace JSONDiagnostics -static const DiagnosticInfo* const kJSONDiagnostics[] = -{ -#define DIAGNOSTIC(id, severity, name, messageFormat) &JSONDiagnostics::name, +static const DiagnosticInfo* const kJSONDiagnostics[] = { +#define DIAGNOSTIC(id, severity, name, messageFormat) &JSONDiagnostics::name, #include "slang-json-diagnostic-defs.h" #undef DIAGNOSTIC }; diff --git a/source/compiler-core/slang-json-diagnostics.h b/source/compiler-core/slang-json-diagnostics.h index d819d8947..183178d2b 100644 --- a/source/compiler-core/slang-json-diagnostics.h +++ b/source/compiler-core/slang-json-diagnostics.h @@ -3,11 +3,9 @@ #include "../core/slang-basic.h" #include "../core/slang-writer.h" - -#include "slang-source-loc.h" #include "slang-diagnostic-sink.h" +#include "slang-source-loc.h" #include "slang-token.h" - #include "slang.h" namespace Slang @@ -19,8 +17,8 @@ namespace JSONDiagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) extern const DiagnosticInfo name; #include "slang-json-diagnostic-defs.h" -} +} // namespace JSONDiagnostics -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-json-lexer.cpp b/source/compiler-core/slang-json-lexer.cpp index a335403e1..84b6b24bc 100644 --- a/source/compiler-core/slang-json-lexer.cpp +++ b/source/compiler-core/slang-json-lexer.cpp @@ -1,16 +1,17 @@ // slang-json-lexer.cpp #include "slang-json-lexer.h" -#include "slang-json-diagnostics.h" #include "../core/slang-char-util.h" +#include "slang-json-diagnostics.h" /* https://www.json.org/json-en.html */ -namespace Slang { +namespace Slang +{ -/* static */UnownedStringSlice JSONLexer::calcLexemeLocation(const UnownedStringSlice& text) +/* static */ UnownedStringSlice JSONLexer::calcLexemeLocation(const UnownedStringSlice& text) { SourceManager sourceManager; sourceManager.initialize(nullptr, nullptr); @@ -18,7 +19,8 @@ namespace Slang { sink.init(&sourceManager, nullptr); String contents(text); - SourceFile* sourceFile = sourceManager.createSourceFileWithString(PathInfo::makeUnknown(), contents); + SourceFile* sourceFile = + sourceManager.createSourceFileWithString(PathInfo::makeUnknown(), contents); SourceView* sourceView = sourceManager.createSourceView(sourceFile, nullptr, SourceLoc()); JSONLexer lexer; @@ -38,7 +40,7 @@ namespace Slang { } } -SlangResult JSONLexer::init(SourceView* sourceView, DiagnosticSink* sink) +SlangResult JSONLexer::init(SourceView* sourceView, DiagnosticSink* sink) { m_sourceView = sourceView; m_sink = sink; @@ -77,7 +79,11 @@ SlangResult JSONLexer::expect(JSONTokenType type) { if (type != peekType()) { - m_sink->diagnose(m_token.loc, JSONDiagnostics::unexpectedTokenExpectedTokenType, getJSONTokenAsText(peekType()), getJSONTokenAsText(type)); + m_sink->diagnose( + m_token.loc, + JSONDiagnostics::unexpectedTokenExpectedTokenType, + getJSONTokenAsText(peekType()), + getJSONTokenAsText(type)); return SLANG_FAIL; } @@ -89,7 +95,11 @@ SlangResult JSONLexer::expect(JSONTokenType type, JSONToken& out) { if (type != peekType()) { - m_sink->diagnose(m_token.loc, JSONDiagnostics::unexpectedTokenExpectedTokenType, getJSONTokenAsText(peekType()), getJSONTokenAsText(type)); + m_sink->diagnose( + m_token.loc, + JSONDiagnostics::unexpectedTokenExpectedTokenType, + getJSONTokenAsText(peekType()), + getJSONTokenAsText(type)); return SLANG_FAIL; } @@ -137,8 +147,8 @@ JSONTokenType JSONLexer::advance() switch (c) { - case 0: return _setToken(JSONTokenType::EndOfFile, cursor - 1); - case '"': + case 0: return _setToken(JSONTokenType::EndOfFile, cursor - 1); + case '"': { cursor = _lexString(cursor); if (cursor == nullptr) @@ -147,7 +157,7 @@ JSONTokenType JSONLexer::advance() } return _setToken(JSONTokenType::StringLiteral, cursor); } - case '/': + case '/': { // We allow comments const char nextChar = *m_cursor; @@ -160,7 +170,7 @@ JSONTokenType JSONLexer::advance() else if (nextChar == '*') { cursor = _lexBlockComment(cursor); - // Can fail... + // Can fail... if (cursor == nullptr) { return _setInvalidToken(); @@ -172,32 +182,32 @@ JSONTokenType JSONLexer::advance() } break; } - case ' ': - case '\t': - case '\n': - case '\r': + case ' ': + case '\t': + case '\n': + case '\r': { cursor = _lexWhitespace(cursor); break; } - case ':': return _setToken(JSONTokenType::Colon, cursor); - case ',': return _setToken(JSONTokenType::Comma, cursor); - case '[': return _setToken(JSONTokenType::LBracket, cursor); - case ']': return _setToken(JSONTokenType::RBracket, cursor); - case '{': return _setToken(JSONTokenType::LBrace, cursor); - case '}': return _setToken(JSONTokenType::RBrace, cursor); - - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': + case ':': return _setToken(JSONTokenType::Colon, cursor); + case ',': return _setToken(JSONTokenType::Comma, cursor); + case '[': return _setToken(JSONTokenType::LBracket, cursor); + case ']': return _setToken(JSONTokenType::RBracket, cursor); + case '{': return _setToken(JSONTokenType::LBrace, cursor); + case '}': return _setToken(JSONTokenType::RBrace, cursor); + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { LexResult res = _lexNumber(cursor - 1); if (res.cursor == nullptr) @@ -206,7 +216,7 @@ JSONTokenType JSONLexer::advance() } return _setToken(res.type, res.cursor); } - case 't': + case 't': { if (cursor[0] == 'r' && cursor[1] == 'u' && cursor[2] == 'e') { @@ -215,7 +225,7 @@ JSONTokenType JSONLexer::advance() m_sink->diagnose(_getLoc(m_lexemeStart), JSONDiagnostics::expectingValueName); return _setInvalidToken(); } - case 'f': + case 'f': { if (cursor[0] == 'a' && cursor[1] == 'l' && cursor[2] == 's' && cursor[3] == 'e') { @@ -224,7 +234,7 @@ JSONTokenType JSONLexer::advance() m_sink->diagnose(_getLoc(m_lexemeStart), JSONDiagnostics::expectingValueName); return _setInvalidToken(); } - case 'n': + case 'n': { if (cursor[0] == 'u' && cursor[1] == 'l' && cursor[2] == 'l') { @@ -233,7 +243,7 @@ JSONTokenType JSONLexer::advance() m_sink->diagnose(_getLoc(m_lexemeStart), JSONDiagnostics::expectingValueName); return _setInvalidToken(); } - default: + default: { StringBuilder buf; if (c <= ' ' || c >= 0x7e) @@ -241,7 +251,7 @@ JSONTokenType JSONLexer::advance() static const char s_hex[] = "0123456789abcdef"; char hexBuf[5] = "0x"; - + uint32_t value = c; hexBuf[2] = s_hex[((value >> 4) & 0xf)]; hexBuf[3] = s_hex[(value & 0xf)]; @@ -294,12 +304,13 @@ JSONLexer::LexResult JSONLexer::_lexNumber(const char* cursor) if (!CharUtil::isDigit(*cursor)) { m_sink->diagnose(_getLoc(cursor), JSONDiagnostics::expectingADigit); - return LexResult{ JSONTokenType::Invalid, nullptr }; + return LexResult{JSONTokenType::Invalid, nullptr}; } // Skip the digit cursor++; // Skip any more digits - while (CharUtil::isDigit(*cursor)) cursor++; + while (CharUtil::isDigit(*cursor)) + cursor++; } // Theres an exponent @@ -320,13 +331,14 @@ JSONLexer::LexResult JSONLexer::_lexNumber(const char* cursor) if (!CharUtil::isDigit(*cursor)) { m_sink->diagnose(_getLoc(cursor), JSONDiagnostics::expectingADigit); - return LexResult{ JSONTokenType::Invalid, nullptr }; + return LexResult{JSONTokenType::Invalid, nullptr}; } // Skip the digit cursor++; // Skip any more digits - while (CharUtil::isDigit(*cursor)) cursor++; + while (CharUtil::isDigit(*cursor)) + cursor++; } return LexResult{tokenType, cursor}; @@ -341,40 +353,42 @@ const char* JSONLexer::_lexString(const char* cursor) switch (c) { - case 0: + case 0: { m_sink->diagnose(_getLoc(cursor - 1), JSONDiagnostics::endOfFileInLiteral); return nullptr; } - case '"': + case '"': { return cursor; } - case '\\': + case '\\': { const char nextC = *cursor; switch (nextC) { - case '"': - case '\\': - case '/': - case 'b': - case 'f': - case 'n': - case 'r': - case 't': + case '"': + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': { ++cursor; break; } - case 'u': + case 'u': { cursor++; for (Index i = 0; i < 4; ++i) { if (!CharUtil::isHexDigit(cursor[i])) { - m_sink->diagnose(_getLoc(cursor), JSONDiagnostics::expectingAHexDigit); + m_sink->diagnose( + _getLoc(cursor), + JSONDiagnostics::expectingAHexDigit); return nullptr; } } @@ -382,10 +396,9 @@ const char* JSONLexer::_lexString(const char* cursor) break; } } - } - // Somewhat surprisingly it appears it's valid to have \r\n inside of quotes. - default: break; + // Somewhat surprisingly it appears it's valid to have \r\n inside of quotes. + default: break; } } } @@ -398,13 +411,13 @@ const char* JSONLexer::_lexLineComment(const char* cursor) switch (c) { - case '\n': - case '\r': + case '\n': + case '\r': { // We need to skip to the next line return _handleEndOfLine(c, cursor); } - case 0: + case 0: { return cursor - 1; } @@ -419,12 +432,12 @@ const char* JSONLexer::_lexBlockComment(const char* cursor) const char c = *cursor++; switch (c) { - case 0: + case 0: { m_sink->diagnose(_getLoc(cursor), JSONDiagnostics::endOfFileInComment); return nullptr; } - case '*': + case '*': { if (*cursor == '/') { @@ -432,7 +445,7 @@ const char* JSONLexer::_lexBlockComment(const char* cursor) } break; } - default: break; + default: break; } } } @@ -447,21 +460,20 @@ const char* JSONLexer::_lexWhitespace(const char* cursor) switch (c) { - case ' ': - case '\n': - case '\r': - case '\t': + case ' ': + case '\n': + case '\r': + case '\t': { cursor++; break; } - default: + default: { // Hit non white space return cursor; } } - } } @@ -469,21 +481,21 @@ UnownedStringSlice getJSONTokenAsText(JSONTokenType type) { switch (type) { - case JSONTokenType::Invalid: return UnownedStringSlice::fromLiteral("invalid"); - case JSONTokenType::IntegerLiteral: return UnownedStringSlice::fromLiteral("integer literal"); - case JSONTokenType::FloatLiteral: return UnownedStringSlice::fromLiteral("float literal"); - case JSONTokenType::StringLiteral: return UnownedStringSlice::fromLiteral("string literal"); - case JSONTokenType::LBracket: return UnownedStringSlice::fromLiteral("["); - case JSONTokenType::RBracket: return UnownedStringSlice::fromLiteral("]"); - case JSONTokenType::LBrace: return UnownedStringSlice::fromLiteral("{"); - case JSONTokenType::RBrace: return UnownedStringSlice::fromLiteral("}"); - case JSONTokenType::Comma: return UnownedStringSlice::fromLiteral(","); - case JSONTokenType::Colon: return UnownedStringSlice::fromLiteral(":"); - case JSONTokenType::True: return UnownedStringSlice::fromLiteral("true"); - case JSONTokenType::False: return UnownedStringSlice::fromLiteral("false"); - case JSONTokenType::Null: return UnownedStringSlice::fromLiteral("null"); - case JSONTokenType::EndOfFile: return UnownedStringSlice::fromLiteral("end of file"); - default: break; + case JSONTokenType::Invalid: return UnownedStringSlice::fromLiteral("invalid"); + case JSONTokenType::IntegerLiteral: return UnownedStringSlice::fromLiteral("integer literal"); + case JSONTokenType::FloatLiteral: return UnownedStringSlice::fromLiteral("float literal"); + case JSONTokenType::StringLiteral: return UnownedStringSlice::fromLiteral("string literal"); + case JSONTokenType::LBracket: return UnownedStringSlice::fromLiteral("["); + case JSONTokenType::RBracket: return UnownedStringSlice::fromLiteral("]"); + case JSONTokenType::LBrace: return UnownedStringSlice::fromLiteral("{"); + case JSONTokenType::RBrace: return UnownedStringSlice::fromLiteral("}"); + case JSONTokenType::Comma: return UnownedStringSlice::fromLiteral(","); + case JSONTokenType::Colon: return UnownedStringSlice::fromLiteral(":"); + case JSONTokenType::True: return UnownedStringSlice::fromLiteral("true"); + case JSONTokenType::False: return UnownedStringSlice::fromLiteral("false"); + case JSONTokenType::Null: return UnownedStringSlice::fromLiteral("null"); + case JSONTokenType::EndOfFile: return UnownedStringSlice::fromLiteral("end of file"); + default: break; } SLANG_UNEXPECTED("JSONTokenType not known"); } diff --git a/source/compiler-core/slang-json-lexer.h b/source/compiler-core/slang-json-lexer.h index 6e4a42a32..cee97ae04 100644 --- a/source/compiler-core/slang-json-lexer.h +++ b/source/compiler-core/slang-json-lexer.h @@ -3,11 +3,11 @@ #define SLANG_JSON_LEXER_H #include "../core/slang-basic.h" - -#include "slang-source-loc.h" #include "slang-diagnostic-sink.h" +#include "slang-source-loc.h" -namespace Slang { +namespace Slang +{ enum class JSONTokenType { @@ -30,9 +30,9 @@ enum class JSONTokenType struct JSONToken { - JSONTokenType type; ///< The token type - SourceLoc loc; ///< Location in the source file - uint32_t length; ///< The length of the token in bytes + JSONTokenType type; ///< The token type + SourceLoc loc; ///< Location in the source file + uint32_t length; ///< The length of the token in bytes }; UnownedStringSlice getJSONTokenAsText(JSONTokenType type); @@ -40,33 +40,34 @@ UnownedStringSlice getJSONTokenAsText(JSONTokenType type); class JSONLexer { public: - /// Peek the current token + /// Peek the current token JSONToken& peekToken() { return m_token; } - /// Peek the current type + /// Peek the current type JSONTokenType peekType() { return m_token.type; } - /// Peek the current SourceLoc + /// Peek the current SourceLoc SourceLoc peekLoc() { return m_token.loc; } - /// Get the lexeme of JSONToken + /// Get the lexeme of JSONToken UnownedStringSlice getLexeme(const JSONToken& tok) const; - /// Peek the lexeme at the current position + /// Peek the lexeme at the current position UnownedStringSlice peekLexeme() const { return getLexeme(m_token); } - + JSONTokenType advance(); - /// Expects a token of type type. If found advances, if not returns an error and outputs to diagnostic sink + /// Expects a token of type type. If found advances, if not returns an error and outputs to + /// diagnostic sink SlangResult expect(JSONTokenType type); - /// Same as expect except out will hold the token. + /// Same as expect except out will hold the token. SlangResult expect(JSONTokenType type, JSONToken& out); - /// Returns true and advances if current token is type + /// Returns true and advances if current token is type bool advanceIf(JSONTokenType type); bool advanceIf(JSONTokenType type, JSONToken& out); - /// Must be called before use + /// Must be called before use SlangResult init(SourceView* sourceView, DiagnosticSink* sink); - /// Determines the first token from text. Useful for diagnostics on DiagnosticSink + /// Determines the first token from text. Useful for diagnostics on DiagnosticSink static UnownedStringSlice calcLexemeLocation(const UnownedStringSlice& text); protected: @@ -76,8 +77,11 @@ protected: const char* cursor; }; - /// Get the location of the cursor - SLANG_FORCE_INLINE SourceLoc _getLoc(const char* cursor) const { return m_startLoc + (cursor - m_contentStart); } + /// Get the location of the cursor + SLANG_FORCE_INLINE SourceLoc _getLoc(const char* cursor) const + { + return m_startLoc + (cursor - m_contentStart); + } const char* _lexLineComment(const char* cursor); const char* _lexBlockComment(const char* cursor); const char* _lexWhitespace(const char* cursor); diff --git a/source/compiler-core/slang-json-native.cpp b/source/compiler-core/slang-json-native.cpp index eb0f7d9ee..e4b425801 100644 --- a/source/compiler-core/slang-json-native.cpp +++ b/source/compiler-core/slang-json-native.cpp @@ -1,14 +1,13 @@ #include "slang-json-native.h" -#include "slang-com-helper.h" - #include "../core/slang-rtti-util.h" - +#include "slang-com-helper.h" #include "slang-json-diagnostics.h" -namespace Slang { +namespace Slang +{ -/* static */RttiTypeFuncsMap JSONNativeUtil::getTypeFuncsMap() +/* static */ RttiTypeFuncsMap JSONNativeUtil::getTypeFuncsMap() { RttiTypeFuncsMap typeMap; typeMap.add(GetRttiInfo<JSONValue>::get(), GetRttiTypeFuncsForZeroPod<JSONValue>::getFuncs()); @@ -17,7 +16,7 @@ namespace Slang { /* !!!!!!!!!!!!!!!!!!!!!!!!!!!! JSONToNativeConverter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */Index JSONToNativeConverter::_getFieldCount(const StructRttiInfo* structRttiInfo) +/* static */ Index JSONToNativeConverter::_getFieldCount(const StructRttiInfo* structRttiInfo) { if (structRttiInfo->m_super) { @@ -29,7 +28,9 @@ namespace Slang { } } -/* static */Index JSONToNativeConverter::_findFieldIndex(const StructRttiInfo* structRttiInfo, const UnownedStringSlice& fieldName) +/* static */ Index JSONToNativeConverter::_findFieldIndex( + const StructRttiInfo* structRttiInfo, + const UnownedStringSlice& fieldName) { if (structRttiInfo->m_super) { @@ -40,9 +41,13 @@ namespace Slang { } } - ConstArrayView<StructRttiInfo::Field> fields(structRttiInfo->m_fields, structRttiInfo->m_fieldCount); + ConstArrayView<StructRttiInfo::Field> fields( + structRttiInfo->m_fields, + structRttiInfo->m_fieldCount); - Index index = fields.findFirstIndex([fieldName](const StructRttiInfo::Field& field) ->bool { return fieldName == field.m_name; }); + Index index = fields.findFirstIndex( + [fieldName](const StructRttiInfo::Field& field) -> bool + { return fieldName == field.m_name; }); if (index >= 0 && structRttiInfo->m_super) { index += _getFieldCount(structRttiInfo->m_super); @@ -51,7 +56,11 @@ namespace Slang { return index; } -SlangResult JSONToNativeConverter::_structToNative(const ConstArrayView<JSONKeyValue>& pairs, const StructRttiInfo* structRttiInfo, void* out, Index& outFieldCount) +SlangResult JSONToNativeConverter::_structToNative( + const ConstArrayView<JSONKeyValue>& pairs, + const StructRttiInfo* structRttiInfo, + void* out, + Index& outFieldCount) { Index fieldCount = 0; @@ -77,14 +86,19 @@ SlangResult JSONToNativeConverter::_structToNative(const ConstArrayView<JSONKeyV continue; } - m_sink->diagnose(SourceLoc(), JSONDiagnostics::fieldRequiredOnType, field.m_name, structRttiInfo->m_name); + m_sink->diagnose( + SourceLoc(), + JSONDiagnostics::fieldRequiredOnType, + field.m_name, + structRttiInfo->m_name); // Unable to find this key return SLANG_FAIL; } // If there are any of the pairs, that are not in the type.. it's an error - const Index index = pairs.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); + const Index index = pairs.findFirstIndex( + [key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); if (index < 0) { if (field.m_flags & StructRttiInfo::Flag::Optional) @@ -92,7 +106,11 @@ SlangResult JSONToNativeConverter::_structToNative(const ConstArrayView<JSONKeyV continue; } - m_sink->diagnose(SourceLoc(), JSONDiagnostics::fieldRequiredOnType, field.m_name, structRttiInfo->m_name); + m_sink->diagnose( + SourceLoc(), + JSONDiagnostics::fieldRequiredOnType, + field.m_name, + structRttiInfo->m_name); // Unable to find this key return SLANG_FAIL; @@ -107,7 +125,7 @@ SlangResult JSONToNativeConverter::_structToNative(const ConstArrayView<JSONKeyV ++fieldCount; } - // Write off the amount of fields converted/handled. + // Write off the amount of fields converted/handled. outFieldCount = fieldCount; return SLANG_OK; } @@ -125,12 +143,12 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* switch (rttiInfo->m_kind) { - case RttiInfo::Kind::Bool: + case RttiInfo::Kind::Bool: { *(bool*)out = m_container->asBool(in); return SLANG_OK; } - case RttiInfo::Kind::Struct: + case RttiInfo::Kind::Struct: { if (in.getKind() != JSONValue::Kind::Object) { @@ -150,38 +168,44 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* for (auto& pair : pairs) { UnownedStringSlice fieldName = m_container->getStringFromKey(pair.key); - const Index index = _findFieldIndex(structRttiInfo, UnownedStringSlice(fieldName)); + const Index index = + _findFieldIndex(structRttiInfo, UnownedStringSlice(fieldName)); if (index < 0) { - m_sink->diagnose(pair.keyLoc, JSONDiagnostics::fieldNotDefinedOnType, fieldName, structRttiInfo->m_name); + m_sink->diagnose( + pair.keyLoc, + JSONDiagnostics::fieldNotDefinedOnType, + fieldName, + structRttiInfo->m_name); } } - // If these are different then there are fields defined in the object that are *not* defined in class definition + // If these are different then there are fields defined in the object that are *not* + // defined in class definition return SLANG_FAIL; } return SLANG_OK; } - case RttiInfo::Kind::Enum: + case RttiInfo::Kind::Enum: { return SLANG_E_NOT_IMPLEMENTED; } - case RttiInfo::Kind::String: + case RttiInfo::Kind::String: { *(String*)out = m_container->getTransientString(in); return SLANG_OK; } - case RttiInfo::Kind::UnownedStringSlice: + case RttiInfo::Kind::UnownedStringSlice: { - // Problem -> if the slice is a lexeme, then when we decode with getString, it will lose scope. - // So we do something a bit odd and place the decoding string + // Problem -> if the slice is a lexeme, then when we decode with getString, it will lose + // scope. So we do something a bit odd and place the decoding string *(UnownedStringSlice*)out = m_container->getString(in); return SLANG_OK; } - case RttiInfo::Kind::List: + case RttiInfo::Kind::List: { if (in.getKind() == JSONValue::Kind::Null) return SLANG_OK; @@ -200,7 +224,8 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo); auto elementType = listRttiInfo->m_elementType; - SLANG_RETURN_ON_FAIL(RttiUtil::setListCount(m_typeMap, elementType, out, arr.getCount())); + SLANG_RETURN_ON_FAIL( + RttiUtil::setListCount(m_typeMap, elementType, out, arr.getCount())); // Okay, we need to copy over one by one Byte* dstEles = list.getBuffer(); @@ -211,13 +236,14 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* return SLANG_OK; } - case RttiInfo::Kind::FixedArray: + case RttiInfo::Kind::FixedArray: { if (in.getKind() != JSONValue::Kind::Array) { return SLANG_FAIL; } - const FixedArrayRttiInfo* fixedArrayRttiInfo = static_cast<const FixedArrayRttiInfo*>(rttiInfo); + const FixedArrayRttiInfo* fixedArrayRttiInfo = + static_cast<const FixedArrayRttiInfo*>(rttiInfo); const auto elementType = fixedArrayRttiInfo->m_elementType; const Index elementCount = Index(fixedArrayRttiInfo->m_elementCount); const auto elementSize = elementType->m_size; @@ -226,7 +252,11 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* if (srcArray.getCount() > elementCount) { - m_sink->diagnose(in.loc, JSONDiagnostics::tooManyElementsForArray, srcArray.getCount(), elementCount); + m_sink->diagnose( + in.loc, + JSONDiagnostics::tooManyElementsForArray, + srcArray.getCount(), + elementCount); return SLANG_FAIL; } @@ -238,13 +268,13 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* return SLANG_OK; } - case RttiInfo::Kind::Dictionary: + case RttiInfo::Kind::Dictionary: { - // We can *only* serialize this into a straight JSON object iff the key is a string-like type - // We could turn into (say) an array of keys and values + // We can *only* serialize this into a straight JSON object iff the key is a string-like + // type We could turn into (say) an array of keys and values break; } - case RttiInfo::Kind::Other: + case RttiInfo::Kind::Other: { if (rttiInfo == GetRttiInfo<JSONValue>::get()) { @@ -255,16 +285,18 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* } return SLANG_FAIL; } - default: break; + default: break; } return SLANG_FAIL; } -SlangResult JSONToNativeConverter::convertArrayToStruct(const JSONValue& value, const RttiInfo* rttiInfo, void* out) +SlangResult JSONToNativeConverter::convertArrayToStruct( + const JSONValue& value, + const RttiInfo* rttiInfo, + void* out) { // Check converting JSON array into a struct, as that's what this method supports - if (!(rttiInfo->m_kind == RttiInfo::Kind::Struct && - value.getKind() == JSONValue::Kind::Array)) + if (!(rttiInfo->m_kind == RttiInfo::Kind::Struct && value.getKind() == JSONValue::Kind::Array)) { // If they are the wrong types then just fail return SLANG_FAIL; @@ -274,7 +306,8 @@ SlangResult JSONToNativeConverter::convertArrayToStruct(const JSONValue& value, Index totalFieldCount = 0; ShortList<const StructRttiInfo*, 8> infos; - for (const StructRttiInfo* cur = static_cast<const StructRttiInfo*>(rttiInfo); cur; cur = cur->m_super) + for (const StructRttiInfo* cur = static_cast<const StructRttiInfo*>(rttiInfo); cur; + cur = cur->m_super) { totalFieldCount += cur->m_fieldCount; infos.add(cur); @@ -300,7 +333,8 @@ SlangResult JSONToNativeConverter::convertArrayToStruct(const JSONValue& value, { // Convert the field const auto& field = info->m_fields[j]; - SLANG_RETURN_ON_FAIL(convert(array[argIndex++], field.m_type, dstBase + field.m_offset)); + SLANG_RETURN_ON_FAIL( + convert(array[argIndex++], field.m_type, dstBase + field.m_offset)); } } @@ -309,7 +343,10 @@ SlangResult JSONToNativeConverter::convertArrayToStruct(const JSONValue& value, /* !!!!!!!!!!!!!!!!!!!!!!!!!!!! NativeToJSONConverter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -SlangResult NativeToJSONConverter::_structToJSON(const StructRttiInfo* structRttiInfo, const void* src, List<JSONKeyValue>& outPairs) +SlangResult NativeToJSONConverter::_structToJSON( + const StructRttiInfo* structRttiInfo, + const void* src, + List<JSONKeyValue>& outPairs) { // Do the super class first if (structRttiInfo->m_super) @@ -326,7 +363,8 @@ SlangResult NativeToJSONConverter::_structToJSON(const StructRttiInfo* structRtt if (field.m_flags & StructRttiInfo::Flag::Optional) { - const RttiDefaultValue defaultValue = RttiDefaultValue(field.m_flags & uint8_t(RttiDefaultValue::Mask)); + const RttiDefaultValue defaultValue = + RttiDefaultValue(field.m_flags & uint8_t(RttiDefaultValue::Mask)); if (RttiUtil::isDefault(defaultValue, field.m_type, base + field.m_offset)) { // If it's a default, we don't bother writing it @@ -340,7 +378,11 @@ SlangResult NativeToJSONConverter::_structToJSON(const StructRttiInfo* structRtt if (SLANG_FAILED(res)) { - m_sink->diagnose(SourceLoc(), JSONDiagnostics::unableToConvertField, field.m_name, structRttiInfo->m_name); + m_sink->diagnose( + SourceLoc(), + JSONDiagnostics::unableToConvertField, + field.m_name, + structRttiInfo->m_name); return res; } @@ -366,25 +408,25 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* switch (rttiInfo->m_kind) { - case RttiInfo::Kind::Invalid: return SLANG_FAIL; - case RttiInfo::Kind::Bool: + case RttiInfo::Kind::Invalid: return SLANG_FAIL; + case RttiInfo::Kind::Bool: { out = JSONValue::makeBool(RttiUtil::asBool(rttiInfo, in)); return SLANG_OK; } - case RttiInfo::Kind::String: + case RttiInfo::Kind::String: { const String& str = *(const String*)in; out = m_container->createString(str.getUnownedSlice()); return SLANG_OK; } - case RttiInfo::Kind::UnownedStringSlice: + case RttiInfo::Kind::UnownedStringSlice: { const UnownedStringSlice& slice = *(const UnownedStringSlice*)in; out = m_container->createString(slice); return SLANG_OK; } - case RttiInfo::Kind::Struct: + case RttiInfo::Kind::Struct: { const StructRttiInfo* structRttiInfo = static_cast<const StructRttiInfo*>(rttiInfo); @@ -393,11 +435,11 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* out = m_container->createObject(pairs.getBuffer(), pairs.getCount()); return SLANG_OK; } - case RttiInfo::Kind::Enum: - { + case RttiInfo::Kind::Enum: + { return SLANG_E_NOT_IMPLEMENTED; } - case RttiInfo::Kind::List: + case RttiInfo::Kind::List: { const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo); const auto elementRttiInfo = listRttiInfo->m_elementType; @@ -422,9 +464,10 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* out = m_container->createArray(dstValues.getBuffer(), count); return SLANG_OK; } - case RttiInfo::Kind::FixedArray: + case RttiInfo::Kind::FixedArray: { - const FixedArrayRttiInfo* fixedArrayRttiInfo = static_cast<const FixedArrayRttiInfo*>(rttiInfo); + const FixedArrayRttiInfo* fixedArrayRttiInfo = + static_cast<const FixedArrayRttiInfo*>(rttiInfo); const auto elementType = fixedArrayRttiInfo->m_elementType; const auto elementCount = Index(fixedArrayRttiInfo->m_elementCount); const auto elementSize = elementType->m_size; @@ -441,21 +484,22 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* out = m_container->createArray(dstValues.getBuffer(), elementCount); return SLANG_OK; } - case RttiInfo::Kind::Dictionary: + case RttiInfo::Kind::Dictionary: { - const DictionaryRttiInfo* listRttiInfo = static_cast<const DictionaryRttiInfo*>(rttiInfo); + const DictionaryRttiInfo* listRttiInfo = + static_cast<const DictionaryRttiInfo*>(rttiInfo); const auto keyRttiInfo = listRttiInfo->m_keyType; const auto valueRttiInfo = listRttiInfo->m_valueType; SLANG_UNUSED(keyRttiInfo); SLANG_UNUSED(valueRttiInfo); - // We can *only* serialize this into a straight JSON object iff the key is a string-like type - // We could turn into (say) an array of keys and values + // We can *only* serialize this into a straight JSON object iff the key is a string-like + // type We could turn into (say) an array of keys and values break; } - case RttiInfo::Kind::Other: + case RttiInfo::Kind::Other: { if (rttiInfo == GetRttiInfo<JSONValue>::get()) { @@ -468,13 +512,16 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* } break; } - default: break; + default: break; } return SLANG_E_NOT_IMPLEMENTED; } -SlangResult NativeToJSONConverter::convertStructToArray(const RttiInfo* rttiInfo, const void* in, JSONValue& out) +SlangResult NativeToJSONConverter::convertStructToArray( + const RttiInfo* rttiInfo, + const void* in, + JSONValue& out) { if (rttiInfo->m_kind != RttiInfo::Kind::Struct) { @@ -485,7 +532,8 @@ SlangResult NativeToJSONConverter::convertStructToArray(const RttiInfo* rttiInfo // Work out the total amount of fields, and all invloved struct types Index totalFieldsCount = 0; ShortList<const StructRttiInfo*, 8> infos; - for (const StructRttiInfo* cur = static_cast<const StructRttiInfo*>(rttiInfo); cur; cur = cur->m_super) + for (const StructRttiInfo* cur = static_cast<const StructRttiInfo*>(rttiInfo); cur; + cur = cur->m_super) { totalFieldsCount += Index(cur->m_fieldCount); infos.add(cur); @@ -511,7 +559,8 @@ SlangResult NativeToJSONConverter::convertStructToArray(const RttiInfo* rttiInfo { const auto& field = structRttiInfo->m_fields[j]; // Convert the field - SLANG_RETURN_ON_FAIL(convert(field.m_type, argsBase + field.m_offset, argsArray[argsArrayIndex++])); + SLANG_RETURN_ON_FAIL( + convert(field.m_type, argsBase + field.m_offset, argsArray[argsArrayIndex++])); } } } diff --git a/source/compiler-core/slang-json-native.h b/source/compiler-core/slang-json-native.h index 6920d59e9..381d95fe0 100644 --- a/source/compiler-core/slang-json-native.h +++ b/source/compiler-core/slang-json-native.h @@ -1,35 +1,46 @@ #ifndef SLANG_COMPILER_CORE_JSON_NATIVE_H #define SLANG_COMPILER_CORE_JSON_NATIVE_H -#include "slang.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" - #include "slang-json-value.h" +#include "slang.h" -namespace Slang { +namespace Slang +{ struct JSONToNativeConverter { SlangResult convert(const JSONValue& value, const RttiInfo* rttiInfo, void* out); - template <typename T> - SlangResult convert(const JSONValue& value, T* in) { return convert(value, GetRttiInfo<T>::get(), (void*)in); } - - template <typename T> - SlangResult convertArrayToStruct(const JSONValue& value, T* in) { return convertArrayToStruct(value, GetRttiInfo<T>::get(), (void*)in); } + template<typename T> + SlangResult convert(const JSONValue& value, T* in) + { + return convert(value, GetRttiInfo<T>::get(), (void*)in); + } + + template<typename T> + SlangResult convertArrayToStruct(const JSONValue& value, T* in) + { + return convertArrayToStruct(value, GetRttiInfo<T>::get(), (void*)in); + } SlangResult convertArrayToStruct(const JSONValue& value, const RttiInfo* rttiInfo, void* out); - JSONToNativeConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink): - m_container(container), - m_typeMap(typeMap), - m_sink(sink) - {} + JSONToNativeConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink) + : m_container(container), m_typeMap(typeMap), m_sink(sink) + { + } protected: static Index _getFieldCount(const StructRttiInfo* structRttiInfo); - static Index _findFieldIndex(const StructRttiInfo* structRttiInfo, const UnownedStringSlice& fieldName); + static Index _findFieldIndex( + const StructRttiInfo* structRttiInfo, + const UnownedStringSlice& fieldName); - SlangResult _structToNative(const ConstArrayView<JSONKeyValue>& pairs, const StructRttiInfo* structRttiInfo, void* out, Index& outFieldCount); + SlangResult _structToNative( + const ConstArrayView<JSONKeyValue>& pairs, + const StructRttiInfo* structRttiInfo, + void* out, + Index& outFieldCount); DiagnosticSink* m_sink; RttiTypeFuncsMap* m_typeMap; @@ -40,21 +51,29 @@ struct NativeToJSONConverter { SlangResult convert(const RttiInfo* rttiInfo, const void* in, JSONValue& out); - template <typename T> - SlangResult convert(T* in, JSONValue& out) { return convert(GetRttiInfo<T>::get(), (const void*)in, out); } + template<typename T> + SlangResult convert(T* in, JSONValue& out) + { + return convert(GetRttiInfo<T>::get(), (const void*)in, out); + } SlangResult convertStructToArray(const RttiInfo* rttiInfo, const void* in, JSONValue& out); - template <typename T> - SlangResult convertStructToArray(T* in, JSONValue& out) { return convertStructToArray(GetRttiInfo<T>::get(), (const void*)in, out); } + template<typename T> + SlangResult convertStructToArray(T* in, JSONValue& out) + { + return convertStructToArray(GetRttiInfo<T>::get(), (const void*)in, out); + } - NativeToJSONConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink) : - m_container(container), - m_typeMap(typeMap), - m_sink(sink) - {} + NativeToJSONConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink) + : m_container(container), m_typeMap(typeMap), m_sink(sink) + { + } protected: - SlangResult _structToJSON(const StructRttiInfo* structRttiInfo, const void* src, List<JSONKeyValue>& outPairs); + SlangResult _structToJSON( + const StructRttiInfo* structRttiInfo, + const void* src, + List<JSONKeyValue>& outPairs); DiagnosticSink* m_sink; RttiTypeFuncsMap* m_typeMap; diff --git a/source/compiler-core/slang-json-parser.cpp b/source/compiler-core/slang-json-parser.cpp index 52e46258a..c436468a4 100644 --- a/source/compiler-core/slang-json-parser.cpp +++ b/source/compiler-core/slang-json-parser.cpp @@ -1,15 +1,15 @@ // slang-json-parser.cpp #include "slang-json-parser.h" -#include "slang-json-diagnostics.h" - #include "../core/slang-string-escape-util.h" +#include "slang-json-diagnostics.h" /* https://www.json.org/json-en.html */ -namespace Slang { +namespace Slang +{ SlangResult JSONParser::_parseObject() { @@ -92,32 +92,35 @@ SlangResult JSONParser::_parseValue() { switch (m_lexer->peekType()) { - case JSONTokenType::True: - case JSONTokenType::False: - case JSONTokenType::Null: - case JSONTokenType::IntegerLiteral: - case JSONTokenType::FloatLiteral: - case JSONTokenType::StringLiteral: + case JSONTokenType::True: + case JSONTokenType::False: + case JSONTokenType::Null: + case JSONTokenType::IntegerLiteral: + case JSONTokenType::FloatLiteral: + case JSONTokenType::StringLiteral: { const JSONToken& tok = m_lexer->peekToken(); m_listener->addLexemeValue(tok.type, m_lexer->peekLexeme(), tok.loc); m_lexer->advance(); return SLANG_OK; } - case JSONTokenType::LBracket: + case JSONTokenType::LBracket: { return _parseArray(); } - case JSONTokenType::LBrace: + case JSONTokenType::LBrace: { return _parseObject(); } - default: + default: { - m_sink->diagnose(m_lexer->peekLoc(), JSONDiagnostics::unexpectedToken, getJSONTokenAsText(m_lexer->peekType())); + m_sink->diagnose( + m_lexer->peekLoc(), + JSONDiagnostics::unexpectedToken, + getJSONTokenAsText(m_lexer->peekType())); return SLANG_FAIL; } - case JSONTokenType::Invalid: + case JSONTokenType::Invalid: { // It's a lex error, so just fail return SLANG_FAIL; @@ -125,7 +128,11 @@ SlangResult JSONParser::_parseValue() } } -SlangResult JSONParser::parse(JSONLexer* lexer, SourceView* sourceView, JSONListener* listener, DiagnosticSink* sink) +SlangResult JSONParser::parse( + JSONLexer* lexer, + SourceView* sourceView, + JSONListener* listener, + DiagnosticSink* sink) { m_sourceView = sourceView; m_lexer = lexer; @@ -180,7 +187,8 @@ void JSONWriter::_nextLine() void JSONWriter::_maybeNextLine() { - // Nothing has been emitted, because nothing has been indented, and we must indent before an emit + // Nothing has been emitted, because nothing has been indented, and we must indent before an + // emit if (m_emittedIndent < 0) { } @@ -194,13 +202,13 @@ void JSONWriter::_handleFormat(Location loc) { switch (m_format) { - case IndentationStyle::Allman: + case IndentationStyle::Allman: { if (isComma(loc)) { _maybeNextLine(); } - else + else { if (isBefore(loc)) { @@ -221,7 +229,7 @@ void JSONWriter::_handleFormat(Location loc) } break; } - case IndentationStyle::KNR: + case IndentationStyle::KNR: { if (isComma(loc)) { @@ -231,7 +239,7 @@ void JSONWriter::_handleFormat(Location loc) _maybeNextLine(); } } - else + else { if (isBefore(loc)) { @@ -321,7 +329,7 @@ void JSONWriter::startArray(SourceLoc loc) _handleFormat(Location::BeforeOpenArray); _maybeEmitIndent(); - m_builder << "["; + m_builder << "["; _handleFormat(Location::AfterOpenArray); m_state.m_flags |= State::Flag::HasPrevious; @@ -352,7 +360,8 @@ void JSONWriter::endArray(SourceLoc loc) void JSONWriter::addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) { SLANG_UNUSED(loc); - SLANG_ASSERT(m_state.m_kind == State::Kind::Object && (m_state.m_flags & State::Flag::HasKey) == 0); + SLANG_ASSERT( + m_state.m_kind == State::Kind::Object && (m_state.m_flags & State::Flag::HasKey) == 0); _maybeEmitFieldComma(); _maybeEmitIndent(); @@ -371,7 +380,8 @@ void JSONWriter::addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) void JSONWriter::addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) { SLANG_UNUSED(loc); - SLANG_ASSERT(m_state.m_kind == State::Kind::Object && (m_state.m_flags & State::Flag::HasKey) == 0); + SLANG_ASSERT( + m_state.m_kind == State::Kind::Object && (m_state.m_flags & State::Flag::HasKey) == 0); // It should be quoted SLANG_ASSERT(key.getLength() >= 2 && key[0] == '"' && key[key.getLength() - 1] == '"'); @@ -412,29 +422,29 @@ void JSONWriter::addLexemeValue(JSONTokenType type, const UnownedStringSlice& va switch (type) { - case JSONTokenType::IntegerLiteral: - case JSONTokenType::FloatLiteral: - case JSONTokenType::StringLiteral: + case JSONTokenType::IntegerLiteral: + case JSONTokenType::FloatLiteral: + case JSONTokenType::StringLiteral: { m_builder << value; break; } - case JSONTokenType::True: + case JSONTokenType::True: { m_builder << UnownedStringSlice::fromLiteral("true"); break; } - case JSONTokenType::False: + case JSONTokenType::False: { m_builder << UnownedStringSlice::fromLiteral("false"); break; } - case JSONTokenType::Null: + case JSONTokenType::Null: { m_builder << UnownedStringSlice::fromLiteral("null"); break; } - default: + default: { SLANG_ASSERT(!"Can only emit values"); } @@ -460,7 +470,8 @@ void JSONWriter::addFloatValue(double value, SourceLoc loc) void JSONWriter::addBoolValue(bool inValue, SourceLoc loc) { _preValue(loc); - const UnownedStringSlice slice = inValue ? UnownedStringSlice::fromLiteral("true") : UnownedStringSlice::fromLiteral("false"); + const UnownedStringSlice slice = inValue ? UnownedStringSlice::fromLiteral("true") + : UnownedStringSlice::fromLiteral("false"); m_builder << slice; _postValue(); } diff --git a/source/compiler-core/slang-json-parser.h b/source/compiler-core/slang-json-parser.h index 2391ea0d2..d226e7fb9 100644 --- a/source/compiler-core/slang-json-parser.h +++ b/source/compiler-core/slang-json-parser.h @@ -5,54 +5,58 @@ #include "slang-json-lexer.h" -namespace Slang { +namespace Slang +{ class JSONListener { public: - /// Start an object + /// Start an object virtual void startObject(SourceLoc loc) = 0; - /// End an object + /// End an object virtual void endObject(SourceLoc loc) = 0; - /// Start an array + /// Start an array virtual void startArray(SourceLoc loc) = 0; - /// End and array + /// End and array virtual void endArray(SourceLoc loc) = 0; - /// Add the key. Must be followed by addXXXValue. + /// Add the key. Must be followed by addXXXValue. virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) = 0; virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) = 0; - /// Can be performed in an array or after an addLexemeKey in an object - virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) = 0; + /// Can be performed in an array or after an addLexemeKey in an object + virtual void addLexemeValue( + JSONTokenType type, + const UnownedStringSlice& value, + SourceLoc loc) = 0; - /// An integer value + /// An integer value virtual void addIntegerValue(int64_t value, SourceLoc loc) = 0; - /// Add a floating point value + /// Add a floating point value virtual void addFloatValue(double value, SourceLoc loc) = 0; - /// Add a boolean value + /// Add a boolean value virtual void addBoolValue(bool value, SourceLoc loc) = 0; - /// Add a string value. NOTE! string is unescaped/quoted + /// Add a string value. NOTE! string is unescaped/quoted virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) = 0; - /// Add a null value + /// Add a null value virtual void addNullValue(SourceLoc loc) = 0; }; class JSONWriter : public JSONListener { public: - /* + /* https://en.wikipedia.org/wiki/Indentation_style */ enum class IndentationStyle { - Allman, ///< After every value, and opening, closing all other types - KNR, ///< K&R like. Fields have CR. + Allman, ///< After every value, and opening, closing all other types + KNR, ///< K&R like. Fields have CR. }; - enum class LocationType : uint8_t + enum class LocationType : uint8_t { Object, Array, @@ -78,11 +82,22 @@ public: CountOf, }; - static LocationType getLocationType(Location loc) { return isObject(loc) ? LocationType::Object : (isComma(loc) ? LocationType::Comma : LocationType::Array); } + static LocationType getLocationType(Location loc) + { + return isObject(loc) ? LocationType::Object + : (isComma(loc) ? LocationType::Comma : LocationType::Array); + } - static bool isObjectLike(Location loc) { return Index(loc) <= Index(Location::AfterCloseArray); } + static bool isObjectLike(Location loc) + { + return Index(loc) <= Index(Location::AfterCloseArray); + } static bool isObject(Location loc) { return Index(loc) <= Index(Location::AfterCloseObject); } - static bool isArray(Location loc) { return Index(loc) >= Index(Location::BeforeOpenArray) && Index(loc) <= Index(Location::AfterCloseArray); } + static bool isArray(Location loc) + { + return Index(loc) >= Index(Location::BeforeOpenArray) && + Index(loc) <= Index(Location::AfterCloseArray); + } static bool isComma(Location loc) { return Index(loc) >= Index(Location::FieldComma); } static bool isOpen(Location loc) { return isObjectLike(loc) && (Index(loc) & 1) == 0; } static bool isClose(Location loc) { return isObjectLike(loc) && (Index(loc) & 1) != 0; } @@ -96,14 +111,15 @@ public: virtual void endArray(SourceLoc loc) SLANG_OVERRIDE; virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE; virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE; - virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) SLANG_OVERRIDE; + virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) + SLANG_OVERRIDE; virtual void addIntegerValue(int64_t value, SourceLoc loc) SLANG_OVERRIDE; virtual void addFloatValue(double value, SourceLoc loc) SLANG_OVERRIDE; virtual void addBoolValue(bool value, SourceLoc loc) SLANG_OVERRIDE; virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) SLANG_OVERRIDE; virtual void addNullValue(SourceLoc loc) SLANG_OVERRIDE; - /// Get the builder + /// Get the builder StringBuilder& getBuilder() { return m_builder; } JSONWriter(IndentationStyle format, Index lineLengthLimit = -1) @@ -131,7 +147,7 @@ protected: enum Enum : Flags { HasPrevious = 0x01, - HasKey = 0x02, + HasKey = 0x02, }; }; @@ -139,10 +155,10 @@ protected: { switch (m_kind) { - case Kind::Root: return (m_flags & Flag::HasPrevious) == 0; - case Kind::Array: return true; - case Kind::Object: return (m_flags & Flag::HasKey) != 0; - default: return false; + case Kind::Root: return (m_flags & Flag::HasPrevious) == 0; + case Kind::Array: return true; + case Kind::Object: return (m_flags & Flag::HasKey) != 0; + default: return false; } } @@ -156,7 +172,7 @@ protected: Index _getLineLengthAfterIndent(); - /// Only emits the indent if at start of line + /// Only emits the indent if at start of line void _maybeEmitIndent(); void _emitIndent(); @@ -167,20 +183,24 @@ protected: void _postValue(); void _indent() { m_currentIndent++; } - void _dedent() { --m_currentIndent; SLANG_ASSERT(m_currentIndent >= 0); } + void _dedent() + { + --m_currentIndent; + SLANG_ASSERT(m_currentIndent >= 0); + } - /// True if the line is indented at the required level + /// True if the line is indented at the required level bool _hasIndent() { return m_emittedIndent >= 0 && m_emittedIndent == m_currentIndent; } - + Index m_currentIndent = 0; char m_indentChar = ' '; Index m_indentCharCount = 4; Index m_lineIndex = 0; Index m_lineStart = 0; - Index m_emittedIndent = -1; /// If -1 for current line there is no indent emitted + Index m_emittedIndent = -1; /// If -1 for current line there is no indent emitted - Index m_lineLengthLimit = -1; /// The limit is only applied *AFTER* indentation + Index m_lineLengthLimit = -1; /// The limit is only applied *AFTER* indentation IndentationStyle m_format; @@ -192,7 +212,11 @@ protected: class JSONParser { public: - SlangResult parse(JSONLexer* lexer, SourceView* sourceView, JSONListener* listener, DiagnosticSink* sink); + SlangResult parse( + JSONLexer* lexer, + SourceView* sourceView, + JSONListener* listener, + DiagnosticSink* sink); protected: SlangResult _parseValue(); @@ -206,7 +230,6 @@ protected: }; - } // namespace Slang #endif diff --git a/source/compiler-core/slang-json-rpc-connection.cpp b/source/compiler-core/slang-json-rpc-connection.cpp index af9dd9e48..79ffc9583 100644 --- a/source/compiler-core/slang-json-rpc-connection.cpp +++ b/source/compiler-core/slang-json-rpc-connection.cpp @@ -1,23 +1,25 @@ // slang-json-rpc-connection.cpp #include "slang-json-rpc-connection.h" -#include "../core/slang-string-util.h" #include "../core/slang-process-util.h" #include "../core/slang-short-list.h" - -#include "slang-json-rpc.h" +#include "../core/slang-string-util.h" #include "slang-json-native.h" +#include "slang-json-rpc.h" -namespace Slang { +namespace Slang +{ /// Ctor -JSONRPCConnection::JSONRPCConnection(): - m_container(nullptr), - m_typeMap(JSONNativeUtil::getTypeFuncsMap()) +JSONRPCConnection::JSONRPCConnection() + : m_container(nullptr), m_typeMap(JSONNativeUtil::getTypeFuncsMap()) { } -SlangResult JSONRPCConnection::init(HTTPPacketConnection* connection, CallStyle defaultCallStyle, Process* process) +SlangResult JSONRPCConnection::init( + HTTPPacketConnection* connection, + CallStyle defaultCallStyle, + Process* process) { m_connection = connection; m_process = process; @@ -25,11 +27,12 @@ SlangResult JSONRPCConnection::init(HTTPPacketConnection* connection, CallStyle { // If a call style isn't set, use the prefered style const CallStyle preferedCallStyle = CallStyle::Array; - defaultCallStyle = (defaultCallStyle == CallStyle::Default) ? preferedCallStyle : defaultCallStyle; + defaultCallStyle = + (defaultCallStyle == CallStyle::Default) ? preferedCallStyle : defaultCallStyle; m_defaultCallStyle = defaultCallStyle; } - - + + m_sourceManager.initialize(nullptr, nullptr); m_diagnosticSink.init(&m_sourceManager, &JSONLexer::calcLexemeLocation); m_container.setSourceManager(&m_sourceManager); @@ -77,7 +80,7 @@ void JSONRPCConnection::disconnect() { if (m_connection) { - // Send. If succeeded, wait + // Send. If succeeded, wait if (SLANG_SUCCEEDED(sendCall(UnownedStringSlice::fromLiteral("quit")))) { // Wait for termination @@ -126,7 +129,10 @@ SlangResult JSONRPCConnection::sendError(JSONRPC::ErrorCode code, const JSONValu return sendError(code, m_diagnosticSink.outputBuffer.getUnownedSlice(), id); } -SlangResult JSONRPCConnection::sendError(JSONRPC::ErrorCode errorCode, const UnownedStringSlice& msg, const JSONValue& id) +SlangResult JSONRPCConnection::sendError( + JSONRPC::ErrorCode errorCode, + const UnownedStringSlice& msg, + const JSONValue& id) { JSONRPCErrorResponse errorResponse; errorResponse.error.code = Int(errorCode); @@ -136,25 +142,33 @@ SlangResult JSONRPCConnection::sendError(JSONRPC::ErrorCode errorCode, const Uno return sendRPC(&errorResponse); } -SlangResult JSONRPCConnection::checkArrayObjectWrap( const JSONValue& srcArgs, const RttiInfo* dstArgsRttiInfo, void* dstArgs, const JSONValue& id ) +SlangResult JSONRPCConnection::checkArrayObjectWrap( + const JSONValue& srcArgs, + const RttiInfo* dstArgsRttiInfo, + void* dstArgs, + const JSONValue& id) { - if ( dstArgsRttiInfo->m_kind == RttiInfo::Kind::Struct && - srcArgs.getKind() == JSONValue::Kind::Array ) + if (dstArgsRttiInfo->m_kind == RttiInfo::Kind::Struct && + srcArgs.getKind() == JSONValue::Kind::Array) { - auto array = m_container.getArray( srcArgs ); - if ( array.getCount() == 1 ) + auto array = m_container.getArray(srcArgs); + if (array.getCount() == 1) { - return toNativeOrSendError( array[0], dstArgsRttiInfo, dstArgs, id ); + return toNativeOrSendError(array[0], dstArgsRttiInfo, dstArgs, id); } return SLANG_OK; } else { - return toNativeOrSendError( srcArgs, dstArgsRttiInfo, dstArgs, id ); + return toNativeOrSendError(srcArgs, dstArgsRttiInfo, dstArgs, id); } } -SlangResult JSONRPCConnection::toNativeArgsOrSendError(const JSONValue& srcArgs, const RttiInfo* dstArgsRttiInfo, void* dstArgs, const JSONValue& id) +SlangResult JSONRPCConnection::toNativeArgsOrSendError( + const JSONValue& srcArgs, + const RttiInfo* dstArgsRttiInfo, + void* dstArgs, + const JSONValue& id) { if (dstArgsRttiInfo->m_kind == RttiInfo::Kind::Struct && srcArgs.getKind() == JSONValue::Kind::Array) @@ -172,12 +186,16 @@ SlangResult JSONRPCConnection::toNativeArgsOrSendError(const JSONValue& srcArgs, } } -SlangResult JSONRPCConnection::toNativeOrSendError(const JSONValue& value, const RttiInfo* info, void* dst, const JSONValue& id) +SlangResult JSONRPCConnection::toNativeOrSendError( + const JSONValue& value, + const RttiInfo* info, + void* dst, + const JSONValue& id) { m_diagnosticSink.outputBuffer.clear(); JSONToNativeConverter converter(&m_container, &m_typeMap, &m_diagnosticSink); - + if (SLANG_FAILED(converter.convert(value, info, dst))) { return sendError(JSONRPC::ErrorCode::InvalidRequest, id); @@ -196,7 +214,10 @@ SlangResult JSONRPCConnection::sendCall(const UnownedStringSlice& method, const return SLANG_OK; } -SlangResult JSONRPCConnection::sendResult(const RttiInfo* rttiInfo, const void* result, const JSONValue& id) +SlangResult JSONRPCConnection::sendResult( + const RttiInfo* rttiInfo, + const void* result, + const JSONValue& id) { JSONResultResponse response; response.id = id; @@ -209,12 +230,21 @@ SlangResult JSONRPCConnection::sendResult(const RttiInfo* rttiInfo, const void* return SLANG_OK; } -SlangResult JSONRPCConnection::sendCall(const UnownedStringSlice& method, const RttiInfo* argsRttiInfo, const void* args, const JSONValue& id) +SlangResult JSONRPCConnection::sendCall( + const UnownedStringSlice& method, + const RttiInfo* argsRttiInfo, + const void* args, + const JSONValue& id) { return sendCall(m_defaultCallStyle, method, argsRttiInfo, args, id); } -SlangResult JSONRPCConnection::sendCall(CallStyle callStyle, const UnownedStringSlice& method, const RttiInfo* argsRttiInfo, const void* args, const JSONValue& id) +SlangResult JSONRPCConnection::sendCall( + CallStyle callStyle, + const UnownedStringSlice& method, + const RttiInfo* argsRttiInfo, + const void* args, + const JSONValue& id) { JSONRPCCall call; call.id = id; @@ -222,7 +252,7 @@ SlangResult JSONRPCConnection::sendCall(CallStyle callStyle, const UnownedString // Set up the converter to now convert the args. NativeToJSONConverter converter(&m_container, &m_typeMap, &m_diagnosticSink); - + // If we have a struct *and* call style is 'array', do special handling if (argsRttiInfo->m_kind == RttiInfo::Kind::Struct && _getCallStyle(callStyle) == CallStyle::Array) @@ -235,7 +265,7 @@ SlangResult JSONRPCConnection::sendCall(CallStyle callStyle, const UnownedString // Convert the args/params in the 'object' sytle SLANG_RETURN_ON_FAIL(converter.convert(argsRttiInfo, args, call.params)); } - + // Send the RPC SLANG_RETURN_ON_FAIL(sendRPC(&call)); return SLANG_OK; @@ -263,7 +293,8 @@ SlangResult JSONRPCConnection::tryReadMessage() clearBuffers(); { - const SlangResult res = JSONRPCUtil::parseJSON(slice, &m_container, &m_diagnosticSink, m_jsonRoot); + const SlangResult res = + JSONRPCUtil::parseJSON(slice, &m_container, &m_diagnosticSink, m_jsonRoot); // Consume that content/packet m_connection->consumeContent(); @@ -346,4 +377,4 @@ SlangResult JSONRPCConnection::getRPCOrSendError(const RttiInfo* rttiInfo, void* return res; } -} // namespcae Slang +} // namespace Slang diff --git a/source/compiler-core/slang-json-rpc-connection.h b/source/compiler-core/slang-json-rpc-connection.h index f5525d033..5ee963ec8 100644 --- a/source/compiler-core/slang-json-rpc-connection.h +++ b/source/compiler-core/slang-json-rpc-connection.h @@ -3,17 +3,15 @@ #include "../../source/core/slang-http.h" #include "../../source/core/slang-process.h" - #include "slang-diagnostic-sink.h" -#include "slang-source-loc.h" -#include "slang-json-value.h" -#include "slang-json-rpc.h" - #include "slang-json-diagnostics.h" - +#include "slang-json-rpc.h" +#include "slang-json-value.h" +#include "slang-source-loc.h" #include "slang-test-server-protocol.h" -namespace Slang { +namespace Slang +{ /* A type to handle communication via the JSON-RPC protocol. @@ -23,164 +21,245 @@ use the JSON-RPC protocol types. These types will hold items that can vary (like in JSONValue parameters. Code can use regular JSON functions to access/process. Doing conversions to native types and JSON manually can be a fairly monotonous task. To avoid this -effort Rtti and JSON<->Rtti conversions can be used. For example sendCall will send a JSON-RPC 'call' method, -with the parameters being converted from some native type. For this to work the type T must be determinable -via GetRttiType<T>, and T must only contain types that JSON<->Rtti conversion supports. +effort Rtti and JSON<->Rtti conversions can be used. For example sendCall will send a JSON-RPC +'call' method, with the parameters being converted from some native type. For this to work the type +T must be determinable via GetRttiType<T>, and T must only contain types that JSON<->Rtti conversion +supports. */ class JSONRPCConnection : public RefObject { public: - enum class CallStyle { - Default, ///< The default - Object, ///< Params are passed as an object - Array, ///< Params are passed as an array + Default, ///< The default + Object, ///< Params are passed as an object + Array, ///< Params are passed as an array }; - /// An init function must be called before use - /// If a process is implementing the server it should be passed in if the process needs to shut down if the connection does - SlangResult init(HTTPPacketConnection* connection, CallStyle callStyle = CallStyle::Default, Process* process = nullptr); + /// An init function must be called before use + /// If a process is implementing the server it should be passed in if the process needs to shut + /// down if the connection does + SlangResult init( + HTTPPacketConnection* connection, + CallStyle callStyle = CallStyle::Default, + Process* process = nullptr); - /// Initialize using stdin/out streams for input/output. - SlangResult initWithStdStreams(CallStyle callStyle = CallStyle::Default, Process* process = nullptr); + /// Initialize using stdin/out streams for input/output. + SlangResult initWithStdStreams( + CallStyle callStyle = CallStyle::Default, + Process* process = nullptr); - /// Disconnect. May block while server shuts down + /// Disconnect. May block while server shuts down void disconnect(); - SlangResult checkArrayObjectWrap( const JSONValue& srcArgs, const RttiInfo* dstArgsRttiInfo, void* dstArgs, const JSONValue& id ); - - /// Convert value to dst. Will write response on fails - SlangResult toNativeOrSendError(const JSONValue& value, const RttiInfo* info, void* dst, const JSONValue& id); - - template <typename T> - SlangResult toNativeOrSendError(const JSONValue& value, T* data, const JSONValue& id) { return toNativeOrSendError(value, GetRttiInfo<T>::get(), data, id); } - - /// Convert value to dst. - /// The 'Args' aspect here is to handle Args/Params in JSON-RPC which can be specified as an array or object style. - /// This call will automatically handle either case. - /// toNativeOrSendError does not assume the thing being converted is args, and so doesn't allow such a transformation. - /// Will write error response on failure. - SlangResult toNativeArgsOrSendError(const JSONValue& srcArgs, const RttiInfo* dstArgsRttiInfo, void* dstArgs, const JSONValue& id); + SlangResult checkArrayObjectWrap( + const JSONValue& srcArgs, + const RttiInfo* dstArgsRttiInfo, + void* dstArgs, + const JSONValue& id); + + /// Convert value to dst. Will write response on fails + SlangResult toNativeOrSendError( + const JSONValue& value, + const RttiInfo* info, + void* dst, + const JSONValue& id); + + template<typename T> + SlangResult toNativeOrSendError(const JSONValue& value, T* data, const JSONValue& id) + { + return toNativeOrSendError(value, GetRttiInfo<T>::get(), data, id); + } - template <typename T> - SlangResult toNativeArgsOrSendError(const JSONValue& srcArgs, T* dstArgs, const JSONValue& id) { return toNativeArgsOrSendError(srcArgs, GetRttiInfo<T>::get(), dstArgs, id); } + /// Convert value to dst. + /// The 'Args' aspect here is to handle Args/Params in JSON-RPC which can be specified as an + /// array or object style. This call will automatically handle either case. toNativeOrSendError + /// does not assume the thing being converted is args, and so doesn't allow such a + /// transformation. Will write error response on failure. + SlangResult toNativeArgsOrSendError( + const JSONValue& srcArgs, + const RttiInfo* dstArgsRttiInfo, + void* dstArgs, + const JSONValue& id); + + template<typename T> + SlangResult toNativeArgsOrSendError(const JSONValue& srcArgs, T* dstArgs, const JSONValue& id) + { + return toNativeArgsOrSendError(srcArgs, GetRttiInfo<T>::get(), dstArgs, id); + } - template <typename T> + template<typename T> SlangResult toValidNativeOrSendError(const JSONValue& value, T* data, const JSONValue& id); - /// Send a RPC response (ie should only be one of the JSONRPC classes) + /// Send a RPC response (ie should only be one of the JSONRPC classes) SlangResult sendRPC(const RttiInfo* info, const void* data); - template <typename T> - SlangResult sendRPC(const T* data) { return sendRPC(GetRttiInfo<T>::get(), (const void*)data); } + template<typename T> + SlangResult sendRPC(const T* data) + { + return sendRPC(GetRttiInfo<T>::get(), (const void*)data); + } - /// Send an error + /// Send an error SlangResult sendError(JSONRPC::ErrorCode code, const JSONValue& id); - SlangResult sendError(JSONRPC::ErrorCode errorCode, const UnownedStringSlice& msg, const JSONValue& id); - - /// Send a 'call' - /// Uses the default CallStyle as set when init - SlangResult sendCall(const UnownedStringSlice& method, const RttiInfo* argsRttiInfo, const void* args, const JSONValue& id = JSONValue()); - template <typename T> - SlangResult sendCall(const UnownedStringSlice& method, const T* args, const JSONValue& id = JSONValue()) { return sendCall(method, GetRttiInfo<T>::get(), (const void*)args, id); } + SlangResult sendError( + JSONRPC::ErrorCode errorCode, + const UnownedStringSlice& msg, + const JSONValue& id); + + /// Send a 'call' + /// Uses the default CallStyle as set when init + SlangResult sendCall( + const UnownedStringSlice& method, + const RttiInfo* argsRttiInfo, + const void* args, + const JSONValue& id = JSONValue()); + template<typename T> + SlangResult sendCall( + const UnownedStringSlice& method, + const T* args, + const JSONValue& id = JSONValue()) + { + return sendCall(method, GetRttiInfo<T>::get(), (const void*)args, id); + } - /// Send a 'call' - /// Uses the call mechanism specified in callStyle. It is valid to pass as Default. - SlangResult sendCall(CallStyle callStyle, const UnownedStringSlice& method, const RttiInfo* argsRttiInfo, const void* args, const JSONValue& id = JSONValue()); - template <typename T> - SlangResult sendCall(CallStyle callStyle, const UnownedStringSlice& method, const T* args, const JSONValue& id = JSONValue()) { return sendCall(callStyle, method, GetRttiInfo<T>::get(), (const void*)args, id); } + /// Send a 'call' + /// Uses the call mechanism specified in callStyle. It is valid to pass as Default. + SlangResult sendCall( + CallStyle callStyle, + const UnownedStringSlice& method, + const RttiInfo* argsRttiInfo, + const void* args, + const JSONValue& id = JSONValue()); + template<typename T> + SlangResult sendCall( + CallStyle callStyle, + const UnownedStringSlice& method, + const T* args, + const JSONValue& id = JSONValue()) + { + return sendCall(callStyle, method, GetRttiInfo<T>::get(), (const void*)args, id); + } - /// Send a call, wheret there are no arguments + /// Send a call, wheret there are no arguments SlangResult sendCall(const UnownedStringSlice& method, const JSONValue& id = JSONValue()); - template <typename T> - SlangResult sendResult(const T* result, const JSONValue& id) { return sendResult(GetRttiInfo<T>::get(), (const void*)result, id); } + template<typename T> + SlangResult sendResult(const T* result, const JSONValue& id) + { + return sendResult(GetRttiInfo<T>::get(), (const void*)result, id); + } SlangResult sendResult(const RttiInfo* rttiInfo, const void* result, const JSONValue& id); - /// Try to read a message. Will return if message is not available. + /// Try to read a message. Will return if message is not available. SlangResult tryReadMessage(); - /// Will block for message/result up to time + /// Will block for message/result up to time SlangResult waitForResult(Int timeOutInMs = -1); - /// If we have an JSON-RPC message m_jsonRoot the root. + /// If we have an JSON-RPC message m_jsonRoot the root. bool hasMessage() const { return m_jsonRoot.isValid(); } - /// If there is a message returns kind of JSON RPC message + /// If there is a message returns kind of JSON RPC message JSONRPCMessageType getMessageType(); - /// Get JSON-RPC message (ie one of JSONRPC classes) - template <typename T> - SlangResult getRPC(T* out) { return getRPC(GetRttiInfo<T>::get(), (void*)out); } + /// Get JSON-RPC message (ie one of JSONRPC classes) + template<typename T> + SlangResult getRPC(T* out) + { + return getRPC(GetRttiInfo<T>::get(), (void*)out); + } SlangResult getRPC(const RttiInfo* rttiInfo, void* out); - /// Get JSON-RPC message (ie one of JSONRPC prefixed classes) - /// If there is a message and there is a failure, will send an error response - template <typename T> - SlangResult getRPCOrSendError(T* out) { return getRPCOrSendError(GetRttiInfo<T>::get(), (void*)out); } + /// Get JSON-RPC message (ie one of JSONRPC prefixed classes) + /// If there is a message and there is a failure, will send an error response + template<typename T> + SlangResult getRPCOrSendError(T* out) + { + return getRPCOrSendError(GetRttiInfo<T>::get(), (void*)out); + } SlangResult getRPCOrSendError(const RttiInfo* rttiInfo, void* out); - /// Get message (has to be part of JSONRPCResultResponse) - template <typename T> - SlangResult getMessage(T* out) { return getMessage(GetRttiInfo<T>::get(), (void*)out); } + /// Get message (has to be part of JSONRPCResultResponse) + template<typename T> + SlangResult getMessage(T* out) + { + return getMessage(GetRttiInfo<T>::get(), (void*)out); + } SlangResult getMessage(const RttiInfo* rttiInfo, void* out); - /// If there is a message and there is a failure, will send an error response - template <typename T> - SlangResult getMessageOrSendError(T* out) { return getMessageOrSendError(GetRttiInfo<T>::get(), (void*)out); } + /// If there is a message and there is a failure, will send an error response + template<typename T> + SlangResult getMessageOrSendError(T* out) + { + return getMessageOrSendError(GetRttiInfo<T>::get(), (void*)out); + } SlangResult getMessageOrSendError(const RttiInfo* rttiInfo, void* out); - /// Clears all the internal buffers (for JSON/Source/etc). - /// Happens automatically on tryReadMessage/readMessage + /// Clears all the internal buffers (for JSON/Source/etc). + /// Happens automatically on tryReadMessage/readMessage void clearBuffers(); - /// True if this connection is active + /// True if this connection is active bool isActive(); - /// Get the id of the current message + /// Get the id of the current message JSONValue getCurrentMessageId(); - /// Get the diagnostic sink. Can queue up errors before sending an error - DiagnosticSink* getSink() { return &m_diagnosticSink; } + /// Get the diagnostic sink. Can queue up errors before sending an error + DiagnosticSink* getSink() { return &m_diagnosticSink; } - /// Get the container - JSONContainer* getContainer() { return &m_container; } + /// Get the container + JSONContainer* getContainer() { return &m_container; } - /// Turn a value into a persistant value. This will also remove any sourceLoc under the assumption that it's highly likely - /// it will become invalid in most usage scenarios. - PersistentJSONValue getPersistentValue(const JSONValue& value) { return PersistentJSONValue(value, &m_container, SourceLoc()); } + /// Turn a value into a persistant value. This will also remove any sourceLoc under the + /// assumption that it's highly likely it will become invalid in most usage scenarios. + PersistentJSONValue getPersistentValue(const JSONValue& value) + { + return PersistentJSONValue(value, &m_container, SourceLoc()); + } HTTPPacketConnection* getUnderlyingConnection() { return m_connection.Ptr(); } - /// Dtor + /// Dtor ~JSONRPCConnection() { disconnect(); } - /// Ctor + /// Ctor JSONRPCConnection(); protected: - CallStyle _getCallStyle(CallStyle callStyle) const { return (callStyle == CallStyle::Default) ? m_defaultCallStyle : callStyle; } + CallStyle _getCallStyle(CallStyle callStyle) const + { + return (callStyle == CallStyle::Default) ? m_defaultCallStyle : callStyle; + } - RefPtr<Process> m_process; ///< Backing process (optional) - RefPtr<HTTPPacketConnection> m_connection; ///< The underlying 'transport' connection, whilst HTTP currently doesn't have to be + RefPtr<Process> m_process; ///< Backing process (optional) + RefPtr<HTTPPacketConnection> m_connection; ///< The underlying 'transport' connection, whilst + ///< HTTP currently doesn't have to be - DiagnosticSink m_diagnosticSink; ///< Holds any diagnostics typically generated by parsing JSON, producing JSON from native types + DiagnosticSink m_diagnosticSink; ///< Holds any diagnostics typically generated by parsing JSON, + ///< producing JSON from native types - SourceManager m_sourceManager; ///< Holds the JSON text for current message/output. Is cleared regularly. - JSONContainer m_container; ///< Holds the backing memory for jsonMemory, and used when converting input into output JSON + SourceManager + m_sourceManager; ///< Holds the JSON text for current message/output. Is cleared regularly. + JSONContainer m_container; ///< Holds the backing memory for jsonMemory, and used when + ///< converting input into output JSON - JSONValue m_jsonRoot; ///< The root JSON value for the currently read message. + JSONValue m_jsonRoot; ///< The root JSON value for the currently read message. + + CallStyle m_defaultCallStyle = CallStyle::Array; ///< The default calling style - CallStyle m_defaultCallStyle = CallStyle::Array; ///< The default calling style - RttiTypeFuncsMap m_typeMap; - Int m_terminationTimeOutInMs = 1 * 1000; ///< Time to wait for termination response. Default is 1 second + Int m_terminationTimeOutInMs = + 1 * 1000; ///< Time to wait for termination response. Default is 1 second }; // --------------------------------------------------------------------------- -template <typename T> -SlangResult JSONRPCConnection::toValidNativeOrSendError(const JSONValue& value, T* data, const JSONValue& id) +template<typename T> +SlangResult JSONRPCConnection::toValidNativeOrSendError( + const JSONValue& value, + T* data, + const JSONValue& id) { const RttiInfo* rttiInfo = GetRttiInfo<T>::get(); @@ -191,7 +270,10 @@ SlangResult JSONRPCConnection::toValidNativeOrSendError(const JSONValue& value, if (rttiInfo->isNamed()) { const NamedRttiInfo* namedRttiInfo = static_cast<const NamedRttiInfo*>(rttiInfo); - m_diagnosticSink.diagnose(SourceLoc(), JSONDiagnostics::argsAreInvalid, namedRttiInfo->m_name); + m_diagnosticSink.diagnose( + SourceLoc(), + JSONDiagnostics::argsAreInvalid, + namedRttiInfo->m_name); } return sendError(JSONRPC::ErrorCode::InvalidRequest, id); @@ -202,4 +284,3 @@ SlangResult JSONRPCConnection::toValidNativeOrSendError(const JSONValue& value, } // namespace Slang #endif // SLANG_COMPILER_CORE_JSON_RPC_CONNECTION_H - diff --git a/source/compiler-core/slang-json-rpc.cpp b/source/compiler-core/slang-json-rpc.cpp index f4a61da1e..bf96edefa 100644 --- a/source/compiler-core/slang-json-rpc.cpp +++ b/source/compiler-core/slang-json-rpc.cpp @@ -1,17 +1,18 @@ #include "slang-json-rpc.h" #include "slang-com-helper.h" - #include "slang-json-native.h" -namespace Slang { +namespace Slang +{ // https://www.jsonrpc.org/specification /* static */ const UnownedStringSlice JSONRPC::jsonRpc = UnownedStringSlice::fromLiteral("jsonrpc"); -/* static */const UnownedStringSlice JSONRPC::jsonRpcVersion = UnownedStringSlice::fromLiteral("2.0"); -/* static */const UnownedStringSlice JSONRPC::id = UnownedStringSlice::fromLiteral("id"); +/* static */ const UnownedStringSlice JSONRPC::jsonRpcVersion = + UnownedStringSlice::fromLiteral("2.0"); +/* static */ const UnownedStringSlice JSONRPC::id = UnownedStringSlice::fromLiteral("id"); static const auto g_result = UnownedStringSlice::fromLiteral("result"); static const auto g_error = UnownedStringSlice::fromLiteral("error"); @@ -29,7 +30,8 @@ static const StructRttiInfo _makeJSONRPCErrorResponse_ErrorRtti() builder.addField("message", &obj.message); return builder.make(); } -/* static */const StructRttiInfo JSONRPCErrorResponse::Error::g_rttiInfo = _makeJSONRPCErrorResponse_ErrorRtti(); +/* static */ const StructRttiInfo JSONRPCErrorResponse::Error::g_rttiInfo = + _makeJSONRPCErrorResponse_ErrorRtti(); static const StructRttiInfo _makeJSONRPCErrorResponseRtti() { @@ -43,7 +45,8 @@ static const StructRttiInfo _makeJSONRPCErrorResponseRtti() return builder.make(); } -/* static */const StructRttiInfo JSONRPCErrorResponse::g_rttiInfo = _makeJSONRPCErrorResponseRtti(); +/* static */ const StructRttiInfo JSONRPCErrorResponse::g_rttiInfo = + _makeJSONRPCErrorResponseRtti(); static const StructRttiInfo _makeJSONRPCCallResponseRtti() { @@ -58,7 +61,7 @@ static const StructRttiInfo _makeJSONRPCCallResponseRtti() return builder.make(); } -/* static */const StructRttiInfo JSONRPCCall::g_rttiInfo = _makeJSONRPCCallResponseRtti(); +/* static */ const StructRttiInfo JSONRPCCall::g_rttiInfo = _makeJSONRPCCallResponseRtti(); static const StructRttiInfo _makeJSONResultResponseResponseRtti() { @@ -71,9 +74,12 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return builder.make(); } -/* static */const StructRttiInfo JSONResultResponse::g_rttiInfo = _makeJSONResultResponseResponseRtti(); +/* static */ const StructRttiInfo JSONResultResponse::g_rttiInfo = + _makeJSONResultResponseResponseRtti(); -/* static */JSONRPCMessageType JSONRPCUtil::getMessageType(JSONContainer* container, const JSONValue& value) +/* static */ JSONRPCMessageType JSONRPCUtil::getMessageType( + JSONContainer* container, + const JSONValue& value) { if (value.getKind() == JSONValue::Kind::Object) { @@ -103,13 +109,18 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return JSONRPCMessageType::Invalid; } -/* static */SlangResult JSONRPCUtil::parseJSON(const UnownedStringSlice& slice, JSONContainer* container, DiagnosticSink* sink, JSONValue& outValue) +/* static */ SlangResult JSONRPCUtil::parseJSON( + const UnownedStringSlice& slice, + JSONContainer* container, + DiagnosticSink* sink, + JSONValue& outValue) { SourceManager* sourceManager = sink->getSourceManager(); // Now need to parse as JSON String contents(slice); - SourceFile* sourceFile = sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents); + SourceFile* sourceFile = + sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents); SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr, SourceLoc()); JSONLexer lexer; @@ -124,7 +135,12 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return SLANG_OK; } -/* static */SlangResult JSONRPCUtil::convertToNative(JSONContainer* container, const JSONValue& value, DiagnosticSink* sink, const RttiInfo* rttiInfo, void* out) +/* static */ SlangResult JSONRPCUtil::convertToNative( + JSONContainer* container, + const JSONValue& value, + DiagnosticSink* sink, + const RttiInfo* rttiInfo, + void* out) { auto typeMap = JSONNativeUtil::getTypeFuncsMap(); @@ -133,7 +149,11 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return SLANG_OK; } -/* static */SlangResult JSONRPCUtil::convertToJSON(const RttiInfo* rttiInfo, const void* in, DiagnosticSink* sink, StringBuilder& out) +/* static */ SlangResult JSONRPCUtil::convertToJSON( + const RttiInfo* rttiInfo, + const void* in, + DiagnosticSink* sink, + StringBuilder& out) { SourceManager* sourceManager = sink->getSourceManager(); JSONContainer container(sourceManager); @@ -153,7 +173,7 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return SLANG_OK; } -/* static */JSONValue JSONRPCUtil::getId(JSONContainer* container, const JSONValue& root) +/* static */ JSONValue JSONRPCUtil::getId(JSONContainer* container, const JSONValue& root) { if (root.getKind() == JSONValue::Kind::Object) { @@ -162,7 +182,8 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() if (key != JSONKey(0)) { auto obj = container->getObject(root); - Index index = obj.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); + Index index = obj.findFirstIndex( + [key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); if (index >= 0) { diff --git a/source/compiler-core/slang-json-rpc.h b/source/compiler-core/slang-json-rpc.h index 6baba7829..b9140934f 100644 --- a/source/compiler-core/slang-json-rpc.h +++ b/source/compiler-core/slang-json-rpc.h @@ -1,29 +1,28 @@ #ifndef SLANG_COMPILER_CORE_JSON_RPC_H #define SLANG_COMPILER_CORE_JSON_RPC_H -#include "slang.h" +#include "../core/slang-http.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" - -#include "slang-json-value.h" - #include "slang-json-parser.h" -#include "../core/slang-http.h" +#include "slang-json-value.h" +#include "slang.h" -namespace Slang { +namespace Slang +{ /// Struct to hold values associated with JSON-RPC struct JSONRPC { enum class ErrorCode { - ParseError = -32700, ///< Invalid JSON was received by the server. - InvalidRequest = -32600, ///< The JSON sent is not a valid Request object. - MethodNotFound = -32601, ///< The method does not exist / is not available. - InvalidParams = -32602, ///< Invalid method parameter(s). - InternalError = -32603, ///< Internal JSON - RPC error. + ParseError = -32700, ///< Invalid JSON was received by the server. + InvalidRequest = -32600, ///< The JSON sent is not a valid Request object. + MethodNotFound = -32601, ///< The method does not exist / is not available. + InvalidParams = -32602, ///< Invalid method parameter(s). + InternalError = -32603, ///< Internal JSON - RPC error. - ServerImplStart = -32000, ///< Server implementation defined error range + ServerImplStart = -32000, ///< Server implementation defined error range ServerImplEnd = -32099, }; @@ -32,9 +31,9 @@ struct JSONRPC auto kind = value.getKind(); switch (kind) { - case JSONValue::Kind::Integer: - case JSONValue::Kind::Invalid: - case JSONValue::Kind::String: + case JSONValue::Kind::Integer: + case JSONValue::Kind::Invalid: + case JSONValue::Kind::String: { return true; } @@ -53,30 +52,36 @@ struct JSONRPCErrorResponse { bool isValid() const { return code != 0; } - Int code = 0; ///< Value from ErrorCode - UnownedStringSlice message; ///< Error message - + Int code = 0; ///< Value from ErrorCode + UnownedStringSlice message; ///< Error message + static const StructRttiInfo g_rttiInfo; }; - bool isValid() const { return jsonrpc == JSONRPC::jsonRpcVersion && error.isValid() && JSONRPC::isIdOk(id); } + bool isValid() const + { + return jsonrpc == JSONRPC::jsonRpcVersion && error.isValid() && JSONRPC::isIdOk(id); + } UnownedStringSlice jsonrpc = JSONRPC::jsonRpcVersion; Error error; - JSONValue data; ///< Optional data describing the errro - JSONValue id; ///< Id associated with this request + JSONValue data; ///< Optional data describing the errro + JSONValue id; ///< Id associated with this request static const StructRttiInfo g_rttiInfo; }; struct JSONRPCCall { - bool isValid() const { return method.getLength() > 0 && jsonrpc == JSONRPC::jsonRpcVersion && JSONRPC::isIdOk(id); } + bool isValid() const + { + return method.getLength() > 0 && jsonrpc == JSONRPC::jsonRpcVersion && JSONRPC::isIdOk(id); + } UnownedStringSlice jsonrpc = JSONRPC::jsonRpcVersion; - UnownedStringSlice method; ///< The name of the method - JSONValue params; ///< Can be invalid/array/object - JSONValue id; ///< Id associated with this request + UnownedStringSlice method; ///< The name of the method + JSONValue params; ///< Can be invalid/array/object + JSONValue id; ///< Id associated with this request static const StructRttiInfo g_rttiInfo; }; @@ -86,8 +91,8 @@ struct JSONResultResponse bool isValid() const { return jsonrpc == JSONRPC::jsonRpcVersion && JSONRPC::isIdOk(id); } UnownedStringSlice jsonrpc = JSONRPC::jsonRpcVersion; - JSONValue result; ///< The result value - JSONValue id; ///< Id associated with this request + JSONValue result; ///< The result value + JSONValue id; ///< Id associated with this request static const StructRttiInfo g_rttiInfo; }; @@ -105,30 +110,50 @@ enum class JSONRPCMessageType class JSONRPCUtil { public: - - /// Determine the response type + /// Determine the response type static JSONRPCMessageType getMessageType(JSONContainer* container, const JSONValue& value); - /// Parse slice into JSONContainer. outValue is the root of the hierarchy. - /// NOTE! Uses and *assumes* there is a source manager on the sink. outValue is likely only usable whilst the sourceManger is in scope - /// The sourceLoc can only be interpretted with the sourceLoc anyway - static SlangResult parseJSON(const UnownedStringSlice& slice, JSONContainer* container, DiagnosticSink* sink, JSONValue& outValue); - - /// Convert value into out - static SlangResult convertToNative(JSONContainer* container, const JSONValue& value, DiagnosticSink* sink, const RttiInfo* rttiInfo, void* out); - template <typename T> - static SlangResult convertToNative(JSONContainer* container, const JSONValue& value, DiagnosticSink* sink, T& out) { return convertToNative(container, value, sink, GetRttiInfo<T>::get(), (void*)&out); } + /// Parse slice into JSONContainer. outValue is the root of the hierarchy. + /// NOTE! Uses and *assumes* there is a source manager on the sink. outValue is likely only + /// usable whilst the sourceManger is in scope The sourceLoc can only be interpretted with the + /// sourceLoc anyway + static SlangResult parseJSON( + const UnownedStringSlice& slice, + JSONContainer* container, + DiagnosticSink* sink, + JSONValue& outValue); + + /// Convert value into out + static SlangResult convertToNative( + JSONContainer* container, + const JSONValue& value, + DiagnosticSink* sink, + const RttiInfo* rttiInfo, + void* out); + template<typename T> + static SlangResult convertToNative( + JSONContainer* container, + const JSONValue& value, + DiagnosticSink* sink, + T& out) + { + return convertToNative(container, value, sink, GetRttiInfo<T>::get(), (void*)&out); + } - /// Convert to JSON - static SlangResult convertToJSON(const RttiInfo* rttiInfo, const void* in, DiagnosticSink* sink, StringBuilder& out); + /// Convert to JSON + static SlangResult convertToJSON( + const RttiInfo* rttiInfo, + const void* in, + DiagnosticSink* sink, + StringBuilder& out); - template <typename T> + template<typename T> static SlangResult convertToJSON(const T* in, DiagnosticSink* sink, StringBuilder& out) { return convertToJSON(GetRttiInfo<T>::get(), (const void*)in, sink, out); } - /// Get an id directly from root (assumed id: is in root object definition). + /// Get an id directly from root (assumed id: is in root object definition). static JSONValue getId(JSONContainer* container, const JSONValue& root); }; diff --git a/source/compiler-core/slang-json-source-map-util.cpp b/source/compiler-core/slang-json-source-map-util.cpp index f66ee50da..99fe25546 100644 --- a/source/compiler-core/slang-json-source-map-util.cpp +++ b/source/compiler-core/slang-json-source-map-util.cpp @@ -1,21 +1,22 @@ #include "slang-json-source-map-util.h" -#include "slang-com-helper.h" - -#include "../core/slang-string-util.h" #include "../core/slang-blob.h" - +#include "../core/slang-string-util.h" +#include "slang-com-helper.h" #include "slang-json-native.h" -namespace Slang { +namespace Slang +{ /* -Support for source maps. Source maps provide a standardized mechanism to associate a location in one output file -with another. +Support for source maps. Source maps provide a standardized mechanism to associate a location in one +output file with another. -* [Source Map Proposal](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1) +* [Source Map +Proposal](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1) * [Chrome Source Map post](https://developer.chrome.com/blog/sourcemaps/) -* [Base64 VLQs in Source Maps](https://www.lucidchart.com/techblog/2019/08/22/decode-encoding-base64-vlqs-source-maps/) +* [Base64 VLQs in Source +Maps](https://www.lucidchart.com/techblog/2019/08/22/decode-encoding-base64-vlqs-source-maps/) Example... @@ -30,7 +31,8 @@ Example... } */ -namespace { // anonymous +namespace +{ // anonymous struct JSONSourceMap { @@ -38,14 +40,16 @@ struct JSONSourceMap int32_t version = 3; /// An optional name of the generated code that this source map is associated with. String file; - /// An optional source root, useful for relocating source files on a server or removing repeated values in - /// the “sources” entry. This value is prepended to the individual entries in the “source” field. + /// An optional source root, useful for relocating source files on a server or removing repeated + /// values in the “sources” entry. This value is prepended to the individual entries in the + /// “source” field. String sourceRoot; /// A list of original sources used by the “mappings” entry. List<UnownedStringSlice> sources; - /// An optional list of source content, useful when the “source” can’t be hosted. The contents are listed in the same order as the sources in line 5. - /// “null” may be used if some original sources should be retrieved by name. - /// Because could be a string or nullptr, we use JSONValue to hold value. + /// An optional list of source content, useful when the “source” can’t be hosted. The contents + /// are listed in the same order as the sources in line 5. “null” may be used if some original + /// sources should be retrieved by name. Because could be a string or nullptr, we use JSONValue + /// to hold value. List<JSONValue> sourcesContent; /// A list of symbol names used by the “mappings” entry. List<UnownedStringSlice> names; @@ -55,7 +59,7 @@ struct JSONSourceMap static const StructRttiInfo g_rttiInfo; }; -} // anonymous +} // namespace static const StructRttiInfo _makeJSONSourceMap_Rtti() { @@ -73,10 +77,11 @@ static const StructRttiInfo _makeJSONSourceMap_Rtti() return builder.make(); } -/* static */const StructRttiInfo JSONSourceMap::g_rttiInfo = _makeJSONSourceMap_Rtti(); +/* static */ const StructRttiInfo JSONSourceMap::g_rttiInfo = _makeJSONSourceMap_Rtti(); // Encode a 6 bit value to VLQ encoding -static const unsigned char g_vlqEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const unsigned char g_vlqEncodeTable[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; struct VlqDecodeTable { @@ -88,19 +93,22 @@ struct VlqDecodeTable map[g_vlqEncodeTable[i]] = int8_t(i); } } - /// Returns a *negative* value if invalid - SLANG_FORCE_INLINE int8_t operator[](unsigned char c) const { return (c & ~char(0x7f)) ? -1 : map[c]; } + /// Returns a *negative* value if invalid + SLANG_FORCE_INLINE int8_t operator[](unsigned char c) const + { + return (c & ~char(0x7f)) ? -1 : map[c]; + } int8_t map[128]; }; static const VlqDecodeTable g_vlqDecodeTable; -/* +/* https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1# -The VLQ is a Base64 value, where the most significant bit (the 6th bit) is used as the continuation -bit, and the “digits” are encoded into the string least significant first, and where the least significant -bit of the first digit is used as the sign bit. */ +The VLQ is a Base64 value, where the most significant bit (the 6th bit) is used as the continuation +bit, and the “digits” are encoded into the string least significant first, and where the least +significant bit of the first digit is used as the sign bit. */ static SlangResult _decode(UnownedStringSlice& ioEncoded, Index& out) { @@ -125,12 +133,11 @@ static SlangResult _decode(UnownedStringSlice& ioEncoded, Index& out) { return SLANG_FAIL; } - + v += (decodeValue & 0x1f) << shift; shift += 5; - } - while (decodeValue & 0x20); + } while (decodeValue & 0x20); } // Save out the remaining part @@ -148,31 +155,34 @@ void _encode(Index v, StringBuilder& out) // We want to make v always positive to encode // we use the last bit to indicate negativity - v = (v < 0) ? (1 - v) : v; - + v = (v < 0) ? (1 - v) : v; + // We'll use a simple buffer, so as to not have to constantly update he StringBuffer char dst[8]; char* cur = dst; - do + do { const Index nextV = v >> 5; const Index encodeValue = (v & 0x1f) + (nextV ? 0x20 : 0); // Encode 5 bits, plus continuation bit char c = g_vlqEncodeTable[encodeValue]; - + // Save the char *cur++ = c; - + v = nextV; - } - while (v); + } while (v); out.append(dst, cur); } -/* static */SlangResult JSONSourceMapUtil::decode(JSONContainer* container, JSONValue root, DiagnosticSink* sink, SourceMap& outSourceMap) +/* static */ SlangResult JSONSourceMapUtil::decode( + JSONContainer* container, + JSONValue root, + DiagnosticSink* sink, + SourceMap& outSourceMap) { outSourceMap.clear(); @@ -192,7 +202,7 @@ void _encode(Index v, StringBuilder& out) outSourceMap.m_sourceRoot = native.sourceRoot; const Count sourcesCount = native.sources.getCount(); - + // These should all be unique, but for simplicity, we build a table outSourceMap.m_sources.setCount(sourcesCount); for (Index i = 0; i < sourcesCount; ++i) @@ -237,10 +247,10 @@ void _encode(Index v, StringBuilder& out) List<UnownedStringSlice> lines; StringUtil::split(native.mappings, ';', lines); - + List<UnownedStringSlice> segments; - // Index into sources + // Index into sources Index sourceFileIndex = 0; Index sourceLine = 0; @@ -280,9 +290,17 @@ void _encode(Index v, StringBuilder& out) // It can be 4 or 5 parts if (segment.getLength()) { - /* If present, an zero-based index into the "sources" list. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. - If present, the zero-based starting line in the original source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field. - If present, the zero-based starting column of the line in the source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field. + /* If present, an zero-based index into the "sources" list. This field is a base 64 + VLQ relative to the previous occurrence of this field, unless this is the first + occurrence of this field, in which case the whole value is represented. If + present, the zero-based starting line in the original source represented. This + field is a base 64 VLQ relative to the previous occurrence of this field, unless + this is the first occurrence of this field, in which case the whole value is + represented. Always present if there is a source field. If present, the + zero-based starting column of the line in the source represented. This field is a + base 64 VLQ relative to the previous occurrence of this field, unless this is the + first occurrence of this field, in which case the whole value is represented. + Always present if there is a source field. */ Index sourceFileDelta; @@ -304,9 +322,10 @@ void _encode(Index v, StringBuilder& out) // 5 parts if (segment.getLength() > 0) { - /* If present, the zero - based index into the "names" list associated with this segment. - This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence - of this field, in which case the whole value is represented. + /* If present, the zero - based index into the "names" list associated with this + segment. This field is a base 64 VLQ relative to the previous occurrence of this + field, unless this is the first occurrence of this field, in which case the + whole value is represented. */ Index nameDelta; @@ -334,7 +353,11 @@ void _encode(Index v, StringBuilder& out) return SLANG_OK; } -SlangResult JSONSourceMapUtil::encode(const SourceMap& sourceMap, JSONContainer* container, DiagnosticSink* sink, JSONValue& outValue) +SlangResult JSONSourceMapUtil::encode( + const SourceMap& sourceMap, + JSONContainer* container, + DiagnosticSink* sink, + JSONValue& outValue) { // Convert to native JSONSourceMap native; @@ -359,10 +382,11 @@ SlangResult JSONSourceMapUtil::encode(const SourceMap& sourceMap, JSONContainer* for (Index i = 0; i < count; ++i) { const auto srcValue = sourceMap.m_sourcesContent[i]; - - const JSONValue dstValue = (srcValue == StringSlicePool::kNullHandle) ? - native.sourcesContent[i] = JSONValue::makeNull() : - container->createString(sourceMap.m_slicePool.getSlice(srcValue)); + + const JSONValue dstValue = + (srcValue == StringSlicePool::kNullHandle) + ? native.sourcesContent[i] = JSONValue::makeNull() + : container->createString(sourceMap.m_slicePool.getSlice(srcValue)); native.sourcesContent[i] = dstValue; } @@ -408,7 +432,7 @@ SlangResult JSONSourceMapUtil::encode(const SourceMap& sourceMap, JSONContainer* // We reset the generated column index at the start of each new generated line Index generatedColumn = 0; - + for (Index j = 0; j < entriesCount; ++j) { auto entry = entries[j]; @@ -459,18 +483,22 @@ SlangResult JSONSourceMapUtil::encode(const SourceMap& sourceMap, JSONContainer* RttiTypeFuncsMap typeMap = JSONNativeUtil::getTypeFuncsMap(); NativeToJSONConverter converter(container, &typeMap, sink); - SLANG_RETURN_ON_FAIL(converter.convert(GetRttiInfo<JSONSourceMap>::get(), &native, outValue)); + SLANG_RETURN_ON_FAIL( + converter.convert(GetRttiInfo<JSONSourceMap>::get(), &native, outValue)); } return SLANG_OK; } -/* static */SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, SourceMap& outSourceMap) +/* static */ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, SourceMap& outSourceMap) { return read(blob, nullptr, outSourceMap); } -SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink, SourceMap& outSourceMap) +SlangResult JSONSourceMapUtil::read( + ISlangBlob* blob, + DiagnosticSink* parentSink, + SourceMap& outSourceMap) { outSourceMap.clear(); @@ -485,7 +513,8 @@ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink JSONValue rootValue; { // Now need to parse as JSON - SourceFile* sourceFile = sourceManager.createSourceFileWithBlob(PathInfo::makeUnknown(), blob); + SourceFile* sourceFile = + sourceManager.createSourceFileWithBlob(PathInfo::makeUnknown(), blob); SourceView* sourceView = sourceManager.createSourceView(sourceFile, nullptr, SourceLoc()); JSONLexer lexer; @@ -505,7 +534,9 @@ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink } -/* static */SlangResult JSONSourceMapUtil::write(const SourceMap& sourceMap, ComPtr<ISlangBlob>& outBlob) +/* static */ SlangResult JSONSourceMapUtil::write( + const SourceMap& sourceMap, + ComPtr<ISlangBlob>& outBlob) { SourceManager sourceMapSourceManager; sourceMapSourceManager.initialize(nullptr, nullptr); @@ -517,7 +548,10 @@ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink return SLANG_OK; } -/* static */ SlangResult JSONSourceMapUtil::write(const SourceMap& sourceMap, DiagnosticSink* sink, ComPtr<ISlangBlob>& outBlob) +/* static */ SlangResult JSONSourceMapUtil::write( + const SourceMap& sourceMap, + DiagnosticSink* sink, + ComPtr<ISlangBlob>& outBlob) { auto sourceManager = sink->getSourceManager(); diff --git a/source/compiler-core/slang-json-source-map-util.h b/source/compiler-core/slang-json-source-map-util.h index d61936ce4..0e6f4248c 100644 --- a/source/compiler-core/slang-json-source-map-util.h +++ b/source/compiler-core/slang-json-source-map-util.h @@ -1,29 +1,40 @@ #ifndef SLANG_COMPILER_CORE_JSON_SOURCE_MAP_UTIL_H #define SLANG_COMPILER_CORE_JSON_SOURCE_MAP_UTIL_H -#include "slang-source-map.h" - #include "slang-json-value.h" +#include "slang-source-map.h" -namespace Slang { - -struct JSONSourceMapUtil +namespace Slang { - /// Decode from root into the source map - static SlangResult decode(JSONContainer* container, JSONValue root, DiagnosticSink* sink, SourceMap& out); - - /// Converts the source map contents into JSON - static SlangResult encode(const SourceMap& sourceMap, JSONContainer* container, DiagnosticSink* sink, JSONValue& outValue); - /// Read the blob (encoded as JSON) as a source map. - /// Sink is optional, and can be passed as nullptr +struct JSONSourceMapUtil +{ + /// Decode from root into the source map + static SlangResult decode( + JSONContainer* container, + JSONValue root, + DiagnosticSink* sink, + SourceMap& out); + + /// Converts the source map contents into JSON + static SlangResult encode( + const SourceMap& sourceMap, + JSONContainer* container, + DiagnosticSink* sink, + JSONValue& outValue); + + /// Read the blob (encoded as JSON) as a source map. + /// Sink is optional, and can be passed as nullptr static SlangResult read(ISlangBlob* blob, DiagnosticSink* sink, SourceMap& outSourceMap); static SlangResult read(ISlangBlob* blob, SourceMap& outSourceMap); - /// Write source map to outBlob JSON + /// Write source map to outBlob JSON static SlangResult write(const SourceMap& sourceMap, ComPtr<ISlangBlob>& outBlob); - /// Write out the source map into a blob - static SlangResult write(const SourceMap& sourceMap, DiagnosticSink* sink, ComPtr<ISlangBlob>& outBlob); + /// Write out the source map into a blob + static SlangResult write( + const SourceMap& sourceMap, + DiagnosticSink* sink, + ComPtr<ISlangBlob>& outBlob); }; } // namespace Slang diff --git a/source/compiler-core/slang-json-value.cpp b/source/compiler-core/slang-json-value.cpp index 2e1eb6812..2738058ee 100644 --- a/source/compiler-core/slang-json-value.cpp +++ b/source/compiler-core/slang-json-value.cpp @@ -4,28 +4,28 @@ #include "../core/slang-string-escape-util.h" #include "../core/slang-string-util.h" -namespace Slang { - -/* static */const JSONValue::Kind JSONValue::g_typeToKind[] = +namespace Slang { - JSONValue::Kind::Invalid, // Invalid - JSONValue::Kind::Bool, // True, - JSONValue::Kind::Bool, // False - JSONValue::Kind::Null, // Null, +/* static */ const JSONValue::Kind JSONValue::g_typeToKind[] = { + JSONValue::Kind::Invalid, // Invalid + + JSONValue::Kind::Bool, // True, + JSONValue::Kind::Bool, // False + JSONValue::Kind::Null, // Null, - JSONValue::Kind::String, // StringLexeme, - JSONValue::Kind::Integer, // IntegerLexeme, - JSONValue::Kind::Float, // FloatLexeme, + JSONValue::Kind::String, // StringLexeme, + JSONValue::Kind::Integer, // IntegerLexeme, + JSONValue::Kind::Float, // FloatLexeme, - JSONValue::Kind::Integer, // IntegerValue, - JSONValue::Kind::Float, // FloatValue, - JSONValue::Kind::String, // StringValue, + JSONValue::Kind::Integer, // IntegerValue, + JSONValue::Kind::Float, // FloatValue, + JSONValue::Kind::String, // StringValue, - JSONValue::Kind::String, // StringRepresentation + JSONValue::Kind::String, // StringRepresentation - JSONValue::Kind::Array, // Array, - JSONValue::Kind::Object, // Object, + JSONValue::Kind::Array, // Array, + JSONValue::Kind::Object, // Object, }; static bool _isDefault(const RttiInfo* type, const void* in) @@ -44,7 +44,7 @@ static OtherRttiInfo _getJSONValueRttiInfo() info.m_typeFuncs = GetRttiTypeFuncs<JSONValue>::getFuncs(); return info; } -/* static */const OtherRttiInfo JSONValue::g_rttiInfo = _getJSONValueRttiInfo(); +/* static */ const OtherRttiInfo JSONValue::g_rttiInfo = _getJSONValueRttiInfo(); static JSONKeyValue _makeInvalidKeyValue() { @@ -54,7 +54,7 @@ static JSONKeyValue _makeInvalidKeyValue() return keyValue; } -/* static */JSONKeyValue g_invalid = _makeInvalidKeyValue(); +/* static */ JSONKeyValue g_invalid = _makeInvalidKeyValue(); /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -66,15 +66,15 @@ bool JSONValue::asBool() const { switch (type) { - case JSONValue::Type::True: return true; - case JSONValue::Type::False: - case JSONValue::Type::Null: + case JSONValue::Type::True: return true; + case JSONValue::Type::False: + case JSONValue::Type::Null: { return false; } - case JSONValue::Type::IntegerValue: return intValue != 0; - case JSONValue::Type::FloatValue: return floatValue != 0; - default: break; + case JSONValue::Type::IntegerValue: return intValue != 0; + case JSONValue::Type::FloatValue: return floatValue != 0; + default: break; } if (isLexeme(type)) @@ -85,7 +85,7 @@ bool JSONValue::asBool() const { SLANG_ASSERT(!"Not bool convertable"); } - + return false; } @@ -93,15 +93,14 @@ int64_t JSONValue::asInteger() const { switch (type) { - case JSONValue::Type::True: return 1; - case JSONValue::Type::False: - case JSONValue::Type::Null: + case JSONValue::Type::True: return 1; + case JSONValue::Type::False: + case JSONValue::Type::Null: { return 0; } - case JSONValue::Type::IntegerValue: return intValue; - case JSONValue::Type::FloatValue: return int64_t(floatValue); - break; + case JSONValue::Type::IntegerValue: return intValue; + case JSONValue::Type::FloatValue: return int64_t(floatValue); break; } if (isLexeme(type)) @@ -120,15 +119,15 @@ double JSONValue::asFloat() const { switch (type) { - case JSONValue::Type::True: return 1.0; - case JSONValue::Type::False: - case JSONValue::Type::Null: + case JSONValue::Type::True: return 1.0; + case JSONValue::Type::False: + case JSONValue::Type::Null: { return 0.0; } - case JSONValue::Type::IntegerValue: return double(intValue); - case JSONValue::Type::FloatValue: return floatValue; - default: break; + case JSONValue::Type::IntegerValue: return double(intValue); + case JSONValue::Type::FloatValue: return floatValue; + default: break; } if (isLexeme(type)) @@ -139,7 +138,7 @@ double JSONValue::asFloat() const { SLANG_ASSERT(!"Not float convertable"); } - + return 0; } @@ -197,7 +196,8 @@ UnownedStringSlice PersistentJSONValue::getSlice() const void PersistentJSONValue::set(const UnownedStringSlice& slice, SourceLoc inLoc) { - StringRepresentation* oldRep = (type == JSONValue::Type::StringRepresentation) ? stringRep : nullptr; + StringRepresentation* oldRep = + (type == JSONValue::Type::StringRepresentation) ? stringRep : nullptr; type = Type::StringRepresentation; loc = inLoc; @@ -205,13 +205,11 @@ void PersistentJSONValue::set(const UnownedStringSlice& slice, SourceLoc inLoc) StringRepresentation* newRep = nullptr; const auto sliceLength = slice.getLength(); - + // If we have an oldRep that is unique and large enough reuse it if (sliceLength) { - if (oldRep && - oldRep->isUniquelyReferenced() && - sliceLength <= oldRep->capacity) + if (oldRep && oldRep->isUniquelyReferenced() && sliceLength <= oldRep->capacity) { oldRep->setContents(slice); newRep = oldRep; @@ -220,7 +218,7 @@ void PersistentJSONValue::set(const UnownedStringSlice& slice, SourceLoc inLoc) } else { - newRep = StringRepresentation::createWithReference(slice); + newRep = StringRepresentation::createWithReference(slice); } SLANG_ASSERT(newRep->debugGetReferenceCount() >= 1); @@ -248,25 +246,24 @@ bool PersistentJSONValue::operator==(const ThisType& rhs) const return true; } - if (type != rhs.type || - loc != rhs.loc) + if (type != rhs.type || loc != rhs.loc) { return false; } switch (type) { - case Type::Invalid: - case Type::True: - case Type::False: - case Type::Null: + case Type::Invalid: + case Type::True: + case Type::False: + case Type::Null: { // The type is all that needs to be checked return true; } - case Type::IntegerValue: return intValue == rhs.intValue; - case Type::FloatValue: return floatValue == rhs.floatValue; - case Type::StringRepresentation: + case Type::IntegerValue: return intValue == rhs.intValue; + case Type::FloatValue: return floatValue == rhs.floatValue; + case Type::StringRepresentation: { if (stringRep == rhs.stringRep) { @@ -276,7 +273,7 @@ bool PersistentJSONValue::operator==(const ThisType& rhs) const auto rhsSlice = StringRepresentation::asSlice(rhs.stringRep); return thisSlice == rhsSlice; } - default: break; + default: break; } SLANG_ASSERT(!"Not valid Persistent type"); @@ -290,8 +287,8 @@ void PersistentJSONValue::_init(const JSONValue& in, JSONContainer* container) switch (in.type) { - case Type::StringValue: - case Type::StringLexeme: + case Type::StringValue: + case Type::StringLexeme: { if (!container) { @@ -301,7 +298,7 @@ void PersistentJSONValue::_init(const JSONValue& in, JSONContainer* container) _init(container->getTransientString(in), in.loc); break; } - case Type::StringRepresentation: + case Type::StringRepresentation: { *(JSONValue*)this = in; if (stringRep) @@ -310,27 +307,27 @@ void PersistentJSONValue::_init(const JSONValue& in, JSONContainer* container) } break; } - case Type::IntegerLexeme: + case Type::IntegerLexeme: { type = JSONValue::Type::IntegerValue; intValue = container->asInteger(in); loc = in.loc; break; } - case Type::FloatLexeme: + case Type::FloatLexeme: { type = JSONValue::Type::FloatValue; floatValue = container->asFloat(in); loc = in.loc; break; } - case Type::Array: - case Type::Object: + case Type::Array: + case Type::Object: { SLANG_ASSERT(!"Not a simple JSON type"); break; } - default: + default: { *(JSONValue*)this = in; break; @@ -364,9 +361,8 @@ void PersistentJSONValue::set(const JSONValue& in, JSONContainer* container) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -JSONContainer::JSONContainer(SourceManager* sourceManager): - m_slicePool(StringSlicePool::Style::Default), - m_sourceManager(sourceManager) +JSONContainer::JSONContainer(SourceManager* sourceManager) + : m_slicePool(StringSlicePool::Style::Default), m_sourceManager(sourceManager) { // Index 0 is the empty array or object _addRange(Range::Type::None, 0, 0); @@ -385,7 +381,7 @@ void JSONContainer::reset() m_currentView = nullptr; } -/* static */bool JSONContainer::areKeysUnique(const JSONKeyValue* keyValues, Index keyValueCount) +/* static */ bool JSONContainer::areKeysUnique(const JSONKeyValue* keyValues, Index keyValueCount) { for (Index i = 1; i < keyValueCount; ++i) { @@ -447,7 +443,10 @@ JSONValue JSONContainer::createArray(const JSONValue* values, Index valuesCount, return value; } -JSONValue JSONContainer::createObject(const JSONKeyValue* keyValues, Index keyValueCount, SourceLoc loc) +JSONValue JSONContainer::createObject( + const JSONKeyValue* keyValues, + Index keyValueCount, + SourceLoc loc) { if (keyValueCount <= 0) { @@ -514,7 +513,9 @@ ArrayView<JSONValue> JSONContainer::getArray(const JSONValue& in) return ArrayView<JSONValue>((JSONValue*)nullptr, 0); } const Range& range = m_ranges[in.rangeIndex]; - SLANG_ASSERT(range.startIndex <= m_arrayValues.getCount() && range.startIndex + range.count <= m_arrayValues.getCount()); + SLANG_ASSERT( + range.startIndex <= m_arrayValues.getCount() && + range.startIndex + range.count <= m_arrayValues.getCount()); return ArrayView<JSONValue>(m_arrayValues.getBuffer() + range.startIndex, range.count); } @@ -558,27 +559,27 @@ UnownedStringSlice JSONContainer::getString(const JSONValue& in) { switch (in.type) { - case JSONValue::Type::StringValue: + case JSONValue::Type::StringValue: { return getStringFromKey(in.stringKey); } - case JSONValue::Type::StringLexeme: + case JSONValue::Type::StringLexeme: { auto slice = getTransientString(in); auto handle = m_slicePool.add(slice); return m_slicePool.getSlice(handle); } - case JSONValue::Type::StringRepresentation: + case JSONValue::Type::StringRepresentation: { return StringRepresentation::asSlice(in.stringRep); } - case JSONValue::Type::Null: + case JSONValue::Type::Null: { return UnownedStringSlice(); } - default: break; + default: break; } - + SLANG_ASSERT(!"Not a string type"); return UnownedStringSlice(); } @@ -587,17 +588,18 @@ UnownedStringSlice JSONContainer::getTransientString(const JSONValue& in) { switch (in.type) { - case JSONValue::Type::StringRepresentation: + case JSONValue::Type::StringRepresentation: { return StringRepresentation::asSlice(in.stringRep); } - case JSONValue::Type::StringValue: + case JSONValue::Type::StringValue: { return getStringFromKey(in.stringKey); } - case JSONValue::Type::StringLexeme: + case JSONValue::Type::StringLexeme: { - StringEscapeHandler* handler = StringEscapeUtil::getHandler(StringEscapeUtil::Style::JSON); + StringEscapeHandler* handler = + StringEscapeUtil::getHandler(StringEscapeUtil::Style::JSON); UnownedStringSlice lexeme = getLexeme(in); UnownedStringSlice unquoted = StringEscapeUtil::unquote(handler, lexeme); @@ -613,7 +615,7 @@ UnownedStringSlice JSONContainer::getTransientString(const JSONValue& in) return unquoted; } } - case JSONValue::Type::Null: + case JSONValue::Type::Null: { return UnownedStringSlice(); } @@ -625,16 +627,17 @@ UnownedStringSlice JSONContainer::getTransientString(const JSONValue& in) JSONKey JSONContainer::getStringKey(const JSONValue& in) { - return (in.type == JSONValue::Type::StringValue) ? in.stringKey : getKey(getTransientString(in)); + return (in.type == JSONValue::Type::StringValue) ? in.stringKey + : getKey(getTransientString(in)); } - + bool JSONContainer::asBool(const JSONValue& value) { switch (value.type) { - case JSONValue::Type::IntegerLexeme: return asInteger(value) != 0; - case JSONValue::Type::FloatLexeme: return asFloat(value) != 0.0; - default: return value.asBool(); + case JSONValue::Type::IntegerLexeme: return asInteger(value) != 0; + case JSONValue::Type::FloatLexeme: return asFloat(value) != 0.0; + default: return value.asBool(); } } @@ -643,26 +646,26 @@ JSONValue JSONContainer::asValue(const JSONValue& inValue) JSONValue value = inValue; switch (value.type) { - case JSONValue::Type::StringLexeme: + case JSONValue::Type::StringLexeme: { const UnownedStringSlice slice = getTransientString(inValue); value.stringKey = getKey(slice); value.type = JSONValue::Type::StringValue; break; } - case JSONValue::Type::IntegerLexeme: + case JSONValue::Type::IntegerLexeme: { value.floatValue = value.asFloat(); value.type = JSONValue::Type::IntegerValue; break; } - case JSONValue::Type::FloatLexeme: + case JSONValue::Type::FloatLexeme: { value.floatValue = value.asFloat(); value.type = JSONValue::Type::FloatValue; break; } - default: break; + default: break; } return value; @@ -687,12 +690,14 @@ void JSONContainer::clearSourceManagerDependency(JSONValue* ioValues, Index valu { switch (range.type) { - case Range::Type::Array: + case Range::Type::Array: { - _clearSourceManagerDependency(m_arrayValues.getBuffer() + range.startIndex, range.count); + _clearSourceManagerDependency( + m_arrayValues.getBuffer() + range.startIndex, + range.count); break; } - case Range::Type::Object: + case Range::Type::Object: { const Index count = range.count; auto pairs = m_objectValues.getBuffer() + range.startIndex; @@ -706,7 +711,7 @@ void JSONContainer::clearSourceManagerDependency(JSONValue* ioValues, Index valu } break; } - default: break; + default: break; } } @@ -718,7 +723,7 @@ int64_t JSONContainer::asInteger(const JSONValue& value) { switch (value.type) { - case JSONValue::Type::IntegerLexeme: + case JSONValue::Type::IntegerLexeme: { UnownedStringSlice slice = getLexeme(value); int64_t intValue; @@ -729,8 +734,8 @@ int64_t JSONContainer::asInteger(const JSONValue& value) SLANG_ASSERT(!"Couldn't convert int"); return 0; } - case JSONValue::Type::FloatLexeme: return int64_t(asFloat(value)); - default: return value.asInteger(); + case JSONValue::Type::FloatLexeme: return int64_t(asFloat(value)); + default: return value.asInteger(); } } @@ -738,8 +743,8 @@ double JSONContainer::asFloat(const JSONValue& value) { switch (value.type) { - case JSONValue::Type::IntegerLexeme: return double(asInteger(value)); - case JSONValue::Type::FloatLexeme: + case JSONValue::Type::IntegerLexeme: return double(asInteger(value)); + case JSONValue::Type::FloatLexeme: { UnownedStringSlice slice = getLexeme(value); double floatValue; @@ -750,20 +755,22 @@ double JSONContainer::asFloat(const JSONValue& value) SLANG_ASSERT(!"Couldn't convert double"); return 0.0; } - default: return value.asFloat(); + default: return value.asFloat(); } } Index JSONContainer::findObjectIndex(const JSONValue& obj, JSONKey key) const { auto pairs = getObject(obj); - return pairs.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); + return pairs.findFirstIndex( + [key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); } JSONValue JSONContainer::findObjectValue(const JSONValue& obj, JSONKey key) const { auto pairs = getObject(obj); - const Index index = pairs.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); + const Index index = + pairs.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); return (index >= 0) ? pairs[index].value : JSONValue::makeInvalid(); } @@ -787,7 +794,6 @@ void JSONContainer::addToArray(JSONValue& array, const JSONValue& value) // We can just add to the end array.rangeIndex = _addRange(Range::Type::Array, m_arrayValues.getCount(), 1); m_arrayValues.add(value); - } else { @@ -837,7 +843,10 @@ void JSONContainer::_removeKey(JSONValue& obj, Index globalIndex) if (localIndex < range.count - 1) { auto localBuf = m_objectValues.getBuffer() + range.startIndex; - ::memmove(localBuf + localIndex, localBuf + localIndex + 1, sizeof(*localBuf) * (range.count - (localIndex + 1))); + ::memmove( + localBuf + localIndex, + localBuf + localIndex + 1, + sizeof(*localBuf) * (range.count - (localIndex + 1))); } --range.count; @@ -865,8 +874,8 @@ bool JSONContainer::removeKey(JSONValue& obj, const UnownedStringSlice& slice) return false; } -template <typename T> -/* static */void JSONContainer::_add(Range& ioRange, List<T>& ioList, const T& value) +template<typename T> +/* static */ void JSONContainer::_add(Range& ioRange, List<T>& ioList, const T& value) { // If we have capacity, we can add to the end if (ioRange.count < ioRange.capacity) @@ -938,7 +947,7 @@ void JSONContainer::_destroyRange(Index rangeIndex) // If the range is at the end, shrink it switch (range.type) { - case Range::Type::Array: + case Range::Type::Array: { if (range.startIndex + range.capacity == m_arrayValues.getCount()) { @@ -946,7 +955,7 @@ void JSONContainer::_destroyRange(Index rangeIndex) } break; } - case Range::Type::Object: + case Range::Type::Object: { if (range.startIndex + range.capacity == m_objectValues.getCount()) { @@ -954,7 +963,7 @@ void JSONContainer::_destroyRange(Index rangeIndex) } break; } - default: break; + default: break; } range.type = Range::Type::Destroyed; @@ -971,7 +980,7 @@ void JSONContainer::destroy(JSONValue& value) } void JSONContainer::destroyRecursively(JSONValue& inValue) -{ +{ if (!(inValue.needsDestroy() && m_ranges[inValue.rangeIndex].isActive())) { inValue.type = JSONValue::Type::Invalid; @@ -1000,7 +1009,7 @@ void JSONContainer::destroyRecursively(JSONValue& inValue) for (Index i = 0; i < count; ++i) { auto& value = buf[i]; - // If we have an active range, add to work list, and destroy + // If we have an active range, add to work list, and destroy if (value.needsDestroy() && m_ranges[value.rangeIndex].isActive()) { activeRanges.add(m_ranges[value.rangeIndex]); @@ -1009,7 +1018,7 @@ void JSONContainer::destroyRecursively(JSONValue& inValue) value.type = JSONValue::Type::Invalid; } } - else + else { SLANG_ASSERT(type == Range::Type::Object); @@ -1019,7 +1028,8 @@ void JSONContainer::destroyRecursively(JSONValue& inValue) { auto& keyValue = buf[i]; auto& value = keyValue.value; - // We want to mark that it's in the list so that if we have a badly formed tree we don't read + // We want to mark that it's in the list so that if we have a badly formed tree we + // don't read if (value.needsDestroy() && m_ranges[value.rangeIndex].isActive()) { activeRanges.add(m_ranges[value.rangeIndex]); @@ -1045,7 +1055,10 @@ bool JSONContainer::areEqual(const JSONValue* a, const JSONValue* b, Index count } -/* static */bool JSONContainer::_sameKeyOrder(const JSONKeyValue* a, const JSONKeyValue* b, Index count) +/* static */ bool JSONContainer::_sameKeyOrder( + const JSONKeyValue* a, + const JSONKeyValue* b, + Index count) { for (Index i = 0; i < count; ++i) { @@ -1064,8 +1077,7 @@ bool JSONContainer::_areEqualOrderedKeys(const JSONKeyValue* a, const JSONKeyVal const auto& curA = a[i]; const auto& curB = b[i]; - if (curA.key != curB.key || - !areEqual(curA.value, curB.value)) + if (curA.key != curB.key || !areEqual(curA.value, curB.value)) { return false; } @@ -1102,15 +1114,17 @@ bool JSONContainer::areEqual(const JSONKeyValue* a, const JSONKeyValue* b, Index } else { - // We need to compare with keys in the same order + // We need to compare with keys in the same order List<JSONKeyValue> sortedAs; sortedAs.addRange(a, count); List<JSONKeyValue> sortedBs; sortedBs.addRange(b, count); - sortedAs.sort([](const JSONKeyValue&a, const JSONKeyValue& b) -> bool { return a.key < b.key; }); - sortedBs.sort([](const JSONKeyValue&a, const JSONKeyValue& b) -> bool { return a.key < b.key; }); + sortedAs.sort( + [](const JSONKeyValue& a, const JSONKeyValue& b) -> bool { return a.key < b.key; }); + sortedBs.sort( + [](const JSONKeyValue& a, const JSONKeyValue& b) -> bool { return a.key < b.key; }); return _areEqualOrderedKeys(sortedAs.getBuffer(), sortedBs.getBuffer(), count); } @@ -1132,18 +1146,18 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) { switch (a.type) { - default: - // Invalid are never equal - case JSONValue::Type::Invalid: return false; - case JSONValue::Type::True: - case JSONValue::Type::False: - case JSONValue::Type::Null: + default: + // Invalid are never equal + case JSONValue::Type::Invalid: return false; + case JSONValue::Type::True: + case JSONValue::Type::False: + case JSONValue::Type::Null: { return true; } - case JSONValue::Type::IntegerLexeme:return asInteger(a) == asInteger(b); - case JSONValue::Type::FloatLexeme: return asFloat(a) == asFloat(b); - case JSONValue::Type::StringLexeme: + case JSONValue::Type::IntegerLexeme: return asInteger(a) == asInteger(b); + case JSONValue::Type::FloatLexeme: return asFloat(a) == asFloat(b); + case JSONValue::Type::StringLexeme: { // If the lexemes are equal they are equal UnownedStringSlice lexemeA = getLexeme(a); @@ -1151,15 +1165,15 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) // Else we want to decode the string to be sure if they are equal. return lexemeA == lexemeB || getStringKey(a) == getStringKey(b); } - case JSONValue::Type::IntegerValue: return a.intValue == b.intValue; - case JSONValue::Type::FloatValue: return a.floatValue == b.floatValue; - case JSONValue::Type::StringValue: return a.stringKey == b.stringKey; - case JSONValue::Type::StringRepresentation: + case JSONValue::Type::IntegerValue: return a.intValue == b.intValue; + case JSONValue::Type::FloatValue: return a.floatValue == b.floatValue; + case JSONValue::Type::StringValue: return a.stringKey == b.stringKey; + case JSONValue::Type::StringRepresentation: { - return a.stringRep == b.stringRep || - StringRepresentation::asSlice(a.stringRep) == StringRepresentation::asSlice(b.stringRep); + return a.stringRep == b.stringRep || StringRepresentation::asSlice(a.stringRep) == + StringRepresentation::asSlice(b.stringRep); } - case JSONValue::Type::Array: + case JSONValue::Type::Array: { if (a.rangeIndex == b.rangeIndex) { @@ -1169,9 +1183,10 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) auto arrayB = getArray(b); const Index count = arrayA.getCount(); - return (count == arrayB.getCount()) && areEqual(arrayA.getBuffer(), arrayB.getBuffer(), count); + return (count == arrayB.getCount()) && + areEqual(arrayA.getBuffer(), arrayB.getBuffer(), count); } - case JSONValue::Type::Object: + case JSONValue::Type::Object: { if (a.rangeIndex == b.rangeIndex) { @@ -1181,7 +1196,8 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) const auto bValues = getObject(b); const Index count = aValues.getCount(); - return (count == bValues.getCount()) && areEqual(aValues.getBuffer(), bValues.getBuffer(), count); + return (count == bValues.getCount()) && + areEqual(aValues.getBuffer(), bValues.getBuffer(), count); } } } @@ -1192,10 +1208,10 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) { switch (kind) { - case JSONValue::Kind::String: return getStringKey(a) == getStringKey(b); - case JSONValue::Kind::Integer: return asInteger(a) == asInteger(b); - case JSONValue::Kind::Float: return asFloat(a) == asFloat(b); - default: break; + case JSONValue::Kind::String: return getStringKey(a) == getStringKey(b); + case JSONValue::Kind::Integer: return asInteger(a) == asInteger(b); + case JSONValue::Kind::Float: return asFloat(a) == asFloat(b); + default: break; } } @@ -1207,27 +1223,30 @@ void JSONContainer::traverseRecursively(const JSONValue& value, JSONListener* li typedef JSONValue::Type Type; switch (value.type) - { - case Type::True: return listener->addBoolValue(true, value.loc); - case Type::False: return listener->addBoolValue(false, value.loc); - case Type::Null: return listener->addNullValue(value.loc); - - case Type::StringLexeme: return listener->addLexemeValue(JSONTokenType::StringLiteral, getLexeme(value), value.loc); - case Type::IntegerLexeme: return listener->addLexemeValue(JSONTokenType::IntegerLiteral, getLexeme(value), value.loc); - case Type::FloatLexeme: return listener->addLexemeValue(JSONTokenType::FloatLiteral, getLexeme(value), value.loc); - - case Type::IntegerValue: return listener->addIntegerValue(value.intValue, value.loc); - case Type::FloatValue: return listener->addFloatValue(value.floatValue, value.loc); - case Type::StringValue: + { + case Type::True: return listener->addBoolValue(true, value.loc); + case Type::False: return listener->addBoolValue(false, value.loc); + case Type::Null: return listener->addNullValue(value.loc); + + case Type::StringLexeme: + return listener->addLexemeValue(JSONTokenType::StringLiteral, getLexeme(value), value.loc); + case Type::IntegerLexeme: + return listener->addLexemeValue(JSONTokenType::IntegerLiteral, getLexeme(value), value.loc); + case Type::FloatLexeme: + return listener->addLexemeValue(JSONTokenType::FloatLiteral, getLexeme(value), value.loc); + + case Type::IntegerValue: return listener->addIntegerValue(value.intValue, value.loc); + case Type::FloatValue: return listener->addFloatValue(value.floatValue, value.loc); + case Type::StringValue: { const auto slice = getStringFromKey(value.stringKey); return listener->addStringValue(slice, value.loc); } - case Type::StringRepresentation: + case Type::StringRepresentation: { return listener->addStringValue(getTransientString(value), value.loc); } - case Type::Array: + case Type::Array: { listener->startArray(value.loc); @@ -1241,7 +1260,7 @@ void JSONContainer::traverseRecursively(const JSONValue& value, JSONListener* li listener->endArray(SourceLoc()); break; } - case Type::Object: + case Type::Object: { listener->startObject(value.loc); @@ -1260,7 +1279,7 @@ void JSONContainer::traverseRecursively(const JSONValue& value, JSONListener* li listener->endObject(SourceLoc()); break; } - default: + default: { SLANG_ASSERT(!"Invalid type"); return; @@ -1274,9 +1293,8 @@ void JSONContainer::traverseRecursively(const JSONValue& value, JSONListener* li !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -JSONBuilder::JSONBuilder(JSONContainer* container, Flags flags): - m_container(container), - m_flags(flags) +JSONBuilder::JSONBuilder(JSONContainer* container, Flags flags) + : m_container(container), m_flags(flags) { m_state.m_kind = State::Kind::Root; m_state.m_startIndex = 0; @@ -1308,12 +1326,12 @@ void JSONBuilder::_popState() // Reset the end depending on typpe switch (m_state.m_kind) { - case State::Kind::Array: + case State::Kind::Array: { m_values.setCount(m_state.m_startIndex); break; } - case State::Kind::Object: + case State::Kind::Object: { m_keyValues.setCount(m_state.m_startIndex); break; @@ -1346,18 +1364,18 @@ void JSONBuilder::_add(const JSONValue& value) SLANG_ASSERT(value.isValid()); switch (m_state.m_kind) { - case State::Kind::Root: + case State::Kind::Root: { SLANG_ASSERT(!m_rootValue.isValid()); m_rootValue = value; break; } - case State::Kind::Array: + case State::Kind::Array: { m_values.add(value); break; } - case State::Kind::Object: + case State::Kind::Object: { SLANG_ASSERT(m_state.hasKey()); @@ -1398,7 +1416,10 @@ void JSONBuilder::endObject(SourceLoc loc) SLANG_ASSERT(m_state.m_kind == State::Kind::Object); const Index count = m_keyValues.getCount() - m_state.m_startIndex; - const JSONValue value = m_container->createObject(m_keyValues.getBuffer() + m_state.m_startIndex, count, m_state.m_loc); + const JSONValue value = m_container->createObject( + m_keyValues.getBuffer() + m_state.m_startIndex, + count, + m_state.m_loc); // Pop current state _popState(); @@ -1422,7 +1443,8 @@ void JSONBuilder::endArray(SourceLoc loc) SLANG_ASSERT(m_state.m_kind == State::Kind::Array); const Index count = m_values.getCount() - m_state.m_startIndex; - const JSONValue value = m_container->createArray(m_values.getBuffer() + m_state.m_startIndex, count, m_state.m_loc); + const JSONValue value = + m_container->createArray(m_values.getBuffer() + m_state.m_startIndex, count, m_state.m_loc); // Pop current state _popState(); @@ -1449,11 +1471,11 @@ void JSONBuilder::addLexemeValue(JSONTokenType type, const UnownedStringSlice& v { switch (type) { - case JSONTokenType::True: return _add(JSONValue::makeBool(true, loc)); - case JSONTokenType::False: return _add(JSONValue::makeBool(false, loc)); - case JSONTokenType::Null: return _add(JSONValue::makeNull(loc)); - - case JSONTokenType::IntegerLiteral: + case JSONTokenType::True: return _add(JSONValue::makeBool(true, loc)); + case JSONTokenType::False: return _add(JSONValue::makeBool(false, loc)); + case JSONTokenType::Null: return _add(JSONValue::makeNull(loc)); + + case JSONTokenType::IntegerLiteral: { if (m_flags & Flag::ConvertLexemes) { @@ -1470,7 +1492,7 @@ void JSONBuilder::addLexemeValue(JSONTokenType type, const UnownedStringSlice& v } break; } - case JSONTokenType::FloatLiteral: + case JSONTokenType::FloatLiteral: { if (m_flags & Flag::ConvertLexemes) { @@ -1487,7 +1509,7 @@ void JSONBuilder::addLexemeValue(JSONTokenType type, const UnownedStringSlice& v } break; } - case JSONTokenType::StringLiteral: + case JSONTokenType::StringLiteral: { if (m_flags & Flag::ConvertLexemes) { @@ -1504,7 +1526,7 @@ void JSONBuilder::addLexemeValue(JSONTokenType type, const UnownedStringSlice& v } break; } - default: + default: { SLANG_ASSERT(!"Unhandled type"); } diff --git a/source/compiler-core/slang-json-value.h b/source/compiler-core/slang-json-value.h index 0abe7c9a6..d9b17f1d5 100644 --- a/source/compiler-core/slang-json-value.h +++ b/source/compiler-core/slang-json-value.h @@ -3,15 +3,13 @@ #define SLANG_JSON_VALUE_H #include "../core/slang-basic.h" - -#include "slang-source-loc.h" +#include "../core/slang-rtti-info.h" #include "slang-diagnostic-sink.h" - #include "slang-json-parser.h" +#include "slang-source-loc.h" -#include "../core/slang-rtti-info.h" - -namespace Slang { +namespace Slang +{ typedef uint32_t JSONKey; @@ -31,7 +29,7 @@ struct JSONValue Array, Object, - CountOf, + CountOf, }; enum class Type @@ -58,39 +56,96 @@ struct JSONValue CountOf, }; - static bool isLexeme(Type type) { return Index(type) >= Index(Type::StringLexeme) && Index(type) <= Index(Type::FloatLexeme); } + static bool isLexeme(Type type) + { + return Index(type) >= Index(Type::StringLexeme) && Index(type) <= Index(Type::FloatLexeme); + } - static JSONValue makeInt(int64_t inValue, SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::IntegerValue; value.loc = loc; value.intValue = inValue; return value; } - static JSONValue makeFloat(double inValue, SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::FloatValue; value.loc = loc; value.floatValue = inValue; return value; } - static JSONValue makeNull(SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::Null; value.loc = loc; return value; } - static JSONValue makeBool(bool inValue, SourceLoc loc = SourceLoc()) { JSONValue value; value.type = (inValue ? Type::True : Type::False); value.loc = loc; return value; } + static JSONValue makeInt(int64_t inValue, SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::IntegerValue; + value.loc = loc; + value.intValue = inValue; + return value; + } + static JSONValue makeFloat(double inValue, SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::FloatValue; + value.loc = loc; + value.floatValue = inValue; + return value; + } + static JSONValue makeNull(SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::Null; + value.loc = loc; + return value; + } + static JSONValue makeBool(bool inValue, SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = (inValue ? Type::True : Type::False); + value.loc = loc; + return value; + } - static JSONValue makeLexeme(Type type, SourceLoc loc, Index length) { SLANG_ASSERT(isLexeme(type)); JSONValue value; value.type = type; value.loc = loc; value.length = length; return value; } + static JSONValue makeLexeme(Type type, SourceLoc loc, Index length) + { + SLANG_ASSERT(isLexeme(type)); + JSONValue value; + value.type = type; + value.loc = loc; + value.length = length; + return value; + } - static JSONValue makeEmptyArray(SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::Array; value.loc = loc; value.rangeIndex = 0; return value; } - static JSONValue makeEmptyObject(SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::Object; value.loc = loc; value.rangeIndex = 0; return value; } + static JSONValue makeEmptyArray(SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::Array; + value.loc = loc; + value.rangeIndex = 0; + return value; + } + static JSONValue makeEmptyObject(SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::Object; + value.loc = loc; + value.rangeIndex = 0; + return value; + } - static JSONValue makeInvalid(SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::Invalid; value.loc = loc; return value; } - // The following functions only work if the value is stored directly NOT as a lexeme. Use the methods on the container - // to access values if it is potentially stored as a lexeme + static JSONValue makeInvalid(SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::Invalid; + value.loc = loc; + return value; + } + // The following functions only work if the value is stored directly NOT as a lexeme. Use the + // methods on the container to access values if it is potentially stored as a lexeme - /// As a boolean value + /// As a boolean value bool asBool() const; - /// As an integer value + /// As an integer value int64_t asInteger() const; - /// As a float value + /// As a float value double asFloat() const; - /// True if this is a object like + /// True if this is a object like bool isObjectLike() const { return Index(type) >= Index(Type::Array); } - /// True if this appears to be a valid value + /// True if this appears to be a valid value bool isValid() const { return type != JSONValue::Type::Invalid; } - /// True if needs destroy + /// True if needs destroy bool needsDestroy() const { return isObjectLike() && rangeIndex != 0; } - /// Get the kind + /// Get the kind SLANG_FORCE_INLINE Kind getKind() const { return getKindForType(type); } void reset() @@ -99,20 +154,20 @@ struct JSONValue loc = SourceLoc(); } - /// Given a type return the associated kind + /// Given a type return the associated kind static Kind getKindForType(Type type) { return g_typeToKind[Index(type)]; } - Type type = Type::Invalid; ///< The type of value - SourceLoc loc; ///< The (optional) location in source of this value. + Type type = Type::Invalid; ///< The type of value + SourceLoc loc; ///< The (optional) location in source of this value. - union + union { - Index rangeIndex; ///< Used for Array/Object - Index length; ///< Length in bytes if it is a 'Lexeme' - double floatValue; ///< Float value - int64_t intValue; ///< Integer value - JSONKey stringKey; ///< The pool key if it's a string - StringRepresentation* stringRep; ///< Only ever used on a 'PersistentJSONValue' + Index rangeIndex; ///< Used for Array/Object + Index length; ///< Length in bytes if it is a 'Lexeme' + double floatValue; ///< Float value + int64_t intValue; ///< Integer value + JSONKey stringKey; ///< The pool key if it's a string + StringRepresentation* stringRep; ///< Only ever used on a 'PersistentJSONValue' }; static const Kind g_typeToKind[Index(Type::CountOf)]; @@ -120,12 +175,15 @@ struct JSONValue static const OtherRttiInfo g_rttiInfo; }; -template <> -struct GetRttiInfo<JSONValue> { static const RttiInfo* get() { return &JSONValue::g_rttiInfo; } }; +template<> +struct GetRttiInfo<JSONValue> +{ + static const RttiInfo* get() { return &JSONValue::g_rttiInfo; } +}; struct JSONKeyValue { - /// True if it's valid + /// True if it's valid bool isValid() const { return value.type != JSONValue::Type::Invalid; } void reset() @@ -141,7 +199,7 @@ struct JSONKeyValue static JSONKeyValue make(JSONKey inKey, JSONValue inValue, SourceLoc inKeyLoc = SourceLoc()) { - return JSONKeyValue{ inKey, inKeyLoc, inValue }; + return JSONKeyValue{inKey, inKeyLoc, inValue}; } static JSONKeyValue g_invalid; @@ -168,31 +226,35 @@ public: typedef JSONValue Super; typedef PersistentJSONValue ThisType; - /// If it's a string type this will always work + /// If it's a string type this will always work String getString() const; UnownedStringSlice getSlice() const; - /// Set to the value + /// Set to the value void set(const JSONValue& in, JSONContainer* container); - /// Set directly to a string + /// Set directly to a string void set(const UnownedStringSlice& slice, SourceLoc loc); - /// True if identical + /// True if identical bool operator==(const ThisType& rhs) const; bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Assignable + /// Assignable void operator=(const ThisType& rhs); PersistentJSONValue(const JSONValue& in, JSONContainer* container) { _init(in, container); } - PersistentJSONValue(const JSONValue& in, JSONContainer* container, SourceLoc inLoc) { _init(in, container); loc = inLoc; } + PersistentJSONValue(const JSONValue& in, JSONContainer* container, SourceLoc inLoc) + { + _init(in, container); + loc = inLoc; + } - /// Copy Ctor + /// Copy Ctor PersistentJSONValue(const ThisType& rhs); - /// Default Ctor (will be set to invalid) + /// Default Ctor (will be set to invalid) PersistentJSONValue() {} - + ~PersistentJSONValue() { if (type == Type::StringRepresentation && stringRep) @@ -200,8 +262,9 @@ public: stringRep->releaseReference(); } } + protected: - /// Assumes this has no valid data + /// Assumes this has no valid data void _init(const JSONValue& in, JSONContainer* container); void _init(const UnownedStringSlice& slice, SourceLoc loc); }; @@ -209,13 +272,15 @@ protected: class JSONContainer : public RefObject { public: - - /// Make a new array + /// Make a new array JSONValue createArray(const JSONValue* values, Index valuesCount, SourceLoc loc = SourceLoc()); - /// Make a new object - JSONValue createObject(const JSONKeyValue* keyValues, Index keyValueCount, SourceLoc loc = SourceLoc()); - /// Make a string - JSONValue createString(const UnownedStringSlice& slice, SourceLoc loc = SourceLoc()); + /// Make a new object + JSONValue createObject( + const JSONKeyValue* keyValues, + Index keyValueCount, + SourceLoc loc = SourceLoc()); + /// Make a string + JSONValue createString(const UnownedStringSlice& slice, SourceLoc loc = SourceLoc()); ConstArrayView<JSONValue> getArray(const JSONValue& in) const; ConstArrayView<JSONKeyValue> getObject(const JSONValue& in) const; @@ -223,104 +288,111 @@ public: ArrayView<JSONValue> getArray(const JSONValue& in); ArrayView<JSONKeyValue> getObject(const JSONValue& in); - /// Add value to array. + /// Add value to array. void addToArray(JSONValue& array, const JSONValue& value); - /// Get the value at the index in the array + /// Get the value at the index in the array JSONValue& getAt(const JSONValue& array, Index index); - /// Returns the index of key in obj, or -1 if not found + /// Returns the index of key in obj, or -1 if not found Index findObjectIndex(const JSONValue& obj, JSONKey key) const; - /// Get the value in the object at key. Returns invalid if not found. + /// Get the value in the object at key. Returns invalid if not found. JSONValue findObjectValue(const JSONValue& obj, JSONKey key) const; - /// Returns the index + /// Returns the index Index findKeyGlobalIndex(const JSONValue& obj, JSONKey key); Index findKeyGlobalIndex(const JSONValue& obj, const UnownedStringSlice& slice); - /// Set a key value for the obj - void setKeyValue(JSONValue& obj, JSONKey key, const JSONValue& value, SourceLoc loc = SourceLoc()); + /// Set a key value for the obj + void setKeyValue( + JSONValue& obj, + JSONKey key, + const JSONValue& value, + SourceLoc loc = SourceLoc()); - /// Returns true if found + /// Returns true if found bool removeKey(JSONValue& obj, JSONKey key); bool removeKey(JSONValue& obj, const UnownedStringSlice& slice); - /// As a boolean value + /// As a boolean value bool asBool(const JSONValue& value); - /// As an integer value + /// As an integer value int64_t asInteger(const JSONValue& value); - /// As a float value + /// As a float value double asFloat(const JSONValue& value); - /// Returns string as a key + /// Returns string as a key JSONKey getStringKey(const JSONValue& in); - /// Get as a string. The slice may used backing lexeme (ie will only last - /// as long as the backing JSON text, or be decoded and be transitory). + /// Get as a string. The slice may used backing lexeme (ie will only last + /// as long as the backing JSON text, or be decoded and be transitory). UnownedStringSlice getTransientString(const JSONValue& in); - /// Get as a string. The contents will stay in scope as long as the container + /// Get as a string. The contents will stay in scope as long as the container UnownedStringSlice getString(const JSONValue& in); - /// Gets the lexeme + /// Gets the lexeme UnownedStringSlice getLexeme(const JSONValue& in); - /// Get a key for a name + /// Get a key for a name JSONKey getKey(const UnownedStringSlice& slice); - /// Returns JSONKey(0) if not found + /// Returns JSONKey(0) if not found JSONKey findKey(const UnownedStringSlice& slice) const; - /// Get the string from the key - UnownedStringSlice getStringFromKey(JSONKey key) const { return m_slicePool.getSlice(StringSlicePool::Handle(key)); } + /// Get the string from the key + UnownedStringSlice getStringFromKey(JSONKey key) const + { + return m_slicePool.getSlice(StringSlicePool::Handle(key)); + } - /// True if they are the same value - /// If object like type comparison is performed recursively. - /// NOTE! That Float and Integer values do not compare & source locations are ignored. + /// True if they are the same value + /// If object like type comparison is performed recursively. + /// NOTE! That Float and Integer values do not compare & source locations are ignored. bool areEqual(const JSONValue& a, const JSONValue& b); bool areEqual(const JSONValue* a, const JSONValue* b, Index count); bool areEqual(const JSONKeyValue* a, const JSONKeyValue* b, Index count); bool areEqual(const JSONValue& a, const UnownedStringSlice& slice); - /// Destroy value + /// Destroy value void destroy(JSONValue& value); - /// Destroy recursively from value + /// Destroy recursively from value void destroyRecursively(JSONValue& value); - /// Traverse a JSON hierarchy from value, outputting to the listener + /// Traverse a JSON hierarchy from value, outputting to the listener void traverseRecursively(const JSONValue& value, JSONListener* listener); - /// Returns the source manager used. - SourceManager* getSourceManager() const { return m_sourceManager; } - /// Set the source manager - void setSourceManager(SourceManager* sourceManger) { m_sourceManager = sourceManger; } + /// Returns the source manager used. + SourceManager* getSourceManager() const { return m_sourceManager; } + /// Set the source manager + void setSourceManager(SourceManager* sourceManger) { m_sourceManager = sourceManger; } - /// Clears all the source locs. Useful if the sourceManager is no longer available, or has itself been reset. - /// All JSONValues which were Lexeme based will become held in the container - /// The source manager will set to nullptr + /// Clears all the source locs. Useful if the sourceManager is no longer available, or has + /// itself been reset. All JSONValues which were Lexeme based will become held in the container + /// The source manager will set to nullptr void clearSourceManagerDependency(JSONValue* ioValues, Index count); - /// Reset the state + /// Reset the state void reset(); - /// Return inValue as a regular value (ie not held as a lexeme) + /// Return inValue as a regular value (ie not held as a lexeme) JSONValue asValue(const JSONValue& inValue); - // Ctor + // Ctor JSONContainer(SourceManager* sourceManger); - /// Returns true if all the keys are unique + /// Returns true if all the keys are unique static bool areKeysUnique(const JSONKeyValue* keyValues, Index keyValueCount); - /// Access the internal set of strings, removing anything from this - /// will invalidate the container, so only do it immediately prior to - /// destruction. - StringSlicePool& getStringSlicePool() {return m_slicePool;}; + /// Access the internal set of strings, removing anything from this + /// will invalidate the container, so only do it immediately prior to + /// destruction. + StringSlicePool& getStringSlicePool() { return m_slicePool; }; protected: struct Range { - // We want to record the underlying range, because we don't track JSONValue, and so we need to know what the range - // applies to if we want to reorder, flatten etc. + // We want to record the underlying range, because we don't track JSONValue, and so we need + // to know what the range applies to if we want to reorder, flatten etc. enum class Type { None, @@ -329,7 +401,7 @@ protected: Array, }; - /// Is active if it consuming some part of a value list (even if zero count) + /// Is active if it consuming some part of a value list (even if zero count) SLANG_FORCE_INLINE bool isActive() const { return Index(type) >= Index(Type::Object); } Type type; @@ -338,24 +410,24 @@ protected: Index capacity; }; - template <typename T> + template<typename T> static void _add(Range& range, List<T>& list, const T& value); Index _addRange(Range::Type type, Index startIndex, Index count); void _removeKey(JSONValue& obj, Index globalIndex); - /// Note does not destroy values in range. + /// Note does not destroy values in range. void _destroyRange(Index rangeIndex); static bool _sameKeyOrder(const JSONKeyValue* a, const JSONKeyValue* b, Index count); - /// True if the values are equal + /// True if the values are equal bool _areEqualValues(const JSONKeyValue* a, const JSONKeyValue* b, Index count); - /// True if the key and value are equal + /// True if the key and value are equal bool _areEqualOrderedKeys(const JSONKeyValue* a, const JSONKeyValue* b, Index count); void _clearSourceManagerDependency(JSONValue* ioValues, Index count); JSONValue _removeManagerDependency(const JSONValue& inValue); - StringBuilder m_buf; ///< A temporary buffer used to hold unescaped strings + StringBuilder m_buf; ///< A temporary buffer used to hold unescaped strings SourceView* m_currentView = nullptr; SourceManager* m_sourceManager; @@ -370,7 +442,6 @@ protected: class JSONBuilder : public JSONListener { public: - typedef uint32_t Flags; struct Flag { @@ -387,23 +458,23 @@ public: virtual void endArray(SourceLoc loc) SLANG_OVERRIDE; virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE; virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE; - virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) SLANG_OVERRIDE; + virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) + SLANG_OVERRIDE; virtual void addIntegerValue(int64_t value, SourceLoc loc) SLANG_OVERRIDE; virtual void addFloatValue(double value, SourceLoc loc) SLANG_OVERRIDE; virtual void addBoolValue(bool value, SourceLoc loc) SLANG_OVERRIDE; virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) SLANG_OVERRIDE; virtual void addNullValue(SourceLoc loc) SLANG_OVERRIDE; - /// Reset the state + /// Reset the state void reset(); - /// Get the root value. Will be set after valid construction + /// Get the root value. Will be set after valid construction const JSONValue& getRootValue() const { return m_rootValue; } JSONBuilder(JSONContainer* container, Flags flags = 0); protected: - struct State { enum class Kind : uint8_t @@ -412,8 +483,16 @@ protected: Object, Array, }; - void setKey(JSONKey key, SourceLoc loc) { m_key = key; m_keyLoc = loc; } - void resetKey() { m_key = JSONKey(0); m_keyLoc = SourceLoc(); } + void setKey(JSONKey key, SourceLoc loc) + { + m_key = key; + m_keyLoc = loc; + } + void resetKey() + { + m_key = JSONKey(0); + m_keyLoc = SourceLoc(); + } bool hasKey() const { return m_key != JSONKey(0); } Kind m_kind; diff --git a/source/compiler-core/slang-language-server-protocol.cpp b/source/compiler-core/slang-language-server-protocol.cpp index 93ea0c9e3..9a382e756 100644 --- a/source/compiler-core/slang-language-server-protocol.cpp +++ b/source/compiler-core/slang-language-server-protocol.cpp @@ -38,18 +38,25 @@ const StructRttiInfo InlayHintOptions::g_rttiInfo = _makeInlayHintOptionsRtti(); static const StructRttiInfo _makeDocumentOnTypeFormattingOptionsRtti() { DocumentOnTypeFormattingOptions obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DocumentOnTypeFormattingOptions", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DocumentOnTypeFormattingOptions", + nullptr); builder.addField("firstTriggerCharacter", &obj.firstTriggerCharacter); builder.addField("moreTriggerCharacter", &obj.moreTriggerCharacter); builder.ignoreUnknownFields(); return builder.make(); } -const StructRttiInfo DocumentOnTypeFormattingOptions::g_rttiInfo = _makeDocumentOnTypeFormattingOptionsRtti(); +const StructRttiInfo DocumentOnTypeFormattingOptions::g_rttiInfo = + _makeDocumentOnTypeFormattingOptionsRtti(); static const StructRttiInfo _makeCompletionOptionsRtti() { CompletionOptions obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::CompletionOptions", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::CompletionOptions", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("triggerCharacters", &obj.triggerCharacters); builder.addField("resolveProvider", &obj.resolveProvider); builder.addField("allCommitCharacters", &obj.allCommitCharacters); @@ -118,7 +125,10 @@ const StructRttiInfo TextDocumentIdentifier::g_rttiInfo = _makeTextDocumentIdent static const StructRttiInfo _makeVersionedTextDocumentIdentifierRtti() { VersionedTextDocumentIdentifier obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::VersionedTextDocumentIdentifier", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::VersionedTextDocumentIdentifier", + nullptr); builder.addField("uri", &obj.uri); builder.addField("version", &obj.version); builder.ignoreUnknownFields(); @@ -130,8 +140,7 @@ const StructRttiInfo VersionedTextDocumentIdentifier::g_rttiInfo = static const StructRttiInfo _makePositionRtti() { Position obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::Position", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::Position", nullptr); builder.addField("line", &obj.line); builder.addField("character", &obj.character); builder.ignoreUnknownFields(); @@ -176,7 +185,10 @@ const UnownedStringSlice DidOpenTextDocumentParams::methodName = static const StructRttiInfo _makeTextDocumentContentChangeEventRtti() { TextDocumentContentChangeEvent obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::TextDocumentContentChangeEvent", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::TextDocumentContentChangeEvent", + nullptr); builder.addField("range", &obj.range, StructRttiInfo::Flag::Optional); builder.addField("text", &obj.text); builder.ignoreUnknownFields(); @@ -188,8 +200,7 @@ const StructRttiInfo TextDocumentContentChangeEvent::g_rttiInfo = static const StructRttiInfo _makeDidChangeTextDocumentParamsRtti() { DidChangeTextDocumentParams obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::DidChangeTextDocumentParams", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::DidChangeTextDocumentParams", nullptr); builder.addField("textDocument", &obj.textDocument); builder.addField("contentChanges", &obj.contentChanges); builder.ignoreUnknownFields(); @@ -216,7 +227,10 @@ const UnownedStringSlice DidCloseTextDocumentParams::methodName = static const StructRttiInfo _makeWorkspaceFoldersServerCapabilitiesRtti() { WorkspaceFoldersServerCapabilities obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::WorkspaceFoldersServerCapabilities", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::WorkspaceFoldersServerCapabilities", + nullptr); builder.addField("supported", &obj.supported); builder.addField("changeNotifications", &obj.changeNotifications); builder.ignoreUnknownFields(); @@ -370,7 +384,10 @@ const StructRttiInfo Location::g_rttiInfo = _makeLocationRtti(); static const StructRttiInfo _makeDiagnosticRelatedInformationRtti() { DiagnosticRelatedInformation obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DiagnosticRelatedInformation", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DiagnosticRelatedInformation", + nullptr); builder.addField("location", &obj.location); builder.addField("message", &obj.message); builder.ignoreUnknownFields(); @@ -382,8 +399,7 @@ const StructRttiInfo DiagnosticRelatedInformation::g_rttiInfo = static const StructRttiInfo _makeDiagnosticRtti() { Diagnostic obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::Diagnostic", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::Diagnostic", nullptr); builder.addField("code", &obj.code); builder.addField("message", &obj.message); builder.addField("range", &obj.range); @@ -420,7 +436,10 @@ const StructRttiInfo TextDocumentPositionParams::g_rttiInfo = _makeTextDocumentP static const StructRttiInfo _makeHoverParamsRtti() { HoverParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::HoverParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::HoverParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.ignoreUnknownFields(); @@ -466,7 +485,10 @@ const StructRttiInfo CompletionContext::g_rttiInfo = _makeCompletionContextRtti( static const StructRttiInfo _makeDefinitionParamsRtti() { DefinitionParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DefinitionParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DefinitionParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.ignoreUnknownFields(); @@ -479,7 +501,10 @@ const UnownedStringSlice DefinitionParams::methodName = static const StructRttiInfo _makeCompletionParamsRtti() { CompletionParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::CompletionParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::CompletionParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.addField("context", &obj.context, StructRttiInfo::Flag::Optional); @@ -524,7 +549,10 @@ const StructRttiInfo TextEditCompletionItem::g_rttiInfo = _makeTextEditCompletio static const StructRttiInfo _makeSemanticTokensParamsRtti() { SemanticTokensParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::SemanticTokensParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::SemanticTokensParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.ignoreUnknownFields(); return builder.make(); @@ -547,7 +575,10 @@ const StructRttiInfo SemanticTokens::g_rttiInfo = _makeSemanticTokensRtti(); static const StructRttiInfo _makeSignatureHelpParamsRtti() { SignatureHelpParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::SignatureHelpParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::SignatureHelpParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.ignoreUnknownFields(); @@ -595,7 +626,10 @@ const StructRttiInfo SignatureHelp::g_rttiInfo = _makeSignatureHelpRtti(); static const StructRttiInfo _makeDidChangeConfigurationParamsRtti() { DidChangeConfigurationParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DidChangeConfigurationParams", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DidChangeConfigurationParams", + nullptr); builder.addField("settings", &obj.settings, StructRttiInfo::Flag::Optional); builder.ignoreUnknownFields(); return builder.make(); @@ -608,8 +642,7 @@ const UnownedStringSlice DidChangeConfigurationParams::methodName = static const StructRttiInfo _makeConfigurationItemRtti() { ConfigurationItem obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::ConfigurationItem", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::ConfigurationItem", nullptr); builder.addField("section", &obj.section, StructRttiInfo::Flag::Optional); builder.ignoreUnknownFields(); return builder.make(); @@ -619,8 +652,7 @@ const StructRttiInfo ConfigurationItem::g_rttiInfo = _makeConfigurationItemRtti( static const StructRttiInfo _makeConfigurationParamsRtti() { ConfigurationParams obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::ConfigurationParams", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::ConfigurationParams", nullptr); builder.addField("items", &obj.items, StructRttiInfo::Flag::Optional); builder.ignoreUnknownFields(); return builder.make(); @@ -677,7 +709,9 @@ static const StructRttiInfo _makeDocumentSymbolParamsRtti() { DocumentSymbolParams obj; StructRttiBuilder builder( - &obj, "LanguageServerProtocol::DocumentSymbolParams", &WorkDoneProgressParams::g_rttiInfo); + &obj, + "LanguageServerProtocol::DocumentSymbolParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.ignoreUnknownFields(); return builder.make(); @@ -689,8 +723,7 @@ const UnownedStringSlice DocumentSymbolParams::methodName = static const StructRttiInfo _makeDocumentSymbolRtti() { DocumentSymbol obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::DocumentSymbol", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::DocumentSymbol", nullptr); builder.addField("name", &obj.name); builder.addField("detail", &obj.detail); builder.addField("kind", &obj.kind); @@ -705,8 +738,7 @@ const StructRttiInfo DocumentSymbol::g_rttiInfo = _makeDocumentSymbolRtti(); static const StructRttiInfo _makeInlayHintParamsRtti() { InlayHintParams obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::InlayHintParams", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::InlayHintParams", nullptr); builder.addField("range", &obj.range); builder.addField("textDocument", &obj.textDocument); builder.ignoreUnknownFields(); @@ -719,8 +751,7 @@ const UnownedStringSlice InlayHintParams::methodName = static const StructRttiInfo _makeInlayHintRtti() { InlayHint obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::InlayHint", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::InlayHint", nullptr); builder.addField("position", &obj.position); builder.addField("label", &obj.label); builder.addField("kind", &obj.kind); @@ -748,30 +779,38 @@ const UnownedStringSlice DocumentFormattingParams::methodName = static const StructRttiInfo _makeDocumentRangeFormattingParamsRtti() { DocumentRangeFormattingParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DocumentRangeFormattingParams", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DocumentRangeFormattingParams", + nullptr); builder.addField("textDocument", &obj.textDocument); builder.addField("range", &obj.range); builder.ignoreUnknownFields(); return builder.make(); } -const StructRttiInfo DocumentRangeFormattingParams::g_rttiInfo = _makeDocumentRangeFormattingParamsRtti(); +const StructRttiInfo DocumentRangeFormattingParams::g_rttiInfo = + _makeDocumentRangeFormattingParamsRtti(); const UnownedStringSlice DocumentRangeFormattingParams::methodName = UnownedStringSlice::fromLiteral("textDocument/rangeFormatting"); static const StructRttiInfo _makeDocumentOnTypeFormattingParamsRtti() { DocumentOnTypeFormattingParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DocumentOnTypeFormattingParams", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DocumentOnTypeFormattingParams", + nullptr); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.addField("ch", &obj.ch); builder.ignoreUnknownFields(); return builder.make(); } -const StructRttiInfo DocumentOnTypeFormattingParams::g_rttiInfo = _makeDocumentOnTypeFormattingParamsRtti(); +const StructRttiInfo DocumentOnTypeFormattingParams::g_rttiInfo = + _makeDocumentOnTypeFormattingParamsRtti(); const UnownedStringSlice DocumentOnTypeFormattingParams::methodName = UnownedStringSlice::fromLiteral("textDocument/onTypeFormatting"); } // namespace LanguageServerProtocol -} +} // namespace Slang diff --git a/source/compiler-core/slang-language-server-protocol.h b/source/compiler-core/slang-language-server-protocol.h index 506969dcc..d96099da6 100644 --- a/source/compiler-core/slang-language-server-protocol.h +++ b/source/compiler-core/slang-language-server-protocol.h @@ -1,11 +1,11 @@ #pragma once +#include "../../source/compiler-core/slang-json-value.h" +#include "../../source/core/slang-rtti-info.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" #include "slang.h" -#include "../../source/core/slang-rtti-info.h" -#include "../../source/compiler-core/slang-json-value.h" #include <optional> namespace Slang @@ -192,7 +192,6 @@ struct TextEdit String newText; static const StructRttiInfo g_rttiInfo; - }; struct DidOpenTextDocumentParams @@ -264,7 +263,6 @@ struct InlayHintOptions */ bool resolveProvider = false; static const StructRttiInfo g_rttiInfo; - }; struct DocumentOnTypeFormattingOptions @@ -436,8 +434,7 @@ struct Diagnostic HashCode getHashCode() const { - return combineHash( - code, combineHash(range.start.line, message.getHashCode())); + return combineHash(code, combineHash(range.start.line, message.getHashCode())); } static const StructRttiInfo g_rttiInfo; @@ -473,17 +470,13 @@ struct TextDocumentPositionParams static const StructRttiInfo g_rttiInfo; }; -struct HoverParams - : WorkDoneProgressParams - ,TextDocumentPositionParams +struct HoverParams : WorkDoneProgressParams, TextDocumentPositionParams { static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; }; -struct DefinitionParams - : WorkDoneProgressParams - , TextDocumentPositionParams +struct DefinitionParams : WorkDoneProgressParams, TextDocumentPositionParams { static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; @@ -556,9 +549,7 @@ struct CompletionContext static const StructRttiInfo g_rttiInfo; }; -struct CompletionParams - : WorkDoneProgressParams - , TextDocumentPositionParams +struct CompletionParams : WorkDoneProgressParams, TextDocumentPositionParams { CompletionContext context; @@ -713,9 +704,7 @@ struct SemanticTokens static const StructRttiInfo g_rttiInfo; }; -struct SignatureHelpParams - : WorkDoneProgressParams - , TextDocumentPositionParams +struct SignatureHelpParams : WorkDoneProgressParams, TextDocumentPositionParams { static const UnownedStringSlice methodName; @@ -740,7 +729,7 @@ struct ParameterInformation * signature label. Its intended use case is to highlight the parameter * label part in the `SignatureInformation.label`. */ - uint32_t label[2] = { 0, 0 }; + uint32_t label[2] = {0, 0}; /** * The human-readable doc-comment of this parameter. Will be shown @@ -848,14 +837,14 @@ struct ConfigurationParams struct Registration { /** - * The id used to register the request. The id can be used to deregister - * the request again. - */ + * The id used to register the request. The id can be used to deregister + * the request again. + */ String id; /** - * The method / capability to register for. - */ + * The method / capability to register for. + */ String method; static const StructRttiInfo g_rttiInfo; @@ -1052,7 +1041,6 @@ struct InlayHint bool paddingRight = false; static const StructRttiInfo g_rttiInfo; - }; struct DocumentOnTypeFormattingParams @@ -1080,7 +1068,7 @@ struct DocumentOnTypeFormattingParams /** * The formatting options. */ - //FormattingOptions options; + // FormattingOptions options; static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; @@ -1101,7 +1089,7 @@ struct DocumentRangeFormattingParams /** * The format options */ - //FormattingOptions options; + // FormattingOptions options; static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; @@ -1117,7 +1105,7 @@ struct DocumentFormattingParams /** * The format options */ - //FormattingOptions options; + // FormattingOptions options; static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; @@ -1128,29 +1116,20 @@ struct DocumentFormattingParams namespace Slang { - template<typename T> - struct LanguageServerResult +template<typename T> +struct LanguageServerResult +{ + SlangResult returnCode; + bool isNull = true; + T result; + LanguageServerResult() { returnCode = SLANG_OK; } + LanguageServerResult(std::nullopt_t) { returnCode = SLANG_OK; } + LanguageServerResult(const T& value) { - SlangResult returnCode; - bool isNull = true; - T result; - LanguageServerResult() - { - returnCode = SLANG_OK; - } - LanguageServerResult(std::nullopt_t) - { - returnCode = SLANG_OK; - } - LanguageServerResult(const T& value) - { - result = value; - isNull = false; - returnCode = SLANG_OK; - } - LanguageServerResult(SlangResult code) - { - returnCode = code; - } - }; -} + result = value; + isNull = false; + returnCode = SLANG_OK; + } + LanguageServerResult(SlangResult code) { returnCode = code; } +}; +} // namespace Slang diff --git a/source/compiler-core/slang-lexer-diagnostic-defs.h b/source/compiler-core/slang-lexer-diagnostic-defs.h index bce287685..cae8e4157 100644 --- a/source/compiler-core/slang-lexer-diagnostic-defs.h +++ b/source/compiler-core/slang-lexer-diagnostic-defs.h @@ -12,7 +12,7 @@ // for any arguments. #ifndef DIAGNOSTIC -#error Need to #define DIAGNOSTIC(...) before including +#error Need to #define DIAGNOSTIC(...) before including #define DIAGNOSTIC(id, severity, name, messageFormat) /* */ #endif @@ -29,7 +29,11 @@ DIAGNOSTIC(10003, Error, invalidDigitForBase, "invalid digit for base-$1 literal DIAGNOSTIC(10004, Error, endOfFileInLiteral, "end of file in literal") DIAGNOSTIC(10005, Error, newlineInLiteral, "newline in literal") -DIAGNOSTIC(10010, Error, quoteCannotBeDelimiter, "'\"' encountered before '(' in raw string literal. '\"' cannot be a part of a delimiter.") +DIAGNOSTIC( + 10010, + Error, + quoteCannotBeDelimiter, + "'\"' encountered before '(' in raw string literal. '\"' cannot be a part of a delimiter.") DIAGNOSTIC(10011, Error, unexpectedEndOfInput, "unexpected end of input") diff --git a/source/compiler-core/slang-lexer.cpp b/source/compiler-core/slang-lexer.cpp index 366af9114..df95f5f1e 100644 --- a/source/compiler-core/slang-lexer.cpp +++ b/source/compiler-core/slang-lexer.cpp @@ -6,196 +6,197 @@ // #include "core/slang-char-encode.h" +#include "slang-core-diagnostics.h" #include "slang-name.h" #include "slang-source-loc.h" -#include "slang-core-diagnostics.h" namespace Slang { - Token TokenReader::getEndOfFileToken() - { - return Token(TokenType::EndOfFile, UnownedStringSlice::fromLiteral(""), SourceLoc()); - } +Token TokenReader::getEndOfFileToken() +{ + return Token(TokenType::EndOfFile, UnownedStringSlice::fromLiteral(""), SourceLoc()); +} - const Token* TokenList::begin() const - { - SLANG_ASSERT(m_tokens.getCount()); - return &m_tokens[0]; - } +const Token* TokenList::begin() const +{ + SLANG_ASSERT(m_tokens.getCount()); + return &m_tokens[0]; +} - const Token* TokenList::end() const - { - SLANG_ASSERT(m_tokens.getCount()); - SLANG_ASSERT(m_tokens[m_tokens.getCount() - 1].type == TokenType::EndOfFile); - return &m_tokens[m_tokens.getCount() - 1]; - } +const Token* TokenList::end() const +{ + SLANG_ASSERT(m_tokens.getCount()); + SLANG_ASSERT(m_tokens[m_tokens.getCount() - 1].type == TokenType::EndOfFile); + return &m_tokens[m_tokens.getCount() - 1]; +} - TokenSpan::TokenSpan() - : m_begin(nullptr) - , m_end (nullptr) - {} +TokenSpan::TokenSpan() + : m_begin(nullptr), m_end(nullptr) +{ +} - TokenReader::TokenReader() - : m_cursor(nullptr) - , m_end (nullptr) - { - _updateLookaheadToken(); - } +TokenReader::TokenReader() + : m_cursor(nullptr), m_end(nullptr) +{ + _updateLookaheadToken(); +} - Token& TokenReader::peekToken() - { - return m_nextToken; - } +Token& TokenReader::peekToken() +{ + return m_nextToken; +} - TokenType TokenReader::peekTokenType() const - { - return m_nextToken.type; - } +TokenType TokenReader::peekTokenType() const +{ + return m_nextToken.type; +} - SourceLoc TokenReader::peekLoc() const - { - return m_nextToken.loc; - } +SourceLoc TokenReader::peekLoc() const +{ + return m_nextToken.loc; +} - Token TokenReader::advanceToken() - { - Token result = m_nextToken; - if (m_cursor != m_end) - m_cursor++; - _updateLookaheadToken(); - return result; - } +Token TokenReader::advanceToken() +{ + Token result = m_nextToken; + if (m_cursor != m_end) + m_cursor++; + _updateLookaheadToken(); + return result; +} - void TokenReader::_updateLookaheadToken() - { - // We assume here that we can read a token from a non-null `m_cursor` - // *even* in the case where `m_cursor == m_end`, because the invariant - // for lists of tokens is that they should be terminated with and - // end-of-file token, so that there is always a token "one past the end." - // - m_nextToken = m_cursor ? *m_cursor : getEndOfFileToken(); +void TokenReader::_updateLookaheadToken() +{ + // We assume here that we can read a token from a non-null `m_cursor` + // *even* in the case where `m_cursor == m_end`, because the invariant + // for lists of tokens is that they should be terminated with and + // end-of-file token, so that there is always a token "one past the end." + // + m_nextToken = m_cursor ? *m_cursor : getEndOfFileToken(); - // If the token we read came from the end of the sub-sequence we are - // reading, then we will change the token type to an end-of-file token - // so that code that reads from the sequence and expects a terminating - // EOF will find it. - // - // TODO: We might eventually want a way to look at the actual token type - // and not just use EOF in all cases: e.g., when emitting diagnostic - // messages that include the token that is seen. - // - if(m_cursor == m_end) - m_nextToken.type = TokenType::EndOfFile; - } + // If the token we read came from the end of the sub-sequence we are + // reading, then we will change the token type to an end-of-file token + // so that code that reads from the sequence and expects a terminating + // EOF will find it. + // + // TODO: We might eventually want a way to look at the actual token type + // and not just use EOF in all cases: e.g., when emitting diagnostic + // messages that include the token that is seen. + // + if (m_cursor == m_end) + m_nextToken.type = TokenType::EndOfFile; +} - // Lexer +// Lexer - void Lexer::initialize( - SourceView* sourceView, - DiagnosticSink* sink, - NamePool* namePool, - MemoryArena* memoryArena) - { - m_sourceView = sourceView; - m_sink = sink; - m_namePool = namePool; - m_memoryArena = memoryArena; - - auto content = sourceView->getContent(); - - m_begin = content.begin(); - m_cursor = content.begin(); - m_end = content.end(); - - // Set the start location - m_startLoc = sourceView->getRange().begin; - - // The first token read from a translation unit should be considered to be at - // the start of a line, and *also* as coming after whitespace (conceptually - // both the end-of-file and beginning-of-file pseudo-tokens are whitespace). - // - m_tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; - m_lexerFlags = 0; - } +void Lexer::initialize( + SourceView* sourceView, + DiagnosticSink* sink, + NamePool* namePool, + MemoryArena* memoryArena) +{ + m_sourceView = sourceView; + m_sink = sink; + m_namePool = namePool; + m_memoryArena = memoryArena; - Lexer::~Lexer() - { - } + auto content = sourceView->getContent(); - enum { kEOF = -1 }; + m_begin = content.begin(); + m_cursor = content.begin(); + m_end = content.end(); - // Get the next input byte, without any handling of - // escaped newlines, non-ASCII code points, source locations, etc. - static int _peekRaw(Lexer* lexer) - { - // If we are at the end of the input, return a designated end-of-file value - if(lexer->m_cursor == lexer->m_end) - return kEOF; + // Set the start location + m_startLoc = sourceView->getRange().begin; - // Otherwise, just look at the next byte - return *lexer->m_cursor; - } + // The first token read from a translation unit should be considered to be at + // the start of a line, and *also* as coming after whitespace (conceptually + // both the end-of-file and beginning-of-file pseudo-tokens are whitespace). + // + m_tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; + m_lexerFlags = 0; +} - // Read one input byte without any special handling (similar to `peekRaw`) - static int _advanceRaw(Lexer* lexer) - { - // The logic here is basically the same as for `peekRaw()`, - // escape we advance `cursor` if we aren't at the end. +Lexer::~Lexer() {} - if (lexer->m_cursor == lexer->m_end) - return kEOF; +enum +{ + kEOF = -1 +}; - return *lexer->m_cursor++; - } +// Get the next input byte, without any handling of +// escaped newlines, non-ASCII code points, source locations, etc. +static int _peekRaw(Lexer* lexer) +{ + // If we are at the end of the input, return a designated end-of-file value + if (lexer->m_cursor == lexer->m_end) + return kEOF; - // When the cursor is already at the first byte of an end-of-line sequence, - // consume one or two bytes that compose the sequence. - // - // Basically, a newline is one of: - // - // "\n" - // "\r" - // "\r\n" - // "\n\r" - // - // We always look for the longest match possible. - // - static void _handleNewLineInner(Lexer* lexer, int c) - { - SLANG_ASSERT(c == '\n' || c == '\r'); + // Otherwise, just look at the next byte + return *lexer->m_cursor; +} - int d = _peekRaw(lexer); - if( (c ^ d) == ('\n' ^ '\r') ) - { - _advanceRaw(lexer); - } - } +// Read one input byte without any special handling (similar to `peekRaw`) +static int _advanceRaw(Lexer* lexer) +{ + // The logic here is basically the same as for `peekRaw()`, + // escape we advance `cursor` if we aren't at the end. - // Look ahead one code point, dealing with complications like - // escaped newlines. - static int _peek(Lexer* lexer, int offset = 0) + if (lexer->m_cursor == lexer->m_end) + return kEOF; + + return *lexer->m_cursor++; +} + +// When the cursor is already at the first byte of an end-of-line sequence, +// consume one or two bytes that compose the sequence. +// +// Basically, a newline is one of: +// +// "\n" +// "\r" +// "\r\n" +// "\n\r" +// +// We always look for the longest match possible. +// +static void _handleNewLineInner(Lexer* lexer, int c) +{ + SLANG_ASSERT(c == '\n' || c == '\r'); + + int d = _peekRaw(lexer); + if ((c ^ d) == ('\n' ^ '\r')) { - int pos = 0; - int c = kEOF; + _advanceRaw(lexer); + } +} - do - { - if (lexer->m_cursor + pos == lexer->m_end) - return kEOF; +// Look ahead one code point, dealing with complications like +// escaped newlines. +static int _peek(Lexer* lexer, int offset = 0) +{ + int pos = 0; + int c = kEOF; + + do + { + if (lexer->m_cursor + pos == lexer->m_end) + return kEOF; - c = lexer->m_cursor[pos++]; + c = lexer->m_cursor[pos++]; - while (c == '\\') + while (c == '\\') + { + // We might have a backslash-escaped newline. + // Look at the next byte (if any) to see. + // + // Note(tfoley): We are assuming a null-terminated input here, + // so that we can safely look at the next byte without issue. + int d = lexer->m_cursor[pos++]; + switch (d) { - // We might have a backslash-escaped newline. - // Look at the next byte (if any) to see. - // - // Note(tfoley): We are assuming a null-terminated input here, - // so that we can safely look at the next byte without issue. - int d = lexer->m_cursor[pos++]; - switch (d) - { - case '\r': case '\n': + case '\r': + case '\n': { // The newline was escaped, so return the code point after *that* int e = lexer->m_cursor[pos++]; @@ -205,1139 +206,1198 @@ namespace Slang c = e; continue; } - default: - break; - } - - // Only continue this while loop in the case where we consumed - // some newlines - break; - } - if (isUtf8LeadingByte((Byte)c)) - { - // Consume all unicode characters. - pos--; - c = getUnicodePointFromUTF8([&]() {return lexer->m_cursor[pos++]; }); + default: break; } - // Default case is to just hand along the byte we read as an ASCII code point. - } while (offset--); - return c; - } + // Only continue this while loop in the case where we consumed + // some newlines + break; + } + if (isUtf8LeadingByte((Byte)c)) + { + // Consume all unicode characters. + pos--; + c = getUnicodePointFromUTF8([&]() { return lexer->m_cursor[pos++]; }); + } + // Default case is to just hand along the byte we read as an ASCII code point. + } while (offset--); + + return c; +} - // Get the next code point from the input, and advance the cursor. - static int _advance(Lexer* lexer) +// Get the next code point from the input, and advance the cursor. +static int _advance(Lexer* lexer) +{ + // We are going to loop, but only as a way of handling + // escaped line endings. + for (;;) { - // We are going to loop, but only as a way of handling - // escaped line endings. - for (;;) - { - // If we are at the end of the input, then the task is easy. - if (lexer->m_cursor == lexer->m_end) - return kEOF; + // If we are at the end of the input, then the task is easy. + if (lexer->m_cursor == lexer->m_end) + return kEOF; - // Look at the next raw byte, and decide what to do - int c = *lexer->m_cursor++; + // Look at the next raw byte, and decide what to do + int c = *lexer->m_cursor++; - if (c == '\\') + if (c == '\\') + { + // We might have a backslash-escaped newline. + // Look at the next byte (if any) to see. + // + // Note(tfoley): We are assuming a null-terminated input here, + // so that we can safely look at the next byte without issue. + int d = *lexer->m_cursor; + switch (d) { - // We might have a backslash-escaped newline. - // Look at the next byte (if any) to see. - // - // Note(tfoley): We are assuming a null-terminated input here, - // so that we can safely look at the next byte without issue. - int d = *lexer->m_cursor; - switch (d) - { - case '\r': case '\n': - // handle the end-of-line for our source location tracking - lexer->m_cursor++; - _handleNewLineInner(lexer, d); - - lexer->m_tokenFlags |= TokenFlag::ScrubbingNeeded; + case '\r': + case '\n': + // handle the end-of-line for our source location tracking + lexer->m_cursor++; + _handleNewLineInner(lexer, d); - // Now try again, looking at the character after the - // escaped newline. - continue; + lexer->m_tokenFlags |= TokenFlag::ScrubbingNeeded; - default: - break; - } - } + // Now try again, looking at the character after the + // escaped newline. + continue; - // Consume all unicode characters. - if (isUtf8LeadingByte((Byte)c)) - { - lexer->m_cursor--; - c = getUnicodePointFromUTF8([&]() {return *lexer->m_cursor++; }); + default: break; } + } - // Default case is to return the raw byte we saw. - return c; + // Consume all unicode characters. + if (isUtf8LeadingByte((Byte)c)) + { + lexer->m_cursor--; + c = getUnicodePointFromUTF8([&]() { return *lexer->m_cursor++; }); } - } - static void _handleNewLine(Lexer* lexer) - { - int c = _advance(lexer); - _handleNewLineInner(lexer, c); + // Default case is to return the raw byte we saw. + return c; } +} + +static void _handleNewLine(Lexer* lexer) +{ + int c = _advance(lexer); + _handleNewLineInner(lexer, c); +} - static void _lexLineComment(Lexer* lexer) +static void _lexLineComment(Lexer* lexer) +{ + for (;;) { - for(;;) + switch (_peek(lexer)) { - switch(_peek(lexer)) - { - case '\n': case '\r': case kEOF: - return; + case '\n': + case '\r': + case kEOF: return; - default: - _advance(lexer); - continue; - } + default: _advance(lexer); continue; } } +} - static void _lexBlockComment(Lexer* lexer) +static void _lexBlockComment(Lexer* lexer) +{ + for (;;) { - for(;;) + switch (_peek(lexer)) { - switch(_peek(lexer)) - { - case kEOF: - // TODO(tfoley) diagnostic! - return; - - case '\n': case '\r': - _handleNewLine(lexer); - continue; + case kEOF: + // TODO(tfoley) diagnostic! + return; - case '*': - _advance(lexer); - switch( _peek(lexer) ) - { - case '/': - _advance(lexer); - return; + case '\n': + case '\r': _handleNewLine(lexer); continue; - default: - continue; - } + case '*': + _advance(lexer); + switch (_peek(lexer)) + { + case '/': _advance(lexer); return; - default: - _advance(lexer); - continue; + default: continue; } + + default: _advance(lexer); continue; } } +} - static void _lexHorizontalSpace(Lexer* lexer) +static void _lexHorizontalSpace(Lexer* lexer) +{ + for (;;) { - for(;;) + switch (_peek(lexer)) { - switch(_peek(lexer)) - { - case ' ': case '\t': - _advance(lexer); - continue; + case ' ': + case '\t': _advance(lexer); continue; - default: - return; - } + default: return; } } +} - static bool isNonAsciiCodePoint(unsigned int codePoint) - { - return codePoint != 0xFFFFFFFF && codePoint >= 0x80; - } +static bool isNonAsciiCodePoint(unsigned int codePoint) +{ + return codePoint != 0xFFFFFFFF && codePoint >= 0x80; +} - static void _lexIdentifier(Lexer* lexer) +static void _lexIdentifier(Lexer* lexer) +{ + for (;;) { - for(;;) + int c = _peek(lexer); + if (('a' <= c) && (c <= 'z') || ('A' <= c) && (c <= 'Z') || ('0' <= c) && (c <= '9') || + (c == '_') || isNonAsciiCodePoint((unsigned int)c)) { - int c = _peek(lexer); - if(('a' <= c ) && (c <= 'z') - || ('A' <= c) && (c <= 'Z') - || ('0' <= c) && (c <= '9') - || (c == '_') - || isNonAsciiCodePoint((unsigned int)c)) - { - _advance(lexer); - continue; - } - return; + _advance(lexer); + continue; } + return; } +} - static SourceLoc _getSourceLoc(Lexer* lexer) - { - return lexer->m_startLoc + (lexer->m_cursor - lexer->m_begin); - } +static SourceLoc _getSourceLoc(Lexer* lexer) +{ + return lexer->m_startLoc + (lexer->m_cursor - lexer->m_begin); +} - static void _lexDigits(Lexer* lexer, int base) +static void _lexDigits(Lexer* lexer, int base) +{ + for (;;) { - for(;;) - { - int c = _peek(lexer); - - int digitVal = 0; - switch(c) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - digitVal = c - '0'; - break; + int c = _peek(lexer); - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - if(base <= 10) return; - digitVal = 10 + c - 'a'; - break; - - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - if(base <= 10) return; - digitVal = 10 + c - 'A'; - break; - - default: - // Not more digits! + int digitVal = 0; + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': digitVal = c - '0'; break; + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + if (base <= 10) return; - } + digitVal = 10 + c - 'a'; + break; - if(digitVal >= base) - { - if (auto sink = lexer->getDiagnosticSink()) - { - char buffer[] = { (char) c, 0 }; - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::invalidDigitForBase, buffer, base); - } - } + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + if (base <= 10) + return; + digitVal = 10 + c - 'A'; + break; - _advance(lexer); + default: + // Not more digits! + return; } - } - static TokenType _maybeLexNumberSuffix(Lexer* lexer, TokenType tokenType) - { - // Be liberal in what we accept here, so that figuring out - // the semantics of a numeric suffix is left up to the parser - // and semantic checking logic. - // - for( ;;) + if (digitVal >= base) { - int c = _peek(lexer); - - // Accept any alphanumeric character, plus underscores. - if(('a' <= c ) && (c <= 'z') - || ('A' <= c) && (c <= 'Z') - || ('0' <= c) && (c <= '9') - || (c == '_')) + if (auto sink = lexer->getDiagnosticSink()) { - _advance(lexer); - continue; + char buffer[] = {(char)c, 0}; + sink->diagnose( + _getSourceLoc(lexer), + LexerDiagnostics::invalidDigitForBase, + buffer, + base); } - - // Stop at the first character that isn't - // alphanumeric. - return tokenType; } + + _advance(lexer); } +} - static bool _isNumberExponent(int c, int base) +static TokenType _maybeLexNumberSuffix(Lexer* lexer, TokenType tokenType) +{ + // Be liberal in what we accept here, so that figuring out + // the semantics of a numeric suffix is left up to the parser + // and semantic checking logic. + // + for (;;) { - switch( c ) - { - default: - return false; - - case 'e': case 'E': - if(base != 10) return false; - break; + int c = _peek(lexer); - case 'p': case 'P': - if(base != 16) return false; - break; + // Accept any alphanumeric character, plus underscores. + if (('a' <= c) && (c <= 'z') || ('A' <= c) && (c <= 'Z') || ('0' <= c) && (c <= '9') || + (c == '_')) + { + _advance(lexer); + continue; } - return true; + // Stop at the first character that isn't + // alphanumeric. + return tokenType; } +} - static bool _maybeLexNumberExponent(Lexer* lexer, int base) +static bool _isNumberExponent(int c, int base) +{ + switch (c) { - if (_peek(lexer) == '#') - { - // Special case #INF - const auto inf = toSlice("#INF"); - for (auto c : inf) - { - if (_peek(lexer) != c) - { - return false; - } - _advance(lexer); - } + default: return false; - return true; - } + case 'e': + case 'E': + if (base != 10) + return false; + break; - if(!_isNumberExponent(_peek(lexer), base)) + case 'p': + case 'P': + if (base != 16) return false; + break; + } - // we saw an exponent marker - _advance(lexer); + return true; +} - // Now start to read the exponent - switch( _peek(lexer) ) +static bool _maybeLexNumberExponent(Lexer* lexer, int base) +{ + if (_peek(lexer) == '#') + { + // Special case #INF + const auto inf = toSlice("#INF"); + for (auto c : inf) { - case '+': case '-': + if (_peek(lexer) != c) + { + return false; + } _advance(lexer); - break; } - // TODO(tfoley): it would be an error to not see digits here... - - _lexDigits(lexer, 10); - return true; } - static TokenType _lexNumberAfterDecimalPoint(Lexer* lexer, int base) - { - _lexDigits(lexer, base); - _maybeLexNumberExponent(lexer, base); + if (!_isNumberExponent(_peek(lexer), base)) + return false; - return _maybeLexNumberSuffix(lexer, TokenType::FloatingPointLiteral); - } + // we saw an exponent marker + _advance(lexer); - static TokenType _lexNumber(Lexer* lexer, int base) + // Now start to read the exponent + switch (_peek(lexer)) { - // TODO(tfoley): Need to consider whether to allow any kind of digit separator character. + case '+': + case '-': _advance(lexer); break; + } - TokenType tokenType = TokenType::IntegerLiteral; + // TODO(tfoley): it would be an error to not see digits here... - // At the start of things, we just concern ourselves with digits - _lexDigits(lexer, base); + _lexDigits(lexer, 10); - if( _peek(lexer) == '.' ) - { - switch (_peek(lexer, 1)) - { - // 123.xxxx or 123.rrrr - case 'x': - case 'r': - break; + return true; +} - default: - tokenType = TokenType::FloatingPointLiteral; +static TokenType _lexNumberAfterDecimalPoint(Lexer* lexer, int base) +{ + _lexDigits(lexer, base); + _maybeLexNumberExponent(lexer, base); - _advance(lexer); - _lexDigits(lexer, base); - } - } + return _maybeLexNumberSuffix(lexer, TokenType::FloatingPointLiteral); +} + +static TokenType _lexNumber(Lexer* lexer, int base) +{ + // TODO(tfoley): Need to consider whether to allow any kind of digit separator character. + + TokenType tokenType = TokenType::IntegerLiteral; - if( _maybeLexNumberExponent(lexer, base)) + // At the start of things, we just concern ourselves with digits + _lexDigits(lexer, base); + + if (_peek(lexer) == '.') + { + switch (_peek(lexer, 1)) { + // 123.xxxx or 123.rrrr + case 'x': + case 'r': break; + + default: tokenType = TokenType::FloatingPointLiteral; - } - _maybeLexNumberSuffix(lexer, tokenType); - return tokenType; + _advance(lexer); + _lexDigits(lexer, base); + } } - static int _maybeReadDigit(char const** ioCursor, int base) + if (_maybeLexNumberExponent(lexer, base)) { - auto& cursor = *ioCursor; + tokenType = TokenType::FloatingPointLiteral; + } - for(;;) - { - int c = *cursor; - switch(c) - { - default: - return -1; + _maybeLexNumberSuffix(lexer, tokenType); + return tokenType; +} - // TODO: need to decide on digit separator characters - case '_': - cursor++; - continue; +static int _maybeReadDigit(char const** ioCursor, int base) +{ + auto& cursor = *ioCursor; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - cursor++; - return c - '0'; + for (;;) + { + int c = *cursor; + switch (c) + { + default: return -1; - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - if(base > 10) - { - cursor++; - return 10 + c - 'a'; - } - return -1; + // TODO: need to decide on digit separator characters + case '_': cursor++; continue; - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - if(base > 10) - { - cursor++; - return 10 + c - 'A'; - } - return -1; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': cursor++; return c - '0'; + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + if (base > 10) + { + cursor++; + return 10 + c - 'a'; + } + return -1; + + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + if (base > 10) + { + cursor++; + return 10 + c - 'A'; } + return -1; } } +} - static int _readOptionalBase(char const** ioCursor) +static int _readOptionalBase(char const** ioCursor) +{ + auto& cursor = *ioCursor; + if (*cursor == '0') { - auto& cursor = *ioCursor; - if( *cursor == '0' ) + cursor++; + switch (*cursor) { - cursor++; - switch(*cursor) - { - case 'x': case 'X': - cursor++; - return 16; + case 'x': + case 'X': cursor++; return 16; - case 'b': case 'B': - cursor++; - return 2; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return 8; + case 'b': + case 'B': cursor++; return 2; - default: - return 10; - } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return 8; + + default: return 10; } - - return 10; } + return 10; +} - IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix) - { - IntegerLiteralValue value = 0; - - const UnownedStringSlice content = token.getContent(); - - char const* cursor = content.begin(); - char const* end = content.end(); +IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix) +{ + IntegerLiteralValue value = 0; - int base = _readOptionalBase(&cursor); + const UnownedStringSlice content = token.getContent(); - for( ;;) - { - int digit = _maybeReadDigit(&cursor, base); - if(digit < 0) - break; + char const* cursor = content.begin(); + char const* end = content.end(); - value = value*base + digit; - } + int base = _readOptionalBase(&cursor); - if(outSuffix) - { - *outSuffix = UnownedStringSlice(cursor, end); - } + for (;;) + { + int digit = _maybeReadDigit(&cursor, base); + if (digit < 0) + break; - return value; + value = value * base + digit; } - FloatingPointLiteralValue getFloatingPointLiteralValue(Token const& token, UnownedStringSlice* outSuffix) + if (outSuffix) { - FloatingPointLiteralValue value = 0; + *outSuffix = UnownedStringSlice(cursor, end); + } + + return value; +} + +FloatingPointLiteralValue getFloatingPointLiteralValue( + Token const& token, + UnownedStringSlice* outSuffix) +{ + FloatingPointLiteralValue value = 0; - const UnownedStringSlice content = token.getContent(); + const UnownedStringSlice content = token.getContent(); - char const* cursor = content.begin(); - char const* end = content.end(); + char const* cursor = content.begin(); + char const* end = content.end(); - int radix = _readOptionalBase(&cursor); + int radix = _readOptionalBase(&cursor); - bool seenDot = false; - FloatingPointLiteralValue divisor = 1; - for( ;;) + bool seenDot = false; + FloatingPointLiteralValue divisor = 1; + for (;;) + { + if (*cursor == '.') { - if(*cursor == '.') - { - cursor++; - seenDot = true; - continue; - } + cursor++; + seenDot = true; + continue; + } - int digit = _maybeReadDigit(&cursor, radix); - if(digit < 0) - break; + int digit = _maybeReadDigit(&cursor, radix); + if (digit < 0) + break; - value = value*radix + digit; + value = value * radix + digit; - if(seenDot) - { - divisor *= radix; - } + if (seenDot) + { + divisor *= radix; } + } - if (*cursor == '#') - { - // It must be INF - const auto inf = toSlice("#INF"); + if (*cursor == '#') + { + // It must be INF + const auto inf = toSlice("#INF"); - if (UnownedStringSlice(cursor, end).startsWith(inf)) + if (UnownedStringSlice(cursor, end).startsWith(inf)) + { + if (outSuffix) { - if(outSuffix) - { - *outSuffix = UnownedStringSlice(cursor + inf.getLength(), end); - } + *outSuffix = UnownedStringSlice(cursor + inf.getLength(), end); + } - value = INFINITY; + value = INFINITY; - return value; - } + return value; } + } + + // Now read optional exponent + if (_isNumberExponent(*cursor, radix)) + { + cursor++; - // Now read optional exponent - if(_isNumberExponent(*cursor, radix)) + bool exponentIsNegative = false; + switch (*cursor) { + default: break; + + case '-': + exponentIsNegative = true; cursor++; + break; - bool exponentIsNegative = false; - switch(*cursor) - { - default: - break; + case '+': cursor++; break; + } - case '-': - exponentIsNegative = true; - cursor++; - break; + int exponentRadix = 10; + int exponent = 0; - case '+': - cursor++; + for (;;) + { + int digit = _maybeReadDigit(&cursor, exponentRadix); + if (digit < 0) break; - } - - int exponentRadix = 10; - int exponent = 0; - - for(;;) - { - int digit = _maybeReadDigit(&cursor, exponentRadix); - if(digit < 0) - break; - - exponent = exponent*exponentRadix + digit; - } - - FloatingPointLiteralValue exponentBase = 10; - if(radix == 16) - { - exponentBase = 2; - } - FloatingPointLiteralValue exponentValue = pow(exponentBase, exponent); + exponent = exponent * exponentRadix + digit; + } - if( exponentIsNegative ) - { - divisor *= exponentValue; - } - else - { - value *= exponentValue; - } + FloatingPointLiteralValue exponentBase = 10; + if (radix == 16) + { + exponentBase = 2; } - value /= divisor; + FloatingPointLiteralValue exponentValue = pow(exponentBase, exponent); - if(outSuffix) + if (exponentIsNegative) { - *outSuffix = UnownedStringSlice(cursor, end); + divisor *= exponentValue; } + else + { + value *= exponentValue; + } + } - return value; + value /= divisor; + + if (outSuffix) + { + *outSuffix = UnownedStringSlice(cursor, end); } - static void _lexStringLiteralBody(Lexer* lexer, char quote) + return value; +} + +static void _lexStringLiteralBody(Lexer* lexer, char quote) +{ + for (;;) { - for(;;) + int c = _peek(lexer); + if (c == quote) + { + _advance(lexer); + return; + } + + switch (c) { - int c = _peek(lexer); - if(c == quote) + case kEOF: + if (auto sink = lexer->getDiagnosticSink()) { - _advance(lexer); - return; + sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::endOfFileInLiteral); } + return; - switch(c) + case '\n': + case '\r': + if (auto sink = lexer->getDiagnosticSink()) { - case kEOF: - if (auto sink = lexer->getDiagnosticSink()) - { - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::endOfFileInLiteral); - } - return; + sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::newlineInLiteral); + } + return; - case '\n': case '\r': - if (auto sink = lexer->getDiagnosticSink()) + case '\\': + // Need to handle various escape sequence cases + _advance(lexer); + switch (_peek(lexer)) + { + case '\'': + case '\"': + case '\\': + case '?': + case 'a': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': _advance(lexer); break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + // octal escape: up to 3 characters + _advance(lexer); + for (int ii = 0; ii < 3; ++ii) { - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::newlineInLiteral); + int d = _peek(lexer); + if (('0' <= d) && (d <= '7')) + { + _advance(lexer); + continue; + } + else + { + break; + } } - return; + break; - case '\\': - // Need to handle various escape sequence cases + case 'x': + // hexadecimal escape: any number of characters _advance(lexer); - switch(_peek(lexer)) + for (;;) { - case '\'': - case '\"': - case '\\': - case '?': - case 'a': - case 'b': - case 'f': - case 'n': - case 'r': - case 't': - case 'v': - _advance(lexer); - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': - // octal escape: up to 3 characters - _advance(lexer); - for(int ii = 0; ii < 3; ++ii) + int d = _peek(lexer); + if (('0' <= d) && (d <= '9') || ('a' <= d) && (d <= 'f') || + ('A' <= d) && (d <= 'F')) { - int d = _peek(lexer); - if(('0' <= d) && (d <= '7')) - { - _advance(lexer); - continue; - } - else - { - break; - } + _advance(lexer); + continue; } - break; - - case 'x': - // hexadecimal escape: any number of characters - _advance(lexer); - for(;;) + else { - int d = _peek(lexer); - if(('0' <= d) && (d <= '9') - || ('a' <= d) && (d <= 'f') - || ('A' <= d) && (d <= 'F')) - { - _advance(lexer); - continue; - } - else - { - break; - } + break; } - break; - - // TODO: Unicode escape sequences - } break; - default: - _advance(lexer); - continue; + // TODO: Unicode escape sequences } + break; + + default: _advance(lexer); continue; } } +} - static void _lexRawStringLiteralBody(Lexer* lexer) +static void _lexRawStringLiteralBody(Lexer* lexer) +{ + const char* start = lexer->m_cursor; + const char* endOfDelimiter = nullptr; + for (;;) { - const char* start = lexer->m_cursor; - const char* endOfDelimiter = nullptr; - for (;;) + int c = _peek(lexer); + if (c == '(' && endOfDelimiter == nullptr) + endOfDelimiter = lexer->m_cursor; + if (c == '\"') { - int c = _peek(lexer); - if (c == '(' && endOfDelimiter == nullptr) - endOfDelimiter = lexer->m_cursor; - if (c == '\"') + if (!endOfDelimiter) { - if (!endOfDelimiter) + if (auto sink = lexer->getDiagnosticSink()) { - if (auto sink = lexer->getDiagnosticSink()) - { - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::quoteCannotBeDelimiter); - } + sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::quoteCannotBeDelimiter); } - else + } + else + { + auto testStart = lexer->m_cursor - (endOfDelimiter - start); + if (testStart > endOfDelimiter) { - auto testStart = lexer->m_cursor - (endOfDelimiter - start); - if (testStart > endOfDelimiter) + auto testDelimiter = UnownedStringSlice(testStart, lexer->m_cursor); + auto delimiter = UnownedStringSlice(start, endOfDelimiter); + if (*(testStart - 1) == ')' && testDelimiter == delimiter) { - auto testDelimiter = UnownedStringSlice(testStart, lexer->m_cursor); - auto delimiter = UnownedStringSlice(start, endOfDelimiter); - if (*(testStart - 1) == ')' && testDelimiter == delimiter) - { - _advance(lexer); - return; - } + _advance(lexer); + return; } } } + } - switch (c) + switch (c) + { + case kEOF: + if (auto sink = lexer->getDiagnosticSink()) { - case kEOF: - if (auto sink = lexer->getDiagnosticSink()) - { - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::endOfFileInLiteral); - } - return; - default: - _advance(lexer); - continue; + sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::endOfFileInLiteral); } + return; + default: _advance(lexer); continue; } } +} - UnownedStringSlice getRawStringLiteralTokenValue(Token const& token) - { - auto content = token.getContent(); - if (content.getLength() <= 5) - return UnownedStringSlice(); - auto start = content.begin() + 2; - auto delimEnd = start; - while (delimEnd < content.end() && *delimEnd != '(') - delimEnd++; - auto delimLength = delimEnd - start; - auto contentEnd = content.end() - delimLength - 2; - auto contentBegin = start + delimLength + 1; - if (contentEnd <= contentBegin) - return UnownedStringSlice(); - return UnownedStringSlice(contentBegin, contentEnd); - } +UnownedStringSlice getRawStringLiteralTokenValue(Token const& token) +{ + auto content = token.getContent(); + if (content.getLength() <= 5) + return UnownedStringSlice(); + auto start = content.begin() + 2; + auto delimEnd = start; + while (delimEnd < content.end() && *delimEnd != '(') + delimEnd++; + auto delimLength = delimEnd - start; + auto contentEnd = content.end() - delimLength - 2; + auto contentBegin = start + delimLength + 1; + if (contentEnd <= contentBegin) + return UnownedStringSlice(); + return UnownedStringSlice(contentBegin, contentEnd); +} - String getStringLiteralTokenValue(Token const& token) - { - SLANG_ASSERT(token.type == TokenType::StringLiteral - || token.type == TokenType::CharLiteral); +String getStringLiteralTokenValue(Token const& token) +{ + SLANG_ASSERT(token.type == TokenType::StringLiteral || token.type == TokenType::CharLiteral); - if (token.getContent().startsWith("R")) - return getRawStringLiteralTokenValue(token); + if (token.getContent().startsWith("R")) + return getRawStringLiteralTokenValue(token); - const UnownedStringSlice content = token.getContent(); + const UnownedStringSlice content = token.getContent(); - char const* cursor = content.begin(); - char const* end = content.end(); - SLANG_UNREFERENCED_VARIABLE(end); + char const* cursor = content.begin(); + char const* end = content.end(); + SLANG_UNREFERENCED_VARIABLE(end); - auto quote = *cursor++; - SLANG_ASSERT(quote == '\'' || quote == '"'); + auto quote = *cursor++; + SLANG_ASSERT(quote == '\'' || quote == '"'); - StringBuilder valueBuilder; - for(;;) - { - SLANG_ASSERT(cursor != end); + StringBuilder valueBuilder; + for (;;) + { + SLANG_ASSERT(cursor != end); - auto c = *cursor++; + auto c = *cursor++; - // If we see a closing quote, then we are at the end of the string literal - if(c == quote) - { - SLANG_ASSERT(cursor == end); - return valueBuilder.produceString(); - } + // If we see a closing quote, then we are at the end of the string literal + if (c == quote) + { + SLANG_ASSERT(cursor == end); + return valueBuilder.produceString(); + } - // Characters that don't being escape sequences are easy; - // just append them to the buffer and move on. - if(c != '\\') - { - valueBuilder.append(c); - continue; - } + // Characters that don't being escape sequences are easy; + // just append them to the buffer and move on. + if (c != '\\') + { + valueBuilder.append(c); + continue; + } - // Now we look at another character to figure out the kind of - // escape sequence we are dealing with: + // Now we look at another character to figure out the kind of + // escape sequence we are dealing with: - char d = *cursor++; + char d = *cursor++; - switch(d) + switch (d) + { + // Simple characters that just needed to be escaped + case '\'': + case '\"': + case '\\': + case '?': valueBuilder.append(d); continue; + + // Traditional escape sequences for special characters + case 'a': valueBuilder.append('\a'); continue; + case 'b': valueBuilder.append('\b'); continue; + case 'f': valueBuilder.append('\f'); continue; + case 'n': valueBuilder.append('\n'); continue; + case 'r': valueBuilder.append('\r'); continue; + case 't': valueBuilder.append('\t'); continue; + case 'v': valueBuilder.append('\v'); continue; + + // Octal escape: up to 3 characters + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { - // Simple characters that just needed to be escaped - case '\'': - case '\"': - case '\\': - case '?': - valueBuilder.append(d); - continue; - - // Traditional escape sequences for special characters - case 'a': valueBuilder.append('\a'); continue; - case 'b': valueBuilder.append('\b'); continue; - case 'f': valueBuilder.append('\f'); continue; - case 'n': valueBuilder.append('\n'); continue; - case 'r': valueBuilder.append('\r'); continue; - case 't': valueBuilder.append('\t'); continue; - case 'v': valueBuilder.append('\v'); continue; - - // Octal escape: up to 3 characters - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': + cursor--; + int value = 0; + for (int ii = 0; ii < 3; ++ii) { - cursor--; - int value = 0; - for(int ii = 0; ii < 3; ++ii) + d = *cursor; + if (('0' <= d) && (d <= '7')) { - d = *cursor; - if(('0' <= d) && (d <= '7')) - { - value = value*8 + (d - '0'); + value = value * 8 + (d - '0'); - cursor++; - continue; - } - else - { - break; - } + cursor++; + continue; + } + else + { + break; } - - // TODO: add support for appending an arbitrary code point? - valueBuilder.append((char) value); } - continue; - // Hexadecimal escape: any number of characters - case 'x': + // TODO: add support for appending an arbitrary code point? + valueBuilder.append((char)value); + } + continue; + + // Hexadecimal escape: any number of characters + case 'x': + { + int value = 0; + for (;;) { - int value = 0; - for(;;) + d = *cursor++; + int digitValue = 0; + if (('0' <= d) && (d <= '9')) { - d = *cursor++; - int digitValue = 0; - if(('0' <= d) && (d <= '9')) - { - digitValue = d - '0'; - } - else if( ('a' <= d) && (d <= 'f') ) - { - digitValue = d - 'a'; - } - else if( ('A' <= d) && (d <= 'F') ) - { - digitValue = d - 'A'; - } - else - { - cursor--; - break; - } - - value = value*16 + digitValue; + digitValue = d - '0'; + } + else if (('a' <= d) && (d <= 'f')) + { + digitValue = d - 'a'; + } + else if (('A' <= d) && (d <= 'F')) + { + digitValue = d - 'A'; + } + else + { + cursor--; + break; } - // TODO: add support for appending an arbitrary code point? - valueBuilder.append((char) value); + value = value * 16 + digitValue; } - continue; - - // TODO: Unicode escape sequences + // TODO: add support for appending an arbitrary code point? + valueBuilder.append((char)value); } + continue; + + // TODO: Unicode escape sequences } } +} - String getFileNameTokenValue(Token const& token) - { - const UnownedStringSlice content = token.getContent(); +String getFileNameTokenValue(Token const& token) +{ + const UnownedStringSlice content = token.getContent(); - // A file name usually doesn't process escape sequences - // (this is import on Windows, where `\\` is a valid - // path separator character). + // A file name usually doesn't process escape sequences + // (this is import on Windows, where `\\` is a valid + // path separator character). - // Just trim off the first and last characters to remove the quotes - // (whether they were `""` or `<>`. - return String(content.begin() + 1, content.end() - 1); - } + // Just trim off the first and last characters to remove the quotes + // (whether they were `""` or `<>`. + return String(content.begin() + 1, content.end() - 1); +} - static TokenType _lexTokenImpl(Lexer* lexer) +static TokenType _lexTokenImpl(Lexer* lexer) +{ + int nextCodePoint = _peek(lexer); + switch (nextCodePoint) { - int nextCodePoint = _peek(lexer); - switch(nextCodePoint) - { - default: - break; + default: break; - case kEOF: - return TokenType::EndOfFile; + case kEOF: return TokenType::EndOfFile; + + case '\r': + case '\n': _handleNewLine(lexer); return TokenType::NewLine; - case '\r': case '\n': - _handleNewLine(lexer); - return TokenType::NewLine; + case ' ': + case '\t': _lexHorizontalSpace(lexer); return TokenType::WhiteSpace; - case ' ': case '\t': - _lexHorizontalSpace(lexer); - return TokenType::WhiteSpace; + case '.': + _advance(lexer); + switch (_peek(lexer)) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return _lexNumberAfterDecimalPoint(lexer, 10); case '.': + // Note: consuming the second `.` here means that + // we cannot back up and return a `.` token by itself + // any more. We thus end up having distinct tokens for + // `.`, `..`, and `...` even though the `..` case is + // not part of HLSL. + // _advance(lexer); - switch(_peek(lexer)) + switch (_peek(lexer)) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return _lexNumberAfterDecimalPoint(lexer, 10); - - case '.': - // Note: consuming the second `.` here means that - // we cannot back up and return a `.` token by itself - // any more. We thus end up having distinct tokens for - // `.`, `..`, and `...` even though the `..` case is - // not part of HLSL. - // - _advance(lexer); - switch(_peek(lexer)) - { - case '.': - _advance(lexer); - return TokenType::Ellipsis; + case '.': _advance(lexer); return TokenType::Ellipsis; - default: - return TokenType::DotDot; - } - - default: - return TokenType::Dot; + default: return TokenType::DotDot; } - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return _lexNumber(lexer, 10); + default: return TokenType::Dot; + } - case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return _lexNumber(lexer, 10); + + case '0': + { + auto loc = _getSourceLoc(lexer); + _advance(lexer); + switch (_peek(lexer)) { - auto loc = _getSourceLoc(lexer); - _advance(lexer); - switch(_peek(lexer)) - { - default: - return _maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral); - - case '.': - switch (_peek(lexer, 1)) - { - // 0.xxxx or 0.rrrr - case 'x': - case 'r': - return _maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral); - default: - _advance(lexer); - return _lexNumberAfterDecimalPoint(lexer, 10); - } - - case 'x': case 'X': - _advance(lexer); - return _lexNumber(lexer, 16); + default: return _maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral); - case 'b': case 'B': - _advance(lexer); - return _lexNumber(lexer, 2); - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (auto sink = lexer->getDiagnosticSink()) - { - sink->diagnose(loc, LexerDiagnostics::octalLiteral); - } - return _lexNumber(lexer, 8); + case '.': + switch (_peek(lexer, 1)) + { + // 0.xxxx or 0.rrrr + case 'x': + case 'r': return _maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral); + default: _advance(lexer); return _lexNumberAfterDecimalPoint(lexer, 10); } - } - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': - case '_': - _lexIdentifier(lexer); - return TokenType::Identifier; - case 'R': - _advance(lexer); - switch (_peek(lexer)) - { - default: - _lexIdentifier(lexer); - return TokenType::Identifier; - case '\"': - _advance(lexer); - _lexRawStringLiteralBody(lexer); - return TokenType::StringLiteral; + case 'x': + case 'X': _advance(lexer); return _lexNumber(lexer, 16); + + case 'b': + case 'B': _advance(lexer); return _lexNumber(lexer, 2); + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (auto sink = lexer->getDiagnosticSink()) + { + sink->diagnose(loc, LexerDiagnostics::octalLiteral); + } + return _lexNumber(lexer, 8); } + } + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': _lexIdentifier(lexer); return TokenType::Identifier; + case 'R': + _advance(lexer); + switch (_peek(lexer)) + { + default: _lexIdentifier(lexer); return TokenType::Identifier; case '\"': _advance(lexer); - _lexStringLiteralBody(lexer, '\"'); + _lexRawStringLiteralBody(lexer); return TokenType::StringLiteral; + } - case '\'': - _advance(lexer); - _lexStringLiteralBody(lexer, '\''); - return TokenType::CharLiteral; + case '\"': + _advance(lexer); + _lexStringLiteralBody(lexer, '\"'); + return TokenType::StringLiteral; + case '\'': + _advance(lexer); + _lexStringLiteralBody(lexer, '\''); + return TokenType::CharLiteral; - case '+': - _advance(lexer); - switch(_peek(lexer)) - { - case '+': _advance(lexer); return TokenType::OpInc; - case '=': _advance(lexer); return TokenType::OpAddAssign; - default: - return TokenType::OpAdd; - } - case '-': - _advance(lexer); - switch(_peek(lexer)) - { - case '-': _advance(lexer); return TokenType::OpDec; - case '=': _advance(lexer); return TokenType::OpSubAssign; - case '>': _advance(lexer); return TokenType::RightArrow; - default: - return TokenType::OpSub; - } + case '+': + _advance(lexer); + switch (_peek(lexer)) + { + case '+': _advance(lexer); return TokenType::OpInc; + case '=': _advance(lexer); return TokenType::OpAddAssign; + default: return TokenType::OpAdd; + } - case '*': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpMulAssign; - default: - return TokenType::OpMul; - } + case '-': + _advance(lexer); + switch (_peek(lexer)) + { + case '-': _advance(lexer); return TokenType::OpDec; + case '=': _advance(lexer); return TokenType::OpSubAssign; + case '>': _advance(lexer); return TokenType::RightArrow; + default: return TokenType::OpSub; + } + + case '*': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpMulAssign; + default: return TokenType::OpMul; + } + case '/': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpDivAssign; case '/': _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpDivAssign; - case '/': _advance(lexer); _lexLineComment(lexer); return TokenType::LineComment; - case '*': _advance(lexer); _lexBlockComment(lexer); return TokenType::BlockComment; - default: - return TokenType::OpDiv; - } - - case '%': + _lexLineComment(lexer); + return TokenType::LineComment; + case '*': _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpModAssign; - default: - return TokenType::OpMod; - } + _lexBlockComment(lexer); + return TokenType::BlockComment; + default: return TokenType::OpDiv; + } - case '|': - _advance(lexer); - switch(_peek(lexer)) - { - case '|': _advance(lexer); return TokenType::OpOr; - case '=': _advance(lexer); return TokenType::OpOrAssign; - default: - return TokenType::OpBitOr; - } + case '%': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpModAssign; + default: return TokenType::OpMod; + } - case '&': - _advance(lexer); - switch(_peek(lexer)) - { - case '&': _advance(lexer); return TokenType::OpAnd; - case '=': _advance(lexer); return TokenType::OpAndAssign; - default: - return TokenType::OpBitAnd; - } + case '|': + _advance(lexer); + switch (_peek(lexer)) + { + case '|': _advance(lexer); return TokenType::OpOr; + case '=': _advance(lexer); return TokenType::OpOrAssign; + default: return TokenType::OpBitOr; + } - case '^': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpXorAssign; - default: - return TokenType::OpBitXor; - } + case '&': + _advance(lexer); + switch (_peek(lexer)) + { + case '&': _advance(lexer); return TokenType::OpAnd; + case '=': _advance(lexer); return TokenType::OpAndAssign; + default: return TokenType::OpBitAnd; + } + case '^': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpXorAssign; + default: return TokenType::OpBitXor; + } + + case '>': + _advance(lexer); + switch (_peek(lexer)) + { case '>': _advance(lexer); - switch(_peek(lexer)) + switch (_peek(lexer)) { - case '>': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpShrAssign; - default: return TokenType::OpRsh; - } - case '=': _advance(lexer); return TokenType::OpGeq; - default: - return TokenType::OpGreater; + case '=': _advance(lexer); return TokenType::OpShrAssign; + default: return TokenType::OpRsh; } + case '=': _advance(lexer); return TokenType::OpGeq; + default: return TokenType::OpGreater; + } + case '<': + _advance(lexer); + switch (_peek(lexer)) + { case '<': _advance(lexer); - switch(_peek(lexer)) + switch (_peek(lexer)) { - case '<': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpShlAssign; - default: return TokenType::OpLsh; - } - case '=': _advance(lexer); return TokenType::OpLeq; - default: - return TokenType::OpLess; + case '=': _advance(lexer); return TokenType::OpShlAssign; + default: return TokenType::OpLsh; } + case '=': _advance(lexer); return TokenType::OpLeq; + default: return TokenType::OpLess; + } - case '=': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpEql; - default: - return TokenType::OpAssign; - } + case '=': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpEql; + default: return TokenType::OpAssign; + } - case '!': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpNeq; - default: - return TokenType::OpNot; - } + case '!': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpNeq; + default: return TokenType::OpNot; + } - case '#': - _advance(lexer); - switch(_peek(lexer)) - { - case '#': _advance(lexer); return TokenType::PoundPound; + case '#': + _advance(lexer); + switch (_peek(lexer)) + { + case '#': _advance(lexer); return TokenType::PoundPound; - case '?': _advance(lexer); return TokenType::CompletionRequest; + case '?': _advance(lexer); return TokenType::CompletionRequest; - default: - return TokenType::Pound; - } + default: return TokenType::Pound; + } - case '~': _advance(lexer); return TokenType::OpBitNot; + case '~': _advance(lexer); return TokenType::OpBitNot; - case ':': + case ':': { _advance(lexer); if (_peek(lexer) == ':') @@ -1347,151 +1407,154 @@ namespace Slang } return TokenType::Colon; } - case ';': _advance(lexer); return TokenType::Semicolon; - case ',': _advance(lexer); return TokenType::Comma; - - case '{': _advance(lexer); return TokenType::LBrace; - case '}': _advance(lexer); return TokenType::RBrace; - case '[': _advance(lexer); return TokenType::LBracket; - case ']': _advance(lexer); return TokenType::RBracket; - case '(': _advance(lexer); return TokenType::LParent; - case ')': _advance(lexer); return TokenType::RParent; - - case '?': _advance(lexer); return TokenType::QuestionMark; - case '@': _advance(lexer); return TokenType::At; - case '$': + case ';': _advance(lexer); return TokenType::Semicolon; + case ',': _advance(lexer); return TokenType::Comma; + + case '{': _advance(lexer); return TokenType::LBrace; + case '}': _advance(lexer); return TokenType::RBrace; + case '[': _advance(lexer); return TokenType::LBracket; + case ']': _advance(lexer); return TokenType::RBracket; + case '(': _advance(lexer); return TokenType::LParent; + case ')': _advance(lexer); return TokenType::RParent; + + case '?': _advance(lexer); return TokenType::QuestionMark; + case '@': _advance(lexer); return TokenType::At; + case '$': { _advance(lexer); - if(_peek(lexer) == '$') + if (_peek(lexer) == '$') { _advance(lexer); return TokenType::DollarDollar; } return TokenType::Dollar; } + } - } - - // We treat all unicode characters as a part of an identifier. - if (isNonAsciiCodePoint(nextCodePoint)) - { - _lexIdentifier(lexer); - return TokenType::Identifier; - } + // We treat all unicode characters as a part of an identifier. + if (isNonAsciiCodePoint(nextCodePoint)) + { + _lexIdentifier(lexer); + return TokenType::Identifier; + } - { - // If none of the above cases matched, then we have an - // unexpected/invalid character. + { + // If none of the above cases matched, then we have an + // unexpected/invalid character. - auto loc = _getSourceLoc(lexer); - int c = _advance(lexer); + auto loc = _getSourceLoc(lexer); + int c = _advance(lexer); - if (auto sink = lexer->getDiagnosticSink()) + if (auto sink = lexer->getDiagnosticSink()) + { + if (c >= 0x20 && c <= 0x7E) { - if(c >= 0x20 && c <= 0x7E) - { - char buffer[] = { (char) c, 0 }; - sink->diagnose(loc, LexerDiagnostics::illegalCharacterPrint, buffer); - } - else if(c == kEOF) - { - sink->diagnose(loc, LexerDiagnostics::unexpectedEndOfInput); - } - else - { - // Fallback: print as hexadecimal - sink->diagnose(loc, LexerDiagnostics::illegalCharacterHex, String((unsigned char)c, 16)); - } + char buffer[] = {(char)c, 0}; + sink->diagnose(loc, LexerDiagnostics::illegalCharacterPrint, buffer); + } + else if (c == kEOF) + { + sink->diagnose(loc, LexerDiagnostics::unexpectedEndOfInput); + } + else + { + // Fallback: print as hexadecimal + sink->diagnose( + loc, + LexerDiagnostics::illegalCharacterHex, + String((unsigned char)c, 16)); } - - return TokenType::Invalid; } + + return TokenType::Invalid; } +} - Token Lexer::lexToken() +Token Lexer::lexToken() +{ + for (;;) { - for(;;) - { - Token token; - token.loc = _getSourceLoc(this); + Token token; + token.loc = _getSourceLoc(this); - char const* textBegin = m_cursor; + char const* textBegin = m_cursor; - auto tokenType = _lexTokenImpl(this); + auto tokenType = _lexTokenImpl(this); - // The flags on the token we just lexed will be based - // on the current state of the lexer. - // - auto tokenFlags = m_tokenFlags; - // - // Depending on what kind of token we just lexed, the - // flags that will be used for the *next* token might - // need to be updated. - // - switch(tokenType) + // The flags on the token we just lexed will be based + // on the current state of the lexer. + // + auto tokenFlags = m_tokenFlags; + // + // Depending on what kind of token we just lexed, the + // flags that will be used for the *next* token might + // need to be updated. + // + switch (tokenType) + { + case TokenType::NewLine: { - case TokenType::NewLine: - { - // If we just reached the end of a line, then the next token - // should count as being at the start of a line, and also after - // whitespace. - // - m_tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; - break; - } + // If we just reached the end of a line, then the next token + // should count as being at the start of a line, and also after + // whitespace. + // + m_tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; + break; + } - case TokenType::WhiteSpace: - case TokenType::BlockComment: - case TokenType::LineComment: - { - // True horizontal whitespace and comments both count as whitespace. - // - // Note that a line comment does not include the terminating newline, - // we do not need to set `AtStartOfLine` here. - // - m_tokenFlags |= TokenFlag::AfterWhitespace; - break; - } - - default: - { - // If we read some token other then the above cases, then we are - // neither after whitespace nor at the start of a line. - // - m_tokenFlags = 0; - break; - } + case TokenType::WhiteSpace: + case TokenType::BlockComment: + case TokenType::LineComment: + { + // True horizontal whitespace and comments both count as whitespace. + // + // Note that a line comment does not include the terminating newline, + // we do not need to set `AtStartOfLine` here. + // + m_tokenFlags |= TokenFlag::AfterWhitespace; + break; + } + + default: + { + // If we read some token other then the above cases, then we are + // neither after whitespace nor at the start of a line. + // + m_tokenFlags = 0; + break; } + } - token.type = tokenType; - token.flags = tokenFlags; + token.type = tokenType; + token.flags = tokenFlags; - char const* textEnd = m_cursor; + char const* textEnd = m_cursor; - // Note(tfoley): `StringBuilder::Append()` seems to crash when appending zero bytes - if(textEnd != textBegin) + // Note(tfoley): `StringBuilder::Append()` seems to crash when appending zero bytes + if (textEnd != textBegin) + { + // "scrubbing" token value here to remove escaped newlines... + // + // Only perform this work if we encountered an escaped newline + // while lexing this token (e.g., keep a flag on the lexer), or + // do it on-demand when the actual value of the token is needed. + if (tokenFlags & TokenFlag::ScrubbingNeeded) { - // "scrubbing" token value here to remove escaped newlines... - // - // Only perform this work if we encountered an escaped newline - // while lexing this token (e.g., keep a flag on the lexer), or - // do it on-demand when the actual value of the token is needed. - if (tokenFlags & TokenFlag::ScrubbingNeeded) - { - // Allocate space that will always be more than enough for stripped contents - char* startDst = (char*)m_memoryArena->allocateUnaligned(textEnd - textBegin); - char* dst = startDst; + // Allocate space that will always be more than enough for stripped contents + char* startDst = (char*)m_memoryArena->allocateUnaligned(textEnd - textBegin); + char* dst = startDst; - auto tt = textBegin; - while (tt != textEnd) + auto tt = textBegin; + while (tt != textEnd) + { + char c = *tt++; + if (c == '\\') { - char c = *tt++; - if (c == '\\') + char d = *tt; + switch (d) { - char d = *tt; - switch (d) - { - case '\r': case '\n': + case '\r': + case '\n': { tt++; char e = *tt; @@ -1502,116 +1565,111 @@ namespace Slang } continue; - default: - break; - } + default: break; } - *dst++ = c; } - token.setContent(UnownedStringSlice(startDst, dst)); - } - else - { - token.setContent(UnownedStringSlice(textBegin, textEnd)); + *dst++ = c; } + token.setContent(UnownedStringSlice(startDst, dst)); } - - if (m_namePool) + else { - if (tokenType == TokenType::Identifier || tokenType == TokenType::CompletionRequest) - { - token.setName(m_namePool->getName(token.getContent())); - } + token.setContent(UnownedStringSlice(textBegin, textEnd)); } - - return token; } - } - TokenList Lexer::lexAllSemanticTokens() - { - TokenList tokenList; - for(;;) + if (m_namePool) { - Token token = lexToken(); - - // We are only interested intokens that are semantically - // significant, so we will skip over forms of whitespace - // and comments. - // - switch( token.type ) + if (tokenType == TokenType::Identifier || tokenType == TokenType::CompletionRequest) { - default: - break; - - case TokenType::WhiteSpace: - case TokenType::BlockComment: - case TokenType::LineComment: - case TokenType::NewLine: - continue; + token.setName(m_namePool->getName(token.getContent())); } - - tokenList.add(token); - if(token.type == TokenType::EndOfFile) - return tokenList; } + + return token; } +} - TokenList Lexer::lexAllMarkupTokens() +TokenList Lexer::lexAllSemanticTokens() +{ + TokenList tokenList; + for (;;) { - TokenList tokenList; - for(;;) - { - Token token = lexToken(); - switch( token.type ) - { - default: - break; + Token token = lexToken(); - case TokenType::WhiteSpace: - case TokenType::NewLine: - continue; - } + // We are only interested intokens that are semantically + // significant, so we will skip over forms of whitespace + // and comments. + // + switch (token.type) + { + default: break; - tokenList.add(token); - if(token.type == TokenType::EndOfFile) - return tokenList; + case TokenType::WhiteSpace: + case TokenType::BlockComment: + case TokenType::LineComment: + case TokenType::NewLine: continue; } + + tokenList.add(token); + if (token.type == TokenType::EndOfFile) + return tokenList; } +} - /* static */UnownedStringSlice Lexer::sourceLocationLexer(const UnownedStringSlice& in) +TokenList Lexer::lexAllMarkupTokens() +{ + TokenList tokenList; + for (;;) { - Lexer lexer; + Token token = lexToken(); + switch (token.type) + { + default: break; - SourceManager sourceManager; - sourceManager.initialize(nullptr, nullptr); + case TokenType::WhiteSpace: + case TokenType::NewLine: continue; + } - auto sourceFile = sourceManager.createSourceFileWithString(PathInfo::makeUnknown(), in); - auto sourceView = sourceManager.createSourceView(sourceFile, nullptr, SourceLoc::fromRaw(0)); + tokenList.add(token); + if (token.type == TokenType::EndOfFile) + return tokenList; + } +} - DiagnosticSink sink(&sourceManager, nullptr); +/* static */ UnownedStringSlice Lexer::sourceLocationLexer(const UnownedStringSlice& in) +{ + Lexer lexer; - MemoryArena arena; + SourceManager sourceManager; + sourceManager.initialize(nullptr, nullptr); - RootNamePool rootNamePool; - NamePool namePool; - namePool.setRootNamePool(&rootNamePool); + auto sourceFile = sourceManager.createSourceFileWithString(PathInfo::makeUnknown(), in); + auto sourceView = sourceManager.createSourceView(sourceFile, nullptr, SourceLoc::fromRaw(0)); - lexer.initialize(sourceView, &sink, &namePool, &arena); + DiagnosticSink sink(&sourceManager, nullptr); - Token tok = lexer.lexToken(); + MemoryArena arena; - if (tok.type == TokenType::Invalid) - { - return UnownedStringSlice(); - } + RootNamePool rootNamePool; + NamePool namePool; + namePool.setRootNamePool(&rootNamePool); - const int offset = sourceView->getRange().getOffset(tok.loc); + lexer.initialize(sourceView, &sink, &namePool, &arena); - SLANG_ASSERT(offset >= 0 && offset <= in.getLength()); - SLANG_ASSERT(Index(offset + tok.charsCount) <= in.getLength()); + Token tok = lexer.lexToken(); - return UnownedStringSlice(in.begin() + offset, in.begin() + offset + tok.charsCount); + if (tok.type == TokenType::Invalid) + { + return UnownedStringSlice(); } + const int offset = sourceView->getRange().getOffset(tok.loc); + + SLANG_ASSERT(offset >= 0 && offset <= in.getLength()); + SLANG_ASSERT(Index(offset + tok.charsCount) <= in.getLength()); + + return UnownedStringSlice(in.begin() + offset, in.begin() + offset + tok.charsCount); } + +} // namespace Slang diff --git a/source/compiler-core/slang-lexer.h b/source/compiler-core/slang-lexer.h index 3a2506d85..a9883ced6 100644 --- a/source/compiler-core/slang-lexer.h +++ b/source/compiler-core/slang-lexer.h @@ -6,173 +6,176 @@ namespace Slang { - struct NamePool; +struct NamePool; - // +// - struct TokenList - { - const Token* begin() const; - const Token* end() const; +struct TokenList +{ + const Token* begin() const; + const Token* end() const; - SLANG_FORCE_INLINE void add(const Token& token) { m_tokens.add(token); } + SLANG_FORCE_INLINE void add(const Token& token) { m_tokens.add(token); } - List<Token> m_tokens; - }; + List<Token> m_tokens; +}; - struct TokenSpan +struct TokenSpan +{ + TokenSpan(); + TokenSpan(TokenList const& tokenList) + : m_begin(tokenList.begin()), m_end(tokenList.end()) { - TokenSpan(); - TokenSpan( - TokenList const& tokenList) - : m_begin(tokenList.begin()) - , m_end (tokenList.end ()) - {} + } - const Token* begin() const { return m_begin; } - const Token* end () const { return m_end ; } + const Token* begin() const { return m_begin; } + const Token* end() const { return m_end; } - int getCount() { return (int)(m_end - m_begin); } + int getCount() { return (int)(m_end - m_begin); } - const Token* m_begin; - const Token* m_end; - }; + const Token* m_begin; + const Token* m_end; +}; - struct TokenReader +struct TokenReader +{ + Token m_nextToken; + TokenReader(); + explicit TokenReader(TokenSpan const& tokens) + : m_cursor(tokens.begin()), m_end(tokens.end()) { - Token m_nextToken; - TokenReader(); - explicit TokenReader(TokenSpan const& tokens) - : m_cursor(tokens.begin()) - , m_end (tokens.end ()) - { - _updateLookaheadToken(); - } - explicit TokenReader(TokenList const& tokens) - : m_cursor(tokens.begin()) - , m_end (tokens.end ()) - { - _updateLookaheadToken(); - } - explicit TokenReader(Token const* begin, Token const* end) - : m_cursor(begin) - , m_end (end) + _updateLookaheadToken(); + } + explicit TokenReader(TokenList const& tokens) + : m_cursor(tokens.begin()), m_end(tokens.end()) + { + _updateLookaheadToken(); + } + explicit TokenReader(Token const* begin, Token const* end) + : m_cursor(begin), m_end(end) + { + _updateLookaheadToken(); + } + struct ParsingCursor + { + bool operator==(const ParsingCursor& rhs) const { - _updateLookaheadToken(); + return tokenReaderCursor == rhs.tokenReaderCursor; } - struct ParsingCursor - { - bool operator==(const ParsingCursor& rhs) const { return tokenReaderCursor == rhs.tokenReaderCursor; } - bool operator!=(const ParsingCursor& rhs) const { return !(*this == rhs); } + bool operator!=(const ParsingCursor& rhs) const { return !(*this == rhs); } - bool isValid() const { return tokenReaderCursor != nullptr; } + bool isValid() const { return tokenReaderCursor != nullptr; } - Token nextToken; - const Token* tokenReaderCursor = nullptr; - }; - ParsingCursor getCursor() - { - ParsingCursor rs; - rs.nextToken = m_nextToken; - rs.tokenReaderCursor = m_cursor; - return rs; - } - void setCursor(ParsingCursor cursor) - { - m_cursor = cursor.tokenReaderCursor; - m_nextToken = cursor.nextToken; - } - bool isAtCursor(const ParsingCursor& cursor) const - { - return cursor.tokenReaderCursor == m_cursor; - } - bool isAtEnd() const { return m_cursor == m_end; } - Token& peekToken(); - TokenType peekTokenType() const; - SourceLoc peekLoc() const; + Token nextToken; + const Token* tokenReaderCursor = nullptr; + }; + ParsingCursor getCursor() + { + ParsingCursor rs; + rs.nextToken = m_nextToken; + rs.tokenReaderCursor = m_cursor; + return rs; + } + void setCursor(ParsingCursor cursor) + { + m_cursor = cursor.tokenReaderCursor; + m_nextToken = cursor.nextToken; + } + bool isAtCursor(const ParsingCursor& cursor) const + { + return cursor.tokenReaderCursor == m_cursor; + } + bool isAtEnd() const { return m_cursor == m_end; } + Token& peekToken(); + TokenType peekTokenType() const; + SourceLoc peekLoc() const; - Token advanceToken(); + Token advanceToken(); - int getCount() { return (int)(m_end - m_cursor); } + int getCount() { return (int)(m_end - m_cursor); } - const Token* m_cursor; - const Token* m_end; - static Token getEndOfFileToken(); + const Token* m_cursor; + const Token* m_end; + static Token getEndOfFileToken(); - private: - /// Update the lookahead token in `m_nextToken` to reflect the cursor state - void _updateLookaheadToken(); - }; +private: + /// Update the lookahead token in `m_nextToken` to reflect the cursor state + void _updateLookaheadToken(); +}; - typedef unsigned int LexerFlags; - enum - { - kLexerFlag_SuppressDiagnostics = 1 << 2, ///< Suppress errors about invalid/unsupported characters - }; +typedef unsigned int LexerFlags; +enum +{ + kLexerFlag_SuppressDiagnostics = 1 + << 2, ///< Suppress errors about invalid/unsupported characters +}; - struct Lexer +struct Lexer +{ + void initialize( + SourceView* sourceView, + DiagnosticSink* sink, + NamePool* namePool, + MemoryArena* memoryArena); + + ~Lexer(); + + /// Runs the lexer to try and extract a single token, which is returned. + /// This can be used by the DiagnosticSink to be able to display more appropriate + /// information when displaying a source location - such as underscoring the + /// token at that location. + /// + /// NOTE! This function is relatively slow, and is designed for use around this specific + /// purpose. It does not return a token or a token type, because that information is + /// not needed by the DiagnosticSink. + static UnownedStringSlice sourceLocationLexer(const UnownedStringSlice& in); + + /// Lex the next token in the input stream, returning an EOF token if at end. + Token lexToken(); + + /// Lex all tokens (up to the end of the stream) that are semantically relevant + TokenList lexAllSemanticTokens(); + + /// Lex all tokens (up to the end of the stream) that are relevant to things like markup + TokenList lexAllMarkupTokens(); + + /// Get the diagnostic sink, taking into account flags. Will return null if suppressing + /// diagnostics. + DiagnosticSink* getDiagnosticSink() { - void initialize( - SourceView* sourceView, - DiagnosticSink* sink, - NamePool* namePool, - MemoryArena* memoryArena); - - ~Lexer(); - - /// Runs the lexer to try and extract a single token, which is returned. - /// This can be used by the DiagnosticSink to be able to display more appropriate - /// information when displaying a source location - such as underscoring the - /// token at that location. - /// - /// NOTE! This function is relatively slow, and is designed for use around this specific - /// purpose. It does not return a token or a token type, because that information is - /// not needed by the DiagnosticSink. - static UnownedStringSlice sourceLocationLexer(const UnownedStringSlice& in); - - /// Lex the next token in the input stream, returning an EOF token if at end. - Token lexToken(); - - /// Lex all tokens (up to the end of the stream) that are semantically relevant - TokenList lexAllSemanticTokens(); - - /// Lex all tokens (up to the end of the stream) that are relevant to things like markup - TokenList lexAllMarkupTokens(); - - /// Get the diagnostic sink, taking into account flags. Will return null if suppressing diagnostics. - DiagnosticSink* getDiagnosticSink() - { - return ((m_lexerFlags & kLexerFlag_SuppressDiagnostics) == 0) ? m_sink : nullptr; - } + return ((m_lexerFlags & kLexerFlag_SuppressDiagnostics) == 0) ? m_sink : nullptr; + } - SourceView* m_sourceView; - DiagnosticSink* m_sink; - NamePool* m_namePool; + SourceView* m_sourceView; + DiagnosticSink* m_sink; + NamePool* m_namePool; - char const* m_cursor; + char const* m_cursor; - char const* m_begin; - char const* m_end; + char const* m_begin; + char const* m_end; - /// The starting sourceLoc (same as first location of SourceView) - SourceLoc m_startLoc; + /// The starting sourceLoc (same as first location of SourceView) + SourceLoc m_startLoc; - TokenFlags m_tokenFlags; - LexerFlags m_lexerFlags; + TokenFlags m_tokenFlags; + LexerFlags m_lexerFlags; + + MemoryArena* m_memoryArena; +}; - MemoryArena* m_memoryArena; - }; - - // Helper routines for extracting values from tokens - String getStringLiteralTokenValue(Token const& token); - String getFileNameTokenValue(Token const& token); +// Helper routines for extracting values from tokens +String getStringLiteralTokenValue(Token const& token); +String getFileNameTokenValue(Token const& token); - typedef int64_t IntegerLiteralValue; - typedef double FloatingPointLiteralValue; +typedef int64_t IntegerLiteralValue; +typedef double FloatingPointLiteralValue; - IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix = 0); - FloatingPointLiteralValue getFloatingPointLiteralValue(Token const& token, UnownedStringSlice* outSuffix = 0); -} +IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix = 0); +FloatingPointLiteralValue getFloatingPointLiteralValue( + Token const& token, + UnownedStringSlice* outSuffix = 0); +} // namespace Slang #endif diff --git a/source/compiler-core/slang-llvm-compiler.cpp b/source/compiler-core/slang-llvm-compiler.cpp index 3d24d3aa1..457268b98 100644 --- a/source/compiler-core/slang-llvm-compiler.cpp +++ b/source/compiler-core/slang-llvm-compiler.cpp @@ -6,11 +6,15 @@ namespace Slang { -/* static */SlangResult LLVMDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult LLVMDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { ComPtr<ISlangSharedLibrary> library; - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-llvm", library)); + SLANG_RETURN_ON_FAIL( + DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-llvm", library)); SLANG_ASSERT(library); if (!library) @@ -18,14 +22,17 @@ namespace Slang return SLANG_FAIL; } - typedef SlangResult(*CreateDownstreamCompilerFunc)(const Guid& intf, IDownstreamCompiler** outCompiler); + typedef SlangResult ( + *CreateDownstreamCompilerFunc)(const Guid& intf, IDownstreamCompiler** outCompiler); ComPtr<IDownstreamCompiler> downstreamCompiler; // Only accept V4, so we can update IArtifact without breaking anything - if (auto fnV4 = (CreateDownstreamCompilerFunc)library->findFuncByName("createLLVMDownstreamCompiler_V4")) + if (auto fnV4 = (CreateDownstreamCompilerFunc)library->findFuncByName( + "createLLVMDownstreamCompiler_V4")) { - SLANG_RETURN_ON_FAIL(fnV4(IDownstreamCompiler::getTypeGuid(), downstreamCompiler.writeRef())); + SLANG_RETURN_ON_FAIL( + fnV4(IDownstreamCompiler::getTypeGuid(), downstreamCompiler.writeRef())); } else { @@ -37,4 +44,4 @@ namespace Slang return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-llvm-compiler.h b/source/compiler-core/slang-llvm-compiler.h index a05e1fed9..298d9a0ad 100644 --- a/source/compiler-core/slang-llvm-compiler.h +++ b/source/compiler-core/slang-llvm-compiler.h @@ -1,18 +1,20 @@ #ifndef SLANG_LLVM_COMPILER_UTIL_H #define SLANG_LLVM_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { struct LLVMDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-metal-compiler.cpp b/source/compiler-core/slang-metal-compiler.cpp index f8639b763..af455a0f7 100644 --- a/source/compiler-core/slang-metal-compiler.cpp +++ b/source/compiler-core/slang-metal-compiler.cpp @@ -1,102 +1,111 @@ #include "slang-metal-compiler.h" -#include "slang-gcc-compiler-util.h" + #include "slang-artifact-desc-util.h" -#include "slang-artifact-util.h" #include "slang-artifact-representation.h" +#include "slang-artifact-util.h" +#include "slang-gcc-compiler-util.h" namespace Slang { - class MetalDownstreamCompiler : public DownstreamCompilerBase +class MetalDownstreamCompiler : public DownstreamCompilerBase +{ +public: + // Because the metal compiler shares the same commandline interface with clang, + // we will use GccDownstreamCompilerUtil, which implements both gcc and clang, + // to create the inner compiler and wrap it here. + // + ComPtr<IDownstreamCompiler> cppCompiler; + String executablePath; + + MetalDownstreamCompiler(ComPtr<IDownstreamCompiler>& innerCompiler, String path) + : DownstreamCompilerBase(innerCompiler->getDesc()) + , cppCompiler(innerCompiler) + , executablePath(path) { - public: - // Because the metal compiler shares the same commandline interface with clang, - // we will use GccDownstreamCompilerUtil, which implements both gcc and clang, - // to create the inner compiler and wrap it here. - // - ComPtr<IDownstreamCompiler> cppCompiler; - String executablePath; - - MetalDownstreamCompiler(ComPtr<IDownstreamCompiler>& innerCompiler, String path) - : DownstreamCompilerBase(innerCompiler->getDesc()) - , cppCompiler(innerCompiler) - , executablePath(path) - { - } - - virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() override { return true; } - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) override - { - // All compile requests should be routed directly to the inner compiler. - return cppCompiler->compile(options, outArtifact); - } - - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) override - { - // Report that we can convert Metal IR to disassembly. - return ArtifactDescUtil::isDisassembly(from, to) && from.payload == ArtifactPayload::MetalAIR; - } - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) override - { - // Use metal-objdump to disassemble the Metal IR. - - ExecutableLocation exeLocation(executablePath, "metal-objdump"); - CommandLine cmdLine; - cmdLine.setExecutableLocation(exeLocation); - cmdLine.addArg("--disassemble"); - ComPtr<IOSFileArtifactRepresentation> srcFile; - SLANG_RETURN_ON_FAIL(from->requireFile(IArtifact::Keep::No, srcFile.writeRef())); - cmdLine.addArg(String(srcFile->getPath())); - - ExecuteResult exeRes; - SLANG_RETURN_ON_FAIL(ProcessUtil::execute(cmdLine, exeRes)); - auto artifact = ArtifactUtil::createArtifact(to); - artifact->addRepresentationUnknown(StringBlob::create(exeRes.standardOutput)); - *outArtifact = artifact.detach(); - return SLANG_OK; - } - }; - - static SlangResult locateMetalCompiler(const String& path, DownstreamCompilerSet* set) + } + + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() override { return true; } + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) override { - ComPtr<IDownstreamCompiler> innerCppCompiler; - - ExecutableLocation metalcLocation = ExecutableLocation(path, "metal"); - - String metalSDKPath = path; - -#if defined (SLANG_APPLE_FAMILY) - // Use xcrun command to find the metal compiler. - CommandLine xcrunCmdLine; - ExecutableLocation xcrunLocation("xcrun"); - xcrunCmdLine.setExecutableLocation(xcrunLocation); - xcrunCmdLine.addArg("--sdk"); - xcrunCmdLine.addArg("macosx"); - xcrunCmdLine.addArg("--find"); - xcrunCmdLine.addArg("metal"); - ExecuteResult exeRes; - if (SLANG_SUCCEEDED(ProcessUtil::execute(xcrunCmdLine, exeRes))) - { - String metalPath = exeRes.standardOutput.trim(); - metalcLocation = ExecutableLocation(ExecutableLocation::Type::Path, metalPath); - metalSDKPath = Path::getParentDirectory(metalcLocation.m_pathOrName); - } -#endif + // All compile requests should be routed directly to the inner compiler. + return cppCompiler->compile(options, outArtifact); + } - SLANG_RETURN_ON_FAIL(GCCDownstreamCompilerUtil::createCompiler(metalcLocation, innerCppCompiler)); + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) override + { + // Report that we can convert Metal IR to disassembly. + return ArtifactDescUtil::isDisassembly(from, to) && + from.payload == ArtifactPayload::MetalAIR; + } + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) override + { + // Use metal-objdump to disassemble the Metal IR. - ComPtr<IDownstreamCompiler> compiler = ComPtr<IDownstreamCompiler>( - new MetalDownstreamCompiler(innerCppCompiler, metalSDKPath)); - set->addCompiler(compiler); + ExecutableLocation exeLocation(executablePath, "metal-objdump"); + CommandLine cmdLine; + cmdLine.setExecutableLocation(exeLocation); + cmdLine.addArg("--disassemble"); + ComPtr<IOSFileArtifactRepresentation> srcFile; + SLANG_RETURN_ON_FAIL(from->requireFile(IArtifact::Keep::No, srcFile.writeRef())); + cmdLine.addArg(String(srcFile->getPath())); + + ExecuteResult exeRes; + SLANG_RETURN_ON_FAIL(ProcessUtil::execute(cmdLine, exeRes)); + auto artifact = ArtifactUtil::createArtifact(to); + artifact->addRepresentationUnknown(StringBlob::create(exeRes.standardOutput)); + *outArtifact = artifact.detach(); return SLANG_OK; } +}; - SlangResult MetalDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +static SlangResult locateMetalCompiler(const String& path, DownstreamCompilerSet* set) +{ + ComPtr<IDownstreamCompiler> innerCppCompiler; + + ExecutableLocation metalcLocation = ExecutableLocation(path, "metal"); + + String metalSDKPath = path; + +#if defined(SLANG_APPLE_FAMILY) + // Use xcrun command to find the metal compiler. + CommandLine xcrunCmdLine; + ExecutableLocation xcrunLocation("xcrun"); + xcrunCmdLine.setExecutableLocation(xcrunLocation); + xcrunCmdLine.addArg("--sdk"); + xcrunCmdLine.addArg("macosx"); + xcrunCmdLine.addArg("--find"); + xcrunCmdLine.addArg("metal"); + ExecuteResult exeRes; + if (SLANG_SUCCEEDED(ProcessUtil::execute(xcrunCmdLine, exeRes))) { - SLANG_UNUSED(loader); - return locateMetalCompiler(path, set); + String metalPath = exeRes.standardOutput.trim(); + metalcLocation = ExecutableLocation(ExecutableLocation::Type::Path, metalPath); + metalSDKPath = Path::getParentDirectory(metalcLocation.m_pathOrName); } +#endif + + SLANG_RETURN_ON_FAIL( + GCCDownstreamCompilerUtil::createCompiler(metalcLocation, innerCppCompiler)); + + ComPtr<IDownstreamCompiler> compiler = + ComPtr<IDownstreamCompiler>(new MetalDownstreamCompiler(innerCppCompiler, metalSDKPath)); + set->addCompiler(compiler); + return SLANG_OK; +} +SlangResult MetalDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) +{ + SLANG_UNUSED(loader); + return locateMetalCompiler(path, set); } + +} // namespace Slang diff --git a/source/compiler-core/slang-metal-compiler.h b/source/compiler-core/slang-metal-compiler.h index 7a14e5fa9..b311a3ea2 100644 --- a/source/compiler-core/slang-metal-compiler.h +++ b/source/compiler-core/slang-metal-compiler.h @@ -1,18 +1,20 @@ #ifndef SLANG_METAL_COMPILER_UTIL_H #define SLANG_METAL_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { - struct MetalDownstreamCompilerUtil - { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); - }; +struct MetalDownstreamCompilerUtil +{ + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); +}; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-misc-diagnostic-defs.h b/source/compiler-core/slang-misc-diagnostic-defs.h index a2ccc4657..984a3a017 100644 --- a/source/compiler-core/slang-misc-diagnostic-defs.h +++ b/source/compiler-core/slang-misc-diagnostic-defs.h @@ -14,7 +14,7 @@ // for any arguments. #ifndef DIAGNOSTIC -#error Need to #define DIAGNOSTIC(...) before including +#error Need to #define DIAGNOSTIC(...) before including #define DIAGNOSTIC(id, severity, name, messageFormat) /* */ #endif @@ -24,15 +24,39 @@ DIAGNOSTIC(-1, Note, seeTokenPasteLocation, "see token pasted location") -DIAGNOSTIC(100000, Error, downstreamNameNotKnown, "downstream tool name not known, allowed names are $0") -DIAGNOSTIC(100001, Error, expectedArgumentForOption, "expected an argument for command-line option '$0'") +DIAGNOSTIC( + 100000, + Error, + downstreamNameNotKnown, + "downstream tool name not known, allowed names are $0") +DIAGNOSTIC( + 100001, + Error, + expectedArgumentForOption, + "expected an argument for command-line option '$0'") DIAGNOSTIC(100002, Error, unbalancedDownstreamArguments, "unbalanced downstream arguments") -DIAGNOSTIC(100003, Error, closeOfUnopenDownstreamArgs, "close of an unopen downstream argument scope") +DIAGNOSTIC( + 100003, + Error, + closeOfUnopenDownstreamArgs, + "close of an unopen downstream argument scope") DIAGNOSTIC(100004, Error, downstreamToolNameNotDefined, "downstream tool name not defined") -DIAGNOSTIC(100005, Error, invalidArgumentForOption, "invalid argument format for command-line option '$0'") - -DIAGNOSTIC(99999, Note, noteLocationOfInternalError, "an internal error threw an exception while working on code near this location") - -DIAGNOSTIC(29104, Error, spirvCoreGrammarJSONParseFailure, "unexpected JSON in spirv core grammar file: $0") +DIAGNOSTIC( + 100005, + Error, + invalidArgumentForOption, + "invalid argument format for command-line option '$0'") + +DIAGNOSTIC( + 99999, + Note, + noteLocationOfInternalError, + "an internal error threw an exception while working on code near this location") + +DIAGNOSTIC( + 29104, + Error, + spirvCoreGrammarJSONParseFailure, + "unexpected JSON in spirv core grammar file: $0") #undef DIAGNOSTIC diff --git a/source/compiler-core/slang-name-convention-util.cpp b/source/compiler-core/slang-name-convention-util.cpp index c3d08326c..cb44aa10e 100644 --- a/source/compiler-core/slang-name-convention-util.cpp +++ b/source/compiler-core/slang-name-convention-util.cpp @@ -7,14 +7,15 @@ namespace Slang { -/* static */NameConvention NameConventionUtil::inferConventionFromText(const UnownedStringSlice& slice) +/* static */ NameConvention NameConventionUtil::inferConventionFromText( + const UnownedStringSlice& slice) { // If no chars, or first char isn't alpha we don't know what it is if (slice.getLength() <= 0 || !CharUtil::isAlpha(slice[0])) { return NameConvention::Invalid; } - + typedef int Flags; struct Flag { @@ -33,9 +34,9 @@ namespace Slang { switch (c) { - case '-': flags |= Flag::Dash; break; - case '_': flags |= Flag::Underscore; break; - default: + case '-': flags |= Flag::Dash; break; + case '_': flags |= Flag::Underscore; break; + default: { if (CharUtil::isLower(c)) { @@ -61,62 +62,66 @@ namespace Slang // Use flags to determine what convention is used switch (flags) { - // We'll assume it's lower camel. - case Flag::Lower: return NameConvention::LowerCamel; - // We'll assume it's upper snake. It almost certainly isn't camel, and snake is more usual - // than kabab. - case Flag::Upper: return NameConvention::UpperSnake; - case Flag::Upper | Flag::Lower: + // We'll assume it's lower camel. + case Flag::Lower: return NameConvention::LowerCamel; + // We'll assume it's upper snake. It almost certainly isn't camel, and snake is more usual + // than kabab. + case Flag::Upper: return NameConvention::UpperSnake; + case Flag::Upper | Flag::Lower: { // Looks like camel, choose the right case based on first char - return CharUtil::isUpper(slice[0]) ? NameConvention::UpperCamel : NameConvention::LowerCamel; + return CharUtil::isUpper(slice[0]) ? NameConvention::UpperCamel + : NameConvention::LowerCamel; } - case Flag::Lower | Flag::Dash: return NameConvention::LowerKabab; - case Flag::Upper | Flag::Dash: return NameConvention::UpperKabab; - case Flag::Lower | Flag::Underscore: return NameConvention::LowerSnake; - case Flag::Upper | Flag::Underscore: return NameConvention::UpperSnake; - default: break; + case Flag::Lower | Flag::Dash: return NameConvention::LowerKabab; + case Flag::Upper | Flag::Dash: return NameConvention::UpperKabab; + case Flag::Lower | Flag::Underscore: return NameConvention::LowerSnake; + case Flag::Upper | Flag::Underscore: return NameConvention::UpperSnake; + default: break; } // Don't know what this style is return NameConvention::Invalid; } -/* static */NameStyle NameConventionUtil::inferStyleFromText(const UnownedStringSlice& slice) +/* static */ NameStyle NameConventionUtil::inferStyleFromText(const UnownedStringSlice& slice) { for (const char c : slice) { switch (c) { - case '-': return NameStyle::Kabab; - case '_': return NameStyle::Snake; - default: break; + case '-': return NameStyle::Kabab; + case '_': return NameStyle::Snake; + default: break; } } return NameStyle::Camel; } -/* static */void NameConventionUtil::split(NameStyle style, const UnownedStringSlice& slice, List<UnownedStringSlice>& out) +/* static */ void NameConventionUtil::split( + NameStyle style, + const UnownedStringSlice& slice, + List<UnownedStringSlice>& out) { switch (style) { - case NameStyle::Kabab: + case NameStyle::Kabab: { StringUtil::split(slice, '-', out); break; } - case NameStyle::Snake: + case NameStyle::Snake: { StringUtil::split(slice, '_', out); break; } - case NameStyle::Camel: + case NameStyle::Camel: { typedef CharUtil::Flags CharFlags; typedef CharUtil::Flag CharFlag; CharFlags prevFlags = 0; - const char*const end = slice.end(); + const char* const end = slice.end(); const char* start = slice.begin(); for (const char* cur = start; cur < end; ++cur) @@ -134,15 +139,18 @@ namespace Slang } else if ((prevFlags & CharFlag::Upper) && cur + 1 < end) { - // This works with capital or uncapitalized acronyms, but if we have two capitalized acronyms following each other - it can't split. - // - // For example + // This works with capital or uncapitalized acronyms, but if we have two + // capitalized acronyms following each other - it can't split. + // + // For example // "IAABBSystem" -> "IAABB", "System" - // - // If it only accepted lower case acronyms the logic could be changed such that the following could be produced - // "IAabbSystem" -> "I", "Aabb", "System" // - // Since Slang source largely goes with upper case acronyms, we work with the heuristic here.. + // If it only accepted lower case acronyms the logic could be changed such + // that the following could be produced "IAabbSystem" -> "I", "Aabb", + // "System" + // + // Since Slang source largely goes with upper case acronyms, we work with + // the heuristic here.. if (CharUtil::isLower(cur[1])) { @@ -151,7 +159,7 @@ namespace Slang } } } - + prevFlags = flags; } @@ -162,7 +170,7 @@ namespace Slang } break; } - case NameStyle::Unknown: + case NameStyle::Unknown: { out.add(slice); break; @@ -175,7 +183,12 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List<UnownedStri split(inferStyleFromText(slice), slice, out); } -/* static */void NameConventionUtil::join(const UnownedStringSlice* slices, Index slicesCount, NameConvention convention, char joinChar, StringBuilder& out) +/* static */ void NameConventionUtil::join( + const UnownedStringSlice* slices, + Index slicesCount, + NameConvention convention, + char joinChar, + StringBuilder& out) { if (slicesCount <= 0) { @@ -188,7 +201,7 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List<UnownedStri totalSize += slices[i].getLength(); } - char*const dstStart = out.prepareForAppend(totalSize); + char* const dstStart = out.prepareForAppend(totalSize); char* dst = dstStart; const bool upper = isUpper(convention); @@ -197,7 +210,7 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List<UnownedStri { const UnownedStringSlice& slice = slices[i]; const Index count = slice.getLength(); - const char*const src = slice.begin(); + const char* const src = slice.begin(); if (i > 0) { @@ -226,15 +239,19 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List<UnownedStri out.appendInPlace(dstStart, totalSize); } -/* static */void NameConventionUtil::join(const UnownedStringSlice* slices, Index slicesCount, NameConvention convention, StringBuilder& out) +/* static */ void NameConventionUtil::join( + const UnownedStringSlice* slices, + Index slicesCount, + NameConvention convention, + StringBuilder& out) { const auto style = getNameStyle(convention); switch (style) { - case NameStyle::Kabab: return join(slices, slicesCount, convention, '-', out); - case NameStyle::Snake: return join(slices, slicesCount, convention, '_', out); - case NameStyle::Camel: + case NameStyle::Kabab: return join(slices, slicesCount, convention, '-', out); + case NameStyle::Snake: return join(slices, slicesCount, convention, '_', out); + case NameStyle::Camel: { Index totalSize = 0; @@ -243,7 +260,7 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List<UnownedStri totalSize += slices[i].getLength(); } - char*const dstStart = out.prepareForAppend(totalSize); + char* const dstStart = out.prepareForAppend(totalSize); char* dst = dstStart; for (Index i = 0; i < slicesCount; ++i) @@ -276,7 +293,11 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List<UnownedStri } } -/* static */void NameConventionUtil::convert(NameStyle fromStyle, const UnownedStringSlice& slice, NameConvention toConvention, StringBuilder& out) +/* static */ void NameConventionUtil::convert( + NameStyle fromStyle, + const UnownedStringSlice& slice, + NameConvention toConvention, + StringBuilder& out) { // Split into slices List<UnownedStringSlice> slices; @@ -286,10 +307,12 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List<UnownedStri join(slices.getBuffer(), slices.getCount(), toConvention, out); } -/* static */void NameConventionUtil::convert(const UnownedStringSlice& slice, NameConvention toConvention, StringBuilder& out) +/* static */ void NameConventionUtil::convert( + const UnownedStringSlice& slice, + NameConvention toConvention, + StringBuilder& out) { convert(inferStyleFromText(slice), slice, toConvention, out); } -} - +} // namespace Slang diff --git a/source/compiler-core/slang-name-convention-util.h b/source/compiler-core/slang-name-convention-util.h index 95f4f63aa..0ae9e87ca 100644 --- a/source/compiler-core/slang-name-convention-util.h +++ b/source/compiler-core/slang-name-convention-util.h @@ -1,8 +1,8 @@ #ifndef SLANG_COMPILER_CORE_NAME_CONVENTION_UTIL_H #define SLANG_COMPILER_CORE_NAME_CONVENTION_UTIL_H -#include "../core/slang-string.h" #include "../core/slang-list.h" +#include "../core/slang-string.h" namespace Slang { @@ -11,10 +11,11 @@ typedef uint8_t NameConventionBackingType; enum class NameStyle : NameConventionBackingType { - Unknown, /// Unknown style - Kabab, /// Words are separated with -. WORDS-ARE-SEPARATED, words-are-separted - Snake, /// Words are separated with _. WORDS_ARE_SEPARATED, words_are_separated - Camel, /// Words start with a capital. (Upper will make first words character capitalized, aka PascalCase) + Unknown, /// Unknown style + Kabab, /// Words are separated with -. WORDS-ARE-SEPARATED, words-are-separted + Snake, /// Words are separated with _. WORDS_ARE_SEPARATED, words_are_separated + Camel, /// Words start with a capital. (Upper will make first words character capitalized, aka + /// PascalCase) }; struct NameConventionFlag @@ -37,61 +38,98 @@ enum class NameConvention : NameConventionBackingType { Invalid = NameConventionBackingType(NameStyle::Unknown), - LowerKabab = NameConventionBackingType(NameStyle::Kabab), - LowerSnake = NameConventionBackingType(NameStyle::Snake), - LowerCamel = NameConventionBackingType(NameStyle::Camel), + LowerKabab = NameConventionBackingType(NameStyle::Kabab), + LowerSnake = NameConventionBackingType(NameStyle::Snake), + LowerCamel = NameConventionBackingType(NameStyle::Camel), UpperKabab = NameConventionBackingType(NameStyle::Kabab) | NameConventionFlag::UpperCase, UpperSnake = NameConventionBackingType(NameStyle::Snake) | NameConventionFlag::UpperCase, UpperCamel = NameConventionBackingType(NameStyle::Camel) | NameConventionFlag::UpperCase, }; -SLANG_FORCE_INLINE NameConvention makeUpper(NameStyle style) { return NameConvention(NameConventionBackingType(style) | NameConventionFlag::UpperCase); } -SLANG_FORCE_INLINE NameConvention makeLower(NameStyle style) { return NameConvention(style); } +SLANG_FORCE_INLINE NameConvention makeUpper(NameStyle style) +{ + return NameConvention(NameConventionBackingType(style) | NameConventionFlag::UpperCase); +} +SLANG_FORCE_INLINE NameConvention makeLower(NameStyle style) +{ + return NameConvention(style); +} -SLANG_FORCE_INLINE bool isUpper(NameConvention convention) { return (NameConventionBackingType(convention) & NameConventionFlag::UpperCase) != 0; } -SLANG_FORCE_INLINE bool isLower(NameConvention convention) { return (NameConventionBackingType(convention) & NameConventionFlag::UpperCase) == 0; } -SLANG_FORCE_INLINE NameStyle getNameStyle(NameConvention convention) { return NameStyle(NameConventionBackingType(convention) & NameConventionMask::Style); } +SLANG_FORCE_INLINE bool isUpper(NameConvention convention) +{ + return (NameConventionBackingType(convention) & NameConventionFlag::UpperCase) != 0; +} +SLANG_FORCE_INLINE bool isLower(NameConvention convention) +{ + return (NameConventionBackingType(convention) & NameConventionFlag::UpperCase) == 0; +} +SLANG_FORCE_INLINE NameStyle getNameStyle(NameConvention convention) +{ + return NameStyle(NameConventionBackingType(convention) & NameConventionMask::Style); +} -/* This utility is to enable easy conversion and interpretation of names that use standard conventions, typically in programming -languages. The conventions are largely how to represent multiple words together. +/* This utility is to enable easy conversion and interpretation of names that use standard +conventions, typically in programming languages. The conventions are largely how to represent +multiple words together. Split is used to split up a name into it's constituent 'words' based on a convention. Join is used to combine words based on a convention/character case -Convert uses split and join to allow easy conversion between conventions. +Convert uses split and join to allow easy conversion between conventions. */ struct NameConventionUtil { - /// Given a slice tries to determine the convention used. - /// If no separators are found, will assume Camel - /// Doesn't exhaustively test the string slice, or determine invalid scenarios - /// Use 'getConvention' to get error checking + /// Given a slice tries to determine the convention used. + /// If no separators are found, will assume Camel + /// Doesn't exhaustively test the string slice, or determine invalid scenarios + /// Use 'getConvention' to get error checking static NameStyle inferStyleFromText(const UnownedStringSlice& slice); - /// Gets the naming convention based on the slice. - /// Will return invalid convention if cannot be determined. - /// - /// TODO(JS): - /// Does not handle leading `_` styles: "_a" and "_1" will be invalid. - /// We may want to make it do so, but requires changes in infer, split and join. + /// Gets the naming convention based on the slice. + /// Will return invalid convention if cannot be determined. + /// + /// TODO(JS): + /// Does not handle leading `_` styles: "_a" and "_1" will be invalid. + /// We may want to make it do so, but requires changes in infer, split and join. static NameConvention inferConventionFromText(const UnownedStringSlice& slice); - /// Given a slice and a naming convention, split into it's constituent parts. If convention isn't specified, will infer from slice using getConvention. - static void split(NameStyle nameStyle, const UnownedStringSlice& slice, List<UnownedStringSlice>& out); + /// Given a slice and a naming convention, split into it's constituent parts. If convention + /// isn't specified, will infer from slice using getConvention. + static void split( + NameStyle nameStyle, + const UnownedStringSlice& slice, + List<UnownedStringSlice>& out); static void split(const UnownedStringSlice& slice, List<UnownedStringSlice>& out); - /// Given slices, join together with the specified convention into out - static void join(const UnownedStringSlice* slices, Index slicesCount, NameConvention convention, StringBuilder& out); - - /// Join with a join char, and potentially changing case of input slices - static void join(const UnownedStringSlice* slices, Index slicesCount, NameConvention convention, char joinChar, StringBuilder& out); - - /// Convert from one convention to another. If fromConvention isn't specified, will infer from slice using getConvention. - static void convert(NameStyle fromStyle, const UnownedStringSlice& slice, NameConvention toConvention, StringBuilder& out); - static void convert(const UnownedStringSlice& slice, NameConvention toConvention, StringBuilder& out); + /// Given slices, join together with the specified convention into out + static void join( + const UnownedStringSlice* slices, + Index slicesCount, + NameConvention convention, + StringBuilder& out); + + /// Join with a join char, and potentially changing case of input slices + static void join( + const UnownedStringSlice* slices, + Index slicesCount, + NameConvention convention, + char joinChar, + StringBuilder& out); + + /// Convert from one convention to another. If fromConvention isn't specified, will infer from + /// slice using getConvention. + static void convert( + NameStyle fromStyle, + const UnownedStringSlice& slice, + NameConvention toConvention, + StringBuilder& out); + static void convert( + const UnownedStringSlice& slice, + NameConvention toConvention, + StringBuilder& out); }; -} +} // namespace Slang #endif // SLANG_COMPILER_CORE_NAME_CONVENTION_UTIL_H diff --git a/source/compiler-core/slang-name.cpp b/source/compiler-core/slang-name.cpp index c815b8aa8..6f79d25b5 100644 --- a/source/compiler-core/slang-name.cpp +++ b/source/compiler-core/slang-name.cpp @@ -1,11 +1,13 @@ // slang-name.cpp #include "slang-name.h" -namespace Slang { +namespace Slang +{ String getText(Name* name) { - if (!name) return String(); + if (!name) + return String(); return name->text; } diff --git a/source/compiler-core/slang-name.h b/source/compiler-core/slang-name.h index f8c1201af..331086d77 100644 --- a/source/compiler-core/slang-name.h +++ b/source/compiler-core/slang-name.h @@ -7,7 +7,8 @@ #include "../core/slang-basic.h" -namespace Slang { +namespace Slang +{ // The `Name` type is used to represent the name of a type, variable, etc. // @@ -36,7 +37,7 @@ public: // (e.g., so that it can be printed). String getText(Name* name); -/// Get the text as unowned string slice +/// Get the text as unowned string slice UnownedStringSlice getUnownedStringSliceText(Name* name); // Get a name as a C style string, or nullptr if name is nullptr @@ -50,7 +51,7 @@ const char* getCstr(Name* name); struct RootNamePool { // The mapping from text strings to the corresponding name. - Dictionary<String, RefPtr<Name> > names; + Dictionary<String, RefPtr<Name>> names; }; // A `NamePool` is effectively a way of storing a subset of the @@ -74,10 +75,7 @@ struct NamePool // If the name does not exist, return nullptr Name* tryGetName(String const& text); // Set the parent name pool to use for lookup - void setRootNamePool(RootNamePool* rootNamePool) - { - this->rootPool = rootNamePool; - } + void setRootNamePool(RootNamePool* rootNamePool) { this->rootPool = rootNamePool; } // diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp index 8e234e634..2a4597ddc 100644 --- a/source/compiler-core/slang-nvrtc-compiler.cpp +++ b/source/compiler-core/slang-nvrtc-compiler.cpp @@ -1,45 +1,40 @@ // slang-nvrtc-compiler.cpp #include "slang-nvrtc-compiler.h" -#include "../core/slang-common.h" -#include "slang-com-helper.h" - #include "../core/slang-blob.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-string-slice-pool.h" - +#include "../core/slang-char-util.h" +#include "../core/slang-common.h" #include "../core/slang-io.h" -#include "../core/slang-shared-library.h" #include "../core/slang-semantic-version.h" - #include "../core/slang-shared-library.h" -#include "../core/slang-char-util.h" - +#include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" +#include "slang-artifact-associated-impl.h" +#include "slang-artifact-desc-util.h" #include "slang-artifact-diagnostic-util.h" #include "slang-artifact-util.h" -#include "slang-artifact-desc-util.h" -#include "slang-artifact-associated-impl.h" +#include "slang-com-helper.h" namespace nvrtc { -typedef enum { - NVRTC_SUCCESS = 0, - NVRTC_ERROR_OUT_OF_MEMORY = 1, - NVRTC_ERROR_PROGRAM_CREATION_FAILURE = 2, - NVRTC_ERROR_INVALID_INPUT = 3, - NVRTC_ERROR_INVALID_PROGRAM = 4, - NVRTC_ERROR_INVALID_OPTION = 5, - NVRTC_ERROR_COMPILATION = 6, - NVRTC_ERROR_BUILTIN_OPERATION_FAILURE = 7, - NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION = 8, - NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION = 9, - NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID = 10, - NVRTC_ERROR_INTERNAL_ERROR = 11 +typedef enum +{ + NVRTC_SUCCESS = 0, + NVRTC_ERROR_OUT_OF_MEMORY = 1, + NVRTC_ERROR_PROGRAM_CREATION_FAILURE = 2, + NVRTC_ERROR_INVALID_INPUT = 3, + NVRTC_ERROR_INVALID_PROGRAM = 4, + NVRTC_ERROR_INVALID_OPTION = 5, + NVRTC_ERROR_COMPILATION = 6, + NVRTC_ERROR_BUILTIN_OPERATION_FAILURE = 7, + NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION = 8, + NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION = 9, + NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID = 10, + NVRTC_ERROR_INTERNAL_ERROR = 11 } nvrtcResult; -typedef struct _nvrtcProgram *nvrtcProgram; +typedef struct _nvrtcProgram* nvrtcProgram; // clang-format off #define SLANG_NVRTC_FUNCS(x) \ @@ -66,37 +61,37 @@ static SlangResult _asResult(nvrtcResult res) { switch (res) { - case NVRTC_SUCCESS: + case NVRTC_SUCCESS: { return SLANG_OK; } - case NVRTC_ERROR_OUT_OF_MEMORY: + case NVRTC_ERROR_OUT_OF_MEMORY: { return SLANG_E_OUT_OF_MEMORY; } - case NVRTC_ERROR_PROGRAM_CREATION_FAILURE: - case NVRTC_ERROR_INVALID_INPUT: - case NVRTC_ERROR_INVALID_PROGRAM: + case NVRTC_ERROR_PROGRAM_CREATION_FAILURE: + case NVRTC_ERROR_INVALID_INPUT: + case NVRTC_ERROR_INVALID_PROGRAM: { return SLANG_FAIL; } - case NVRTC_ERROR_INVALID_OPTION: + case NVRTC_ERROR_INVALID_OPTION: { return SLANG_E_INVALID_ARG; } - case NVRTC_ERROR_COMPILATION: - case NVRTC_ERROR_BUILTIN_OPERATION_FAILURE: - case NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION: - case NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION: - case NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID: + case NVRTC_ERROR_COMPILATION: + case NVRTC_ERROR_BUILTIN_OPERATION_FAILURE: + case NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION: + case NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION: + case NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID: { return SLANG_FAIL; } - case NVRTC_ERROR_INTERNAL_ERROR: + case NVRTC_ERROR_INTERNAL_ERROR: { return SLANG_E_INTERNAL_FAIL; } - default: return SLANG_FAIL; + default: return SLANG_FAIL; } } @@ -106,29 +101,27 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; - /// Must be called before use + /// Must be called before use SlangResult init(ISlangSharedLibrary* library); NVRTCDownstreamCompiler() {} - -protected: +protected: struct ScopeProgram { - ScopeProgram(NVRTCDownstreamCompiler* compiler, nvrtcProgram program): - m_compiler(compiler), - m_program(program) - { - } - ~ScopeProgram() + ScopeProgram(NVRTCDownstreamCompiler* compiler, nvrtcProgram program) + : m_compiler(compiler), m_program(program) { - m_compiler->m_nvrtcDestroyProgram(&m_program); } + ~ScopeProgram() { m_compiler->m_nvrtcDestroyProgram(&m_program); } NVRTCDownstreamCompiler* m_compiler; nvrtcProgram m_program; }; @@ -139,8 +132,7 @@ protected: SlangResult _maybeAddHalfSupport(const CompileOptions& options, CommandLine& ioCmdLine); -#define SLANG_NVTRC_MEMBER_FUNCS(ret, name, params) \ - ret (*m_##name) params; +#define SLANG_NVTRC_MEMBER_FUNCS(ret, name, params) ret(*m_##name) params; SLANG_NVRTC_FUNCS(SLANG_NVTRC_MEMBER_FUNCS); @@ -148,19 +140,25 @@ protected: List<String> m_cudaFp16FoundPaths; bool m_includeSearched = false; - // Holds location of where include (for cuda_fp16.h) is found. + // Holds location of where include (for cuda_fp16.h) is found. String m_includePath; - ComPtr<ISlangSharedLibrary> m_sharedLibrary; + ComPtr<ISlangSharedLibrary> m_sharedLibrary; }; -#define SLANG_NVRTC_RETURN_ON_FAIL(x) { nvrtcResult _res = x; if (_res != NVRTC_SUCCESS) return _asResult(_res); } +#define SLANG_NVRTC_RETURN_ON_FAIL(x) \ + { \ + nvrtcResult _res = x; \ + if (_res != NVRTC_SUCCESS) \ + return _asResult(_res); \ + } SlangResult NVRTCDownstreamCompiler::init(ISlangSharedLibrary* library) { -#define SLANG_NVTRC_GET_FUNC(ret, name, params) \ - m_##name = (ret (*) params)library->findFuncByName(#name); \ - if (m_##name == nullptr) return SLANG_FAIL; +#define SLANG_NVTRC_GET_FUNC(ret, name, params) \ + m_##name = (ret(*) params)library->findFuncByName(#name); \ + if (m_##name == nullptr) \ + return SLANG_FAIL; SLANG_NVRTC_FUNCS(SLANG_NVTRC_GET_FUNC) @@ -174,7 +172,10 @@ SlangResult NVRTCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseLocation(SliceAllocator& allocator, const UnownedStringSlice& in, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseLocation( + SliceAllocator& allocator, + const UnownedStringSlice& in, + ArtifactDiagnostic& outDiagnostic) { const Index startIndex = in.indexOf('('); @@ -184,7 +185,8 @@ static SlangResult _parseLocation(SliceAllocator& allocator, const UnownedString UnownedStringSlice remaining(in.begin() + startIndex + 1, in.end()); const Int endIndex = remaining.indexOf(')'); - UnownedStringSlice lineText = UnownedStringSlice(remaining.begin(), remaining.begin() + endIndex); + UnownedStringSlice lineText = + UnownedStringSlice(remaining.begin(), remaining.begin() + endIndex); Int line; SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineText, line)); @@ -208,7 +210,10 @@ static bool _hasDriveLetter(const UnownedStringSlice& line) return line.getLength() > 2 && line[1] == ':' && _isDriveLetter(line[0]); } -static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStringSlice& line, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseNVRTCLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + ArtifactDiagnostic& outDiagnostic) { typedef ArtifactDiagnostic Diagnostic; typedef ArtifactDiagnostic::Severity Severity; @@ -218,7 +223,7 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin List<UnownedStringSlice> split; if (_hasDriveLetter(line)) { - // The drive letter has :, which confuses things, so skip that and then fix up first entry + // The drive letter has :, which confuses things, so skip that and then fix up first entry UnownedStringSlice lineWithoutDrive(line.begin() + 2, line.end()); StringUtil::split(lineWithoutDrive, ':', split); split[0] = UnownedStringSlice(line.begin(), split[0].end()); @@ -235,8 +240,7 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin Severity severity = Severity::Unknown; - if (split1 == toSlice("error") || - split1 == toSlice("catastrophic error")) + if (split1 == toSlice("error") || split1 == toSlice("catastrophic error")) { severity = Severity::Error; } @@ -246,14 +250,14 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin } else { - // Fall back position to try and determine if this really is some kind of - // error/warning without succeeding when it's due to some other property - // of the output diagnostics. + // Fall back position to try and determine if this really is some kind of + // error/warning without succeeding when it's due to some other property + // of the output diagnostics. // // Anything ending with " warning:" or " error:" in effect. - - // We can expand to include character after as this is split1, as must be followed by at a minimum - // : (as the split has at least 3 parts). + + // We can expand to include character after as this is split1, as must be followed by at + // a minimum : (as the split has at least 3 parts). const UnownedStringSlice expandSplit1(split1.begin(), split1.end() + 1); if (expandSplit1.endsWith(toSlice(" error:"))) @@ -268,9 +272,9 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin if (severity != Severity::Unknown) { - // The text is everything following the : after the warning. + // The text is everything following the : after the warning. UnownedStringSlice text(split[2].begin(), split.getLast().end()); - + // Trim whitespace at start and end text = text.trim(); @@ -282,19 +286,18 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin return SLANG_OK; } - // TODO(JS): Note here if it's not possible to determine a line as being the main diagnostics - // we fall through to it potentially being a note. + // TODO(JS): Note here if it's not possible to determine a line as being the main + // diagnostics we fall through to it potentially being a note. + // + // That could mean a valid diagnostic (from NVRTCs point of view) is ignored/noted, because + // this code can't parse it. Ideally that situation would lead to an error such that we can + // detect and things will fail. // - // That could mean a valid diagnostic (from NVRTCs point of view) is ignored/noted, because this code - // can't parse it. Ideally that situation would lead to an error such that we can detect - // and things will fail. - // // So we might want to revisit this determination in the future. } // There isn't a diagnostic on this line - if (line.getLength() == 0 || - line.trim().getLength() == 0) + if (line.getLength() == 0 || line.trim().getLength() == 0) { return SLANG_E_NOT_FOUND; } @@ -306,14 +309,18 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin return SLANG_OK; } -/* An implementation of Path::Visitor that can be used for finding NVRTC shared library installations. */ +/* An implementation of Path::Visitor that can be used for finding NVRTC shared library + * installations. */ struct NVRTCPathVisitor : Path::Visitor { struct Candidate { typedef Candidate ThisType; - bool operator==(const ThisType& rhs) const { return path == rhs.path && version == rhs.version; } + bool operator==(const ThisType& rhs) const + { + return path == rhs.path && version == rhs.version; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } static Candidate make(const String& path, const SemanticVersion& version) @@ -340,10 +347,13 @@ struct NVRTCPathVisitor : Path::Visitor return -1; } - static bool _orderCandiate(const Candidate& a, const Candidate& b) { return a.version < b.version; } + static bool _orderCandiate(const Candidate& a, const Candidate& b) + { + return a.version < b.version; + } void sortCandidates() { m_candidates.sort(_orderCandiate); } - + #if SLANG_WINDOWS_FAMILY SlangResult getVersion(const UnownedStringSlice& filename, SemanticVersion& outVersion) { @@ -356,7 +366,9 @@ struct NVRTCPathVisitor : Path::Visitor endIndex = (endIndex < 0) ? filename.getLength() : endIndex; // If we have a version slice, split it - UnownedStringSlice versionSlice = UnownedStringSlice(filename.begin() + m_prefix.getLength(), filename.begin() + endIndex); + UnownedStringSlice versionSlice = UnownedStringSlice( + filename.begin() + m_prefix.getLength(), + filename.begin() + endIndex); if (versionSlice.getLength() <= 0) { @@ -382,7 +394,8 @@ struct NVRTCPathVisitor : Path::Visitor } UnownedStringSlice majorSlice = majorMinorSlice.head(majorMinorSlice.getLength() - 1); - UnownedStringSlice minorSlice = majorMinorSlice.subString(majorMinorSlice.getLength() - 1, 1); + UnownedStringSlice minorSlice = + majorMinorSlice.subString(majorMinorSlice.getLength() - 1, 1); Int major; Int minor; @@ -396,7 +409,8 @@ struct NVRTCPathVisitor : Path::Visitor #else // How the path is constructed depends on platform // https://docs.nvidia.com/cuda/nvrtc/index.html - // TODO(JS): Handle version number depending on the platform - it's different for Windows/OSX/Linux + // TODO(JS): Handle version number depending on the platform - it's different for + // Windows/OSX/Linux SlangResult getVersion(const UnownedStringSlice& filename, SemanticVersion& outVersion) { SLANG_UNUSED(filename); @@ -415,16 +429,18 @@ struct NVRTCPathVisitor : Path::Visitor if (m_postfix.getLength() && filename.getLength() >= m_postfix.getLength()) { // We test without case - really for windows - UnownedStringSlice filenamePostfix = filename.tail(filename.getLength() - m_postfix.getLength()); + UnownedStringSlice filenamePostfix = + filename.tail(filename.getLength() - m_postfix.getLength()); if (!filenamePostfix.caseInsensitiveEquals(m_postfix.getUnownedSlice())) { return; } } - + if (filename.getLength() >= m_prefix.getLength() && - filename.subString(0, m_prefix.getLength()).caseInsensitiveEquals(m_prefix.getUnownedSlice())) + filename.subString(0, m_prefix.getLength()) + .caseInsensitiveEquals(m_prefix.getUnownedSlice())) { SemanticVersion version; // If it produces an error, just use 0.0.0 @@ -433,8 +449,9 @@ struct NVRTCPathVisitor : Path::Visitor version = SemanticVersion(); } - // We may want to add multiple versions, if they are in different locations - as there may be multiple entries - // in the PATH, and only one works. We'll only know which works by loading + // We may want to add multiple versions, if they are in different locations - as + // there may be multiple entries in the PATH, and only one works. We'll only know + // which works by loading #if 0 // We already found this version, so let's not add it again @@ -445,10 +462,12 @@ struct NVRTCPathVisitor : Path::Visitor #endif // Strip to make a shared library name - UnownedStringSlice sharedLibraryName = filename.tail(m_prefix.getLength() - m_sharedLibraryStem.getLength()); + UnownedStringSlice sharedLibraryName = + filename.tail(m_prefix.getLength() - m_sharedLibraryStem.getLength()); sharedLibraryName = filename.head(filename.getLength() - m_postfix.getLength()); - auto candidate = Candidate::make(Path::combine(m_basePath, sharedLibraryName), version); + auto candidate = + Candidate::make(Path::combine(m_basePath, sharedLibraryName), version); // If we already have this candidate, then skip if (m_candidates.indexOf(candidate) >= 0) @@ -470,8 +489,8 @@ struct NVRTCPathVisitor : Path::Visitor bool hasCandidates() const { return m_candidates.getCount() > 0; } - NVRTCPathVisitor(const UnownedStringSlice& sharedLibraryStem) : - m_sharedLibraryStem(sharedLibraryStem) + NVRTCPathVisitor(const UnownedStringSlice& sharedLibraryStem) + : m_sharedLibraryStem(sharedLibraryStem) { // Work out the prefix and postfix of the shader StringBuilder buf; @@ -491,7 +510,7 @@ struct NVRTCPathVisitor : Path::Visitor List<Candidate> m_candidates; }; -template <typename T> +template<typename T> SLANG_FORCE_INLINE static void _unusedFunction(const T& func) { SLANG_UNUSED(func); @@ -508,7 +527,8 @@ static UnownedStringSlice _getNVRTCBaseName() #endif } -// Candidates are in m_candidates list. Will be ordered from the oldest to newest (in version number) +// Candidates are in m_candidates list. Will be ordered from the oldest to newest (in version +// number) static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) { // First try the instance path (if supported on platform) @@ -524,7 +544,9 @@ static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) if (!visitor.hasCandidates()) { StringBuilder buf; - if (!SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable(UnownedStringSlice::fromLiteral("CUDA_PATH"), buf))) + if (!SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable( + UnownedStringSlice::fromLiteral("CUDA_PATH"), + buf))) { // Look for candidates in the directory visitor.findInDirectory(Path::combine(buf, "bin")); @@ -537,7 +559,8 @@ static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) List<UnownedStringSlice> splitPath; StringBuilder buf; - if (SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable(UnownedStringSlice::fromLiteral("PATH"), buf))) + if (SLANG_SUCCEEDED( + PlatformUtil::getEnvironmentVariable(UnownedStringSlice::fromLiteral("PATH"), buf))) { // Split so we get individual paths List<UnownedStringSlice> paths; @@ -546,19 +569,22 @@ static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) // We use a pool to make sure we only check each path once StringSlicePool pool(StringSlicePool::Style::Empty); - // We are going to search the paths in order + // We are going to search the paths in order for (const auto& path : paths) { - // PATH can have the same path multiple times. If we have already searched this path, we don't need to again + // PATH can have the same path multiple times. If we have already searched this + // path, we don't need to again if (!pool.has(path)) { pool.add(path); Path::split(path, splitPath); - // We could search every path, but here we restrict to paths that look like CUDA installations. - // It's a path that contains a CUDA directory and has bin - if (splitPath.indexOf("CUDA") >= 0 && splitPath[splitPath.getCount() - 1].caseInsensitiveEquals(UnownedStringSlice::fromLiteral("bin"))) + // We could search every path, but here we restrict to paths that look like CUDA + // installations. It's a path that contains a CUDA directory and has bin + if (splitPath.indexOf("CUDA") >= 0 && + splitPath[splitPath.getCount() - 1].caseInsensitiveEquals( + UnownedStringSlice::fromLiteral("bin"))) { // Okay lets search it visitor.findInDirectory(path); @@ -568,11 +594,11 @@ static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) } } - // Put into version order with oldest first. + // Put into version order with oldest first. visitor.sortCandidates(); return SLANG_OK; -} +} static const UnownedStringSlice g_fp16HeaderName = UnownedStringSlice::fromLiteral("cuda_fp16.h"); @@ -591,7 +617,10 @@ SlangResult NVRTCDownstreamCompiler::_getIncludePath(String& outPath) return m_includePath.getLength() ? SLANG_OK : SLANG_E_NOT_FOUND; } -SlangResult _findFileInIncludePath(const String& path, const UnownedStringSlice& filename, String& outPath) +SlangResult _findFileInIncludePath( + const String& path, + const UnownedStringSlice& filename, + String& outPath) { if (File::exists(Path::combine(path, filename))) { @@ -624,8 +653,8 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) { outPath = String(); - // Try looking up from a symbol. This will work as long as the nvrtc is loaded somehow from a dll/sharedlibrary - // And the header is included from there + // Try looking up from a symbol. This will work as long as the nvrtc is loaded somehow from a + // dll/sharedlibrary And the header is included from there { String libPath = SharedLibraryUtils::getSharedLibraryFileName((void*)m_nvrtcCreateProgram); if (libPath.getLength()) @@ -646,8 +675,7 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) // This -2 split holds the version number. const auto pathSplitCount = pathSlices.getCount(); - if (pathSplitCount >= 3 && - pathSlices[pathSplitCount - 1] == toSlice("bin") && + if (pathSplitCount >= 3 && pathSlices[pathSplitCount - 1] == toSlice("bin") && pathSlices[pathSplitCount - 3] == toSlice("CUDA")) { // We want to make sure that one of these paths is CUDA... @@ -665,7 +693,9 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) // Try CUDA_PATH environment variable { StringBuilder buf; - if (SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable(UnownedStringSlice::fromLiteral("CUDA_PATH"), buf))) + if (SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable( + UnownedStringSlice::fromLiteral("CUDA_PATH"), + buf))) { String includePath = Path::combine(buf, "include"); @@ -680,7 +710,9 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) return SLANG_E_NOT_FOUND; } -SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const DownstreamCompileOptions& options, CommandLine& ioCmdLine) +SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport( + const DownstreamCompileOptions& options, + CommandLine& ioCmdLine) { if ((options.flags & DownstreamCompileOptions::Flag::EnableFloat16) == 0) { @@ -725,7 +757,9 @@ SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const DownstreamCompil return SLANG_OK; } -SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inOptions, IArtifact** outArtifact) +SlangResult NVRTCDownstreamCompiler::compile( + const DownstreamCompileOptions& inOptions, + IArtifact** outArtifact) { if (!isVersionCompatible(inOptions)) { @@ -747,16 +781,16 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO switch (options.debugInfoType) { - case DebugInfoType::None: + case DebugInfoType::None: { break; } - default: + default: { cmdLine.addArg("--device-debug"); break; } - case DebugInfoType::Maximal: + case DebugInfoType::Maximal: { cmdLine.addArg("--device-debug"); cmdLine.addArg("--generate-line-info"); @@ -765,19 +799,19 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO } // Don't seem to have such a control, so ignore for now - //switch (options.optimizationLevel) + // switch (options.optimizationLevel) //{ // default: break; //} switch (options.floatingPointMode) { - case FloatingPointMode::Default: break; - case FloatingPointMode::Precise: + case FloatingPointMode::Default: break; + case FloatingPointMode::Precise: { break; } - case FloatingPointMode::Fast: + case FloatingPointMode::Fast: { cmdLine.addArg("--use_fast_math"); break; @@ -815,8 +849,9 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO cmdLine.addArg("-std=c++17"); // Disable all warnings - // This is arguably too much - but nvrtc does not appear to have a mechanism to switch off individual warnings. - // I tried the -Xcudafe mechanism but that does not appear to work for nvrtc + // This is arguably too much - but nvrtc does not appear to have a mechanism to switch off + // individual warnings. I tried the -Xcudafe mechanism but that does not appear to work for + // nvrtc cmdLine.addArg("-w"); } @@ -827,13 +862,13 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO SemanticVersion version(3); // Newer releases of NVRTC only support newer CUDA architectures. - if ( m_desc.version.m_major >= 12 ) + if (m_desc.version.m_major >= 12) { // NVRTC in CUDA 12 only supports `compute_50` and up // (with everything before `compute_52` being deprecated). version = SemanticVersion(5, 0); } - else if ( m_desc.version.m_major == 11 ) + else if (m_desc.version.m_major == 11) { // NVRTC in CUDA 11 only supports `compute_35` and up // (with everything before `compute_52` being deprecated). @@ -871,7 +906,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO // If compiling for OptiX, we need to add the appropriate search paths to the command line. // - if(options.pipelineType == PipelineType::RayTracing) + if (options.pipelineType == PipelineType::RayTracing) { // The device-side OptiX API is accessed through a constellation // of headers provided by the OptiX SDK, so we need to set an @@ -906,7 +941,8 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO // TODO: Confirm that the `LP64` definition here is actually needed. // headerIncludeNames.add("stddef.h"); - headers.add("#pragma once\n" "#define LP64\n"); + headers.add("#pragma once\n" + "#define LP64\n"); // Finally, we want the CUDA prelude to be able to react to whether // or not OptiX is required (most notably by `#include`ing the appropriate @@ -923,7 +959,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO { for (auto compilerSpecificArg : options.compilerSpecificArguments) { - const char*const arg = compilerSpecificArg; + const char* const arg = compilerSpecificArg; cmdLine.addArg(arg); } } @@ -939,7 +975,10 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO auto sourceContents = SliceUtil::toTerminatedCharSlice(storage, sourceBlob); nvrtcProgram program = nullptr; - nvrtcResult res = m_nvrtcCreateProgram(&program, sourceContents, String(sourcePath).getBuffer(), + nvrtcResult res = m_nvrtcCreateProgram( + &program, + sourceContents, + String(sourcePath).getBuffer(), (int)headers.getCount(), headers.getBuffer(), headerIncludeNames.getBuffer()); @@ -956,7 +995,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO dstOptions[i] = cmdLine.m_args[i].getBuffer(); } - res = m_nvrtcCompileProgram(program, int(dstOptions.getCount()), dstOptions.getBuffer()); + res = m_nvrtcCompileProgram(program, int(dstOptions.getCount()), dstOptions.getBuffer()); auto artifact = ArtifactUtil::createArtifactForCompileTarget(options.targetType); auto diagnostics = ArtifactDiagnostics::create(); @@ -1024,7 +1063,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO if (SLANG_SUCCEEDED(lineRes)) { // We only allow info diagnostics after a 'regular' diagnostic. - if (diagnostic.severity == ArtifactDiagnostic::Severity::Info && + if (diagnostic.severity == ArtifactDiagnostic::Severity::Info && diagnostics->getCount() == 0) { continue; @@ -1042,7 +1081,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO // If it has a compilation error.. and there isn't already an error set // set as failed. - if (SLANG_SUCCEEDED(diagnostics->getResult()) && + if (SLANG_SUCCEEDED(diagnostics->getResult()) && diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error)) { diagnostics->setResult(SLANG_FAIL); @@ -1072,7 +1111,10 @@ bool NVRTCDownstreamCompiler::canConvert(const ArtifactDesc& from, const Artifac return ArtifactDescUtil::isDisassembly(from, to) || ArtifactDescUtil::isDisassembly(to, from); } -SlangResult NVRTCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult NVRTCDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { if (!canConvert(from->getDesc(), to)) { @@ -1080,8 +1122,8 @@ SlangResult NVRTCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc } // PTX is 'binary like' and 'assembly like' so we allow conversion either way - // We do it by just getting as a blob and sharing that blob. - // A more sophisticated implementation could proxy to the original artifact, but this + // We do it by just getting as a blob and sharing that blob. + // A more sophisticated implementation could proxy to the original artifact, but this // is simpler, and probably fine in most scenarios. ComPtr<ISlangBlob> blob; SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::Yes, blob.writeRef())); @@ -1093,11 +1135,13 @@ SlangResult NVRTCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc return SLANG_OK; } -static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr<ISlangSharedLibrary>& outLibrary) +static SlangResult _findAndLoadNVRTC( + ISlangSharedLibraryLoader* loader, + ComPtr<ISlangSharedLibrary>& outLibrary) { #if SLANG_WINDOWS_FAMILY && SLANG_PTR_IS_64 - // We only need to search 64 bit versions on windows + // We only need to search 64 bit versions on windows NVRTCPathVisitor visitor(_getNVRTCBaseName()); SLANG_RETURN_ON_FAIL(_findNVRTC(visitor)); @@ -1105,7 +1149,8 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr<I for (Index i = visitor.m_candidates.getCount() - 1; i >= 0; --i) { const auto& candidate = visitor.m_candidates[i]; - if (SLANG_SUCCEEDED(loader->loadSharedLibrary(candidate.path.getBuffer(), outLibrary.writeRef()))) + if (SLANG_SUCCEEDED( + loader->loadSharedLibrary(candidate.path.getBuffer(), outLibrary.writeRef()))) { return SLANG_OK; } @@ -1121,16 +1166,19 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr<I // This is an official-ish list of versions is here: // https://developer.nvidia.com/cuda-toolkit-archive - + // Filenames for NVRTC // https://docs.nvidia.com/cuda/nvrtc/index.html // // From this it appears on platforms other than windows the SharedLibrary name - // should be nvrtc which is already tried, so we can give up now. + // should be nvrtc which is already tried, so we can give up now. return SLANG_E_NOT_FOUND; } -/* static */SlangResult NVRTCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult NVRTCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { ComPtr<ISlangSharedLibrary> library; @@ -1148,8 +1196,8 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr<I // // On Windows an installation could place the version of nvrtc it uses in the same directory // as the slang binary, such that it's loaded. - // Using this name also allows a ISlangSharedLibraryLoader to easily identify what is required - // and perhaps load a specific version + // Using this name also allows a ISlangSharedLibraryLoader to easily identify what is + // required and perhaps load a specific version if (SLANG_FAILED(loader->loadSharedLibrary("nvrtc", library.writeRef()))) { // Try something more sophisticated to locate NVRTC @@ -1171,4 +1219,4 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr<I return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-nvrtc-compiler.h b/source/compiler-core/slang-nvrtc-compiler.h index 215fc4c23..d6bc5520d 100644 --- a/source/compiler-core/slang-nvrtc-compiler.h +++ b/source/compiler-core/slang-nvrtc-compiler.h @@ -1,9 +1,8 @@ #ifndef SLANG_NVRTC_COMPILER_UTIL_H #define SLANG_NVRTC_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { @@ -11,9 +10,12 @@ namespace Slang struct NVRTCDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-perfect-hash-codegen.cpp b/source/compiler-core/slang-perfect-hash-codegen.cpp index c09ee4a2c..77f88de15 100644 --- a/source/compiler-core/slang-perfect-hash-codegen.cpp +++ b/source/compiler-core/slang-perfect-hash-codegen.cpp @@ -1,55 +1,62 @@ #include "slang-perfect-hash-codegen.h" + #include "../core/slang-io.h" namespace Slang { - SlangResult writeHashFile( - String outCppPath, - String valueType, - const List<String> includes, - const HashParams& hashParams, - const List<String> values) - { - StringBuilder sb; - StringWriter writer(&sb, WriterFlags(0)); - WriterHelper w(&writer); +SlangResult writeHashFile( + String outCppPath, + String valueType, + const List<String> includes, + const HashParams& hashParams, + const List<String> values) +{ + StringBuilder sb; + StringWriter writer(&sb, WriterFlags(0)); + WriterHelper w(&writer); - w.print("// Hash function for %s\n", valueType.getBuffer()); - w.print("//\n"); - w.print("// This file was thoughtfully generated by a machine,\n"); - w.print("// don't even think about modifying it yourself!\n"); - w.print("//\n"); - w.print("\n"); - for (const auto& i : includes) - { - if (i.getLength()) - w.print("#include \"%s\"\n", i.getBuffer()); - } - w.print("\n"); - w.print("\n"); - w.print("namespace Slang\n"); - w.print("{\n"); - w.print("\n"); + w.print("// Hash function for %s\n", valueType.getBuffer()); + w.print("//\n"); + w.print("// This file was thoughtfully generated by a machine,\n"); + w.print("// don't even think about modifying it yourself!\n"); + w.print("//\n"); + w.print("\n"); + for (const auto& i : includes) + { + if (i.getLength()) + w.print("#include \"%s\"\n", i.getBuffer()); + } + w.print("\n"); + w.print("\n"); + w.print("namespace Slang\n"); + w.print("{\n"); + w.print("\n"); - w.put(perfectHashToEmbeddableCpp( - hashParams, - valueType.getUnownedSlice(), - (String("lookup") + valueType).getUnownedSlice(), - values - ).getBuffer()); + w.put(perfectHashToEmbeddableCpp( + hashParams, + valueType.getUnownedSlice(), + (String("lookup") + valueType).getUnownedSlice(), + values) + .getBuffer()); - w.print("}\n"); + w.print("}\n"); - return File::writeAllTextIfChanged(outCppPath, sb.getUnownedSlice()); - } + return File::writeAllTextIfChanged(outCppPath, sb.getUnownedSlice()); +} - SlangResult writePerfectHashLookupCppFile(String fileName, List<String> opnames, String enumName, String enumerantPrefix, String enumHeaderFile, DiagnosticSink* sink) +SlangResult writePerfectHashLookupCppFile( + String fileName, + List<String> opnames, + String enumName, + String enumerantPrefix, + String enumHeaderFile, + DiagnosticSink* sink) +{ + HashParams hashParams; + auto r = minimalPerfectHash(opnames, hashParams); + switch (r) { - HashParams hashParams; - auto r = minimalPerfectHash(opnames, hashParams); - switch (r) - { - case HashFindResult::UnavoidableHashCollision: + case HashFindResult::UnavoidableHashCollision: { sink->diagnoseRaw( Severity::Error, @@ -58,24 +65,24 @@ namespace Slang "collision for some input words\n"); return SLANG_FAIL; } - case HashFindResult::NonUniqueKeys: + case HashFindResult::NonUniqueKeys: { sink->diagnoseRaw(Severity::Error, "Input word list has duplicates\n"); return SLANG_FAIL; } - case HashFindResult::Success:; - } - - List<String> values; - values.reserve(hashParams.destTable.getCount()); - for (const auto& v : hashParams.destTable) - values.add(enumerantPrefix + v); - return writeHashFile( - fileName, - enumName, - { "core/slang-common.h", "core/slang-string.h", enumHeaderFile }, - hashParams, - values); + case HashFindResult::Success:; } + List<String> values; + values.reserve(hashParams.destTable.getCount()); + for (const auto& v : hashParams.destTable) + values.add(enumerantPrefix + v); + return writeHashFile( + fileName, + enumName, + {"core/slang-common.h", "core/slang-string.h", enumHeaderFile}, + hashParams, + values); } + +} // namespace Slang diff --git a/source/compiler-core/slang-perfect-hash-codegen.h b/source/compiler-core/slang-perfect-hash-codegen.h index 557f4dba5..d1ddd49b5 100644 --- a/source/compiler-core/slang-perfect-hash-codegen.h +++ b/source/compiler-core/slang-perfect-hash-codegen.h @@ -1,9 +1,15 @@ #pragma once -#include "slang-perfect-hash.h" #include "slang-diagnostic-sink.h" +#include "slang-perfect-hash.h" namespace Slang { - SlangResult writePerfectHashLookupCppFile(String fileName, List<String> opnames, String enumName, String enumPrefix, String enumHeaderFile, DiagnosticSink* sink); +SlangResult writePerfectHashLookupCppFile( + String fileName, + List<String> opnames, + String enumName, + String enumPrefix, + String enumHeaderFile, + DiagnosticSink* sink); } diff --git a/source/compiler-core/slang-perfect-hash.cpp b/source/compiler-core/slang-perfect-hash.cpp index a741f013c..a2dd88f98 100644 --- a/source/compiler-core/slang-perfect-hash.cpp +++ b/source/compiler-core/slang-perfect-hash.cpp @@ -23,7 +23,7 @@ HashFindResult minimalPerfectHash(const List<String>& ss, HashParams& hashParams } SLANG_ASSERT(UIndex(ss.getCount()) < std::numeric_limits<UInt32>::max()); - const UInt32 nBuckets = UInt32(ss.getCount()); + const UInt32 nBuckets = UInt32(ss.getCount()); List<List<String>> initialBuckets; initialBuckets.setCount(nBuckets); @@ -55,7 +55,8 @@ HashFindResult minimalPerfectHash(const List<String>& ss, HashParams& hashParams { initialBuckets[hash(s)].add(s); } - initialBuckets.stableSort([](const List<String>& a, const List<String>& b) { return a.getCount() > b.getCount(); }); + initialBuckets.stableSort([](const List<String>& a, const List<String>& b) + { return a.getCount() > b.getCount(); }); // These are our outputs, the salts are calculated such that for all input // word, x, hash(x, salt[hash(x, 0)]) is unique @@ -138,12 +139,16 @@ String perfectHashToEmbeddableCpp( StringBuilder sb; StringWriter writer(&sb, WriterFlags(0)); WriterHelper w(&writer); - const auto line = [&](const char* l){ + const auto line = [&](const char* l) + { w.put(l); w.put("\n"); }; - w.print("bool %s(const UnownedStringSlice& str, %s& value)\n", String(funcName).getBuffer(), String(valueType).getBuffer()); + w.print( + "bool %s(const UnownedStringSlice& str, %s& value)\n", + String(funcName).getBuffer(), + String(valueType).getBuffer()); line("{"); w.print(" static const unsigned tableSalt[%d] = {\n", (int)hashParams.saltTable.getCount()); @@ -176,11 +181,7 @@ String perfectHashToEmbeddableCpp( { const auto& s = hashParams.destTable[i]; const auto& v = values[i]; - w.print( - " {\"%s\", %s},\n", - s.getBuffer(), - v.getBuffer() - ); + w.print(" {\"%s\", %s},\n", s.getBuffer(), v.getBuffer()); } line(" };"); line(""); @@ -211,4 +212,4 @@ String perfectHashToEmbeddableCpp( return sb.produceString(); } -} +} // namespace Slang diff --git a/source/compiler-core/slang-perfect-hash.h b/source/compiler-core/slang-perfect-hash.h index 1488c7a62..50553eee7 100644 --- a/source/compiler-core/slang-perfect-hash.h +++ b/source/compiler-core/slang-perfect-hash.h @@ -1,7 +1,7 @@ #pragma once -#include "../core/slang-string.h" #include "../core/slang-list.h" +#include "../core/slang-string.h" namespace Slang { @@ -12,7 +12,8 @@ struct HashParams List<String> destTable; }; -enum class HashFindResult { +enum class HashFindResult +{ Success, NonUniqueKeys, UnavoidableHashCollision, @@ -27,4 +28,4 @@ String perfectHashToEmbeddableCpp( const UnownedStringSlice& funcName, const List<String>& values); -} +} // namespace Slang diff --git a/source/compiler-core/slang-slice-allocator.cpp b/source/compiler-core/slang-slice-allocator.cpp index 49fd6a571..d24c05e9f 100644 --- a/source/compiler-core/slang-slice-allocator.cpp +++ b/source/compiler-core/slang-slice-allocator.cpp @@ -3,7 +3,8 @@ #include "../core/slang-blob.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SliceUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -20,7 +21,7 @@ namespace Slang { return list; } -/* static */const char* SliceUtil::getTerminated(ISlangBlob* blob, TerminatedCharSlice& outSlice) +/* static */ const char* SliceUtil::getTerminated(ISlangBlob* blob, TerminatedCharSlice& outSlice) { const auto size = blob->getBufferSize(); if (size == 0) @@ -29,7 +30,7 @@ namespace Slang { return outSlice.begin(); } - // If there is a 0 at the end byte, we are zero terminated + // If there is a 0 at the end byte, we are zero terminated const char* chars = (const char*)blob->getBufferPointer(); if (chars[size - 1] == 0) { @@ -51,7 +52,9 @@ namespace Slang { return nullptr; } -/* static */TerminatedCharSlice SliceUtil::toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob) +/* static */ TerminatedCharSlice SliceUtil::toTerminatedCharSlice( + SliceAllocator& allocator, + ISlangBlob* blob) { TerminatedCharSlice slice; if (SliceUtil::getTerminated(blob, slice)) @@ -59,25 +62,29 @@ namespace Slang { return slice; } const auto size = blob->getBufferSize(); - // We are out of options, we just have to allocate with zero termination which allocateString does - auto dst = allocator.getArena().allocateString((const char*)blob->getBufferPointer(), Count(size)); + // We are out of options, we just have to allocate with zero termination which allocateString + // does + auto dst = + allocator.getArena().allocateString((const char*)blob->getBufferPointer(), Count(size)); return TerminatedCharSlice(dst, Count(size)); } -/* static */TerminatedCharSlice SliceUtil::toTerminatedCharSlice(StringBuilder& storage, ISlangBlob* blob) +/* static */ TerminatedCharSlice SliceUtil::toTerminatedCharSlice( + StringBuilder& storage, + ISlangBlob* blob) { TerminatedCharSlice slice; if (SliceUtil::getTerminated(blob, slice)) { return slice; } - + const auto size = blob->getBufferSize(); auto chars = (const char*)blob->getBufferPointer(); storage.clear(); storage.append(UnownedStringSlice(chars, size)); - + return TerminatedCharSlice(storage.getBuffer(), Count(size)); } diff --git a/source/compiler-core/slang-slice-allocator.h b/source/compiler-core/slang-slice-allocator.h index 8d61fa211..504fbe1b7 100644 --- a/source/compiler-core/slang-slice-allocator.h +++ b/source/compiler-core/slang-slice-allocator.h @@ -2,12 +2,11 @@ #ifndef SLANG_SLICE_ALLOCATOR_H #define SLANG_SLICE_ALLOCATOR_H -// Has definition of CharSlice +// Has definition of CharSlice +#include "../core/slang-memory-arena.h" #include "slang-artifact.h" #include "slang-com-ptr.h" -#include "../core/slang-memory-arena.h" - namespace Slang { @@ -16,50 +15,64 @@ struct SliceAllocator; struct SliceUtil { - /// Convert into a list of strings + /// Convert into a list of strings static List<String> toList(const Slice<TerminatedCharSlice>& in); - /// Gets a 0 terminated string from a blob. If not possible returns nullptr + /// Gets a 0 terminated string from a blob. If not possible returns nullptr static const char* getTerminated(ISlangBlob* blob, TerminatedCharSlice& outSlice); - /// NOTE! the slice is only guarenteed to stay in scope whilst the blob does + /// NOTE! the slice is only guarenteed to stay in scope whilst the blob does static TerminatedCharSlice toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob); - /// + /// static TerminatedCharSlice toTerminatedCharSlice(StringBuilder& storage, ISlangBlob* blob); - /// The slice will only be in scope whilst the string is - static TerminatedCharSlice asTerminatedCharSlice(const String& in) { auto unowned = in.getUnownedSlice(); return TerminatedCharSlice(unowned.begin(), unowned.getLength()); } + /// The slice will only be in scope whilst the string is + static TerminatedCharSlice asTerminatedCharSlice(const String& in) + { + auto unowned = in.getUnownedSlice(); + return TerminatedCharSlice(unowned.begin(), unowned.getLength()); + } - /// Get string as a char slice - static CharSlice asCharSlice(const String& in) { auto unowned = in.getUnownedSlice(); return CharSlice(unowned.begin(), unowned.getLength()); } + /// Get string as a char slice + static CharSlice asCharSlice(const String& in) + { + auto unowned = in.getUnownedSlice(); + return CharSlice(unowned.begin(), unowned.getLength()); + } - template <typename T> - static Slice<T*> asSlice(const List<ComPtr<T>>& list) { return makeSlice((T* const*)list.getBuffer(), list.getCount()); } + template<typename T> + static Slice<T*> asSlice(const List<ComPtr<T>>& list) + { + return makeSlice((T* const*)list.getBuffer(), list.getCount()); + } - /// Get a list as a slice - template <typename T> - static Slice<T> asSlice(const List<T>& list) { return Slice<T>(list.getBuffer(), list.getCount()); } + /// Get a list as a slice + template<typename T> + static Slice<T> asSlice(const List<T>& list) + { + return Slice<T>(list.getBuffer(), list.getCount()); + } - template <typename T> + template<typename T> static List<ComPtr<T>> toComPtrList(const Slice<T*>& in) { ISlangUnknown* check = (T*)nullptr; SLANG_UNUSED(check); List<ComPtr<T>> list; list.setCount(in.count); - for (Index i = 0; i < in.count; ++i) list[i] = ComPtr<T>(in[i]); + for (Index i = 0; i < in.count; ++i) + list[i] = ComPtr<T>(in[i]); return list; } private: - /* - A reason to wrap in a struct rather than have as free functions is doing so will lead to compile time - errors with incorrect usage around temporaries. + A reason to wrap in a struct rather than have as free functions is doing so will lead to compile + time errors with incorrect usage around temporaries. */ /// We don't want to make a temporary list into a slice.. - template <typename T> + template<typename T> static Slice<T> asSlice(const List<T>&& list) = delete; // We don't want temporaries to be 'asSliced' so disable static TerminatedCharSlice asTerminatedCharSlice(const String&& in) = delete; @@ -78,7 +91,7 @@ SLANG_FORCE_INLINE CharSlice asCharSlice(const UnownedStringSlice& slice) SLANG_FORCE_INLINE String asString(const CharSlice& slice) { - return String(slice.begin(), slice.end()); + return String(slice.begin(), slice.end()); } struct SliceAllocator @@ -87,21 +100,24 @@ struct SliceAllocator TerminatedCharSlice allocate(const UnownedStringSlice& slice); TerminatedCharSlice allocate(const String& in) { return allocate(in.getUnownedSlice()); } TerminatedCharSlice allocate(const char* in); - TerminatedCharSlice allocate(const char* start, const char* end) { return allocate(UnownedStringSlice(start, end)); } + TerminatedCharSlice allocate(const char* start, const char* end) + { + return allocate(UnownedStringSlice(start, end)); + } Slice<TerminatedCharSlice> allocate(const List<String>& in); - /// Get the backing arena + /// Get the backing arena MemoryArena& getArena() { return m_arena; } void deallocateAll() { m_arena.deallocateAll(); } - SliceAllocator(): - m_arena(2097152) + SliceAllocator() + : m_arena(2097152) { } + protected: - MemoryArena m_arena; }; diff --git a/source/compiler-core/slang-source-embed-util.cpp b/source/compiler-core/slang-source-embed-util.cpp index ec0c005cf..a4d3bf629 100644 --- a/source/compiler-core/slang-source-embed-util.cpp +++ b/source/compiler-core/slang-source-embed-util.cpp @@ -3,35 +3,35 @@ // Artifact #include "../compiler-core/slang-artifact-desc-util.h" #include "../compiler-core/slang-artifact-util.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-char-util.h" - -#include "../core/slang-string-escape-util.h" - #include "../core/slang-blob.h" +#include "../core/slang-char-util.h" #include "../core/slang-io.h" +#include "../core/slang-string-escape-util.h" +#include "../core/slang-string-util.h" namespace Slang { -namespace { // anonymous +namespace +{ // anonymous typedef SourceEmbedUtil::Style Style; -} // anonymous - -static const NamesDescriptionValue kSourceEmbedStyleInfos[] = -{ - { ValueInt(Style::None), "none", "No source level embedding" }, - { ValueInt(Style::Default), "default", "The default embedding for the type to be embedded"}, - { ValueInt(Style::Text), "text", "Embed as text. May change line endings. If output isn't text will use 'default'. Size will *not* contain terminating 0." }, - { ValueInt(Style::BinaryText), "binary-text", "Embed as text assuming contents is binary. "}, - { ValueInt(Style::U8), "u8", "Embed as unsigned bytes."}, - { ValueInt(Style::U16), "u16", "Embed as uint16_t."}, - { ValueInt(Style::U32), "u32", "Embed as uint32_t."}, - { ValueInt(Style::U64), "u64", "Embed as uint64_t."}, +} // namespace + +static const NamesDescriptionValue kSourceEmbedStyleInfos[] = { + {ValueInt(Style::None), "none", "No source level embedding"}, + {ValueInt(Style::Default), "default", "The default embedding for the type to be embedded"}, + {ValueInt(Style::Text), + "text", + "Embed as text. May change line endings. If output isn't text will use 'default'. Size will " + "*not* contain terminating 0."}, + {ValueInt(Style::BinaryText), "binary-text", "Embed as text assuming contents is binary. "}, + {ValueInt(Style::U8), "u8", "Embed as unsigned bytes."}, + {ValueInt(Style::U16), "u16", "Embed as uint16_t."}, + {ValueInt(Style::U32), "u32", "Embed as uint32_t."}, + {ValueInt(Style::U64), "u64", "Embed as uint64_t."}, }; -/* static */ConstArrayView<NamesDescriptionValue> SourceEmbedUtil::getStyleInfos() +/* static */ ConstArrayView<NamesDescriptionValue> SourceEmbedUtil::getStyleInfos() { return makeConstArrayView(kSourceEmbedStyleInfos); } @@ -44,14 +44,11 @@ static const NamesDescriptionValue kSourceEmbedStyleInfos[] = static bool _isHeaderExtension(const UnownedStringSlice& in) { // Some "typical" header extensions - return in == toSlice("h") || - in == toSlice("hpp") || - in == toSlice("hxx") || - in == toSlice("h++") || - in == toSlice("hh"); + return in == toSlice("h") || in == toSlice("hpp") || in == toSlice("hxx") || + in == toSlice("h++") || in == toSlice("hh"); } -/* static */String SourceEmbedUtil::getPath(const String& path, const Options& options) +/* static */ String SourceEmbedUtil::getPath(const String& path, const Options& options) { if (!isSupported(options.language)) { @@ -76,7 +73,7 @@ static bool _isHeaderExtension(const UnownedStringSlice& in) return buf; } -/* static */SourceEmbedUtil::Style SourceEmbedUtil::getDefaultStyle(const ArtifactDesc& desc) +/* static */ SourceEmbedUtil::Style SourceEmbedUtil::getDefaultStyle(const ArtifactDesc& desc) { if (ArtifactDescUtil::isText(desc)) { @@ -97,7 +94,7 @@ static bool _isHeaderExtension(const UnownedStringSlice& in) return Style::U8; } -// True if we need to copy into a buffer. Necessary if there is an alignement +// True if we need to copy into a buffer. Necessary if there is an alignement // issue or if there is a partial entry static bool _needsCopy(const uint8_t* cur, Count bytesPerElement, Count bytesPerLine) { @@ -105,8 +102,13 @@ static bool _needsCopy(const uint8_t* cur, Count bytesPerElement, Count bytesPer } // NOTE! Assumes T is an unsigned type. Behavior will be incorrect if it is not. -template <typename T> -static void _appendHex(const T* in, ArrayView<char> elementWork, char* dst, size_t bytesForLine, StringBuilder& out) +template<typename T> +static void _appendHex( + const T* in, + ArrayView<char> elementWork, + char* dst, + size_t bytesForLine, + StringBuilder& out) { // Check that T is unsigned SLANG_COMPILE_TIME_ASSERT((T(~T(0))) > T(0)); @@ -138,10 +140,13 @@ static void _appendHex(const T* in, ArrayView<char> elementWork, char* dst, size } } -static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayView<uint8_t> data, StringBuilder& buf) +static SlangResult _append( + const SourceEmbedUtil::Options& options, + ConstArrayView<uint8_t> data, + StringBuilder& buf) { const uint8_t* cur = data.begin(); - + const auto prefix = toSlice("0x"); const auto suffix = toSlice(", "); UnownedStringSlice literalSuffix; @@ -152,42 +157,42 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi switch (options.style) { - case Style::U8: + case Style::U8: { elementType = toSlice("unsigned char"); bytesPerElement = 1; break; } - case Style::U16: + case Style::U16: { elementType = toSlice("uint16_t"); bytesPerElement = 2; break; } - case Style::U32: + case Style::U32: { elementType = toSlice("uint32_t"); bytesPerElement = 4; break; } - case Style::U64: + case Style::U64: { elementType = toSlice("uint64_t"); bytesPerElement = 8; - // On testing on GCC/CLANG/Recent VS, there is no warning/error without suffix, so + // On testing on GCC/CLANG/Recent VS, there is no warning/error without suffix, so // will leave off for now. // literalSuffix = toSlice("ULL"); break; } - default: return SLANG_FAIL; + default: return SLANG_FAIL; } // Output the variable buf << "const " << elementType << " " << options.variableName << "[] = \n"; buf << "{\n"; - - // Work out the element work + + // Work out the element work char work[80]; Count elementSizeInChars; { @@ -227,7 +232,7 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi // We copy if we want alignment of if we hit a partial at the end if (_needsCopy(lineBytes, bytesPerElement, bytesForLine)) { - // Make sure the last element is zeroed, before copying + // Make sure the last element is zeroed, before copying // Needed if the last element is partial. alignedElements[Index(bytesForLine / sizeof(uint64_t))] = 0; @@ -242,10 +247,16 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi switch (bytesPerElement) { - case 1: _appendHex<uint8_t>(lineBytes, workView, dstChars, bytesForLine, buf); break; - case 2: _appendHex<uint16_t>((const uint16_t*)lineBytes, workView, dstChars, bytesForLine, buf); break; - case 4: _appendHex<uint32_t>((const uint32_t*)lineBytes, workView, dstChars, bytesForLine, buf); break; - case 8: _appendHex<uint64_t>((const uint64_t*)lineBytes, workView, dstChars, bytesForLine, buf); break; + case 1: _appendHex<uint8_t>(lineBytes, workView, dstChars, bytesForLine, buf); break; + case 2: + _appendHex<uint16_t>((const uint16_t*)lineBytes, workView, dstChars, bytesForLine, buf); + break; + case 4: + _appendHex<uint32_t>((const uint32_t*)lineBytes, workView, dstChars, bytesForLine, buf); + break; + case 8: + _appendHex<uint64_t>((const uint64_t*)lineBytes, workView, dstChars, bytesForLine, buf); + break; } buf << "\n"; @@ -256,7 +267,10 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi return SLANG_OK; } -/* static */SlangResult SourceEmbedUtil::createEmbedded(IArtifact* artifact, const Options& inOptions, ComPtr<IArtifact>& outArtifact) +/* static */ SlangResult SourceEmbedUtil::createEmbedded( + IArtifact* artifact, + const Options& inOptions, + ComPtr<IArtifact>& outArtifact) { if (!isSupported(inOptions.language)) { @@ -270,10 +284,9 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi Options options(inOptions); - // If the style is text, but the artifact *isn't* a text type, we'll + // If the style is text, but the artifact *isn't* a text type, we'll // use 'default' for the type - if (options.style == Style::Text && - !ArtifactDescUtil::isText(desc)) + if (options.style == Style::Text && !ArtifactDescUtil::isText(desc)) { options.style = Style::Default; } @@ -282,7 +295,7 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi { options.style = getDefaultStyle(desc); } - + // If there is no style there is nothing to do if (options.style == Style::None) { @@ -299,10 +312,10 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi ConstArrayView<uint8_t> data((const uint8_t*)blob->getBufferPointer(), blob->getBufferSize()); size_t totalSizeInBytes = data.getCount(); - + switch (options.style) { - case Style::Text: + case Style::Text: { totalSizeInBytes = 0; @@ -321,8 +334,8 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi handler->appendEscaped(line, buf); - // Work out the total size, taking into account we may encode line endings and \0 differently - // The +1 is for \n + // Work out the total size, taking into account we may encode line endings and \0 + // differently The +1 is for \n totalSizeInBytes += line.getLength() + 1; buf << "\\n\"\n"; @@ -331,7 +344,7 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi buf << ";\n"; break; } - case Style::BinaryText: + case Style::BinaryText: { auto handler = StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp); @@ -340,10 +353,10 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi // We could encode everything and then split // but if we do that we probably want to not split across an escaped character, // although that may be handled correctly. - + // The other way to this is incrementally, so that's what we will do here UnownedStringSlice text((const char*)data.begin(), data.getCount()); - + auto cur = text.begin(); auto end = text.end(); @@ -358,8 +371,7 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi { handler->appendEscaped(UnownedStringSlice(cur, 1), buf); cur++; - } - while (buf.getLength() - startOffset < options.lineLength - 1); + } while (buf.getLength() - startOffset < options.lineLength - 1); buf << "\"\n"; } @@ -367,24 +379,26 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi buf << ";\n"; break; } - case Style::U8: - case Style::U16: - case Style::U32: - case Style::U64: + case Style::U8: + case Style::U16: + case Style::U32: + case Style::U64: { SLANG_RETURN_ON_FAIL(_append(options, data, buf)); break; } - default: + default: { return SLANG_E_NOT_IMPLEMENTED; } } - buf << "const size_t " << options.variableName << "_sizeInBytes = " << uint64_t(totalSizeInBytes) << ";\n\n"; + buf << "const size_t " << options.variableName + << "_sizeInBytes = " << uint64_t(totalSizeInBytes) << ";\n\n"; // Make into an artifact - ArtifactPayload payload = options.language == SLANG_SOURCE_LANGUAGE_C ? ArtifactPayload::C : ArtifactPayload::Cpp; + ArtifactPayload payload = + options.language == SLANG_SOURCE_LANGUAGE_C ? ArtifactPayload::C : ArtifactPayload::Cpp; auto dstDesc = ArtifactDesc::make(ArtifactKind::Source, payload); auto dstArtifact = ArtifactUtil::createArtifact(dstDesc); diff --git a/source/compiler-core/slang-source-embed-util.h b/source/compiler-core/slang-source-embed-util.h index 52115e4ef..9144bcb4c 100644 --- a/source/compiler-core/slang-source-embed-util.h +++ b/source/compiler-core/slang-source-embed-util.h @@ -2,13 +2,10 @@ #define SLANG_SOURCE_EMBED_UTIL_H #include "../core/slang-basic.h" - +#include "../core/slang-name-value.h" #include "slang-artifact.h" -#include "slang-diagnostic-sink.h" - #include "slang-com-ptr.h" - -#include "../core/slang-name-value.h" +#include "slang-diagnostic-sink.h" namespace Slang { @@ -18,42 +15,47 @@ struct SourceEmbedUtil { enum class Style : uint32_t { - None, ///< No embedding - Default, ///< Default embedding for the type - Text, ///< Embed as text. May change line endings. If output isn't text will use 'default'. Size will *not* contain terminating 0 - BinaryText, ///< Embed as text assuming contents is binary. - U8, ///< Embed as unsigned bytes - U16, ///< Embed as uint16_t - U32, ///< Embed as uint32_t - U64, ///< Embed as uint64_t + None, ///< No embedding + Default, ///< Default embedding for the type + Text, ///< Embed as text. May change line endings. If output isn't text will use 'default'. + ///< Size will *not* contain terminating 0 + BinaryText, ///< Embed as text assuming contents is binary. + U8, ///< Embed as unsigned bytes + U16, ///< Embed as uint16_t + U32, ///< Embed as uint32_t + U64, ///< Embed as uint64_t CountOf, }; struct Options { - Style style = Style::Default; ///< Style of embedding - Count lineLength = 120; ///< The line length, lines can be larger for some styles, but will aim to keep within range - SlangSourceLanguage language = SLANG_SOURCE_LANGUAGE_C; ///< The language to output for - String variableName; ///< The name to give the variable - String indent = " "; ///< Indenting + Style style = Style::Default; ///< Style of embedding + Count lineLength = 120; ///< The line length, lines can be larger for some styles, but will + ///< aim to keep within range + SlangSourceLanguage language = SLANG_SOURCE_LANGUAGE_C; ///< The language to output for + String variableName; ///< The name to give the variable + String indent = " "; ///< Indenting }; - /// Get the style infos + /// Get the style infos static ConstArrayView<NamesDescriptionValue> getStyleInfos(); - /// Given an artifact and - static SlangResult createEmbedded(IArtifact* artifact, const Options& options, ComPtr<IArtifact>& outArtifact); + /// Given an artifact and + static SlangResult createEmbedded( + IArtifact* artifact, + const Options& options, + ComPtr<IArtifact>& outArtifact); - /// Returns the default style for the desc + /// Returns the default style for the desc static Style getDefaultStyle(const ArtifactDesc& desc); - /// Returns true if supports the specified language for embedding + /// Returns true if supports the specified language for embedding static bool isSupported(SlangSourceLanguage lang); - /// Given the path return the output path. If no path is available return the empty string + /// Given the path return the output path. If no path is available return the empty string static String getPath(const String& path, const Options& options); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-source-loc.cpp b/source/compiler-core/slang-source-loc.cpp index 5f1f51a38..53eafbeaa 100644 --- a/source/compiler-core/slang-source-loc.cpp +++ b/source/compiler-core/slang-source-loc.cpp @@ -1,15 +1,16 @@ // slang-source-loc.cpp #include "slang-source-loc.h" -#include "../core/slang-string-util.h" -#include "../core/slang-string-escape-util.h" #include "../core/slang-char-encode.h" -#include "slang-artifact-representation-impl.h" +#include "../core/slang-string-escape-util.h" +#include "../core/slang-string-util.h" +#include "slang-artifact-desc-util.h" #include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" #include "slang-artifact-util.h" -#include "slang-artifact-desc-util.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!! SourceView !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -17,13 +18,13 @@ const String PathInfo::getMostUniqueIdentity() const { switch (type) { - case Type::Normal: return uniqueIdentity; - case Type::FoundPath: - case Type::FromString: + case Type::Normal: return uniqueIdentity; + case Type::FoundPath: + case Type::FromString: { return foundPath; } - default: return ""; + default: return ""; } } @@ -31,9 +32,9 @@ String PathInfo::getName() const { switch (type) { - case Type::Normal: - case Type::FromString: - case Type::FoundPath: + case Type::Normal: + case Type::FromString: + case Type::FoundPath: { return foundPath; } @@ -51,24 +52,24 @@ bool PathInfo::operator==(const ThisType& rhs) const switch (type) { - case Type::TokenPaste: - case Type::TypeParse: - case Type::Unknown: - case Type::CommandLine: + case Type::TokenPaste: + case Type::TypeParse: + case Type::Unknown: + case Type::CommandLine: { return true; } - case Type::Normal: + case Type::Normal: { return foundPath == rhs.foundPath && uniqueIdentity == rhs.uniqueIdentity; } - case Type::FromString: - case Type::FoundPath: + case Type::FromString: + case Type::FoundPath: { // Only have a found path return foundPath == rhs.foundPath; } - default: break; + default: break; } return false; @@ -78,18 +79,21 @@ void PathInfo::appendDisplayName(StringBuilder& out) const { switch (type) { - case Type::TokenPaste: out << "[Token Paste]"; break; - case Type::TypeParse: out << "[Type Parse]"; break; - case Type::Unknown: out << "[Unknown]"; break; - case Type::CommandLine: out << "[Command Line]"; break; - case Type::Normal: - case Type::FromString: - case Type::FoundPath: + case Type::TokenPaste: out << "[Token Paste]"; break; + case Type::TypeParse: out << "[Type Parse]"; break; + case Type::Unknown: out << "[Unknown]"; break; + case Type::CommandLine: out << "[Command Line]"; break; + case Type::Normal: + case Type::FromString: + case Type::FoundPath: { - StringEscapeUtil::appendQuoted(StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp), foundPath.getUnownedSlice(), out); + StringEscapeUtil::appendQuoted( + StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp), + foundPath.getUnownedSlice(), + out); break; } - default: break; + default: break; } } @@ -104,10 +108,10 @@ int SourceView::findEntryIndex(SourceLoc sourceLoc) const const auto rawValue = sourceLoc.getRaw(); - Index hi = m_entries.getCount(); - // If there are no entries, or it is in front of the first entry, then there is no associated entry - if (hi == 0 || - m_entries[0].m_startLoc.getRaw() > sourceLoc.getRaw()) + Index hi = m_entries.getCount(); + // If there are no entries, or it is in front of the first entry, then there is no associated + // entry + if (hi == 0 || m_entries[0].m_startLoc.getRaw() > sourceLoc.getRaw()) { return -1; } @@ -133,29 +137,35 @@ int SourceView::findEntryIndex(SourceLoc sourceLoc) const return int(lo); } -void SourceView::addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handle pathHandle, int line) +void SourceView::addLineDirective( + SourceLoc directiveLoc, + StringSlicePool::Handle pathHandle, + int line) { SLANG_ASSERT(pathHandle != StringSlicePool::Handle(0)); SLANG_ASSERT(m_range.contains(directiveLoc)); // Check that the directiveLoc values are always increasing - SLANG_ASSERT(m_entries.getCount() == 0 || (m_entries.getLast().m_startLoc.getRaw() < directiveLoc.getRaw())); + SLANG_ASSERT( + m_entries.getCount() == 0 || + (m_entries.getLast().m_startLoc.getRaw() < directiveLoc.getRaw())); // Calculate the offset const int offset = m_range.getOffset(directiveLoc); - + // Get the line index in the original file const int lineIndex = m_sourceFile->calcLineIndexFromOffset(offset); Entry entry; entry.m_startLoc = directiveLoc; entry.m_pathHandle = pathHandle; - + // We also need to make sure that any lookups for line numbers will // get corrected based on this files location. - // We assume the line number coming from the directive is a line number, NOT an index, so the correction needs + 1 - // There is an additional + 1 because we want the NEXT line - ie the line after the #line directive, to the specified value - // Taking both into account means +2 is correct 'fix' + // We assume the line number coming from the directive is a line number, NOT an index, so the + // correction needs + 1 There is an additional + 1 because we want the NEXT line - ie the line + // after the #line directive, to the specified value Taking both into account means +2 is + // correct 'fix' entry.m_lineAdjust = line - (lineIndex + 2); m_entries.add(entry); @@ -163,7 +173,8 @@ void SourceView::addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handl void SourceView::addLineDirective(SourceLoc directiveLoc, const String& path, int line) { - StringSlicePool::Handle pathHandle = getSourceManager()->getStringSlicePool().add(path.getUnownedSlice()); + StringSlicePool::Handle pathHandle = + getSourceManager()->getStringSlicePool().add(path.getUnownedSlice()); return addLineDirective(directiveLoc, pathHandle, line); } @@ -171,9 +182,12 @@ void SourceView::addDefaultLineDirective(SourceLoc directiveLoc) { SLANG_ASSERT(m_range.contains(directiveLoc)); // Check that the directiveLoc values are always increasing - SLANG_ASSERT(m_entries.getCount() == 0 || (m_entries.getLast().m_startLoc.getRaw() < directiveLoc.getRaw())); + SLANG_ASSERT( + m_entries.getCount() == 0 || + (m_entries.getLast().m_startLoc.getRaw() < directiveLoc.getRaw())); - // Well if there are no entries, or the last one puts it in default case, then we don't need to add anything + // Well if there are no entries, or the last one puts it in default case, then we don't need to + // add anything if (m_entries.getCount() == 0 || (m_entries.getCount() && m_entries.getLast().isDefault())) { return; @@ -181,8 +195,9 @@ void SourceView::addDefaultLineDirective(SourceLoc directiveLoc) Entry entry; entry.m_startLoc = directiveLoc; - entry.m_lineAdjust = 0; // No line adjustment... we are going back to default - entry.m_pathHandle = StringSlicePool::Handle(0); // Mark that there is no path, and that this is a 'default' + entry.m_lineAdjust = 0; // No line adjustment... we are going back to default + entry.m_pathHandle = + StringSlicePool::Handle(0); // Mark that there is no path, and that this is a 'default' SLANG_ASSERT(entry.isDefault()); @@ -204,16 +219,20 @@ static bool _canFollowSourceMap(SourceFile* sourceFile, SourceLocType type) } // If it's obfuscated we can't follow if we are emitting - if (sourceFile->getSourceMapKind() == SourceMapKind::Obfuscated && - type == SourceLocType::Emit) + if (sourceFile->getSourceMapKind() == SourceMapKind::Obfuscated && type == SourceLocType::Emit) { return false; } - return _isNominalLike(type); + return _isNominalLike(type); } -static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, SourceView* sourceView, SourceLoc loc, SourceLocType type, HandleSourceLoc& outLoc) +static SlangResult _findLocWithSourceMap( + SourceManager* lookupSourceManager, + SourceView* sourceView, + SourceLoc loc, + SourceLocType type, + HandleSourceLoc& outLoc) { auto sourceFile = sourceView->getSourceFile(); @@ -229,9 +248,9 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou Index entryIndex = -1; // Do the initial lookup using the loc - { + { const auto offset = sourceView->getRange().getOffset(loc); - + const auto lineIndex = sourceFile->calcLineIndexFromOffset(offset); const auto colIndex = sourceFile->calcColumnIndex(lineIndex, offset); @@ -239,7 +258,7 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou auto sourceMap = sourceFile->getSourceMap(); SLANG_ASSERT(sourceMap); - entryIndex = sourceMap->get().findEntry(lineIndex, colIndex); + entryIndex = sourceMap->get().findEntry(lineIndex, colIndex); } if (entryIndex < 0) @@ -247,8 +266,8 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou return SLANG_FAIL; } - // Keep searching through source maps - do + // Keep searching through source maps + do { auto sourceMap = sourceFile->getSourceMap()->getPtr(); @@ -259,7 +278,8 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou // If we have a source name, see if it already exists in source manager if (sourceFileName.getLength()) { - if (auto foundSourceFile = lookupSourceManager->findSourceFileByPathRecursively(sourceFileName)) + if (auto foundSourceFile = + lookupSourceManager->findSourceFileByPathRecursively(sourceFileName)) { // We only follow if the source file hasn't already been visisted if (sourceFiles.indexOf(foundSourceFile) < 0) @@ -267,12 +287,14 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou // Add so we don't reprocess sourceFiles.add(foundSourceFile); - // If it has a source map, we try and look up the current location in it's source map + // If it has a source map, we try and look up the current location in it's + // source map if (_canFollowSourceMap(foundSourceFile, type)) { auto foundSourceMap = foundSourceFile->getSourceMap(); - const auto foundEntryIndex = foundSourceMap->get().findEntry(entry.sourceLine, entry.sourceColumn); + const auto foundEntryIndex = + foundSourceMap->get().findEntry(entry.sourceLine, entry.sourceColumn); // If we found the entry repeat the lookup if (foundEntryIndex >= 0) @@ -304,7 +326,10 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou } -SlangResult SourceView::_findSourceMapLoc(SourceLoc loc, SourceLocType type, HandleSourceLoc& outLoc) +SlangResult SourceView::_findSourceMapLoc( + SourceLoc loc, + SourceLocType type, + HandleSourceLoc& outLoc) { // We only do source map lookups with nominal if (!_isNominalLike(type)) @@ -312,9 +337,9 @@ SlangResult SourceView::_findSourceMapLoc(SourceLoc loc, SourceLocType type, Han return SLANG_E_NOT_FOUND; } - // 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. + // 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(); SLANG_RETURN_ON_FAIL(_findLocWithSourceMap(lookupSourceManager, this, loc, type, outLoc)); @@ -324,31 +349,32 @@ SlangResult SourceView::_findSourceMapLoc(SourceLoc loc, SourceLocType type, Han HandleSourceLoc SourceView::getHandleLoc(SourceLoc loc, SourceLocType type) { - { HandleSourceLoc handleLoc; + { + HandleSourceLoc handleLoc; if (SLANG_SUCCEEDED(_findSourceMapLoc(loc, type, handleLoc))) { return handleLoc; } } - // Get the offset in bytes for this loc + // Get the offset in bytes for this loc const int offset = m_range.getOffset(loc); // We need the line index from the original source file const int lineIndex = m_sourceFile->calcLineIndexFromOffset(offset); - // TODO: + // TODO: // - Tab characters, which should really adjust how we report // columns (although how are we supposed to know the setting // that an IDE expects us to use when reporting locations?) - // + // // For now we just count tabs as single chars const int columnIndex = m_sourceFile->calcColumnIndex(lineIndex, offset); HandleSourceLoc handleLoc; handleLoc.column = columnIndex + 1; handleLoc.line = lineIndex + 1; - + // Only bother looking up the entry information if we want a 'Norminal'-like lookup if (_isNominalLike(type)) { @@ -411,7 +437,7 @@ PathInfo SourceView::getPathInfo(SourceLoc loc, SourceLocType type) return getViewPathInfo(); } - { + { HandleSourceLoc handleLoc; if (SLANG_SUCCEEDED(_findSourceMapLoc(loc, type, handleLoc))) { @@ -420,7 +446,8 @@ PathInfo SourceView::getPathInfo(SourceLoc loc, SourceLocType type) } const int entryIndex = findEntryIndex(loc); - return _getPathInfoFromHandle((entryIndex >= 0) ? m_entries[entryIndex].m_pathHandle : StringSlicePool::Handle(0)); + return _getPathInfoFromHandle( + (entryIndex >= 0) ? m_entries[entryIndex].m_pathHandle : StringSlicePool::Handle(0)); } /* !!!!!!!!!!!!!!!!!!!!!!! SourceFile !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -464,13 +491,13 @@ SourceFile::OffsetRange SourceFile::getOffsetRangeAtLineIndex(Index lineIndex) const uint32_t offsetEnd = uint32_t(getContentSize()); const uint32_t offsetStart = (lineIndex >= count) ? offsetEnd : offsets[lineIndex]; // The line is the span from start, to the end of the content - return OffsetRange{ offsetStart, offsetEnd }; + return OffsetRange{offsetStart, offsetEnd}; } else { const uint32_t offsetStart = offsets[lineIndex]; const uint32_t offsetEnd = offsets[lineIndex + 1]; - return OffsetRange { offsetStart, offsetEnd }; + return OffsetRange{offsetStart, offsetEnd}; } } @@ -483,7 +510,7 @@ UnownedStringSlice SourceFile::getLineAtIndex(Index lineIndex) const UnownedStringSlice content = getContent(); SLANG_ASSERT(range.end <= uint32_t(content.getLength())); - const char*const text = content.begin(); + const char* const text = content.begin(); return UnownedStringSlice(text + range.start, text + range.end); } @@ -517,7 +544,7 @@ int SourceFile::calcLineIndexFromOffset(int offset) while (lo + 1 < hi) { - const Index mid = (hi + lo) >> 1; + const Index mid = (hi + lo) >> 1; const uint32_t midOffset = lineBreakOffsets[mid]; if (midOffset <= uint32_t(offset)) { @@ -535,14 +562,15 @@ int SourceFile::calcLineIndexFromOffset(int offset) int SourceFile::calcColumnOffset(int lineIndex, int offset) { const auto& lineBreakOffsets = getLineBreakOffsets(); - return offset - lineBreakOffsets[lineIndex]; + return offset - lineBreakOffsets[lineIndex]; } int SourceFile::calcColumnIndex(int lineIndex, int offset, int tabSize) { const int colOffset = calcColumnOffset(lineIndex, offset); - // If we don't have the content of the file, the best we can do is to assume there is a char per column + // If we don't have the content of the file, the best we can do is to assume there is a char per + // column if (!hasContent()) { return colOffset; @@ -553,7 +581,7 @@ int SourceFile::calcColumnIndex(int lineIndex, int offset, int tabSize) const auto head = line.head(colOffset); auto colCount = UTF8Util::calcCodePointCount(head); - + if (tabSize >= 0) { Count tabCount = 0; @@ -581,10 +609,7 @@ void SourceFile::setContents(ISlangBlob* blob) // Query the encoding type and discard the Unicode Byte-Order-Marker before decoding size_t offset; - auto type = CharEncoding::determineEncoding( - rawContentBegin, - rawContentSize, - offset); + auto type = CharEncoding::determineEncoding(rawContentBegin, rawContentSize, offset); SLANG_ASSERT(rawContentSize >= offset); List<char> decodedBuffer; @@ -608,16 +633,12 @@ void SourceFile::setContents(const String& content) setContents(contentBlob); } -SourceFile::SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize) : - m_sourceManager(sourceManager), - m_pathInfo(pathInfo), - m_contentSize(contentSize) +SourceFile::SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize) + : m_sourceManager(sourceManager), m_pathInfo(pathInfo), m_contentSize(contentSize) { } -SourceFile::~SourceFile() -{ -} +SourceFile::~SourceFile() {} SHA1::Digest SourceFile::getDigest() { @@ -638,7 +659,10 @@ String SourceFile::calcVerbosePath() const { String displayPath; ComPtr<ISlangBlob> displayPathBlob; - if (SLANG_SUCCEEDED(fileSystemExt->getPath(PathKind::Display, m_pathInfo.foundPath.getBuffer(), displayPathBlob.writeRef()))) + if (SLANG_SUCCEEDED(fileSystemExt->getPath( + PathKind::Display, + m_pathInfo.foundPath.getBuffer(), + displayPathBlob.writeRef()))) { displayPath = StringUtil::getString(displayPathBlob); } @@ -653,9 +677,7 @@ String SourceFile::calcVerbosePath() const /* !!!!!!!!!!!!!!!!!!!!!!!!! SourceManager !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -void SourceManager::initialize( - SourceManager* p, - ISlangFileSystemExt* fileSystemExt) +void SourceManager::initialize(SourceManager* p, ISlangFileSystemExt* fileSystemExt) { m_fileSystemExt = fileSystemExt; @@ -730,8 +752,8 @@ SourceRange SourceManager::allocateSourceRange(UInt size) // TODO: consider using atomics here - SourceLoc beginLoc = m_nextLoc; - SourceLoc endLoc = beginLoc + size; + SourceLoc beginLoc = m_nextLoc; + SourceLoc endLoc = beginLoc + size; // We need to be able to represent the location that is *at* the end of // the input source, so the next available location for a new file @@ -749,7 +771,9 @@ SourceFile* SourceManager::createSourceFileWithSize(const PathInfo& pathInfo, si return sourceFile; } -SourceFile* SourceManager::createSourceFileWithString(const PathInfo& pathInfo, const String& contents) +SourceFile* SourceManager::createSourceFileWithString( + const PathInfo& pathInfo, + const String& contents) { SourceFile* sourceFile = new SourceFile(this, pathInfo, contents.getLength()); m_sourceFiles.add(sourceFile); @@ -765,13 +789,16 @@ SourceFile* SourceManager::createSourceFileWithBlob(const PathInfo& pathInfo, IS return sourceFile; } -SourceView* SourceManager::createSourceView(SourceFile* sourceFile, const PathInfo* pathInfo, SourceLoc initiatingSourceLoc) +SourceView* SourceManager::createSourceView( + SourceFile* sourceFile, + const PathInfo* pathInfo, + SourceLoc initiatingSourceLoc) { SourceRange range = allocateSourceRange(sourceFile->getContentSize()); SourceView* sourceView = nullptr; - if (pathInfo && - (pathInfo->foundPath.getLength() && sourceFile->getPathInfo().foundPath != pathInfo->foundPath)) + if (pathInfo && (pathInfo->foundPath.getLength() && + sourceFile->getPathInfo().foundPath != pathInfo->foundPath)) { sourceView = new SourceView(sourceFile, range, &pathInfo->foundPath, initiatingSourceLoc); } @@ -844,7 +871,7 @@ SourceView* SourceManager::findSourceViewRecursively(SourceLoc loc) const { // Start with this manager const SourceManager* manager = this; - do + do { SourceView* sourceView = manager->findSourceView(loc); // If we found a hit we are done @@ -854,8 +881,7 @@ SourceView* SourceManager::findSourceViewRecursively(SourceLoc loc) const } // Try the parent manager = manager->m_parent; - } - while (manager); + } while (manager); // Didn't find it return nullptr; } @@ -881,7 +907,7 @@ SourceFile* SourceManager::findSourceFileByPathRecursively(const String& name) c SourceFile* SourceManager::findSourceFileByPath(const String& name) const { - for(auto sourceFile : m_sourceFiles) + for (auto sourceFile : m_sourceFiles) { if (sourceFile->getPathInfo().foundPath == name) { @@ -893,14 +919,14 @@ SourceFile* SourceManager::findSourceFileByPath(const String& name) const SourceFile* SourceManager::findSourceFile(const String& uniqueIdentity) const { - SourceFile*const* filePtr = m_sourceFileMap.tryGetValue(uniqueIdentity); + SourceFile* const* filePtr = m_sourceFileMap.tryGetValue(uniqueIdentity); return (filePtr) ? *filePtr : nullptr; } SourceFile* SourceManager::findSourceFileRecursively(const String& uniqueIdentity) const { const SourceManager* manager = this; - do + do { SourceFile* sourceFile = manager->findSourceFile(uniqueIdentity); if (sourceFile) diff --git a/source/compiler-core/slang-source-loc.h b/source/compiler-core/slang-source-loc.h index bf0be47f6..c46c9063a 100644 --- a/source/compiler-core/slang-source-loc.h +++ b/source/compiler-core/slang-source-loc.h @@ -3,91 +3,126 @@ #define SLANG_SOURCE_LOC_H_INCLUDED #include "../core/slang-basic.h" -#include "../core/slang-memory-arena.h" -#include "../core/slang-string-slice-pool.h" #include "../core/slang-castable.h" #include "../core/slang-crypto.h" - -#include "slang-source-map.h" - +#include "../core/slang-memory-arena.h" +#include "../core/slang-string-slice-pool.h" #include "slang-com-ptr.h" +#include "slang-source-map.h" #include "slang.h" -namespace Slang { - -/** Overview: - -There needs to be a mechanism where we can easily and quickly track a specific locations in any source file used during a compilation. -This is important because that original location is meaningful to the user as it relates to their original source. Thus SourceLoc are -used so we can display meaningful and accurate errors/warnings as well as being able to always map generated code locations back to their origins. - -A 'SourceLoc' along with associated structures (SourceView, SourceFile, SourceMangager) this can pinpoint the location down to the byte across the -compilation. This could be achieved by storing for every token and instruction the file, line and column number came from. The SourceLoc is used in -lots of places - every AST node, every Token from the lexer, every IRInst - so we really want to make it small. So for this reason we actually -encode SourceLoc as a single integer and then use the associated structures when needed to determine what the location actually refers to - -the source file, line and column number, or in effect the byte in the original file. - -Unfortunately there is extra complications. When a source is parsed it's interpretation (in terms of how a piece of source maps to an 'original' file etc) -can be overridden - for example by using #line directives. Moreover a single source file can be parsed multiple times. When it's parsed multiple times the -interpretation of the mapping (#line directives for example) can change. This is the purpose of the SourceView - it holds the interpretation of a source file -for a specific Lex/Parse. - -Another complication is that not all 'source' comes from SourceFiles, a macro expansion, may generate new 'source' we need to handle this, but also be able -to have a SourceLoc map to the expansion unambiguously. This is handled by creating a SourceFile and SourceView that holds only the macro generated -specific information. +namespace Slang +{ -SourceFile - Is the immutable text contents of a file (or perhaps some generated source - say from doing a macro substitution) -SourceView - Tracks a single parse of a SourceFile. Each SourceView defines a range of source locations used. If a SourceFile is parsed twice, two -SourceViews are created, with unique SourceRanges. This is so that it is possible to tell which specific parse a SourceLoc is from - and so know the right -interpretation for that lex/parse. +/** Overview: + +There needs to be a mechanism where we can easily and quickly track a specific locations in any +source file used during a compilation. This is important because that original location is +meaningful to the user as it relates to their original source. Thus SourceLoc are used so we can +display meaningful and accurate errors/warnings as well as being able to always map generated code +locations back to their origins. + +A 'SourceLoc' along with associated structures (SourceView, SourceFile, SourceMangager) this can +pinpoint the location down to the byte across the compilation. This could be achieved by storing for +every token and instruction the file, line and column number came from. The SourceLoc is used in +lots of places - every AST node, every Token from the lexer, every IRInst - so we really want to +make it small. So for this reason we actually encode SourceLoc as a single integer and then use the +associated structures when needed to determine what the location actually refers to - the source +file, line and column number, or in effect the byte in the original file. + +Unfortunately there is extra complications. When a source is parsed it's interpretation (in terms of +how a piece of source maps to an 'original' file etc) can be overridden - for example by using #line +directives. Moreover a single source file can be parsed multiple times. When it's parsed multiple +times the interpretation of the mapping (#line directives for example) can change. This is the +purpose of the SourceView - it holds the interpretation of a source file for a specific Lex/Parse. + +Another complication is that not all 'source' comes from SourceFiles, a macro expansion, may +generate new 'source' we need to handle this, but also be able to have a SourceLoc map to the +expansion unambiguously. This is handled by creating a SourceFile and SourceView that holds only the +macro generated specific information. + +SourceFile - Is the immutable text contents of a file (or perhaps some generated source - say from +doing a macro substitution) SourceView - Tracks a single parse of a SourceFile. Each SourceView +defines a range of source locations used. If a SourceFile is parsed twice, two SourceViews are +created, with unique SourceRanges. This is so that it is possible to tell which specific parse a +SourceLoc is from - and so know the right interpretation for that lex/parse. */ struct PathInfo { typedef PathInfo ThisType; - /// To be more rigorous about where a path comes from, the type identifies what a paths origin is + /// To be more rigorous about where a path comes from, the type identifies what a paths origin + /// is enum class Type : uint8_t { - Unknown, ///< The path is not known - Normal, ///< Normal has both path and uniqueIdentity - FoundPath, ///< Just has a found path (uniqueIdentity is unknown, or even 'unknowable') - FromString, ///< Created from a string (so found path might not be defined and should not be taken as to map to a loaded file) - TokenPaste, ///< No paths, just created to do a macro expansion - TypeParse, ///< No path, just created to do a type parse - CommandLine, ///< A macro constructed from the command line + Unknown, ///< The path is not known + Normal, ///< Normal has both path and uniqueIdentity + FoundPath, ///< Just has a found path (uniqueIdentity is unknown, or even 'unknowable') + FromString, ///< Created from a string (so found path might not be defined and should not be + ///< taken as to map to a loaded file) + TokenPaste, ///< No paths, just created to do a macro expansion + TypeParse, ///< No path, just created to do a type parse + CommandLine, ///< A macro constructed from the command line }; - /// True if has a canonical path - SLANG_FORCE_INLINE bool hasUniqueIdentity() const { return type == Type::Normal && uniqueIdentity.getLength() > 0; } - /// True if has a regular found path - SLANG_FORCE_INLINE bool hasFoundPath() const { return (type == Type::Normal || type == Type::FoundPath || type == Type::FromString) && foundPath.getLength() > 0; } - /// True if has a found path that has originated from a file (as opposed to string or some other origin) - SLANG_FORCE_INLINE bool hasFileFoundPath() const { return (type == Type::Normal || type == Type::FoundPath) && foundPath.getLength() > 0; } - /// Get the 'name'/path of the item. Will return an empty string if not applicable or not set. + /// True if has a canonical path + SLANG_FORCE_INLINE bool hasUniqueIdentity() const + { + return type == Type::Normal && uniqueIdentity.getLength() > 0; + } + /// True if has a regular found path + SLANG_FORCE_INLINE bool hasFoundPath() const + { + return (type == Type::Normal || type == Type::FoundPath || type == Type::FromString) && + foundPath.getLength() > 0; + } + /// True if has a found path that has originated from a file (as opposed to string or some other + /// origin) + SLANG_FORCE_INLINE bool hasFileFoundPath() const + { + return (type == Type::Normal || type == Type::FoundPath) && foundPath.getLength() > 0; + } + /// Get the 'name'/path of the item. Will return an empty string if not applicable or not set. String getName() const; bool operator==(const ThisType& rhs) const; bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Returns the 'most unique' identity for the path. If has a 'uniqueIdentity' returns that, else the foundPath, else "". + /// Returns the 'most unique' identity for the path. If has a 'uniqueIdentity' returns that, + /// else the foundPath, else "". const String getMostUniqueIdentity() const; - /// Append to out, how to display the path + /// Append to out, how to display the path void appendDisplayName(StringBuilder& out) const; - // So simplify construction. In normal usage it's safer to use make methods over constructing directly. - static PathInfo makeUnknown() { return PathInfo { Type::Unknown, String(), String() }; } - static PathInfo makeTokenPaste() { return PathInfo{ Type::TokenPaste, "token paste", String()}; } - static PathInfo makeNormal(const String& foundPathIn, const String& uniqueIdentity) { SLANG_ASSERT(uniqueIdentity.getLength() > 0 && foundPathIn.getLength() > 0); return PathInfo { Type::Normal, foundPathIn, uniqueIdentity }; } - static PathInfo makePath(const String& pathIn) { SLANG_ASSERT(pathIn.getLength() > 0); return PathInfo { Type::FoundPath, pathIn, String()}; } - static PathInfo makeTypeParse() { return PathInfo { Type::TypeParse, "type string", String() }; } - static PathInfo makeCommandLine() { return PathInfo { Type::CommandLine, "command line", String() }; } - static PathInfo makeFromString(const String& userPath) { return PathInfo{ Type::FromString, userPath, String() }; } - - Type type; ///< The type of path - String foundPath; ///< The path where the file was found (might contain relative elements) - String uniqueIdentity; ///< The unique identity of the file on the path found + // So simplify construction. In normal usage it's safer to use make methods over constructing + // directly. + static PathInfo makeUnknown() { return PathInfo{Type::Unknown, String(), String()}; } + static PathInfo makeTokenPaste() { return PathInfo{Type::TokenPaste, "token paste", String()}; } + static PathInfo makeNormal(const String& foundPathIn, const String& uniqueIdentity) + { + SLANG_ASSERT(uniqueIdentity.getLength() > 0 && foundPathIn.getLength() > 0); + return PathInfo{Type::Normal, foundPathIn, uniqueIdentity}; + } + static PathInfo makePath(const String& pathIn) + { + SLANG_ASSERT(pathIn.getLength() > 0); + return PathInfo{Type::FoundPath, pathIn, String()}; + } + static PathInfo makeTypeParse() { return PathInfo{Type::TypeParse, "type string", String()}; } + static PathInfo makeCommandLine() + { + return PathInfo{Type::CommandLine, "command line", String()}; + } + static PathInfo makeFromString(const String& userPath) + { + return PathInfo{Type::FromString, userPath, String()}; + } + + Type type; ///< The type of path + String foundPath; ///< The path where the file was found (might contain relative elements) + String uniqueIdentity; ///< The unique identity of the file on the path found }; class SourceLoc @@ -102,12 +137,13 @@ private: public: SourceLoc() : raw(0) - {} + { + } - SourceLoc( - SourceLoc const& loc) + SourceLoc(SourceLoc const& loc) : raw(loc.raw) - {} + { + } SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const { return raw == rhs.raw; } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(raw == rhs.raw); } @@ -122,10 +158,7 @@ public: return result; } - bool isValid() const - { - return raw != 0; - } + bool isValid() const { return raw != 0; } SourceLoc& operator=(const ThisType& rhs) = default; }; @@ -137,43 +170,54 @@ inline SourceLoc operator+(SourceLoc loc, Int offset) // A range of locations in the input source struct SourceRange { - /// True if the loc is in the range. Range is inclusive on begin to end. - bool contains(SourceLoc loc) const { const auto rawLoc = loc.getRaw(); return rawLoc >= begin.getRaw() && rawLoc <= end.getRaw(); } - /// Get the total size + /// True if the loc is in the range. Range is inclusive on begin to end. + bool contains(SourceLoc loc) const + { + const auto rawLoc = loc.getRaw(); + return rawLoc >= begin.getRaw() && rawLoc <= end.getRaw(); + } + /// Get the total size UInt getSize() const { return UInt(end.getRaw() - begin.getRaw()); } - /// Get the offset of a loc in this range - int getOffset(SourceLoc loc) const { SLANG_ASSERT(contains(loc)); return int(loc.getRaw() - begin.getRaw()); } + /// Get the offset of a loc in this range + int getOffset(SourceLoc loc) const + { + SLANG_ASSERT(contains(loc)); + return int(loc.getRaw() - begin.getRaw()); + } - /// Convert an offset to a loc - SourceLoc getSourceLocFromOffset(uint32_t offset) const { SLANG_ASSERT(offset <= getSize()); return begin + Int(offset); } + /// Convert an offset to a loc + SourceLoc getSourceLocFromOffset(uint32_t offset) const + { + SLANG_ASSERT(offset <= getSize()); + return begin + Int(offset); + } - SourceRange() - {} + SourceRange() {} SourceRange(SourceLoc loc) - : begin(loc) - , end(loc) - {} + : begin(loc), end(loc) + { + } SourceRange(SourceLoc begin, SourceLoc end) - : begin(begin) - , end(end) - {} + : begin(begin), end(end) + { + } SourceLoc begin; 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"). +/// 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 + Normal, ///< A regular source map + Obfuscated, ///< Obfuscated source map }; // Pre-declare @@ -181,113 +225,124 @@ struct SourceManager; // A logical or physical storage object for a range of input code // that has logically contiguous source locations. -class SourceFile +class SourceFile { public: - struct OffsetRange { - /// We need a value to indicate an invalid range. We can't use 0 as that is valid for an offset range - /// We can't use a negative number, and don't want to make signed so we get the full 32-bits. - /// So we just use the max value as invalid + /// We need a value to indicate an invalid range. We can't use 0 as that is valid for an + /// offset range We can't use a negative number, and don't want to make signed so we get the + /// full 32-bits. So we just use the max value as invalid static const uint32_t kInvalid = 0xffffffff; - /// True if the range is valid + /// True if the range is valid SLANG_FORCE_INLINE bool isValid() const { return end >= start && start != kInvalid; } - /// True if offset is within range (inclusively) - SLANG_FORCE_INLINE bool containsInclusive(uint32_t offset) const { return offset >= start && offset <= end; } + /// True if offset is within range (inclusively) + SLANG_FORCE_INLINE bool containsInclusive(uint32_t offset) const + { + return offset >= start && offset <= end; + } - /// Get the count + /// Get the count SLANG_FORCE_INLINE uint32_t getCount() const { return end - start; } - /// Return an invalid range. - static OffsetRange makeInvalid() { return OffsetRange{ kInvalid, kInvalid }; } + /// Return an invalid range. + static OffsetRange makeInvalid() { return OffsetRange{kInvalid, kInvalid}; } uint32_t start; uint32_t end; }; - /// Returns the line break offsets (in bytes from start of content) - /// Note that this is lazily evaluated - the line breaks are only calculated on the first request + /// Returns the line break offsets (in bytes from start of content) + /// Note that this is lazily evaluated - the line breaks are only calculated on the first + /// request const List<uint32_t>& getLineBreakOffsets(); - /// Returns true if the offset is on the specified line - /// NOTE! If offsets are not fully setup (because we don't have source), will only be correct for lines that have offsets + /// Returns true if the offset is on the specified line + /// NOTE! If offsets are not fully setup (because we don't have source), will only be correct + /// for lines that have offsets bool isOffsetOnLine(uint32_t offset, Index lineIndex); - /// Get the line containing the offset. Requires that content is available, else will return an empty slice. + /// Get the line containing the offset. Requires that content is available, else will return an + /// empty slice. UnownedStringSlice getLineContainingOffset(uint32_t offset); - /// Get the line at the specified line index. Requires that content is available, else will return an empty slice. + /// Get the line at the specified line index. Requires that content is available, else will + /// return an empty slice. UnownedStringSlice getLineAtIndex(Index lineIndex); - /// Get the offset range at the specified line index. Works without content. + /// Get the offset range at the specified line index. Works without content. OffsetRange getOffsetRangeAtLineIndex(Index lineIndex); - /// Set the line break offsets + /// Set the line break offsets void setLineBreakOffsets(const uint32_t* offsets, UInt numOffsets); - /// Calculate the line based on the offset + /// Calculate the line based on the offset int calcLineIndexFromOffset(int offset); - /// Calculate the offset (in bytes) for a line + /// Calculate the offset (in bytes) for a line int calcColumnOffset(int line, int offset); - /// Given a line and offset (in bytes for the whole file), return the column index, taking into account tabs - /// and utf8 encoding. - /// Passing tabSize uses the default tab size (currently tab set to 1) + /// Given a line and offset (in bytes for the whole file), return the column index, taking into + /// account tabs and utf8 encoding. Passing tabSize uses the default tab size (currently tab set + /// to 1) int calcColumnIndex(int line, int offset, int tabSize = -1); - /// Get the content holding blob - ISlangBlob* getContentBlob() const { return m_contentBlob; } + /// Get the content holding blob + ISlangBlob* getContentBlob() const { return m_contentBlob; } - /// True if has full set content - bool hasContent() const { return m_contentBlob != nullptr; } + /// True if has full set content + bool hasContent() const { return m_contentBlob != nullptr; } - /// Get the content size - size_t getContentSize() const { return m_contentSize; } + /// Get the content size + size_t getContentSize() const { return m_contentSize; } - /// Get the content - const UnownedStringSlice& getContent() const { return m_content; } + /// Get the content + const UnownedStringSlice& getContent() const { return m_content; } - /// Get path info - const PathInfo& getPathInfo() const { return m_pathInfo; } + /// Get path info + const PathInfo& getPathInfo() const { return m_pathInfo; } - /// Set the content as a blob + /// Set the content as a blob void setContents(ISlangBlob* blob); - /// Set the content as a string + /// Set the content as a string void setContents(const String& content); - /// Calculate a display path -> can canonicalize if necessary + /// Calculate a display path -> can canonicalize if necessary String calcVerbosePath() const; - /// Get the source manager this was created on + /// Get the source manager this was created on SourceManager* getSourceManager() const { return m_sourceManager; } - /// Get the source map associated with this file. If it's set when doing - /// lookup for source locations, the source map will be used + /// 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 + /// Get the source map kind SourceMapKind getSourceMapKind() const { return m_sourceMapKind; } - /// Set a source map - void setSourceMap(IBoxValue<SourceMap>* sourceMap, SourceMapKind sourceMapKind) { m_sourceMap = sourceMap; m_sourceMapKind = sourceMapKind; } + /// Set a source map + void setSourceMap(IBoxValue<SourceMap>* sourceMap, SourceMapKind sourceMapKind) + { + m_sourceMap = sourceMap; + m_sourceMapKind = sourceMapKind; + } - /// Ctor + /// Ctor SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize); - /// Dtor + /// Dtor ~SourceFile(); SHA1::Digest getDigest(); - protected: - - SourceManager* m_sourceManager; ///< The source manager this belongs to - PathInfo m_pathInfo; ///< The path The logical file path to report for locations inside this span. +protected: + SourceManager* m_sourceManager; ///< The source manager this belongs to + PathInfo + m_pathInfo; ///< The path The logical file path to report for locations inside this span. - ComPtr<ISlangBlob> m_contentBlob; ///< A blob that owns the storage for the file contents. If nullptr, there is no contents - UnownedStringSlice m_content; ///< The actual contents of the file. - size_t m_contentSize; ///< The size of the actual contents + ComPtr<ISlangBlob> m_contentBlob; ///< A blob that owns the storage for the file contents. If + ///< nullptr, there is no contents + UnownedStringSlice m_content; ///< The actual contents of the file. + size_t m_contentSize; ///< The size of the actual contents SHA1::Digest m_digest; @@ -296,7 +351,7 @@ public: // the input file: List<uint32_t> m_lineBreakOffsets; - // If set then the locations in this file are really from locations from elsewhere, + // 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) @@ -305,17 +360,20 @@ public: 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. + 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 struct HumaneSourceLoc { PathInfo pathInfo = PathInfo::makeUnknown(); - Int line = 0; - Int column = 0; + Int line = 0; + Int column = 0; }; // Same as HumaneSourceLoc but stores the path only as a handle. @@ -326,85 +384,95 @@ struct HandleSourceLoc Int column = 0; }; -/* A SourceView maps to a single span of SourceLoc range and is equivalent to a single include or more precisely use of a source file. -It is distinct from a SourceFile - because a SourceFile may be included multiple times, with different interpretations (depending -on #defines for example). -*/ +/* A SourceView maps to a single span of SourceLoc range and is equivalent to a single include or +more precisely use of a source file. It is distinct from a SourceFile - because a SourceFile may be +included multiple times, with different interpretations (depending on #defines for example). +*/ class SourceView { - public: - +public: // Each entry represents some contiguous span of locations that // all map to the same logical file. struct Entry { - /// True if this resets the line numbering. It is distinct from a m_lineAdjust being 0, because it also means the path returns to the default. + /// True if this resets the line numbering. It is distinct from a m_lineAdjust being 0, + /// because it also means the path returns to the default. bool isDefault() const { return m_pathHandle == StringSlicePool::Handle(0); } - SourceLoc m_startLoc; ///< Where does this entry begin? - StringSlicePool::Handle m_pathHandle; ///< What is the presumed path for this entry. If 0 it means there is no path. - int32_t m_lineAdjust; ///< Adjustment to apply to source line numbers when printing presumed locations. Relative to the line number in the underlying file. + SourceLoc m_startLoc; ///< Where does this entry begin? + StringSlicePool::Handle m_pathHandle; ///< What is the presumed path for this entry. If 0 it + ///< means there is no path. + int32_t m_lineAdjust; ///< Adjustment to apply to source line numbers when printing presumed + ///< locations. Relative to the line number in the underlying file. }; - /// Given a sourceLoc finds the entry associated with it. If returns -1 then no entry is - /// associated with this location, and therefore the location should be interpreted as an offset - /// into the underlying sourceFile. + /// Given a sourceLoc finds the entry associated with it. If returns -1 then no entry is + /// associated with this location, and therefore the location should be interpreted as an offset + /// into the underlying sourceFile. int findEntryIndex(SourceLoc sourceLoc) const; - /// Add a line directive for this view. The directiveLoc must of course be in this SourceView - /// The path handle, must have been constructed on the SourceManager associated with the view - /// NOTE! Directives are assumed to be added IN ORDER during parsing such that every directiveLoc > previous + /// Add a line directive for this view. The directiveLoc must of course be in this SourceView + /// The path handle, must have been constructed on the SourceManager associated with the view + /// NOTE! Directives are assumed to be added IN ORDER during parsing such that every + /// directiveLoc > previous void addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handle pathHandle, int line); void addLineDirective(SourceLoc directiveLoc, const String& path, int line); - /// Removes any corrections on line numbers and reverts to the source files path + /// Removes any corrections on line numbers and reverts to the source files path void addDefaultLineDirective(SourceLoc directiveLoc); - /// Get the range that this view applies to + /// Get the range that this view applies to const SourceRange& getRange() const { return m_range; } - /// Get the entries + /// Get the entries const List<Entry>& getEntries() const { return m_entries; } - /// Set the entries list - void setEntries(const Entry* entries, UInt numEntries) { m_entries.clear(); m_entries.addRange(entries, numEntries); } + /// Set the entries list + void setEntries(const Entry* entries, UInt numEntries) + { + m_entries.clear(); + m_entries.addRange(entries, numEntries); + } - /// Get the source file holds the contents this view + /// Get the source file holds the contents this view SourceFile* getSourceFile() const { return m_sourceFile; } - /// Get the source manager + /// Get the source manager SourceManager* getSourceManager() const { return m_sourceFile->getSourceManager(); } - /// Get the associated 'content' (the source text) + /// Get the associated 'content' (the source text) const UnownedStringSlice& getContent() const { return m_sourceFile->getContent(); } - /// Get the size of the content + /// Get the size of the content size_t getContentSize() const { return m_sourceFile->getContentSize(); } - /// Get the humane location - /// Type determines if the location wanted is the original, or the 'normal' (which modifys behavior based on #line directives) + /// Get the humane location + /// Type determines if the location wanted is the original, or the 'normal' (which modifys + /// behavior based on #line directives) HumaneSourceLoc getHumaneLoc(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Get the humane location, but store the path as a handle + /// Get the humane location, but store the path as a handle HandleSourceLoc getHandleLoc(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Get the path associated with a location + /// Get the path associated with a location PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Get the initiating source location - that is the source location that caused the this SourceView to be created - /// Can be SourceLoc(0) if there is no initiating location. - /// For example for a #include - the view's initiating source loc for the view that is the contents of the view - /// will be the location of the #include in the source. - /// For the original source file (ie not an include) - the view will have an initiating source loc of SourceLoc(0) + /// Get the initiating source location - that is the source location that caused the this + /// SourceView to be created Can be SourceLoc(0) if there is no initiating location. For example + /// for a #include - the view's initiating source loc for the view that is the contents of the + /// view will be the location of the #include in the source. For the original source file (ie + /// not an include) - the view will have an initiating source loc of SourceLoc(0) SourceLoc getInitiatingSourceLoc() const { return m_initiatingSourceLoc; } - /// Gets the pathInfo for this view. It may be different from the m_sourceFile's if the path has been - /// overridden by m_viewPath + /// Gets the pathInfo for this view. It may be different from the m_sourceFile's if the path has + /// been overridden by m_viewPath PathInfo getViewPathInfo() const; - /// Ctor - SourceView(SourceFile* sourceFile, SourceRange range, const String* viewPath, SourceLoc initiatingSourceLoc): - m_range(range), - m_sourceFile(sourceFile), - m_initiatingSourceLoc(initiatingSourceLoc) + /// Ctor + SourceView( + SourceFile* sourceFile, + SourceRange range, + const String* viewPath, + SourceLoc initiatingSourceLoc) + : m_range(range), m_sourceFile(sourceFile), m_initiatingSourceLoc(initiatingSourceLoc) { if (viewPath) { @@ -412,116 +480,122 @@ class SourceView } } - protected: - /// Get the pathInfo from a string handle. If it's 0, it will return the _getPathInfo +protected: + /// 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 + 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. + SourceLoc m_initiatingSourceLoc; ///< An optional source loc that defines where this view was + ///< initiated from. SourceLoc(0) if not defined. - SourceRange m_range; ///< The range that this SourceView applies to - SourceFile* m_sourceFile; ///< The source file. Can hold the line breaks - List<Entry> m_entries; ///< An array entries describing how we should interpret a range, starting from the start location. + SourceRange m_range; ///< The range that this SourceView applies to + SourceFile* m_sourceFile; ///< The source file. Can hold the line breaks + List<Entry> m_entries; ///< An array entries describing how we should interpret a range, + ///< starting from the start location. }; struct SourceManager { - // Initialize a source manager, with an optional parent + // Initialize a source manager, with an optional parent void initialize(SourceManager* parent, ISlangFileSystemExt* fileSystemExt); - /// Allocate a range of SourceLoc locations, these can be used to identify a specific location in the source + /// Allocate a range of SourceLoc locations, these can be used to identify a specific location + /// in the source SourceRange allocateSourceRange(UInt size); - /// Returns the loc for start of next allocation + /// Returns the loc for start of next allocation SourceLoc getNextRangeStart() const { return m_nextLoc; } - /// Create a SourceFile defined with the specified path, and content held within a blob + /// Create a SourceFile defined with the specified path, and content held within a blob SourceFile* createSourceFileWithSize(const PathInfo& pathInfo, size_t contentSize); SourceFile* createSourceFileWithString(const PathInfo& pathInfo, const String& contents); SourceFile* createSourceFileWithBlob(const PathInfo& pathInfo, ISlangBlob* blob); - /// Get the humane source location + /// Get the humane source location HumaneSourceLoc getHumaneLoc(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Get the path associated with a location + /// Get the path associated with a location PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Create a new source view from a file - /// @param sourceFile is the source file that contains the source - /// @param pathInfo is path used to read the file from - /// @param initiatingSourceLoc the (optional) location in the source that led the the creation of this view. If there isn't an initiating source location pass SourceLoc(0)s - SourceView* createSourceView(SourceFile* sourceFile, const PathInfo* pathInfo, SourceLoc initiatingSourceLoc); - - /// Find a view by a source file location. - /// If not found in this manager will look in the parent SourceManager - /// Returns nullptr if not found. + /// Create a new source view from a file + /// @param sourceFile is the source file that contains the source + /// @param pathInfo is path used to read the file from + /// @param initiatingSourceLoc the (optional) location in the source that led the the creation + /// of this view. If there isn't an initiating source location pass SourceLoc(0)s + SourceView* createSourceView( + SourceFile* sourceFile, + const PathInfo* pathInfo, + SourceLoc initiatingSourceLoc); + + /// Find a view by a source file location. + /// If not found in this manager will look in the parent SourceManager + /// Returns nullptr if not found. SourceView* findSourceViewRecursively(SourceLoc loc) const; - /// Find the SourceView associated with this manager for a specified location - /// Returns nullptr if not found. + /// Find the SourceView associated with this manager for a specified location + /// Returns nullptr if not found. SourceView* findSourceView(SourceLoc loc) const; - /// Searches this manager, and then the parent to see if can find a match for path. - /// If not found returns nullptr. + /// Searches this manager, and then the parent to see if can find a match for path. + /// If not found returns nullptr. SourceFile* findSourceFileRecursively(const String& uniqueIdentity) const; - /// Find if the source file is defined on this manager. + /// Find if the source file is defined on this manager. SourceFile* findSourceFile(const String& uniqueIdentity) const; - /// Find a source file by path. + /// Find a source file by path. SourceFile* findSourceFileByPath(const String& name) const; - /// Find a source file by path recursively. + /// Find a source file by path recursively. SourceFile* findSourceFileByPathRecursively(const String& name) const; - /// Searches this manager, and then the parent to see if can find a match + /// Searches this manager, and then the parent to see if can find a match SourceFile* findSourceFileByContentRecursively(const char* text); - /// Find the source file that contains *the memory* text points to. + /// Find the source file that contains *the memory* text points to. SourceFile* findSourceFileByContent(const char* text) const; - - /// Get the file system associated with this source manager - ISlangFileSystemExt* getFileSystemExt() const { return m_fileSystemExt; } - /// Get the file system associated with this source manager - void setFileSystemExt(ISlangFileSystemExt* fileSystemExt) { m_fileSystemExt = fileSystemExt; } - /// Add a source file, uniqueIdentity must be unique for this manager AND any parents + /// Get the file system associated with this source manager + ISlangFileSystemExt* getFileSystemExt() const { return m_fileSystemExt; } + /// Get the file system associated with this source manager + void setFileSystemExt(ISlangFileSystemExt* fileSystemExt) { m_fileSystemExt = fileSystemExt; } + + /// Add a source file, uniqueIdentity must be unique for this manager AND any parents void addSourceFile(const String& uniqueIdentity, SourceFile* sourceFile); void addSourceFileIfNotExist(const String& uniqueIdentity, SourceFile* sourceFile); - /// Get the slice pool + /// Get the slice pool StringSlicePool& getStringSlicePool() { return m_slicePool; } - /// Get the source range for just this manager - /// Caution - the range will change if allocations are made to this manager. - SourceRange getSourceRange() const { return SourceRange(m_startLoc, m_nextLoc); } - - /// Get the parent manager to this manager. Returns nullptr if there isn't any. + /// Get the source range for just this manager + /// Caution - the range will change if allocations are made to this manager. + SourceRange getSourceRange() const { return SourceRange(m_startLoc, m_nextLoc); } + + /// Get the parent manager to this manager. Returns nullptr if there isn't any. SourceManager* getParent() const { return m_parent; } - /// A memory arena to hold allocations that are in scope for the same time as SourceManager - MemoryArena* getMemoryArena() { return &m_memoryArena; } + /// A memory arena to hold allocations that are in scope for the same time as SourceManager + MemoryArena* getMemoryArena() { return &m_memoryArena; } - /// Allocate a string slice + /// Allocate a string slice UnownedStringSlice allocateStringSlice(const UnownedStringSlice& slice); - /// Get all of the source files + /// Get all of the source files const List<SourceFile*>& getSourceFiles() const { return m_sourceFiles; } - /// Get the source views + /// Get the source views const List<SourceView*>& getSourceViews() const { return m_sourceViews; } - /// Resets state. Will release all views/source + /// Resets state. Will release all views/source void reset(); - SourceManager() : - m_memoryArena(2048), - m_slicePool(StringSlicePool::Style::Default) - {} + SourceManager() + : m_memoryArena(2048), m_slicePool(StringSlicePool::Style::Default) + { + } ~SourceManager(); - protected: - +protected: void _resetLoc(); void _resetSource(); @@ -536,7 +610,8 @@ struct SourceManager // The location to be used by the next source file to be loaded SourceLoc m_nextLoc; - // All of the SourceViews constructed on this SourceManager. These are held in increasing order of range, so can find by doing a binary chop. + // All of the SourceViews constructed on this SourceManager. These are held in increasing order + // of range, so can find by doing a binary chop. List<SourceView*> m_sourceViews; // All of the SourceFiles constructed on this SourceManager. This owns the SourceFile. List<SourceFile*> m_sourceFiles; diff --git a/source/compiler-core/slang-source-map.cpp b/source/compiler-core/slang-source-map.cpp index 533c6bde0..9c38e876f 100644 --- a/source/compiler-core/slang-source-map.cpp +++ b/source/compiler-core/slang-source-map.cpp @@ -1,6 +1,7 @@ #include "slang-source-map.h" -namespace Slang { +namespace Slang +{ void SourceMap::clear() { @@ -35,7 +36,10 @@ void SourceMap::swapWith(ThisType& rhs) m_slicePool.swapWith(rhs.m_slicePool); } -static bool _areEqual(const List<StringSlicePool::Handle>& a, const List<StringSlicePool::Handle>& b, const List<Index>& bToAMap) +static bool _areEqual( + const List<StringSlicePool::Handle>& a, + const List<StringSlicePool::Handle>& b, + const List<Index>& bToAMap) { const auto count = a.getCount(); if (count != b.getCount()) @@ -57,16 +61,20 @@ static bool _areEqual(const List<StringSlicePool::Handle>& a, const List<StringS return true; } -static bool _areEqual(const SourceMap::Entry& a, const SourceMap::Entry& b, const List<Index>& bToAMap) +static bool _areEqual( + const SourceMap::Entry& a, + const SourceMap::Entry& b, + const List<Index>& bToAMap) { - return a.generatedColumn == b.generatedColumn && - a.sourceLine == b.sourceLine && - a.sourceColumn == b.sourceColumn && - a.sourceFileIndex == bToAMap[b.sourceFileIndex] && - a.nameIndex == bToAMap[b.nameIndex]; + return a.generatedColumn == b.generatedColumn && a.sourceLine == b.sourceLine && + a.sourceColumn == b.sourceColumn && a.sourceFileIndex == bToAMap[b.sourceFileIndex] && + a.nameIndex == bToAMap[b.nameIndex]; } -static bool _areEqual(const List<SourceMap::Entry>& a, const List<SourceMap::Entry>&b, const List<Index>& bToAMap) +static bool _areEqual( + const List<SourceMap::Entry>& a, + const List<SourceMap::Entry>& b, + const List<Index>& bToAMap) { const auto count = a.getCount(); if (count != b.getCount()) @@ -92,8 +100,7 @@ bool SourceMap::operator==(const ThisType& rhs) const return true; } - if (m_file != rhs.m_file || - m_sourceRoot != rhs.m_sourceRoot || + if (m_file != rhs.m_file || m_sourceRoot != rhs.m_sourceRoot || m_lineStarts != rhs.m_lineStarts) { return false; @@ -102,21 +109,19 @@ bool SourceMap::operator==(const ThisType& rhs) const if (m_slicePool == rhs.m_slicePool) { // If the slice pools are the same we can just compare indices directly - return m_sources == rhs.m_sources && - m_sourcesContent == rhs.m_sourcesContent && - m_names == rhs.m_names && - m_lineEntries == rhs.m_lineEntries; + return m_sources == rhs.m_sources && m_sourcesContent == rhs.m_sourcesContent && + m_names == rhs.m_names && m_lineEntries == rhs.m_lineEntries; } else { // Otherwise we need to remap the indices - // Maps a pool handle from the rhs source map to the + // Maps a pool handle from the rhs source map to the List<Index> rhsMap; Count count = rhs.m_slicePool.getSlicesCount(); rhsMap.setCount(count); - + const auto startIndex = rhs.m_slicePool.getFirstAddedIndex(); // Work out the map @@ -128,9 +133,9 @@ bool SourceMap::operator==(const ThisType& rhs) const // Do the comparison taking into account the mapping. return _areEqual(m_sources, rhs.m_sources, rhsMap) && - _areEqual(m_sourcesContent, rhs.m_sourcesContent, rhsMap) && - _areEqual(m_names, rhs.m_names, rhsMap) && - _areEqual(m_lineEntries, rhs.m_lineEntries, rhsMap); + _areEqual(m_sourcesContent, rhs.m_sourcesContent, rhsMap) && + _areEqual(m_names, rhs.m_names, rhsMap) && + _areEqual(m_lineEntries, rhs.m_lineEntries, rhsMap); } } @@ -139,7 +144,7 @@ void SourceMap::advanceToLine(Index nextLineIndex) const Count currentLineIndex = getGeneratedLineCount() - 1; SLANG_ASSERT(nextLineIndex >= currentLineIndex); - + if (nextLineIndex <= currentLineIndex) { return; @@ -147,7 +152,7 @@ void SourceMap::advanceToLine(Index nextLineIndex) const auto lastEntryIndex = m_lineEntries.getCount(); - // For all the new entries they will need to point to the end + // For all the new entries they will need to point to the end m_lineStarts.growToCount(nextLineIndex + 1); Index* starts = m_lineStarts.getBuffer(); diff --git a/source/compiler-core/slang-source-map.h b/source/compiler-core/slang-source-map.h index 4060fadb8..73952225a 100644 --- a/source/compiler-core/slang-source-map.h +++ b/source/compiler-core/slang-source-map.h @@ -1,21 +1,20 @@ #ifndef SLANG_COMPILER_CORE_SOURCE_MAP_H #define SLANG_COMPILER_CORE_SOURCE_MAP_H -#include "slang.h" - -#include "../core/slang-string.h" #include "../core/slang-list.h" - #include "../core/slang-string-slice-pool.h" +#include "../core/slang-string.h" +#include "slang.h" -namespace Slang { +namespace Slang +{ -class SourceMap +class SourceMap { public: typedef SourceMap ThisType; - SLANG_CLASS_GUID(0x731383ea, 0xe516, 0x4cc3, { 0xa6, 0xcf, 0x37, 0xd2, 0x8c, 0x24, 0x5c, 0x5e }); + SLANG_CLASS_GUID(0x731383ea, 0xe516, 0x4cc3, {0xa6, 0xcf, 0x37, 0xd2, 0x8c, 0x24, 0x5c, 0x5e}); struct Entry { @@ -33,73 +32,71 @@ public: bool operator==(const ThisType& rhs) const { return generatedColumn == rhs.generatedColumn && - sourceFileIndex == rhs.sourceFileIndex && - sourceLine == rhs.sourceLine && - sourceColumn == rhs.sourceColumn && - nameIndex == rhs.nameIndex; + sourceFileIndex == rhs.sourceFileIndex && sourceLine == rhs.sourceLine && + sourceColumn == rhs.sourceColumn && nameIndex == rhs.nameIndex; } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } // Note! All column/line are zero indexed - Index generatedColumn; ///< The generated column - Index sourceFileIndex; ///< The index into the source name/contents - Index sourceLine; ///< The line number in the originating source - Index sourceColumn; ///< The column number in the originating source - Index nameIndex; ///< Name index + Index generatedColumn; ///< The generated column + Index sourceFileIndex; ///< The index into the source name/contents + Index sourceLine; ///< The line number in the originating source + Index sourceColumn; ///< The column number in the originating source + Index nameIndex; ///< Name index }; - /// Get the total number of generated lines + /// Get the total number of generated lines Count getGeneratedLineCount() const { return m_lineStarts.getCount(); } - /// Get the entries on the line + /// Get the entries on the line SLANG_FORCE_INLINE ConstArrayView<Entry> getEntriesForLine(Index generatedLine) const; - - /// Advance to the specified line index. - /// It is an error to specify a line *before* the current line. It should either be the current - /// output line or a later output line. Interveining lines will be set as empty + + /// Advance to the specified line index. + /// It is an error to specify a line *before* the current line. It should either be the current + /// output line or a later output line. Interveining lines will be set as empty void advanceToLine(Index lineIndex); - /// Add an entry to the current line + /// Add an entry to the current line void addEntry(const Entry& entry) { m_lineEntries.add(entry); } - /// Given the slice returns the index + /// Given the slice returns the index Index getSourceFileIndex(const UnownedStringSlice& slice); - /// Get the name index + /// Get the name index Index getNameIndex(const UnownedStringSlice& slice); - /// Given a row and col index, find the closest entry - /// NOTE! Zero indexed line and column. + /// Given a row and col index, find the closest entry + /// NOTE! Zero indexed line and column. Index findEntry(Index lineIndex, Index colIndex) const; - /// Given an entry index return the entry - const Entry& getEntryByIndex(Index i) const {return m_lineEntries[i]; } + /// Given an entry index return the entry + const Entry& getEntryByIndex(Index i) const { return m_lineEntries[i]; } - /// Given the sourceFileIndex return the name + /// Given the sourceFileIndex return the name UnownedStringSlice getSourceFileName(Index sourceFileIndex) const; - /// Clear the contents of the source map + /// Clear the contents of the source map void clear(); - /// Swap this with rhs + /// Swap this with rhs void swapWith(ThisType& rhs); - /// == - /// - /// Note that equality requires that entries for a line must be *in the same order* - /// even though strictly speaking with different orders could be considered equivalent. + /// == + /// + /// Note that equality requires that entries for a line must be *in the same order* + /// even though strictly speaking with different orders could be considered equivalent. bool operator==(const ThisType& rhs) const; - /// != + /// != bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Ctor - SourceMap(): - m_slicePool(StringSlicePool::Style::Default) + /// Ctor + SourceMap() + : m_slicePool(StringSlicePool::Style::Default) { clear(); } - /// Copy Ctor + /// Copy Ctor SourceMap(const ThisType& rhs) = default; - /// Assignment + /// Assignment ThisType& operator=(const ThisType& rhs) = default; String m_file; @@ -107,10 +104,10 @@ public: List<StringSlicePool::Handle> m_sources; - /// Storage for the contents. Can be unset null to indicate not set. + /// Storage for the contents. Can be unset null to indicate not set. List<StringSlicePool::Handle> m_sourcesContent; - - /// The names + + /// The names List<StringSlicePool::Handle> m_names; List<Index> m_lineStarts; @@ -120,13 +117,16 @@ public: }; // ------------------------------------------------------------- -SLANG_FORCE_INLINE ConstArrayView<SourceMap::Entry> SourceMap::getEntriesForLine(Index generatedLine) const +SLANG_FORCE_INLINE ConstArrayView<SourceMap::Entry> SourceMap::getEntriesForLine( + Index generatedLine) const { SLANG_ASSERT(generatedLine >= 0 && generatedLine < m_lineStarts.getCount()); const Index start = m_lineStarts[generatedLine]; - const Index end = (generatedLine + 1 >= m_lineStarts.getCount()) ? m_lineEntries.getCount() : m_lineStarts[generatedLine + 1]; + const Index end = (generatedLine + 1 >= m_lineStarts.getCount()) + ? m_lineEntries.getCount() + : m_lineStarts[generatedLine + 1]; const auto entries = m_lineEntries.begin(); diff --git a/source/compiler-core/slang-spirv-core-grammar.cpp b/source/compiler-core/slang-spirv-core-grammar.cpp index 0660954fa..8b5e79071 100644 --- a/source/compiler-core/slang-spirv-core-grammar.cpp +++ b/source/compiler-core/slang-spirv-core-grammar.cpp @@ -2,8 +2,9 @@ #include "../core/slang-rtti-util.h" #include "../core/slang-string-util.h" -#include "slang-json-native.h" #include "slang-core-diagnostics.h" +#include "slang-json-native.h" + #include <limits> namespace Slang @@ -22,8 +23,7 @@ struct InstructionPrintingClass SLANG_MAKE_STRUCT_RTTI_INFO( InstructionPrintingClass, SLANG_RTTI_FIELD(tag), - SLANG_OPTIONAL_RTTI_FIELD(heading) -); + SLANG_OPTIONAL_RTTI_FIELD(heading)); struct Operand { @@ -35,7 +35,7 @@ SLANG_MAKE_STRUCT_RTTI_INFO( Operand, SLANG_RTTI_FIELD(kind), SLANG_OPTIONAL_RTTI_FIELD(quantifier) - //SLANG_RTTI_FIELD(name), + // SLANG_RTTI_FIELD(name), ); struct Instruction @@ -52,8 +52,7 @@ SLANG_MAKE_STRUCT_RTTI_INFO( SLANG_RTTI_FIELD_IMPL(class_, "class", 0), SLANG_RTTI_FIELD(opcode), SLANG_OPTIONAL_RTTI_FIELD(capabilities), - SLANG_OPTIONAL_RTTI_FIELD(operands) -); + SLANG_OPTIONAL_RTTI_FIELD(operands)); struct Enumerant { @@ -88,8 +87,7 @@ SLANG_MAKE_STRUCT_RTTI_INFO( OperandKind, SLANG_RTTI_FIELD(category), SLANG_RTTI_FIELD(kind), - SLANG_OPTIONAL_RTTI_FIELD(enumerants) -); + SLANG_OPTIONAL_RTTI_FIELD(enumerants)); struct SPIRVSpec { @@ -111,47 +109,44 @@ SLANG_MAKE_STRUCT_RTTI_INFO( // SLANG_RTTI_FIELD(revision) SLANG_RTTI_FIELD(instruction_printing_class), SLANG_RTTI_FIELD(instructions), - SLANG_RTTI_FIELD(operand_kinds) -); + SLANG_RTTI_FIELD(operand_kinds)); static Dictionary<UnownedStringSlice, SpvWord> operandKindToDict( - JSONContainer& container, - DiagnosticSink& sink, - const OperandKind& k) + JSONContainer& container, + DiagnosticSink& sink, + const OperandKind& k) { Dictionary<UnownedStringSlice, SpvWord> dict; dict.reserve(k.enumerants.getCount()); - for(const auto& e : k.enumerants) + for (const auto& e : k.enumerants) { SpvWord valueInt = 0; - switch(e.value.getKind()) + switch (e.value.getKind()) { - case JSONValue::Kind::Integer: + case JSONValue::Kind::Integer: { // TODO: Range check here? valueInt = SpvWord(container.asInteger(e.value)); break; } - case JSONValue::Kind::String: + case JSONValue::Kind::String: { Int i = 0; const auto str = container.getString(e.value); - if(SLANG_FAILED(StringUtil::parseInt(str, i))) + if (SLANG_FAILED(StringUtil::parseInt(str, i))) sink.diagnose( e.value.loc, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Expected an integer value" - ); + "Expected an integer value"); // TODO: Range check here? valueInt = SpvWord(i); break; - } - default: - sink.diagnose( - e.value.loc, - MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Expected an integer value (or a string with an integer inside)" - ); + } + default: + sink.diagnose( + e.value.loc, + MiscDiagnostics::spirvCoreGrammarJSONParseFailure, + "Expected an integer value (or a string with an integer inside)"); } dict.add(e.enumerant, valueInt); @@ -166,7 +161,9 @@ static Dictionary<UnownedStringSlice, SpvWord> operandKindToDict( // // // -RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& source, DiagnosticSink& sink) +RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON( + SourceView& source, + DiagnosticSink& sink) { // // Load the JSON @@ -182,14 +179,13 @@ RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour SLANG_RETURN_NULL_ON_FAIL(parser.parse(&lexer, &source, &builder, &sink)); JSONToNativeConverter converter(&container, &typeMap, &sink); SPIRVSpec spec; - if(SLANG_FAILED(converter.convert(builder.getRootValue(), &spec))) + if (SLANG_FAILED(converter.convert(builder.getRootValue(), &spec))) { // TODO: not having a source loc here is not great... sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Failed to match SPIR-V grammar JSON to the expected schema" - ); + "Failed to match SPIR-V grammar JSON to the expected schema"); return nullptr; } @@ -200,42 +196,42 @@ RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour res->operandKinds.dict.reserve(spec.operand_kinds.getCount()); uint32_t operandKindIndex = 0; - for(const auto& c : spec.operand_kinds) + for (const auto& c : spec.operand_kinds) { - if(operandKindIndex > std::numeric_limits<decltype(OperandKind::index)>::max()) + if (operandKindIndex > std::numeric_limits<decltype(OperandKind::index)>::max()) { sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Too many enum categories, expected fewer than 256" - ); + "Too many enum categories, expected fewer than 256"); } - res->operandKinds.dict.add(c.kind, {static_cast<decltype(OperandKind::index)>(operandKindIndex)}); + res->operandKinds.dict.add( + c.kind, + {static_cast<decltype(OperandKind::index)>(operandKindIndex)}); operandKindIndex++; } // It's important we reserve the memory now, as we require the iterators to // be stable, as references to them are maintained by the OpInfo structs. Index totalNumOperands = 0; - for(const auto& i : spec.instructions) + for (const auto& i : spec.instructions) totalNumOperands += i.operands.getCapacity(); res->operandTypesStorage.reserve(totalNumOperands); res->opcodes.dict.reserve(spec.instructions.getCount()); - for(const auto& i : spec.instructions) + for (const auto& i : spec.instructions) { res->opcodes.dict.add(i.opname, SpvOp(i.opcode)); - const auto class_ = - i.class_ == "Type-Declaration" ? OpInfo::TypeDeclaration - : i.class_ == "Constant-Creation" ? OpInfo::ConstantCreation - : i.class_ == "Debug" ? OpInfo::Debug - : OpInfo::Other; + const auto class_ = i.class_ == "Type-Declaration" ? OpInfo::TypeDeclaration + : i.class_ == "Constant-Creation" ? OpInfo::ConstantCreation + : i.class_ == "Debug" ? OpInfo::Debug + : OpInfo::Other; - const auto resultTypeIndex - = i.operands.findFirstIndex([](const auto& o){return o.kind == "IdResultType";}); - const auto resultIdIndex - = i.operands.findFirstIndex([](const auto& o){return o.kind == "IdResult";}); + const auto resultTypeIndex = + i.operands.findFirstIndex([](const auto& o) { return o.kind == "IdResultType"; }); + const auto resultIdIndex = + i.operands.findFirstIndex([](const auto& o) { return o.kind == "IdResult"; }); SLANG_ASSERT(resultTypeIndex >= -1 || resultTypeIndex <= 0); SLANG_ASSERT(resultIdIndex >= -1 || resultTypeIndex <= 1); @@ -243,9 +239,9 @@ RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour uint16_t maxOperandCount = 0; uint16_t numOperandTypes = 0; const OperandKind* operandTypes = res->operandTypesStorage.end(); - for(const auto& o : i.operands) + for (const auto& o : i.operands) { - if(maxOperandCount == 0xffff) + if (maxOperandCount == 0xffff) { // We are about to overflow maxWordCount, either someone has // put 2^16 operands in the json, or we have a "*" quantified @@ -254,18 +250,16 @@ RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "\"*\"-qualified operand wasn't the last operand" - ); + "\"*\"-qualified operand wasn't the last operand"); } const auto catIndex = res->operandKinds.lookup(o.kind); - if(!catIndex) + if (!catIndex) { sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Operand references a kind which doesn't exist" - ); + "Operand references a kind which doesn't exist"); continue; } @@ -274,24 +268,23 @@ RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour // The number of "ImageOperands" is dependent on the bitmask // operand, for our purposes treat them as unbounded - if(o.quantifier == "*" || o.kind == "ImageOperands") + if (o.quantifier == "*" || o.kind == "ImageOperands") { maxOperandCount = 0xffff; } - else if(o.quantifier == "?") + else if (o.quantifier == "?") { maxOperandCount++; } - else if(o.quantifier == "") + else if (o.quantifier == "") { // This catches the case where an "?" or "*" qualified operand // appears before any unqualified operands - if(minOperandCount != maxOperandCount) + if (minOperandCount != maxOperandCount) sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "\"*\" or \"?\" operand appeared before an unqualified operand" - ); + "\"*\" or \"?\" operand appeared before an unqualified operand"); minOperandCount++; maxOperandCount++; } @@ -300,31 +293,30 @@ RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour sink.diagnose( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "quantifier wasn't empty, * or ?" - ); + "quantifier wasn't empty, * or ?"); } } // There are duplicate opcodes in the json (for renamed instructions, // or the same instruction with different capabilities), for now just // keep the first one. - res->opInfos.dict.addIfNotExists(SpvOp(i.opcode), { - class_, - static_cast<int8_t>(resultTypeIndex), - static_cast<int8_t>(resultIdIndex), - minOperandCount, - maxOperandCount, - numOperandTypes, - operandTypes - }); + res->opInfos.dict.addIfNotExists( + SpvOp(i.opcode), + {class_, + static_cast<int8_t>(resultTypeIndex), + static_cast<int8_t>(resultIdIndex), + minOperandCount, + maxOperandCount, + numOperandTypes, + operandTypes}); res->opNames.dict.addIfNotExists(SpvOp(i.opcode), i.opname); } - for(const auto& k : spec.operand_kinds) + for (const auto& k : spec.operand_kinds) { const auto kindIndex = res->operandKinds.dict.getValue(k.kind); const auto d = operandKindToDict(container, sink, k); - for(const auto& [n, v] : d) + for (const auto& [n, v] : d) { // Add the string to this slice pool as we'll be taking ownership // of it shortly but don't want to invalidate it in the meantime. @@ -336,17 +328,17 @@ RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour res->operandKindNames.dict.add(kindIndex, k.kind); - if(k.kind == "Capability") - for(const auto& [n, v] : d) + if (k.kind == "Capability") + for (const auto& [n, v] : d) res->capabilities.dict.add(n, SpvCapability(v)); // If this starts with Id, and the suffix is also an operand kind, // assume that this is an Id wrapper - if(k.kind.startsWith("Id")) + if (k.kind.startsWith("Id")) { - const UnownedStringSlice underneathIdKind{k.kind.begin()+2, k.kind.end()}; + const UnownedStringSlice underneathIdKind{k.kind.begin() + 2, k.kind.end()}; OperandKind targetIndex; - if(res->operandKinds.dict.tryGetValue(underneathIdKind, targetIndex)) + if (res->operandKinds.dict.tryGetValue(underneathIdKind, targetIndex)) res->operandKindUnderneathIds.dict.add(kindIndex, targetIndex); } } @@ -354,4 +346,4 @@ RefPtr<SPIRVCoreGrammarInfo> SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour res->strings.swapWith(container.getStringSlicePool()); return res; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-spirv-core-grammar.h b/source/compiler-core/slang-spirv-core-grammar.h index d78a339f1..e91caa79a 100644 --- a/source/compiler-core/slang-spirv-core-grammar.h +++ b/source/compiler-core/slang-spirv-core-grammar.h @@ -1,148 +1,147 @@ #pragma once +#include "../core/slang-dictionary.h" #include "../core/slang-smart-pointer.h" -#include "../core/slang-string.h" #include "../core/slang-string-slice-pool.h" -#include "../core/slang-dictionary.h" - -#include <spirv/unified1/spirv.h> +#include "../core/slang-string.h" #include <optional> +#include <spirv/unified1/spirv.h> namespace Slang { - using SpvWord = uint32_t; - class DiagnosticSink; - class SourceView; +using SpvWord = uint32_t; +class DiagnosticSink; +class SourceView; - struct SPIRVCoreGrammarInfo : public RefObject - { - static RefPtr<SPIRVCoreGrammarInfo> loadFromJSON(SourceView& source, DiagnosticSink& sink); - static RefPtr<SPIRVCoreGrammarInfo>& getEmbeddedVersion(); - static inline void freeEmbeddedGrammerInfo() { getEmbeddedVersion() = nullptr; } +struct SPIRVCoreGrammarInfo : public RefObject +{ + static RefPtr<SPIRVCoreGrammarInfo> loadFromJSON(SourceView& source, DiagnosticSink& sink); + static RefPtr<SPIRVCoreGrammarInfo>& getEmbeddedVersion(); + static inline void freeEmbeddedGrammerInfo() { getEmbeddedVersion() = nullptr; } - template<typename K, typename T> - struct Lookup + template<typename K, typename T> + struct Lookup + { + std::optional<T> lookup(const K& name) const { - std::optional<T> lookup(const K& name) const - { - T ret; - if(embedded ? embedded(name, ret) : dict.tryGetValue(name, ret)) - return ret; - else - return std::nullopt; - } - - bool (*embedded)(const K&, T&) = nullptr; - Dictionary<K, T> dict; - }; + T ret; + if (embedded ? embedded(name, ret) : dict.tryGetValue(name, ret)) + return ret; + else + return std::nullopt; + } + + bool (*embedded)(const K&, T&) = nullptr; + Dictionary<K, T> dict; + }; - struct OperandKind - { - uint8_t index; - SLANG_COMPONENTWISE_HASHABLE_1; - SLANG_COMPONENTWISE_EQUALITY_1(OperandKind); - }; + struct OperandKind + { + uint8_t index; + SLANG_COMPONENTWISE_HASHABLE_1; + SLANG_COMPONENTWISE_EQUALITY_1(OperandKind); + }; - struct QualifiedEnumName - { - OperandKind kind; - UnownedStringSlice name; - SLANG_COMPONENTWISE_HASHABLE_2; - SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumName); - }; + struct QualifiedEnumName + { + OperandKind kind; + UnownedStringSlice name; + SLANG_COMPONENTWISE_HASHABLE_2; + SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumName); + }; - struct QualifiedEnumValue - { - OperandKind kind; - SpvWord value; - SLANG_COMPONENTWISE_HASHABLE_2; - SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumValue); - }; + struct QualifiedEnumValue + { + OperandKind kind; + SpvWord value; + SLANG_COMPONENTWISE_HASHABLE_2; + SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumValue); + }; - struct OpInfo + struct OpInfo + { + enum Class { - enum Class - { - // Unrecognized instructions go in here - Other, - - // Adding to this? Don't forget to update the embedding generator - Miscellaneous, - Debug, - Annotation, - Extension, - ModeSetting, - TypeDeclaration, - ConstantCreation, - Memory, - Function, - Image, - Conversion, - Composite, - Arithmetic, - Bit, - Relational_and_Logical, - Derivative, - ControlFlow, - Atomic, - Primitive, - Barrier, - Group, - DeviceSideEnqueue, - Pipe, - NonUniform, - Reserved, - }; - constexpr static int8_t kNoResultTypeId = -1; - constexpr static int8_t kNoResultId = -1; - - Class class_; - // -1 or 0 - int8_t resultTypeIndex = kNoResultTypeId; - // -1 or 0 or 1 - int8_t resultIdIndex = kNoResultId; - // The range of valid operand counts for this instruction, - // including any result type and id. Multi-word operands count as a - // single operand. - uint16_t minOperandCount; - uint16_t maxOperandCount; - // when looking up an operand type, clamp to this number-1 to - // account for variable length operands at the end - uint16_t numOperandTypes; - const OperandKind* operandTypes; + // Unrecognized instructions go in here + Other, + + // Adding to this? Don't forget to update the embedding generator + Miscellaneous, + Debug, + Annotation, + Extension, + ModeSetting, + TypeDeclaration, + ConstantCreation, + Memory, + Function, + Image, + Conversion, + Composite, + Arithmetic, + Bit, + Relational_and_Logical, + Derivative, + ControlFlow, + Atomic, + Primitive, + Barrier, + Group, + DeviceSideEnqueue, + Pipe, + NonUniform, + Reserved, }; - - // - // Our tables: - // - - // Instruction name to opcode - Lookup<UnownedStringSlice, SpvOp> opcodes; - // Capability name to value - Lookup<UnownedStringSlice, SpvCapability> capabilities; - // String-qualified enum name (one with the type prefix) to value - Lookup<UnownedStringSlice, SpvWord> allEnumsWithTypePrefix; - // kind * enum name to value - Lookup<QualifiedEnumName, SpvWord> allEnums; - // kine * enum value to unqualified name - Lookup<QualifiedEnumValue, UnownedStringSlice> allEnumNames; - // Any other information on instructions - Lookup<SpvOp, OpInfo> opInfos; - // Opcode to instruction name - Lookup<SpvOp, UnownedStringSlice> opNames; - // Operand kind string to numeric id - Lookup<UnownedStringSlice, OperandKind> operandKinds; - // Operand kind id to string - Lookup<OperandKind, UnownedStringSlice> operandKindNames; - // Operand kind to the "un-id" version of itself, for example IdMemorySemantics to MemorySemantics - Lookup<OperandKind, OperandKind> operandKindUnderneathIds; - - private: - - // If this is loaded from JSON, we keep the strings around instead of - // copying them as dictionary keys - StringSlicePool strings = StringSlicePool(StringSlicePool::Style::Empty); - List<OperandKind> operandTypesStorage; + constexpr static int8_t kNoResultTypeId = -1; + constexpr static int8_t kNoResultId = -1; + + Class class_; + // -1 or 0 + int8_t resultTypeIndex = kNoResultTypeId; + // -1 or 0 or 1 + int8_t resultIdIndex = kNoResultId; + // The range of valid operand counts for this instruction, + // including any result type and id. Multi-word operands count as a + // single operand. + uint16_t minOperandCount; + uint16_t maxOperandCount; + // when looking up an operand type, clamp to this number-1 to + // account for variable length operands at the end + uint16_t numOperandTypes; + const OperandKind* operandTypes; }; -} + + // + // Our tables: + // + + // Instruction name to opcode + Lookup<UnownedStringSlice, SpvOp> opcodes; + // Capability name to value + Lookup<UnownedStringSlice, SpvCapability> capabilities; + // String-qualified enum name (one with the type prefix) to value + Lookup<UnownedStringSlice, SpvWord> allEnumsWithTypePrefix; + // kind * enum name to value + Lookup<QualifiedEnumName, SpvWord> allEnums; + // kine * enum value to unqualified name + Lookup<QualifiedEnumValue, UnownedStringSlice> allEnumNames; + // Any other information on instructions + Lookup<SpvOp, OpInfo> opInfos; + // Opcode to instruction name + Lookup<SpvOp, UnownedStringSlice> opNames; + // Operand kind string to numeric id + Lookup<UnownedStringSlice, OperandKind> operandKinds; + // Operand kind id to string + Lookup<OperandKind, UnownedStringSlice> operandKindNames; + // Operand kind to the "un-id" version of itself, for example IdMemorySemantics to + // MemorySemantics + Lookup<OperandKind, OperandKind> operandKindUnderneathIds; + +private: + // If this is loaded from JSON, we keep the strings around instead of + // copying them as dictionary keys + StringSlicePool strings = StringSlicePool(StringSlicePool::Style::Empty); + List<OperandKind> operandTypesStorage; +}; +} // namespace Slang diff --git a/source/compiler-core/slang-test-server-protocol.cpp b/source/compiler-core/slang-test-server-protocol.cpp index 2a3bb3a3b..248c6a07a 100644 --- a/source/compiler-core/slang-test-server-protocol.cpp +++ b/source/compiler-core/slang-test-server-protocol.cpp @@ -1,6 +1,7 @@ #include "slang-test-server-protocol.h" -namespace TestServerProtocol { +namespace TestServerProtocol +{ static const StructRttiInfo _makeExecuteUnitTestArgsRtti() { @@ -12,8 +13,9 @@ static const StructRttiInfo _makeExecuteUnitTestArgsRtti() builder.addField("enabledApis", &obj.enabledApis); return builder.make(); } -/* static */const UnownedStringSlice ExecuteUnitTestArgs::g_methodName = UnownedStringSlice::fromLiteral("unitTest"); -/* static */const StructRttiInfo ExecuteUnitTestArgs::g_rttiInfo = _makeExecuteUnitTestArgsRtti(); +/* static */ const UnownedStringSlice ExecuteUnitTestArgs::g_methodName = + UnownedStringSlice::fromLiteral("unitTest"); +/* static */ const StructRttiInfo ExecuteUnitTestArgs::g_rttiInfo = _makeExecuteUnitTestArgsRtti(); static const StructRttiInfo _makeExecuteToolTestArgsRtti() { @@ -23,8 +25,9 @@ static const StructRttiInfo _makeExecuteToolTestArgsRtti() builder.addField("args", &obj.args); return builder.make(); } -/* static */const StructRttiInfo ExecuteToolTestArgs::g_rttiInfo = _makeExecuteToolTestArgsRtti(); -/* static */const UnownedStringSlice ExecuteToolTestArgs::g_methodName = UnownedStringSlice::fromLiteral("tool"); +/* static */ const StructRttiInfo ExecuteToolTestArgs::g_rttiInfo = _makeExecuteToolTestArgsRtti(); +/* static */ const UnownedStringSlice ExecuteToolTestArgs::g_methodName = + UnownedStringSlice::fromLiteral("tool"); static const StructRttiInfo _makeExecutionResultRtti() { @@ -36,8 +39,9 @@ static const StructRttiInfo _makeExecutionResultRtti() builder.addField("returnCode", &obj.returnCode); return builder.make(); } -/* static */const StructRttiInfo ExecutionResult::g_rttiInfo = _makeExecutionResultRtti(); +/* static */ const StructRttiInfo ExecutionResult::g_rttiInfo = _makeExecutionResultRtti(); -/* static */const UnownedStringSlice QuitArgs::g_methodName = UnownedStringSlice::fromLiteral("quit"); +/* static */ const UnownedStringSlice QuitArgs::g_methodName = + UnownedStringSlice::fromLiteral("quit"); } // namespace TestServerProtocol diff --git a/source/compiler-core/slang-test-server-protocol.h b/source/compiler-core/slang-test-server-protocol.h index b74a1a872..a15e19701 100644 --- a/source/compiler-core/slang-test-server-protocol.h +++ b/source/compiler-core/slang-test-server-protocol.h @@ -1,14 +1,14 @@ #ifndef SLANG_COMPILER_CORE_TEST_PROTOCOL_H #define SLANG_COMPILER_CORE_TEST_PROTOCOL_H -#include "slang.h" +#include "../core/slang-rtti-info.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" - -#include "../core/slang-rtti-info.h" #include "slang-json-value.h" +#include "slang.h" -namespace TestServerProtocol { +namespace TestServerProtocol +{ using namespace Slang; @@ -24,8 +24,9 @@ struct ExecuteUnitTestArgs struct ExecuteToolTestArgs { - String toolName; ///< The name of the tool (will be a shared library typically - like render-test). Doesn't need -tool suffix. - List<String> args; ///< Arguments passed to the tool during exectution + String toolName; ///< The name of the tool (will be a shared library typically - like + ///< render-test). Doesn't need -tool suffix. + List<String> args; ///< Arguments passed to the tool during exectution static const UnownedStringSlice g_methodName; static const StructRttiInfo g_rttiInfo; @@ -41,11 +42,11 @@ struct ExecutionResult String stdOut; String stdError; int32_t result = SLANG_OK; - int32_t returnCode = 0; ///< As returned if invoked as command line + int32_t returnCode = 0; ///< As returned if invoked as command line static const StructRttiInfo g_rttiInfo; }; -} // namespace Slang +} // namespace TestServerProtocol #endif // SLANG_COMPILER_CORE_TEST_PROTOCOL_H diff --git a/source/compiler-core/slang-tint-compiler.cpp b/source/compiler-core/slang-tint-compiler.cpp index 6319ecf9f..c656f9ba1 100644 --- a/source/compiler-core/slang-tint-compiler.cpp +++ b/source/compiler-core/slang-tint-compiler.cpp @@ -1,164 +1,152 @@ #include "slang-tint-compiler.h" -#include "slang-artifact-associated-impl.h" - #include "../../external/slang-tint-headers/slang-tint.h" +#include "slang-artifact-associated-impl.h" namespace Slang { - class TintDownstreamCompiler : public DownstreamCompilerBase - { - - public: - - // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile( - const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert( - const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; +class TintDownstreamCompiler : public DownstreamCompilerBase +{ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert( - IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) - SLANG_OVERRIDE; +public: + // IDownstreamCompiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE - { - return false; - } + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString( - slang::IBlob** outVersionString) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; - SlangResult compile(IArtifact *const sourceArtifact, IArtifact** outArtifact); + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - SlangResult init(ISlangSharedLibrary* library); + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) + SLANG_OVERRIDE; - protected: + SlangResult compile(IArtifact* const sourceArtifact, IArtifact** outArtifact); - ComPtr<ISlangSharedLibrary> m_sharedLibrary; + SlangResult init(ISlangSharedLibrary* library); - private: +protected: + ComPtr<ISlangSharedLibrary> m_sharedLibrary; - tint_CompileFunc m_compile; - tint_FreeResultFunc m_freeResult; - }; +private: + tint_CompileFunc m_compile; + tint_FreeResultFunc m_freeResult; +}; - SlangResult TintDownstreamCompiler::init(ISlangSharedLibrary* library) +SlangResult TintDownstreamCompiler::init(ISlangSharedLibrary* library) +{ + tint_CompileFunc compile = (tint_CompileFunc)library->findFuncByName("tint_compile"); + if (compile == nullptr) { - tint_CompileFunc compile = - (tint_CompileFunc)library->findFuncByName("tint_compile"); - if (compile == nullptr) - { - return SLANG_FAIL; - } - - tint_FreeResultFunc freeResult = - (tint_FreeResultFunc)library->findFuncByName("tint_free_result"); - if (freeResult == nullptr) - { - return SLANG_FAIL; - } - - m_sharedLibrary = library; - m_desc = Desc(SLANG_PASS_THROUGH_TINT); - m_compile = compile; - m_freeResult = freeResult; - return SLANG_OK; + return SLANG_FAIL; } - SlangResult TintDownstreamCompilerUtil::locateCompilers( - const String& path, - ISlangSharedLibraryLoader* loader, - DownstreamCompilerSet* set) + tint_FreeResultFunc freeResult = + (tint_FreeResultFunc)library->findFuncByName("tint_free_result"); + if (freeResult == nullptr) { - ComPtr<ISlangSharedLibrary> library; - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary( - path, loader, nullptr, "slang-tint", library)); - SLANG_ASSERT(library); - - ComPtr<IDownstreamCompiler> compiler = ComPtr<IDownstreamCompiler>( - new TintDownstreamCompiler()); - SLANG_RETURN_ON_FAIL(static_cast<TintDownstreamCompiler*>( - compiler.get())->init(library)); - - set->addCompiler(compiler); - return SLANG_OK; + return SLANG_FAIL; } - SlangResult TintDownstreamCompiler::compile( - const CompileOptions& options, IArtifact** outArtifact) - { - IArtifact * sourceArtifact = options.sourceArtifacts[0]; - return compile(sourceArtifact, outArtifact); - } + m_sharedLibrary = library; + m_desc = Desc(SLANG_PASS_THROUGH_TINT); + m_compile = compile; + m_freeResult = freeResult; + return SLANG_OK; +} - SlangResult TintDownstreamCompiler::compile( - IArtifact *const sourceArtifact, IArtifact** outArtifact) - { - tint_CompileRequest req = {}; - - if (sourceArtifact == nullptr) - return SLANG_FAIL; - - ComPtr<ISlangBlob> sourceBlob; - SLANG_RETURN_FALSE_ON_FAIL(sourceArtifact->loadBlob( - ArtifactKeep::Yes, sourceBlob.writeRef())); - - String wgslCode( - (char*)sourceBlob->getBufferPointer(), - (char*)sourceBlob->getBufferPointer() + sourceBlob->getBufferSize()); - req.wgslCode = wgslCode.begin(); - req.wgslCodeLength = wgslCode.getLength(); - - tint_CompileResult result = {}; - SLANG_DEFER(m_freeResult(&result)); - bool compileSucceeded = m_compile(&req, &result) == 0; - - ComPtr<ISlangBlob> spirvBlob = RawBlob::create(result.buffer, result.bufferSize); - result.buffer = nullptr; - - ComPtr<IArtifact> resultArtifact = ArtifactUtil::createArtifactForCompileTarget( - SlangCompileTarget::SLANG_WGSL_SPIRV); - auto diagnostics = ArtifactDiagnostics::create(); - diagnostics->setResult(compileSucceeded ? SLANG_OK : SLANG_FAIL); - ArtifactUtil::addAssociated(resultArtifact, diagnostics); - if (compileSucceeded) - { - resultArtifact->addRepresentationUnknown(spirvBlob); - } - else - { - diagnostics->setRaw(CharSlice(result.error)); - diagnostics->requireErrorDiagnostic(); - } - - *outArtifact = resultArtifact.detach(); - return SLANG_OK; - } +SlangResult TintDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) +{ + ComPtr<ISlangSharedLibrary> library; + SLANG_RETURN_ON_FAIL( + DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-tint", library)); + SLANG_ASSERT(library); - bool TintDownstreamCompiler::canConvert( - const ArtifactDesc& from, const ArtifactDesc& to) + ComPtr<IDownstreamCompiler> compiler = + ComPtr<IDownstreamCompiler>(new TintDownstreamCompiler()); + SLANG_RETURN_ON_FAIL(static_cast<TintDownstreamCompiler*>(compiler.get())->init(library)); + + set->addCompiler(compiler); + return SLANG_OK; +} + +SlangResult TintDownstreamCompiler::compile(const CompileOptions& options, IArtifact** outArtifact) +{ + IArtifact* sourceArtifact = options.sourceArtifacts[0]; + return compile(sourceArtifact, outArtifact); +} + +SlangResult TintDownstreamCompiler::compile( + IArtifact* const sourceArtifact, + IArtifact** outArtifact) +{ + tint_CompileRequest req = {}; + + if (sourceArtifact == nullptr) + return SLANG_FAIL; + + ComPtr<ISlangBlob> sourceBlob; + SLANG_RETURN_FALSE_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef())); + + String wgslCode( + (char*)sourceBlob->getBufferPointer(), + (char*)sourceBlob->getBufferPointer() + sourceBlob->getBufferSize()); + req.wgslCode = wgslCode.begin(); + req.wgslCodeLength = wgslCode.getLength(); + + tint_CompileResult result = {}; + SLANG_DEFER(m_freeResult(&result)); + bool compileSucceeded = m_compile(&req, &result) == 0; + + ComPtr<ISlangBlob> spirvBlob = RawBlob::create(result.buffer, result.bufferSize); + result.buffer = nullptr; + + ComPtr<IArtifact> resultArtifact = + ArtifactUtil::createArtifactForCompileTarget(SlangCompileTarget::SLANG_WGSL_SPIRV); + auto diagnostics = ArtifactDiagnostics::create(); + diagnostics->setResult(compileSucceeded ? SLANG_OK : SLANG_FAIL); + ArtifactUtil::addAssociated(resultArtifact, diagnostics); + if (compileSucceeded) { - return (from.payload == ArtifactPayload::WGSL) && - (to.payload == ArtifactPayload::SPIRV); + resultArtifact->addRepresentationUnknown(spirvBlob); } - - SlangResult TintDownstreamCompiler::convert( - IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) + else { - if (!canConvert(from->getDesc(), to)) - return SLANG_FAIL; - return compile(from, outArtifact); + diagnostics->setRaw(CharSlice(result.error)); + diagnostics->requireErrorDiagnostic(); } - SlangResult TintDownstreamCompiler::getVersionString( - slang::IBlob** /* outVersionString */) - { - // We just use Tint at whatever version is in our Dawn fork, so nobody should - // depend on the particular version at the moment. + *outArtifact = resultArtifact.detach(); + return SLANG_OK; +} + +bool TintDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) +{ + return (from.payload == ArtifactPayload::WGSL) && (to.payload == ArtifactPayload::SPIRV); +} + +SlangResult TintDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) +{ + if (!canConvert(from->getDesc(), to)) return SLANG_FAIL; - } + return compile(from, outArtifact); +} +SlangResult TintDownstreamCompiler::getVersionString(slang::IBlob** /* outVersionString */) +{ + // We just use Tint at whatever version is in our Dawn fork, so nobody should + // depend on the particular version at the moment. + return SLANG_FAIL; } + +} // namespace Slang diff --git a/source/compiler-core/slang-tint-compiler.h b/source/compiler-core/slang-tint-compiler.h index d5e596d4d..74953c378 100644 --- a/source/compiler-core/slang-tint-compiler.h +++ b/source/compiler-core/slang-tint-compiler.h @@ -1,17 +1,17 @@ #pragma once -#include "slang-downstream-compiler-util.h" #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { - struct TintDownstreamCompilerUtil - { - static SlangResult locateCompilers( - const String& path, - ISlangSharedLibraryLoader* loader, - DownstreamCompilerSet* set); - }; +struct TintDownstreamCompilerUtil +{ + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); +}; -} +} // namespace Slang diff --git a/source/compiler-core/slang-token-defs.h b/source/compiler-core/slang-token-defs.h index 2a66359fe..fea90b3ee 100644 --- a/source/compiler-core/slang-token-defs.h +++ b/source/compiler-core/slang-token-defs.h @@ -16,80 +16,79 @@ #error Need to define TOKEN(ID, DESC) before including "token-defs.h" #endif -TOKEN(Unknown, "<unknown>") -TOKEN(EndOfFile, "end of file") -TOKEN(Invalid, "invalid character") -TOKEN(Identifier, "identifier") -TOKEN(IntegerLiteral, "integer literal") -TOKEN(FloatingPointLiteral, "floating-point literal") -TOKEN(StringLiteral, "string literal") -TOKEN(CharLiteral, "character literal") -TOKEN(WhiteSpace, "whitespace") -TOKEN(NewLine, "end of line") -TOKEN(LineComment, "line comment") -TOKEN(BlockComment, "block comment") +TOKEN(Unknown, "<unknown>") +TOKEN(EndOfFile, "end of file") +TOKEN(Invalid, "invalid character") +TOKEN(Identifier, "identifier") +TOKEN(IntegerLiteral, "integer literal") +TOKEN(FloatingPointLiteral, "floating-point literal") +TOKEN(StringLiteral, "string literal") +TOKEN(CharLiteral, "character literal") +TOKEN(WhiteSpace, "whitespace") +TOKEN(NewLine, "end of line") +TOKEN(LineComment, "line comment") +TOKEN(BlockComment, "block comment") -#define PUNCTUATION(id, text) \ - TOKEN(id, "'" text "'") +#define PUNCTUATION(id, text) TOKEN(id, "'" text "'") -PUNCTUATION(Semicolon, ";") -PUNCTUATION(Comma, ",") -PUNCTUATION(Dot, ".") -PUNCTUATION(DotDot, "..") -PUNCTUATION(Ellipsis, "...") +PUNCTUATION(Semicolon, ";") +PUNCTUATION(Comma, ",") +PUNCTUATION(Dot, ".") +PUNCTUATION(DotDot, "..") +PUNCTUATION(Ellipsis, "...") -PUNCTUATION(LBrace, "{") -PUNCTUATION(RBrace, "}") -PUNCTUATION(LBracket, "[") -PUNCTUATION(RBracket, "]") -PUNCTUATION(LParent, "(") -PUNCTUATION(RParent, ")") +PUNCTUATION(LBrace, "{") +PUNCTUATION(RBrace, "}") +PUNCTUATION(LBracket, "[") +PUNCTUATION(RBracket, "]") +PUNCTUATION(LParent, "(") +PUNCTUATION(RParent, ")") -PUNCTUATION(OpAssign, "=") -PUNCTUATION(OpAdd, "+") -PUNCTUATION(OpSub, "-") -PUNCTUATION(OpMul, "*") -PUNCTUATION(OpDiv, "/") -PUNCTUATION(OpMod, "%") -PUNCTUATION(OpNot, "!") -PUNCTUATION(OpBitNot, "~") -PUNCTUATION(OpLsh, "<<") -PUNCTUATION(OpRsh, ">>") -PUNCTUATION(OpEql, "==") -PUNCTUATION(OpNeq, "!=") -PUNCTUATION(OpGreater, ">") -PUNCTUATION(OpLess, "<") -PUNCTUATION(OpGeq, ">=") -PUNCTUATION(OpLeq, "<=") -PUNCTUATION(OpAnd, "&&") -PUNCTUATION(OpOr, "||") -PUNCTUATION(OpBitAnd, "&") -PUNCTUATION(OpBitOr, "|") -PUNCTUATION(OpBitXor, "^") -PUNCTUATION(OpInc, "++") -PUNCTUATION(OpDec, "--") +PUNCTUATION(OpAssign, "=") +PUNCTUATION(OpAdd, "+") +PUNCTUATION(OpSub, "-") +PUNCTUATION(OpMul, "*") +PUNCTUATION(OpDiv, "/") +PUNCTUATION(OpMod, "%") +PUNCTUATION(OpNot, "!") +PUNCTUATION(OpBitNot, "~") +PUNCTUATION(OpLsh, "<<") +PUNCTUATION(OpRsh, ">>") +PUNCTUATION(OpEql, "==") +PUNCTUATION(OpNeq, "!=") +PUNCTUATION(OpGreater, ">") +PUNCTUATION(OpLess, "<") +PUNCTUATION(OpGeq, ">=") +PUNCTUATION(OpLeq, "<=") +PUNCTUATION(OpAnd, "&&") +PUNCTUATION(OpOr, "||") +PUNCTUATION(OpBitAnd, "&") +PUNCTUATION(OpBitOr, "|") +PUNCTUATION(OpBitXor, "^") +PUNCTUATION(OpInc, "++") +PUNCTUATION(OpDec, "--") -PUNCTUATION(OpAddAssign, "+=") -PUNCTUATION(OpSubAssign, "-=") -PUNCTUATION(OpMulAssign, "*=") -PUNCTUATION(OpDivAssign, "/=") -PUNCTUATION(OpModAssign, "%=") -PUNCTUATION(OpShlAssign, "<<=") -PUNCTUATION(OpShrAssign, ">>=") -PUNCTUATION(OpAndAssign, "&=") -PUNCTUATION(OpOrAssign, "|=") -PUNCTUATION(OpXorAssign, "^=") +PUNCTUATION(OpAddAssign, "+=") +PUNCTUATION(OpSubAssign, "-=") +PUNCTUATION(OpMulAssign, "*=") +PUNCTUATION(OpDivAssign, "/=") +PUNCTUATION(OpModAssign, "%=") +PUNCTUATION(OpShlAssign, "<<=") +PUNCTUATION(OpShrAssign, ">>=") +PUNCTUATION(OpAndAssign, "&=") +PUNCTUATION(OpOrAssign, "|=") +PUNCTUATION(OpXorAssign, "^=") -PUNCTUATION(QuestionMark, "?") -PUNCTUATION(Colon, ":") -PUNCTUATION(RightArrow, "->") -PUNCTUATION(At, "@") -PUNCTUATION(Dollar, "$") -PUNCTUATION(DollarDollar, "$$") -PUNCTUATION(Pound, "#") -PUNCTUATION(PoundPound, "##") +PUNCTUATION(QuestionMark, "?") +PUNCTUATION(Colon, ":") +PUNCTUATION(RightArrow, "->") +PUNCTUATION(At, "@") +PUNCTUATION(Dollar, "$") +PUNCTUATION(DollarDollar, "$$") +PUNCTUATION(Pound, "#") +PUNCTUATION(PoundPound, "##") -PUNCTUATION(Scope, "::") +PUNCTUATION(Scope, "::") PUNCTUATION(CompletionRequest, "#?") diff --git a/source/compiler-core/slang-token.cpp b/source/compiler-core/slang-token.cpp index 576b08d66..5dd64b96a 100644 --- a/source/compiler-core/slang-token.cpp +++ b/source/compiler-core/slang-token.cpp @@ -1,19 +1,19 @@ // slang-token.cpp #include "slang-token.h" -//#include <assert.h> +// #include <assert.h> -namespace Slang { +namespace Slang +{ char const* TokenTypeToString(TokenType type) { - switch( type ) + switch (type) { - default: - SLANG_ASSERT(!"unexpected"); - return "<uknown>"; + default: SLANG_ASSERT(!"unexpected"); return "<uknown>"; -#define TOKEN(NAME, DESC) case TokenType::NAME: return DESC; +#define TOKEN(NAME, DESC) \ + case TokenType::NAME: return DESC; #include "slang-token-defs.h" } } diff --git a/source/compiler-core/slang-token.h b/source/compiler-core/slang-token.h index 7feda6824..9978ec5cf 100644 --- a/source/compiler-core/slang-token.h +++ b/source/compiler-core/slang-token.h @@ -3,11 +3,11 @@ #define SLANG_TOKEN_H_INCLUDED #include "../core/slang-basic.h" - -#include "slang-source-loc.h" #include "slang-name.h" +#include "slang-source-loc.h" -namespace Slang { +namespace Slang +{ class Name; @@ -24,22 +24,21 @@ struct TokenFlag { enum Enum : TokenFlags { - AtStartOfLine = 1 << 0, - AfterWhitespace = 1 << 1, - ScrubbingNeeded = 1 << 2, - Name = 1 << 3, ///< Determines if 'name' is set or 'chars' in the charsNameUnion + AtStartOfLine = 1 << 0, + AfterWhitespace = 1 << 1, + ScrubbingNeeded = 1 << 2, + Name = 1 << 3, ///< Determines if 'name' is set or 'chars' in the charsNameUnion }; }; class Token { public: + TokenType type = TokenType::Unknown; + TokenFlags flags = 0; - TokenType type = TokenType::Unknown; - TokenFlags flags = 0; - - SourceLoc loc; - uint32_t charsCount = 0; ///< Amount of characters. Is set if name or not. + SourceLoc loc; + uint32_t charsCount = 0; ///< Amount of characters. Is set if name or not. union CharsNameUnion { @@ -53,7 +52,7 @@ public: Index getContentLength() const { return charsCount; } UnownedStringSlice getContent() const; - /// Set content + /// Set content void setContent(const UnownedStringSlice& content); Name* getName() const; @@ -62,13 +61,10 @@ public: SourceLoc getLoc() const { return loc; } - /// Set the name + /// Set the name SLANG_FORCE_INLINE void setName(Name* inName); - Token() - { - charsNameUnion.chars = nullptr; - } + Token() { charsNameUnion.chars = nullptr; } Token( TokenType inType, @@ -76,18 +72,14 @@ public: SourceLoc inLoc, TokenFlags inFlags = 0) : flags(inFlags) - { - SLANG_ASSERT((inFlags & TokenFlag::Name) == 0); - type = inType; + { + SLANG_ASSERT((inFlags & TokenFlag::Name) == 0); + type = inType; charsNameUnion.chars = inContent.begin(); charsCount = uint32_t(inContent.getLength()); loc = inLoc; - } - Token( - TokenType inType, - Name* name, - SourceLoc inLoc, - TokenFlags inFlags = 0) + } + Token(TokenType inType, Name* name, SourceLoc inLoc, TokenFlags inFlags = 0) { SLANG_ASSERT(name); type = inType; @@ -101,7 +93,8 @@ public: // --------------------------------------------------------------------------- SLANG_FORCE_INLINE UnownedStringSlice Token::getContent() const { - return (flags & TokenFlag::Name) ? charsNameUnion.name->text.getUnownedSlice() : UnownedStringSlice(charsNameUnion.chars, charsCount); + return (flags & TokenFlag::Name) ? charsNameUnion.name->text.getUnownedSlice() + : UnownedStringSlice(charsNameUnion.chars, charsCount); } // --------------------------------------------------------------------------- diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp index df3285608..449b0f973 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -2,35 +2,45 @@ #include "slang-visual-studio-compiler-util.h" #include "../core/slang-common.h" -#include "slang-com-helper.h" -#include "../core/slang-string-util.h" #include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" +#include "slang-com-helper.h" // if Visual Studio import the visual studio platform specific header #if SLANG_VC -# include "windows/slang-win-visual-studio-util.h" +#include "windows/slang-win-visual-studio-util.h" #endif #include "../core/slang-io.h" - #include "slang-artifact-desc-util.h" #include "slang-artifact-diagnostic-util.h" -#include "slang-artifact-util.h" #include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" namespace Slang { -static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts) +static void _addFile( + const String& path, + const ArtifactDesc& desc, + IOSFileArtifactRepresentation* lockFile, + List<ComPtr<IArtifact>>& outArtifacts) { - auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Owned, path.getUnownedSlice(), lockFile); + auto fileRep = OSFileArtifactRepresentation::create( + IOSFileArtifactRepresentation::Kind::Owned, + path.getUnownedSlice(), + lockFile); auto artifact = ArtifactUtil::createArtifact(desc); artifact->addRepresentation(fileRep); outArtifacts.add(artifact); } -/* static */SlangResult VisualStudioCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts) +/* static */ SlangResult VisualStudioCompilerUtil::calcCompileProducts( + const CompileOptions& options, + ProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List<ComPtr<IArtifact>>& outArtifacts) { SLANG_ASSERT(options.modulePath.count); @@ -44,35 +54,67 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa { StringBuilder builder; const auto desc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, modulePath.getUnownedSlice(), builder)); + SLANG_RETURN_ON_FAIL( + ArtifactDescUtil::calcPathForDesc(desc, modulePath.getUnownedSlice(), builder)); _addFile(builder, desc, lockFile, outArtifacts); } if (flags & ProductFlag::Miscellaneous) { - - _addFile(modulePath + ".ilk", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::Unknown, ArtifactStyle::None), lockFile, outArtifacts); + + _addFile( + modulePath + ".ilk", + ArtifactDesc::make( + ArtifactKind::BinaryFormat, + ArtifactPayload::Unknown, + ArtifactStyle::None), + lockFile, + outArtifacts); if (options.targetType == SLANG_SHADER_SHARED_LIBRARY) { - _addFile(modulePath + ".exp", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::Unknown, ArtifactStyle::None), lockFile, outArtifacts); - _addFile(modulePath + ".lib", ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::HostCPU, targetDesc), lockFile, outArtifacts); + _addFile( + modulePath + ".exp", + ArtifactDesc::make( + ArtifactKind::BinaryFormat, + ArtifactPayload::Unknown, + ArtifactStyle::None), + lockFile, + outArtifacts); + _addFile( + modulePath + ".lib", + ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::HostCPU, targetDesc), + lockFile, + outArtifacts); } } if (flags & ProductFlag::Compile) { - _addFile(modulePath + ".obj", ArtifactDesc::make(ArtifactKind::ObjectCode, ArtifactPayload::HostCPU, targetDesc), lockFile, outArtifacts); + _addFile( + modulePath + ".obj", + ArtifactDesc::make(ArtifactKind::ObjectCode, ArtifactPayload::HostCPU, targetDesc), + lockFile, + outArtifacts); } if (flags & ProductFlag::Debug) { // TODO(JS): Could try and determine based on debug information - _addFile(modulePath + ".pdb", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::PdbDebugInfo, targetDesc), lockFile, outArtifacts); + _addFile( + modulePath + ".pdb", + ArtifactDesc::make( + ArtifactKind::BinaryFormat, + ArtifactPayload::PdbDebugInfo, + targetDesc), + lockFile, + outArtifacts); } return SLANG_OK; } -/* static */SlangResult VisualStudioCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) +/* static */ SlangResult VisualStudioCompilerUtil::calcArgs( + const CompileOptions& options, + CommandLine& cmdLine) { SLANG_ASSERT(options.modulePath.count); @@ -112,17 +154,17 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa switch (options.debugInfoType) { - default: + default: { // Multithreaded statically linked runtime library cmdLine.addArg("/MD"); break; } - case DebugInfoType::None: + case DebugInfoType::None: { break; } - case DebugInfoType::Maximal: + case DebugInfoType::Maximal: { // Multithreaded statically linked *debug* runtime library cmdLine.addArg("/MDd"); @@ -140,44 +182,46 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa switch (options.optimizationLevel) { - case OptimizationLevel::None: + case OptimizationLevel::None: { // No optimization - cmdLine.addArg("/Od"); + cmdLine.addArg("/Od"); break; } - case OptimizationLevel::Default: + case OptimizationLevel::Default: { break; } - case OptimizationLevel::High: + case OptimizationLevel::High: { cmdLine.addArg("/O2"); break; } - case OptimizationLevel::Maximal: + case OptimizationLevel::Maximal: { cmdLine.addArg("/Ox"); break; } - default: break; + default: break; } switch (options.floatingPointMode) { - case FloatingPointMode::Default: break; - case FloatingPointMode::Precise: + case FloatingPointMode::Default: break; + case FloatingPointMode::Precise: { // precise is default behavior, VS also has 'strict' // - // ```/fp:strict has behavior similar to /fp:precise, that is, the compiler preserves the source ordering and rounding properties of floating-point code when - // it generates and optimizes object code for the target machine, and observes the standard when handling special values. In addition, the program may safely - // access or modify the floating-point environment at runtime.``` + // ```/fp:strict has behavior similar to /fp:precise, that is, the compiler preserves + // the source ordering and rounding properties of floating-point code when it generates + // and optimizes object code for the target machine, and observes the standard when + // handling special values. In addition, the program may safely access or modify the + // floating-point environment at runtime.``` cmdLine.addArg("/fp:precise"); break; } - case FloatingPointMode::Fast: + case FloatingPointMode::Fast: { cmdLine.addArg("/fp:fast"); break; @@ -188,8 +232,8 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa switch (options.targetType) { - case SLANG_SHADER_SHARED_LIBRARY: - case SLANG_HOST_SHARED_LIBRARY: + case SLANG_SHADER_SHARED_LIBRARY: + case SLANG_HOST_SHARED_LIBRARY: { // Create dynamic link library if (options.debugInfoType == DebugInfoType::None) @@ -204,12 +248,12 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa cmdLine.addPrefixPathArg("/Fe", modulePath, ".dll"); break; } - case SLANG_HOST_EXECUTABLE: + case SLANG_HOST_EXECUTABLE: { cmdLine.addPrefixPathArg("/Fe", modulePath, ".exe"); break; } - default: break; + default: break; } // Object file specify it's location - needed if we are out @@ -244,12 +288,12 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa { ComPtr<IOSFileArtifactRepresentation> fileRep; - // TODO(JS): + // TODO(JS): // Do we want to keep the file on the file system? It's probably reasonable to do so. SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); cmdLine.addArg(fileRep->getPath()); } - + // Link options (parameters past /link go to linker) cmdLine.addArg("/link"); @@ -288,7 +332,9 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa return SLANG_OK; } -static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnostic::Severity& outSeverity) +static SlangResult _parseSeverity( + const UnownedStringSlice& in, + ArtifactDiagnostic::Severity& outSeverity) { typedef ArtifactDiagnostic::Severity Severity; @@ -311,7 +357,10 @@ static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnost return SLANG_OK; } -static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const UnownedStringSlice& line, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseVisualStudioLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + ArtifactDiagnostic& outDiagnostic) { typedef IArtifactDiagnostics::Diagnostic Diagnostic; @@ -328,8 +377,8 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown outDiagnostic.stage = ArtifactDiagnostic::Stage::Compile; - const char*const start = line.begin(); - const char*const end = line.end(); + const char* const start = line.begin(); + const char* const end = line.end(); UnownedStringSlice postPath; // Handle the path and line no @@ -409,7 +458,8 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown return SLANG_FAIL; } - const UnownedStringSlice errorSection = UnownedStringSlice(postPath.begin(), postPath.begin() + errorColonIndex); + const UnownedStringSlice errorSection = + UnownedStringSlice(postPath.begin(), postPath.begin() + errorColonIndex); Index errorCodeIndex = errorSection.lastIndexOf(' '); if (errorCodeIndex < 0) { @@ -417,17 +467,20 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown } // Extract the code - outDiagnostic.code = allocator.allocate(errorSection.begin() + errorCodeIndex + 1, errorSection.end()); + outDiagnostic.code = + allocator.allocate(errorSection.begin() + errorCodeIndex + 1, errorSection.end()); if (asStringSlice(outDiagnostic.code).startsWith(UnownedStringSlice::fromLiteral("LNK"))) { outDiagnostic.stage = Diagnostic::Stage::Link; } // Extract the bit before the code - SLANG_RETURN_ON_FAIL(_parseSeverity(UnownedStringSlice(errorSection.begin(), errorSection.begin() + errorCodeIndex).trim(), outDiagnostic.severity)); + SLANG_RETURN_ON_FAIL(_parseSeverity( + UnownedStringSlice(errorSection.begin(), errorSection.begin() + errorCodeIndex).trim(), + outDiagnostic.severity)); // Link codes start with LNK prefix - postError = UnownedStringSlice(postPath.begin() + errorColonIndex + 1, end); + postError = UnownedStringSlice(postPath.begin() + errorColonIndex + 1, end); } outDiagnostic.text = allocator.allocate(postError); @@ -435,7 +488,9 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown return SLANG_OK; } -/* static */SlangResult VisualStudioCompilerUtil::parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* diagnostics) +/* static */ SlangResult VisualStudioCompilerUtil::parseOutput( + const ExecuteResult& exeRes, + IArtifactDiagnostics* diagnostics) { diagnostics->reset(); @@ -466,7 +521,7 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown return SLANG_OK; } -/* static */SlangResult VisualStudioCompilerUtil::locateCompilers( +/* static */ SlangResult VisualStudioCompilerUtil::locateCompilers( const String& path, ISlangSharedLibraryLoader* loader, [[maybe_unused]] DownstreamCompilerSet* set) @@ -484,4 +539,4 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-visual-studio-compiler-util.h b/source/compiler-core/slang-visual-studio-compiler-util.h index fa1fb7c69..77227ce97 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.h +++ b/source/compiler-core/slang-visual-studio-compiler-util.h @@ -9,14 +9,21 @@ namespace Slang struct VisualStudioCompilerUtil : public DownstreamCompilerUtilBase { - /// Calculate Visual Studio family compilers cmdLine arguments from options + /// Calculate Visual Studio family compilers cmdLine arguments from options static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine); - /// Parse Visual Studio exeRes into CPPCompiler::Output + /// Parse Visual Studio exeRes into CPPCompiler::Output static SlangResult parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* outOutput); - static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts); + static SlangResult calcCompileProducts( + const CompileOptions& options, + ProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List<ComPtr<IArtifact>>& outArtifacts); - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; class VisualStudioDownstreamCompiler : public CommandLineDownstreamCompiler @@ -26,14 +33,32 @@ public: typedef VisualStudioCompilerUtil Util; // CommandLineDownstreamCompiler impl - just forwards to the Util - virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } - virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE { return Util::parseOutput(exeResult, diagnostics); } - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags productFlags, IOSFileArtifactRepresentation* lockFile, List<ComPtr<IArtifact>>& outArtifacts) SLANG_OVERRIDE { return Util::calcCompileProducts(options, productFlags, lockFile, outArtifacts); } + virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE + { + return Util::calcArgs(options, cmdLine); + } + virtual SlangResult parseOutput( + const ExecuteResult& exeResult, + IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE + { + return Util::parseOutput(exeResult, diagnostics); + } + virtual SlangResult calcCompileProducts( + const CompileOptions& options, + DownstreamProductFlags productFlags, + IOSFileArtifactRepresentation* lockFile, + List<ComPtr<IArtifact>>& outArtifacts) SLANG_OVERRIDE + { + return Util::calcCompileProducts(options, productFlags, lockFile, outArtifacts); + } - VisualStudioDownstreamCompiler(const Desc& desc):Super(desc) {} + VisualStudioDownstreamCompiler(const Desc& desc) + : Super(desc) + { + } }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/windows/slang-win-visual-studio-util.cpp b/source/compiler-core/windows/slang-win-visual-studio-util.cpp index cb784b426..8496bb3fd 100644 --- a/source/compiler-core/windows/slang-win-visual-studio-util.cpp +++ b/source/compiler-core/windows/slang-win-visual-studio-util.cpp @@ -3,15 +3,13 @@ #include "../../core/slang-common.h" #include "../../core/slang-process-util.h" #include "../../core/slang-string-util.h" - #include "../slang-json-parser.h" #include "../slang-json-value.h" - #include "../slang-visual-studio-compiler-util.h" #ifdef _WIN32 -# include <windows.h> -# include <Shlobj.h> +#include <Shlobj.h> +#include <windows.h> #pragma comment(lib, "advapi32") #pragma comment(lib, "Shell32") #endif @@ -19,33 +17,35 @@ // The method used to invoke VS was originally inspired by some ideas in // https://github.com/RuntimeCompiledCPlusPlus/RuntimeCompiledCPlusPlus/ -namespace Slang { +namespace Slang +{ // Information on VS versioning can be found here // https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering -namespace { // anonymous +namespace +{ // anonymous struct RegistryInfo { - const char* regName; ///< The name of the entry in the registry - const char* pathFix; ///< With the value from the registry how to fix the path + const char* regName; ///< The name of the entry in the registry + const char* pathFix; ///< With the value from the registry how to fix the path }; struct VersionInfo { - SemanticVersion version; ///< The version - const char* name; ///< The name of the registry key + SemanticVersion version; ///< The version + const char* name; ///< The name of the registry key }; -} // anonymous +} // namespace static SlangResult _readRegistryKey(const char* path, const char* keyName, String& outString) { // https://docs.microsoft.com/en-us/windows/desktop/api/winreg/nf-winreg-regopenkeyexa - HKEY key; - LONG ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_READ | KEY_WOW64_32KEY, &key); + HKEY key; + LONG ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_READ | KEY_WOW64_32KEY, &key); if (ret != ERROR_SUCCESS) { return SLANG_FAIL; @@ -77,8 +77,8 @@ static DownstreamCompilerMatchVersion _makeVersion(int main) return version; } -static DownstreamCompilerMatchVersion _makeVersion(int main, int dot) -{ +static DownstreamCompilerMatchVersion _makeVersion(int main, int dot) +{ DownstreamCompilerMatchVersion version; version.type = SLANG_PASS_THROUGH_VISUAL_STUDIO; version.matchVersion.set(main, dot); @@ -94,8 +94,7 @@ VersionInfo _makeVersionInfo(const char* name, int high, int dot = 0) } // https://en.wikipedia.org/wiki/Microsoft_Visual_Studio -static const VersionInfo s_versionInfos[] = -{ +static const VersionInfo s_versionInfos[] = { _makeVersionInfo("VS 2005", 8), _makeVersionInfo("VS 2008", 9), _makeVersionInfo("VS 2010", 10), @@ -107,15 +106,14 @@ static const VersionInfo s_versionInfos[] = _makeVersionInfo("VS 2022", 17), }; -// When trying to figure out how this stuff works by running regedit - care is needed, -// because what regedit displays varies on which version of regedit is used. -// In order to use the registry paths used here it's necessary to use Start/Run with +// When trying to figure out how this stuff works by running regedit - care is needed, +// because what regedit displays varies on which version of regedit is used. +// In order to use the registry paths used here it's necessary to use Start/Run with // %systemroot%\syswow64\regedit to view 32 bit keys -static const RegistryInfo s_regInfos[] = -{ - {"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7", "" }, - {"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", "VC\\Auxiliary\\Build\\" }, +static const RegistryInfo s_regInfos[] = { + {"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7", ""}, + {"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", "VC\\Auxiliary\\Build\\"}, }; static bool _canUseVSWhere(SemanticVersion version) @@ -149,7 +147,7 @@ static SlangResult _parseVersion(UnownedStringSlice versionString, SemanticVersi } -/* static */DownstreamCompilerMatchVersion WinVisualStudioUtil::getCompiledVersion() +/* static */ DownstreamCompilerMatchVersion WinVisualStudioUtil::getCompiledVersion() { // Get the version of visual studio used to compile this source // Not const, because otherwise we get an warning/error about constant expression... @@ -157,12 +155,12 @@ static SlangResult _parseVersion(UnownedStringSlice versionString, SemanticVersi switch (version) { - case 1400: return _makeVersion(8); - case 1500: return _makeVersion(9); - case 1600: return _makeVersion(10); - case 1700: return _makeVersion(11); - case 1800: return _makeVersion(12); - default: break; + case 1400: return _makeVersion(8); + case 1500: return _makeVersion(9); + case 1600: return _makeVersion(10); + case 1700: return _makeVersion(11); + case 1800: return _makeVersion(12); + default: break; } // Seems like versions go in runs of 10 at this point @@ -176,58 +174,65 @@ static SlangResult _parseVersion(UnownedStringSlice versionString, SemanticVersi { switch (version) { - case 1910: return _makeVersion(15, 0); - case 1911: return _makeVersion(15, 3); - case 1912: return _makeVersion(15, 5); - case 1913: return _makeVersion(15, 6); - case 1914: return _makeVersion(15, 7); - case 1915: return _makeVersion(15, 8); - case 1916: return _makeVersion(15, 9); - default: return _makeVersion(15); + case 1910: return _makeVersion(15, 0); + case 1911: return _makeVersion(15, 3); + case 1912: return _makeVersion(15, 5); + case 1913: return _makeVersion(15, 6); + case 1914: return _makeVersion(15, 7); + case 1915: return _makeVersion(15, 8); + case 1916: return _makeVersion(15, 9); + default: return _makeVersion(15); } } else if (version >= 1920 && version < 1930) { switch (version) { - case 1920: return _makeVersion(16, 0); - case 1921: return _makeVersion(16, 1); - case 1922: return _makeVersion(16, 2); - case 1923: return _makeVersion(16, 3); - case 1924: return _makeVersion(16, 4); - case 1925: return _makeVersion(16, 5); - case 1926: return _makeVersion(16, 6); - case 1927: return _makeVersion(16, 7); - case 1928: return _makeVersion(16, 9); - case 1929: return _makeVersion(16, 11); - default: return _makeVersion(16); + case 1920: return _makeVersion(16, 0); + case 1921: return _makeVersion(16, 1); + case 1922: return _makeVersion(16, 2); + case 1923: return _makeVersion(16, 3); + case 1924: return _makeVersion(16, 4); + case 1925: return _makeVersion(16, 5); + case 1926: return _makeVersion(16, 6); + case 1927: return _makeVersion(16, 7); + case 1928: return _makeVersion(16, 9); + case 1929: return _makeVersion(16, 11); + default: return _makeVersion(16); } } else if (version >= 1930 && version < 1940) { switch (version) { - case 1930: return _makeVersion(17, 0); - case 1931: return _makeVersion(17, 1); - case 1932: return _makeVersion(17, 2); - default: return _makeVersion(17); + case 1930: return _makeVersion(17, 0); + case 1931: return _makeVersion(17, 1); + case 1932: return _makeVersion(17, 2); + default: return _makeVersion(17); } } else if (version >= 1940) { // Its an unknown newer version - return DownstreamCompilerMatchVersion(SLANG_PASS_THROUGH_VISUAL_STUDIO, MatchSemanticVersion::makeFuture()); + return DownstreamCompilerMatchVersion( + SLANG_PASS_THROUGH_VISUAL_STUDIO, + MatchSemanticVersion::makeFuture()); } // Unknown version return DownstreamCompilerMatchVersion(SLANG_PASS_THROUGH_VISUAL_STUDIO, MatchSemanticVersion()); } -static SlangResult _parseJson(const String& contents, DiagnosticSink* sink, JSONContainer* container, JSONValue& outRoot) +static SlangResult _parseJson( + const String& contents, + DiagnosticSink* sink, + JSONContainer* container, + JSONValue& outRoot) { auto sourceManager = sink->getSourceManager(); - SourceFile* sourceFile = sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents); + SourceFile* sourceFile = + sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents); SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr, SourceLoc()); JSONLexer lexer; @@ -246,10 +251,13 @@ static void _orderVersions(List<WinVisualStudioUtil::VersionPath>& ioVersions) { typedef WinVisualStudioUtil::VersionPath VersionPath; // Put into increasing version order, from oldest to newest - ioVersions.sort([&](const VersionPath& a, const VersionPath& b) -> bool { return a.version < b.version; }); + ioVersions.sort( + [&](const VersionPath& a, const VersionPath& b) -> bool { return a.version < b.version; }); } -static SlangResult _findVersionsWithVSWhere(const VersionInfo* versionInfo, List<WinVisualStudioUtil::VersionPath>& outVersions) +static SlangResult _findVersionsWithVSWhere( + const VersionInfo* versionInfo, + List<WinVisualStudioUtil::VersionPath>& outVersions) { typedef WinVisualStudioUtil::VersionPath VersionPath; @@ -269,12 +277,14 @@ static SlangResult _findVersionsWithVSWhere(const VersionInfo* versionInfo, List // Using -? we can find out vswhere options. - // Previous args - works but returns multiple versions, without listing what version is associated with which path - // or the order. - //String args[] = { "-version", versionName, "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", ""-property", "installationPath" }; + // Previous args - works but returns multiple versions, without listing what version is + // associated with which path or the order. + // String args[] = { "-version", versionName, "-requires", + // "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", ""-property", "installationPath" }; - // Use JSON parsing, we can verify the versions for a path, otherwise multiple versions are returned - // not just the version specified. The ordering isn't defined (and -sort doesn't appear to work) + // Use JSON parsing, we can verify the versions for a path, otherwise multiple versions are + // returned not just the version specified. The ordering isn't defined (and -sort doesn't appear + // to work) SemanticVersion requiredVersion; if (versionInfo) @@ -288,9 +298,14 @@ static SlangResult _findVersionsWithVSWhere(const VersionInfo* versionInfo, List // Add other args { - // TODO(JS): + // TODO(JS): // For arm targets will probably need something different for tooling - String args[] = { "-format", "json", "-utf8", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64" }; + String args[] = { + "-format", + "json", + "-utf8", + "-requires", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"}; cmd.addArgs(args, SLANG_COUNT_OF(args)); } @@ -316,12 +331,13 @@ static SlangResult _findVersionsWithVSWhere(const VersionInfo* versionInfo, List auto arr = container->getArray(jsonRoot); const auto pathKey = container->getKey(UnownedStringSlice::fromLiteral("installationPath")); - const auto versionKey = container->getKey(UnownedStringSlice::fromLiteral("installationVersion")); + const auto versionKey = + container->getKey(UnownedStringSlice::fromLiteral("installationVersion")); // Find all the versions, that match for (auto elem : arr) { - // Get the path and the name + // Get the path and the name if (elem.getKind() != JSONValue::Kind::Object) { continue; @@ -389,7 +405,7 @@ static SlangResult _findVersionsWithRegistery(List<WinVisualStudioUtil::VersionP versionPath.version = versionInfo.version; versionPath.vcvarsPath = value; - // Append + // Append if (keyInfo.pathFix && keyInfo.pathFix[0] != 0) { versionPath.vcvarsPath.append(keyInfo.pathFix); @@ -403,7 +419,7 @@ static SlangResult _findVersionsWithRegistery(List<WinVisualStudioUtil::VersionP return SLANG_OK; } -/* static */SlangResult WinVisualStudioUtil::find(List<VersionPath>& outVersionPaths) +/* static */ SlangResult WinVisualStudioUtil::find(List<VersionPath>& outVersionPaths) { outVersionPaths.clear(); @@ -422,12 +438,15 @@ static SlangResult _findVersionsWithRegistery(List<WinVisualStudioUtil::VersionP { // If there is a major version already from vswhere, we don't need to merge const auto majorVersion = regVersion.version.m_major; - foundIndex = outVersionPaths.findFirstIndex([&](const VersionPath& cur) -> bool { return cur.version.m_major == majorVersion; }); + foundIndex = outVersionPaths.findFirstIndex( + [&](const VersionPath& cur) -> bool + { return cur.version.m_major == majorVersion; }); } else { // See if we can find the exact version - foundIndex = outVersionPaths.findFirstIndex([&](const VersionPath& cur) -> bool { return cur.version == regVersion.version; }); + foundIndex = outVersionPaths.findFirstIndex( + [&](const VersionPath& cur) -> bool { return cur.version == regVersion.version; }); } // If it wasn't found add it. @@ -441,7 +460,7 @@ static SlangResult _findVersionsWithRegistery(List<WinVisualStudioUtil::VersionP return SLANG_OK; } -/* static */SlangResult WinVisualStudioUtil::find(DownstreamCompilerSet* set) +/* static */ SlangResult WinVisualStudioUtil::find(DownstreamCompilerSet* set) { List<VersionPath> versionPaths; SLANG_RETURN_ON_FAIL(find(versionPaths)); @@ -464,20 +483,23 @@ static SlangResult _findVersionsWithRegistery(List<WinVisualStudioUtil::VersionP return SLANG_OK; } -/* static */void WinVisualStudioUtil::calcExecuteCompilerArgs(const VersionPath& versionPath, CommandLine& outCmdLine) +/* static */ void WinVisualStudioUtil::calcExecuteCompilerArgs( + const VersionPath& versionPath, + CommandLine& outCmdLine) { - // To invoke cl we need to run the suitable vcvars. In order to run this we have to have MS CommandLine. - // So here we build up a cl command line that is run by first running vcvars, and then executing cl with the parameters as passed to commandLine + // To invoke cl we need to run the suitable vcvars. In order to run this we have to have MS + // CommandLine. So here we build up a cl command line that is run by first running vcvars, and + // then executing cl with the parameters as passed to commandLine // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa - // To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the - // following arguments: /c plus the name of the batch file. + // To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe + // and set lpCommandLine to the following arguments: /c plus the name of the batch file. CommandLine cmdLine; cmdLine.setExecutableLocation(ExecutableLocation(ExecutableLocation::Type::Name, "cmd.exe")); - + { - String options[] = { "/q", "/c", "@prompt", "$" }; + String options[] = {"/q", "/c", "@prompt", "$"}; cmdLine.addArgs(options, SLANG_COUNT_OF(options)); } @@ -496,7 +518,10 @@ static SlangResult _findVersionsWithRegistery(List<WinVisualStudioUtil::VersionP outCmdLine = cmdLine; } -/* static */SlangResult WinVisualStudioUtil::executeCompiler(const VersionPath& versionPath, const CommandLine& commandLine, ExecuteResult& outResult) +/* static */ SlangResult WinVisualStudioUtil::executeCompiler( + const VersionPath& versionPath, + const CommandLine& commandLine, + ExecuteResult& outResult) { CommandLine cmdLine; calcExecuteCompilerArgs(versionPath, cmdLine); diff --git a/source/compiler-core/windows/slang-win-visual-studio-util.h b/source/compiler-core/windows/slang-win-visual-studio-util.h index d69325f02..3418b9089 100644 --- a/source/compiler-core/windows/slang-win-visual-studio-util.h +++ b/source/compiler-core/windows/slang-win-visual-studio-util.h @@ -2,38 +2,42 @@ #define SLANG_WIN_VISUAL_STUDIO_UTIL_H #include "../../core/slang-list.h" -#include "../../core/slang-string.h" - #include "../../core/slang-process-util.h" - +#include "../../core/slang-string.h" #include "../slang-downstream-compiler-util.h" -namespace Slang { +namespace Slang +{ struct WinVisualStudioUtil { struct VersionPath { - SemanticVersion version; ///< The visual studio version - String vcvarsPath; ///< The path to `vcvars.bat` files, that need to be executed before executing the compiler + SemanticVersion version; ///< The visual studio version + String vcvarsPath; ///< The path to `vcvars.bat` files, that need to be executed before + ///< executing the compiler }; - - /// Find all the installations + + /// Find all the installations static SlangResult find(List<VersionPath>& outVersionPaths); - /// Find and add to the set (if not already there) + /// Find and add to the set (if not already there) static SlangResult find(DownstreamCompilerSet* set); - /// Create the cmdLine to start compiler for specified path + /// Create the cmdLine to start compiler for specified path static void calcExecuteCompilerArgs(const VersionPath& versionPath, CommandLine& outCmdLine); - /// Run visual studio on specified path with the parameters specified on the command line. Output placed in outResult. - static SlangResult executeCompiler(const VersionPath& versionPath, const CommandLine& commandLine, ExecuteResult& outResult); + /// Run visual studio on specified path with the parameters specified on the command line. + /// Output placed in outResult. + static SlangResult executeCompiler( + const VersionPath& versionPath, + const CommandLine& commandLine, + ExecuteResult& outResult); - /// Gets the msc compiler used to compile this version. + /// Gets the msc compiler used to compile this version. static DownstreamCompilerMatchVersion getCompiledVersion(); }; } // namespace Slang -#endif +#endif |
