diff options
Diffstat (limited to 'source')
32 files changed, 659 insertions, 258 deletions
diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index 490020a27..4681b60f4 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -279,6 +279,68 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL SLANG_UNEXPECTED("Unhandled type"); } +/* static */SlangCompileTarget ArtifactDescUtil::getCompileTargetFromDesc(const ArtifactDesc& desc) +{ + switch (desc.kind) + { + 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; + default: break; + } + break; + } + 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; + default: break; + } + } + default: break; + } + + if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike)) + { + if (isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) + { + switch (desc.kind) + { + case Kind::Executable: return SLANG_HOST_EXECUTABLE; + case Kind::SharedLibrary: return 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; + default: break; + } + } + } + + return SLANG_TARGET_UNKNOWN; +} + + namespace { // anonymous struct KindExtension { @@ -699,4 +761,53 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S } } +/* static */bool ArtifactDescUtil::isDissassembly(const ArtifactDesc& from, const ArtifactDesc& to) +{ + // From must be a binary like type + if (!isDerivedFrom(from.kind, ArtifactKind::BinaryLike)) + { + return false; + } + + + // Target must be assembly, and the payload be the same type + if (!(to.kind == ArtifactKind::Assembly && + to.payload == from.payload)) + { + return false; + } + + const auto payload = from.payload; + + // Check the payload seems like something plausible to 'disassemble' + if (!(isDerivedFrom(payload, ArtifactPayload::KernelLike) || + 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)) + { + return false; + } + + return true; +} + +/* 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) +{ + StringBuilder buf; + appendText(desc, buf); + return buf; +} + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-desc-util.h b/source/compiler-core/slang-artifact-desc-util.h index 6f35cb500..ff54198b4 100644 --- a/source/compiler-core/slang-artifact-desc-util.h +++ b/source/compiler-core/slang-artifact-desc-util.h @@ -84,8 +84,21 @@ struct ArtifactDescUtil /// Given a target returns the ArtifactDesc static ArtifactDesc makeDescFromCompileTarget(SlangCompileTarget target); + /// 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 static bool isDescDerivedFrom(const ArtifactDesc& desc, const ArtifactDesc& from); + + /// True if `to` is disassembly of `from` + static bool isDissassembly(const ArtifactDesc& from, const ArtifactDesc& to); + + /// Append the desc as text to out + static void appendText(const ArtifactDesc& desc, StringBuilder& out); + + static String getText(const ArtifactDesc& desc); + }; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp index 028fa1bb9..4f10b8cdd 100644 --- a/source/compiler-core/slang-artifact-handler-impl.cpp +++ b/source/compiler-core/slang-artifact-handler-impl.cpp @@ -8,7 +8,7 @@ #include "slang-artifact-helper.h" -#include "../core/slang-castable-list-impl.h" +#include "../core/slang-castable-util.h" #include "../core/slang-file-system.h" #include "../core/slang-io.h" diff --git a/source/compiler-core/slang-artifact-helper.cpp b/source/compiler-core/slang-artifact-helper.cpp index 39e81b668..49b9e547e 100644 --- a/source/compiler-core/slang-artifact-helper.cpp +++ b/source/compiler-core/slang-artifact-helper.cpp @@ -8,6 +8,7 @@ #include "slang-artifact-util.h" #include "../core/slang-castable-list-impl.h" +#include "../core/slang-castable-util.h" #include "../core/slang-file-system.h" #include "../core/slang-io.h" @@ -126,4 +127,17 @@ void DefaultArtifactHelper::getCastable(ISlangUnknown* unk, ICastable** outCasta *outCastable = CastableUtil::getCastable(unk).detach(); } +SlangResult DefaultArtifactHelper::createCastableList(const Guid& guid, ICastableList** outList) +{ + auto list = new CastableList; + if (auto ptr = list->getInterface(guid)) + { + list->addRef(); + *outList = (ICastableList*)ptr; + return SLANG_OK; + } + delete list; + return SLANG_E_NO_INTERFACE; +} + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-helper.h b/source/compiler-core/slang-artifact-helper.h index 6a07c16ee..58f29ef04 100644 --- a/source/compiler-core/slang-artifact-helper.h +++ b/source/compiler-core/slang-artifact-helper.h @@ -51,6 +51,9 @@ class IArtifactHelper : public ICastable /// 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 an empty ICastableList + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCastableList(const Guid& guid, ICastableList** outList) = 0; }; class DefaultArtifactHelper : public IArtifactHelper @@ -64,7 +67,7 @@ public: // ICastable SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - // IArtifactInterface + // IArtifactHelper virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifactContainer(const ArtifactDesc& desc, const char* name, IArtifactContainer** outArtifactContainer) SLANG_OVERRIDE; @@ -88,6 +91,8 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCastableList(const Guid& guid, ICastableList** outList) SLANG_OVERRIDE; + static IArtifactHelper* getSingleton() { return &g_singleton; } protected: diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp index ed952e72c..d8646eb20 100644 --- a/source/compiler-core/slang-artifact-impl.cpp +++ b/source/compiler-core/slang-artifact-impl.cpp @@ -8,7 +8,7 @@ #include "slang-artifact-handler-impl.h" -#include "../core/slang-castable-list-impl.h" +#include "../core/slang-castable-util.h" namespace Slang { diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp index 802f2c1dd..4e33f2f0c 100644 --- a/source/compiler-core/slang-artifact-representation-impl.cpp +++ b/source/compiler-core/slang-artifact-representation-impl.cpp @@ -9,7 +9,7 @@ #include "slang-artifact-util.h" -#include "../core/slang-castable-list-impl.h" +#include "../core/slang-castable-util.h" namespace Slang { diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index a09454998..084d96062 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -6,8 +6,6 @@ #include "slang-artifact-desc-util.h" -#include "../core/slang-castable-list-impl.h" - #include "../core/slang-io.h" namespace Slang { diff --git a/source/compiler-core/slang-downstream-compiler-util.cpp b/source/compiler-core/slang-downstream-compiler-util.cpp index 9f6a96e43..9f43a6c88 100644 --- a/source/compiler-core/slang-downstream-compiler-util.cpp +++ b/source/compiler-core/slang-downstream-compiler-util.cpp @@ -196,8 +196,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() { DownstreamCompilerDesc desc; desc.type = type; - desc.majorVersion = version.m_major; - desc.minorVersion = version.m_minor; + desc.version = version; return findCompiler(compilers, desc); } @@ -209,7 +208,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() if (desc.type == type) { - outVersions.add(SemanticVersion(int(desc.majorVersion), int(desc.minorVersion), 0)); + outVersions.add(desc.version); } } } @@ -455,12 +454,12 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin out << TypeTextUtil::getPassThroughAsHumanText(desc.type); // Append the version if there is a version - if (desc.majorVersion || desc.minorVersion) + if (desc.version.isSet()) { out << " "; - out << desc.majorVersion; + out << desc.version.m_major; out << "."; - out << desc.minorVersion; + out << desc.version.m_minor; } } diff --git a/source/compiler-core/slang-downstream-compiler-util.h b/source/compiler-core/slang-downstream-compiler-util.h index 9e595bb86..6aad1ca90 100644 --- a/source/compiler-core/slang-downstream-compiler-util.h +++ b/source/compiler-core/slang-downstream-compiler-util.h @@ -56,7 +56,7 @@ struct DownstreamCompilerMatchVersion MatchSemanticVersion matchVersion; ///< The match version }; -struct DownstreamCompilerUtil: public DownstreamCompilerBaseUtil +struct DownstreamCompilerUtil: public DownstreamCompilerUtilBase { enum class MatchType { diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index 4f7462901..498903727 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -12,7 +12,7 @@ #include "../core/slang-blob.h" #include "../core/slang-char-util.h" -#include "../core/slang-castable-list-impl.h" +#include "../core/slang-castable-util.h" #include "slang-artifact-associated-impl.h" #include "slang-artifact-util.h" @@ -22,13 +22,12 @@ namespace Slang /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ -SlangResult DownstreamCompilerBase::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +SlangResult DownstreamCompilerBase::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) { - SLANG_UNUSED(sourceBlobTarget); - SLANG_UNUSED(blob); - SLANG_UNUSED(blobSize); - SLANG_UNUSED(out); - + SLANG_UNUSED(from); + SLANG_UNUSED(to); + SLANG_UNUSED(outArtifact); + return SLANG_E_NOT_AVAILABLE; } @@ -118,7 +117,9 @@ SlangResult CommandLineDownstreamArtifactRepresentation::createRepresentation(co // Read the contents of the binary SLANG_RETURN_ON_FAIL(File::readAllBytes(m_moduleFilePath, contents)); - *outCastable = CastableUtil::getCastable(ScopeRefObjectBlob::create(ListBlob::moveCreate(contents), m_temporaryFiles).detach()).detach(); + auto blob = ScopeRefObjectBlob::create(ListBlob::moveCreate(contents), m_temporaryFiles); + + *outCastable = CastableUtil::getCastable(blob).detach(); return SLANG_OK; } diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index 997a2b099..7ebbd5f95 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -26,27 +26,22 @@ struct DownstreamCompilerDesc { typedef DownstreamCompilerDesc ThisType; - HashCode getHashCode() const { return combineHash(HashCode(type), combineHash(HashCode(majorVersion), HashCode(minorVersion))); } - bool operator==(const ThisType& rhs) const { return type == rhs.type && majorVersion == rhs.majorVersion && minorVersion == rhs.minorVersion; } + 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 !(*this == rhs); } /// Get the version as a value - Int getVersionValue() const { return majorVersion * 100 + minorVersion; } + Int getVersionValue() const { return version.m_major * 100 + version.m_minor; } /// true if has a version set - bool hasVersion() const { return majorVersion || minorVersion; } + bool hasVersion() const { return version.isSet(); } /// Ctor - explicit DownstreamCompilerDesc(SlangPassThrough inType = SLANG_PASS_THROUGH_NONE, Int inMajorVersion = 0, Int inMinorVersion = 0) :type(inType), majorVersion(inMajorVersion), minorVersion(inMinorVersion) {} - - explicit DownstreamCompilerDesc(SlangPassThrough inType, const SemanticVersion& version) :type(inType), majorVersion(version.m_major), minorVersion(version.m_minor) {} + 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 - - /// TODO(JS): Would probably be better if changed to SemanticVersion, but not trivial to change - // because this type is part of the DownstreamCompiler interface, which is used with `slang-llvm`. - Int majorVersion; ///< Major version (interpretation is type specific) - Int minorVersion; ///< Minor version (interpretation is type specific) + SemanticVersion version; ///< The version of the compiler }; struct DownstreamCompileOptions @@ -63,7 +58,7 @@ struct DownstreamCompileOptions }; }; - enum class OptimizationLevel + enum class OptimizationLevel : uint8_t { None, ///< Don't optimize at all. Default, ///< Default optimization level: balance code quality and compilation time. @@ -71,21 +66,21 @@ struct DownstreamCompileOptions Maximal, ///< Include optimizations that may take a very long time, or may involve severe space-vs-speed tradeoffs }; - enum class DebugInfoType + 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. }; - enum class FloatingPointMode + enum class FloatingPointMode : uint8_t { Default, Fast, Precise, }; - enum PipelineType + enum PipelineType : uint8_t { Unknown, Compute, @@ -101,7 +96,7 @@ struct DownstreamCompileOptions struct CapabilityVersion { - enum class Kind + enum class Kind : uint8_t { CUDASM, ///< What the version is for SPIRV, @@ -198,8 +193,10 @@ public: 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; - /// Some compilers have support converting a binary blob into disassembly. Output disassembly is held in the output blob - virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) = 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; /// True if underlying compiler uses file system to communicate source virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() = 0; @@ -215,7 +212,8 @@ public: // IDownstreamCompiler virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE; + 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; DownstreamCompilerBase(const Desc& desc): m_desc(desc) @@ -298,7 +296,7 @@ public: }; /* Only purpose of having base-class here is to make all the DownstreamCompiler types available directly in derived Utils */ -struct DownstreamCompilerBaseUtil +struct DownstreamCompilerUtilBase { typedef DownstreamCompileOptions CompileOptions; diff --git a/source/compiler-core/slang-downstream-dep1.cpp b/source/compiler-core/slang-downstream-dep1.cpp index 25964964f..0745fd9dc 100644 --- a/source/compiler-core/slang-downstream-dep1.cpp +++ b/source/compiler-core/slang-downstream-dep1.cpp @@ -3,8 +3,9 @@ #include "slang-artifact-util.h" #include "slang-artifact-associated-impl.h" +#include "slang-artifact-desc-util.h" -#include "../core/slang-castable-list-impl.h" +#include "../core/slang-castable-util.h" namespace Slang { @@ -45,7 +46,7 @@ void* DownstreamResultArtifactRepresentationAdapater_Dep1::castAs(const SlangUUI void* DownstreamResultArtifactRepresentationAdapater_Dep1::getInterface(const Guid& guid) { - if (guid == ISlangBlob::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid()) { @@ -85,8 +86,78 @@ SlangResult DownstreamResultArtifactRepresentationAdapater_Dep1::createRepresent /* !!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerAdapter_Dep1 !!!!!!!!!!!!!!!!!!!!!!!! */ -SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& options, IArtifact** outArtifact) +DownstreamCompilerAdapter_Dep1::DownstreamCompilerAdapter_Dep1(DownstreamCompiler_Dep1* dep, ArtifactPayload disassemblyPayload) : + m_dep(dep), + m_disassemblyPayload(disassemblyPayload) { + auto desc = dep->getDesc(); + m_desc = DownstreamCompilerDesc(desc.type, desc.majorVersion, desc.minorVersion); +} +SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& inOptions, IArtifact** outArtifact) +{ + typedef DownstreamCompileOptions_Dep1::SomeEnum SomeEnum; + + // Convert to the Deps1 compile options + + DownstreamCompileOptions_Dep1 options; + + options.optimizationLevel = SomeEnum(inOptions.optimizationLevel); + options.debugInfoType = SomeEnum(inOptions.debugInfoType); + options.targetType = inOptions.targetType; + options.sourceLanguage = inOptions.sourceLanguage; + options.floatingPointMode = SomeEnum(inOptions.floatingPointMode); + options.pipelineType = SomeEnum(inOptions.pipelineType); + options.matrixLayout = inOptions.matrixLayout; + + options.flags = inOptions.flags; + options.platform = SomeEnum(inOptions.platform); + + options.modulePath = inOptions.modulePath; + + for (auto& src : inOptions.defines) + { + DownstreamCompileOptions_Dep1::Define dst; + + dst.nameWithSig = src.nameWithSig; + dst.value = src.value; + + options.defines.add(dst); + } + + options.sourceContents = inOptions.sourceContents; + options.sourceContentsPath = inOptions.sourceContentsPath; + + options.sourceFiles = inOptions.sourceFiles; + + options.includePaths = inOptions.includePaths; + options.libraryPaths = inOptions.libraryPaths; + + options.libraries = inOptions.libraries; + + for (auto& src : inOptions.requiredCapabilityVersions) + { + DownstreamCompileOptions_Dep1::CapabilityVersion capVer; + capVer.kind = SomeEnum(src.kind); + + auto& srcVer = src.version; + + capVer.version.m_major = srcVer.m_major; + capVer.version.m_minor = srcVer.m_minor; + capVer.version.m_patch = uint16_t(srcVer.m_patch); + + options.requiredCapabilityVersions.add(capVer); + } + + options.entryPointName = inOptions.entryPointName; + options.profileName = inOptions.profileName; + + options.stage = inOptions.stage; + + options.compilerSpecificArguments = inOptions.compilerSpecificArguments; + + options.fileSystemExt = inOptions.fileSystemExt; + options.sourceManager = inOptions.sourceManager; + RefPtr<DownstreamCompileResult_Dep1> result; SLANG_RETURN_ON_FAIL(m_dep->compile(options, result)); @@ -127,6 +198,36 @@ SlangResult DownstreamCompilerAdapter_Dep1::compile(const CompileOptions& option return SLANG_OK; } +bool DownstreamCompilerAdapter_Dep1::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) +{ + // Can only disassemble blobs that are DXBC + return ArtifactDescUtil::isDissassembly(from, to) && from.payload == m_disassemblyPayload; +} + +SlangResult DownstreamCompilerAdapter_Dep1::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +{ + if (!canConvert(from->getDesc(), to)) + { + return SLANG_FAIL; + } + + ComPtr<ISlangBlob> fromBlob; + SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::No, fromBlob.writeRef())); + + const auto compileTarget = ArtifactDescUtil::getCompileTargetFromDesc(from->getDesc()); + + // Do the disassembly + ComPtr<ISlangBlob> dstBlob; + SLANG_RETURN_ON_FAIL(m_dep->disassemble(compileTarget, fromBlob->getBufferPointer(), fromBlob->getBufferSize(), dstBlob.writeRef())); + + auto artifact = ArtifactUtil::createArtifact(to); + + artifact->addRepresentationUnknown(dstBlob); + + *outArtifact = artifact.detach(); + return SLANG_OK; +} + /* !!!!!!!!!!!!!!!!!!!!!!!!! SharedLibraryDep1Adapter !!!!!!!!!!!!!!!!!!!!!!!! */ // A temporary class that adapts `ISlangSharedLibrary_Dep1` to ISlangSharedLibrary diff --git a/source/compiler-core/slang-downstream-dep1.h b/source/compiler-core/slang-downstream-dep1.h index 19d8a6d68..94d3d73b8 100644 --- a/source/compiler-core/slang-downstream-dep1.h +++ b/source/compiler-core/slang-downstream-dep1.h @@ -8,6 +8,95 @@ namespace Slang { // (DEPRECIATED) + + +struct SemanticVersion_Dep1 +{ + uint32_t m_major; + uint16_t m_minor; + uint16_t m_patch; +}; + +struct DownstreamCompileOptions_Dep1 +{ + typedef uint32_t Flags; + enum class SomeEnum { First, B, C }; + + struct Define + { + String nameWithSig; ///< If macro takes parameters include in brackets + String value; + }; + + struct CapabilityVersion + { + SomeEnum kind; + SemanticVersion_Dep1 version; + }; + + SomeEnum optimizationLevel = SomeEnum::First; + SomeEnum debugInfoType = SomeEnum::First; + SlangCompileTarget targetType = SLANG_HOST_EXECUTABLE; + SlangSourceLanguage sourceLanguage = SLANG_SOURCE_LANGUAGE_CPP; + SomeEnum floatingPointMode = SomeEnum::First; + SomeEnum pipelineType = SomeEnum::First; + SlangMatrixLayoutMode matrixLayout = SLANG_MATRIX_LAYOUT_MODE_UNKNOWN; + + Flags flags = 0; + + SomeEnum platform = SomeEnum::First; + + /// 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 + String modulePath; + + List<Define> defines; + + /// The contents of the source to compile. This can be empty is sourceFiles is set. + /// If the compiler is a commandLine file this source will be written to a temporary file. + String sourceContents; + /// 'Path' that the contents originated from. NOTE! This is for reporting only and doesn't have to exist on file system + String sourceContentsPath; + + /// The names/paths of source to compile. This can be empty if sourceContents is set. + List<String> sourceFiles; + + List<String> includePaths; + List<String> libraryPaths; + + /// Libraries to link against. + List<ComPtr<IArtifact>> libraries; + + List<CapabilityVersion> requiredCapabilityVersions; + + /// For compilers/compiles that require an entry point name, else can be empty + String 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. + String profileName; + + /// The stage being compiled for + SlangStage stage = SLANG_STAGE_NONE; + + /// Arguments that are specific to a particular compiler implementation. + List<String> compilerSpecificArguments; + + /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will be ignored in those scenarios. + ISlangFileSystemExt* fileSystemExt = nullptr; + SourceManager* sourceManager = nullptr; +}; + +// Compiler description +struct DownstreamCompilerDesc_Dep1 +{ + SlangPassThrough type; ///< The type of the compiler + + /// TODO(JS): Would probably be better if changed to SemanticVersion, but not trivial to change + // because this type is part of the DownstreamCompiler interface, which is used with `slang-llvm`. + Int majorVersion; ///< Major version (interpretation is type specific) + Int minorVersion; ///< Minor version (interpretation is type specific) +}; + struct DownstreamDiagnostic_Dep1 { enum class Severity @@ -67,9 +156,9 @@ public: typedef RefObject Super; /// Get the desc of this compiler - const DownstreamCompilerDesc& getDesc() const { return m_desc; } + const DownstreamCompilerDesc_Dep1& getDesc() const { return m_desc; } /// Compile using the specified options. The result is in resOut - virtual SlangResult compile(const DownstreamCompileOptions& options, RefPtr<DownstreamCompileResult_Dep1>& outResult) = 0; + virtual SlangResult compile(const DownstreamCompileOptions_Dep1& options, RefPtr<DownstreamCompileResult_Dep1>& outResult) = 0; /// Some compilers have support converting a binary blob into disassembly. Output disassembly is held in the output blob virtual SlangResult disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out); @@ -78,24 +167,26 @@ public: protected: - DownstreamCompilerDesc m_desc; + DownstreamCompilerDesc_Dep1 m_desc; }; class DownstreamCompilerAdapter_Dep1 : public DownstreamCompilerBase { public: // IDownstreamCompiler - virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_dep->getDesc(); } + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) SLANG_OVERRIDE { return m_dep->disassemble(sourceBlobTarget, blob, blobSize, out); } + 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 m_dep->isFileBased(); } - DownstreamCompilerAdapter_Dep1(DownstreamCompiler_Dep1* dep) : - m_dep(dep) - { - } + DownstreamCompilerAdapter_Dep1(DownstreamCompiler_Dep1* dep, ArtifactPayload disassemblyPayload); protected: + + DownstreamCompilerDesc m_desc; + + ArtifactPayload m_disassemblyPayload; RefPtr<DownstreamCompiler_Dep1> m_dep; }; diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index 7a3281463..3fc7224f3 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -22,6 +22,7 @@ #include "slang-artifact-associated-impl.h" #include "slang-artifact-util.h" #include "slang-artifact-diagnostic-util.h" +#include "slang-artifact-desc-util.h" // Enable calling through to `dxc` to // generate code on Windows. @@ -164,7 +165,8 @@ public: // IDownstreamCompiler virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) 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 @@ -528,14 +530,22 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, IArtif return SLANG_OK; } -SlangResult DXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +bool DXCDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) +{ + return ArtifactDescUtil::isDissassembly(from, to) && from.payload == ArtifactPayload::DXIL; +} + +SlangResult DXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) { // Can only disassemble blobs that are DXIL - if (sourceBlobTarget != SLANG_DXIL) + if (!canConvert(from->getDesc(), to)) { return SLANG_FAIL; } + ComPtr<ISlangBlob> dxilBlob; + 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())); ComPtr<IDxcLibrary> dxcLibrary; @@ -543,13 +553,18 @@ SlangResult DXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarg // Create blob from the input data ComPtr<IDxcBlobEncoding> dxcSourceBlob; - SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned((LPBYTE)blob, (UINT32)blobSize, 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())); + auto artifact = ArtifactUtil::createArtifact(to); + // Is compatible with ISlangBlob - *out = (ISlangBlob*)dxcResultBlob.detach(); + ISlangBlob* disassemblyBlob = (ISlangBlob*)dxcResultBlob.get(); + artifact->addRepresentationUnknown(disassemblyBlob); + + *outArtifact = artifact.detach(); return SLANG_OK; } diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp index 21cd14759..c07952d2d 100644 --- a/source/compiler-core/slang-fxc-compiler.cpp +++ b/source/compiler-core/slang-fxc-compiler.cpp @@ -18,7 +18,7 @@ #include "slang-source-loc.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" @@ -118,7 +118,8 @@ public: // IDownstreamCompiler virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) 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 @@ -324,19 +325,30 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& options, IArtif return SLANG_OK; } -SlangResult FXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +bool FXCDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) { // Can only disassemble blobs that are DXBC - if (sourceBlobTarget != SLANG_DXBC) + return ArtifactDescUtil::isDissassembly(from, to) && from.payload == ArtifactPayload::DXBC; +} + +SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +{ + if (!canConvert(from->getDesc(), to)) { return SLANG_FAIL; } - ComPtr<ID3DBlob> codeBlob; - SLANG_RETURN_ON_FAIL(m_disassemble(blob, blobSize, 0, nullptr, codeBlob.writeRef())); + ComPtr<ISlangBlob> dxbcBlob; + 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())); + auto artifact = ArtifactUtil::createArtifact(to); // ISlangBlob is compatible with ID3DBlob - *out = (ISlangBlob*)codeBlob.detach(); + artifact->addRepresentationUnknown((ISlangBlob*)disassemblyBlob.get()); + + *outArtifact= artifact.detach(); return SLANG_OK; } diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index d33e72824..a4ae7fbd5 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -83,8 +83,7 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return SLANG_FAIL; } - outDesc.majorVersion = digits[0]; - outDesc.minorVersion = digits[1]; + outDesc.version.set(int(digits[0]), int(digits[1])); return SLANG_OK; } @@ -726,7 +725,7 @@ static SlangResult _parseGCCFamilyLine(CharSliceAllocator& allocator, const Unow // but that requires some more complex behavior, so we don't allow for now. auto desc = compiler->getDesc(); - if (desc.majorVersion < 5) + if (desc.version.m_major < 5) { // If the version isn't 5 or higher, we don't add this version of the compiler. return SLANG_OK; diff --git a/source/compiler-core/slang-gcc-compiler-util.h b/source/compiler-core/slang-gcc-compiler-util.h index 7f15f6701..84e68db9c 100644 --- a/source/compiler-core/slang-gcc-compiler-util.h +++ b/source/compiler-core/slang-gcc-compiler-util.h @@ -7,7 +7,7 @@ namespace Slang { /* Utility for processing input and output of gcc-like compilers, including clang */ -struct GCCDownstreamCompilerUtil : public DownstreamCompilerBaseUtil +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); diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp index 5ae9419fd..3a96ed69d 100644 --- a/source/compiler-core/slang-glslang-compiler.cpp +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -15,6 +15,7 @@ #include "../core/slang-char-util.h" #include "slang-artifact-associated-impl.h" +#include "slang-artifact-desc-util.h" #include "slang-include-system.h" #include "slang-source-loc.h" @@ -43,7 +44,8 @@ public: // IDownstreamCompiler virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) 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 @@ -217,14 +219,22 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, IA return SLANG_OK; } -SlangResult GlslangDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarget, const void* blob, size_t blobSize, ISlangBlob** out) +bool GlslangDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) { - // Can only disassemble blobs that are DXBC - if (sourceBlobTarget != SLANG_SPIRV) + // Can only disassemble blobs that are SPIR-V + return ArtifactDescUtil::isDissassembly(from, to) && from.payload == ArtifactPayload::SPIRV; +} + +SlangResult GlslangDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +{ + if (!canConvert(from->getDesc(), to)) { return SLANG_FAIL; } + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::No, blob.writeRef())); + StringBuilder builder; auto outputFunc = [](void const* data, size_t size, void* userData) @@ -240,16 +250,22 @@ SlangResult GlslangDownstreamCompiler::disassemble(SlangCompileTarget sourceBlob request.sourcePath = nullptr; - request.inputBegin = blob; - request.inputEnd = (char*)blob + blobSize; + char* blobData = (char*)blob->getBufferPointer(); + + request.inputBegin = blobData; + request.inputEnd = blobData + blob->getBufferSize(); request.outputFunc = outputFunc; request.outputUserData = &builder; SLANG_RETURN_ON_FAIL(_invoke(request)); - ComPtr<ISlangBlob> disassemblyBlob = StringUtil::createStringBlob(builder); - *out = disassemblyBlob.detach(); + auto disassemblyBlob = StringBlob::moveCreate(builder); + + auto artifact = ArtifactUtil::createArtifact(to); + artifact->addRepresentationUnknown(disassemblyBlob); + + *outArtifact = artifact.detach(); return SLANG_OK; } diff --git a/source/compiler-core/slang-llvm-compiler.cpp b/source/compiler-core/slang-llvm-compiler.cpp index e143500c0..4cb3b7260 100644 --- a/source/compiler-core/slang-llvm-compiler.cpp +++ b/source/compiler-core/slang-llvm-compiler.cpp @@ -48,7 +48,7 @@ namespace Slang SLANG_RETURN_ON_FAIL(fn(downstreamCompilerDep1)); - ComPtr<IDownstreamCompiler> downstreamCompiler(new DownstreamCompilerAdapter_Dep1(downstreamCompilerDep1)); + ComPtr<IDownstreamCompiler> downstreamCompiler(new DownstreamCompilerAdapter_Dep1(downstreamCompilerDep1, ArtifactPayload::None)); set->addSharedLibrary(library); set->addCompiler(downstreamCompiler); diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp index 683aeaedc..99a5cc346 100644 --- a/source/compiler-core/slang-nvrtc-compiler.cpp +++ b/source/compiler-core/slang-nvrtc-compiler.cpp @@ -17,6 +17,7 @@ #include "slang-artifact-diagnostic-util.h" #include "slang-artifact-util.h" +#include "slang-artifact-desc-util.h" #include "slang-artifact-associated-impl.h" namespace nvrtc @@ -104,6 +105,8 @@ public: // IDownstreamCompiler 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; /// Must be called before use SlangResult init(ISlangSharedLibrary* library); @@ -164,9 +167,7 @@ SlangResult NVRTCDownstreamCompiler::init(ISlangSharedLibrary* library) int major, minor; m_nvrtcVersion(&major, &minor); - m_desc.majorVersion = major; - m_desc.minorVersion = minor; - + m_desc.version.set(major, minor); return SLANG_OK; } @@ -734,7 +735,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& opt // Newer releases of NVRTC only support `compute_35` and up // (with everything before `compute_52` being deprecated). // - if( m_desc.majorVersion >= 11 ) + if( m_desc.version.m_major >= 11 ) { version = SemanticVersion(3, 5); } @@ -904,7 +905,31 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& opt return SLANG_OK; } +bool NVRTCDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) +{ + return ArtifactDescUtil::isDissassembly(from, to) || ArtifactDescUtil::isDissassembly(to, from); +} + +SlangResult NVRTCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +{ + if (!canConvert(from->getDesc(), to)) + { + return SLANG_FAIL; + } + + // 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 + // is simpler, and probably fine in most scenarios. + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::Yes, blob.writeRef())); + + auto artifact = ArtifactUtil::createArtifact(to); + artifact->addRepresentationUnknown(blob); + *outArtifact = artifact.detach(); + return SLANG_OK; +} static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr<ISlangSharedLibrary>& outLibrary) { diff --git a/source/compiler-core/slang-visual-studio-compiler-util.h b/source/compiler-core/slang-visual-studio-compiler-util.h index 74d7e6292..4eed9badb 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.h +++ b/source/compiler-core/slang-visual-studio-compiler-util.h @@ -7,7 +7,7 @@ namespace Slang { -struct VisualStudioCompilerUtil : public DownstreamCompilerBaseUtil +struct VisualStudioCompilerUtil : public DownstreamCompilerUtilBase { /// Calculate Visual Studio family compilers cmdLine arguments from options static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine); diff --git a/source/core/slang-castable-list-impl.cpp b/source/core/slang-castable-list-impl.cpp index dcc58e37b..1cc5dc2d4 100644 --- a/source/core/slang-castable-list-impl.cpp +++ b/source/core/slang-castable-list-impl.cpp @@ -1,71 +1,9 @@ // slang-castable-list-impl.cpp #include "slang-castable-list-impl.h" -namespace Slang { - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CastableUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ +#include "slang-castable-util.h" -/* static */ComPtr<ICastable> CastableUtil::getCastable(ISlangUnknown* unk) -{ - SLANG_ASSERT(unk); - ComPtr<ICastable> castable; - if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef()))) - { - SLANG_ASSERT(castable); - } - else - { - castable = new UnknownCastableAdapter(unk); - } - return castable; -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnknownCastableAdapter !!!!!!!!!!!!!!!!!!!!!!!!!!! */ - -void* UnknownCastableAdapter::castAs(const Guid& guid) -{ - if (auto intf = getInterface(guid)) - { - return intf; - } - if (auto obj = getObject(guid)) - { - return obj; - } - - if (m_found && guid == m_foundGuid) - { - return m_found; - } - - ComPtr<ISlangUnknown> cast; - if (SLANG_SUCCEEDED(m_contained->queryInterface(guid, (void**)cast.writeRef())) && cast) - { - // Save the interface in the cache - m_found = cast; - m_foundGuid = guid; - - return cast; - } - return nullptr; -} - -void* UnknownCastableAdapter::getInterface(const Guid& guid) -{ - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || - guid == IUnknownCastableAdapter::getTypeGuid()) - { - return static_cast<IUnknownCastableAdapter*>(this); - } - return nullptr; -} - -void* UnknownCastableAdapter::getObject(const Guid& guid) -{ - SLANG_UNUSED(guid); - return nullptr; -} +namespace Slang { /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CastableList !!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -166,18 +104,7 @@ void CastableList::clear() void CastableList::addUnknown(ISlangUnknown* unk) { - // If it has ICastable interface we can just add as that - { - ComPtr<ICastable> castable; - if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) - { - return add(castable); - } - } - - // Wrap it in an adapter - IUnknownCastableAdapter* adapter = new UnknownCastableAdapter(unk); - add(adapter); + add(CastableUtil::getCastable(unk)); } Index CastableList::indexOfUnknown(ISlangUnknown* unk) @@ -202,6 +129,7 @@ Index CastableList::indexOfUnknown(ISlangUnknown* unk) return i; } } + return -1; } diff --git a/source/core/slang-castable-list-impl.h b/source/core/slang-castable-list-impl.h index 2ce124ce7..7a7f98a6a 100644 --- a/source/core/slang-castable-list-impl.h +++ b/source/core/slang-castable-list-impl.h @@ -1,4 +1,4 @@ -// slang-castable-list.h +// slang-castable-list-impl.h #ifndef SLANG_CASTABLE_LIST_IMPL_H #define SLANG_CASTABLE_LIST_IMPL_H @@ -12,42 +12,8 @@ namespace Slang { -/* An adapter such that types which aren't derived from ICastable, can be used as such. - -With the following caveats. -* the interfaces/objects of the adapter are checked *first*, so IUnknown will always be for the adapter -* assumes when doing a queryInterface on the contained item, it will remain in scope when released (this is *not* strict COM) -*/ -class UnknownCastableAdapter : public ComBaseObject, public IUnknownCastableAdapter -{ -public: - SLANG_COM_BASE_IUNKNOWN_ALL - - // ICastable - SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - - // IUnknownCastableAdapter - virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() SLANG_OVERRIDE { return m_contained; } - - UnknownCastableAdapter(ISlangUnknown* unk): - m_contained(unk) - { - SLANG_ASSERT(unk); - } - -protected: - void* getInterface(const Guid& guid); - void* getObject(const Guid& guid); - - ComPtr<ISlangUnknown> m_contained; - - // We hold a cache for a single lookup to make things a little faster - void* m_found = nullptr; - Guid m_foundGuid; -}; - /* Implementation of the ICastableList interface. -Is atomic reference counted*/ +Is atomic reference counted */ class CastableList : public ComBaseObject, public ICastableList { public: @@ -72,17 +38,12 @@ public: /// Dtor virtual ~CastableList(); -protected: void* getInterface(const Guid& guid); void* getObject(const Guid& guid); - List<ICastable*> m_list; -}; +protected: -struct CastableUtil -{ - /// Given an unk return as an unk - static ComPtr<ICastable> getCastable(ISlangUnknown* unk); + List<ICastable*> m_list; }; } // namespace Slang diff --git a/source/core/slang-castable-util.cpp b/source/core/slang-castable-util.cpp new file mode 100644 index 000000000..408e36cb3 --- /dev/null +++ b/source/core/slang-castable-util.cpp @@ -0,0 +1,70 @@ +// slang-castable-util.cpp +#include "slang-castable-util.h" + +namespace Slang { + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CastableUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */ComPtr<ICastable> CastableUtil::getCastable(ISlangUnknown* unk) +{ + SLANG_ASSERT(unk); + ComPtr<ICastable> castable; + if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef()))) + { + SLANG_ASSERT(castable); + } + else + { + castable = new UnknownCastableAdapter(unk); + } + return castable; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnknownCastableAdapter !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* UnknownCastableAdapter::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + if (auto obj = getObject(guid)) + { + return obj; + } + + if (m_found && guid == m_foundGuid) + { + return m_found; + } + + ComPtr<ISlangUnknown> cast; + if (SLANG_SUCCEEDED(m_contained->queryInterface(guid, (void**)cast.writeRef())) && cast) + { + // Save the interface in the cache + m_found = cast; + m_foundGuid = guid; + + return cast; + } + return nullptr; +} + +void* UnknownCastableAdapter::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IUnknownCastableAdapter::getTypeGuid()) + { + return static_cast<IUnknownCastableAdapter*>(this); + } + return nullptr; +} + +void* UnknownCastableAdapter::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +} // namespace Slang diff --git a/source/core/slang-castable-util.h b/source/core/slang-castable-util.h new file mode 100644 index 000000000..4d3c3900c --- /dev/null +++ b/source/core/slang-castable-util.h @@ -0,0 +1,58 @@ +// slang-castable-util.h +#ifndef SLANG_CASTABLE_UTIL_H +#define SLANG_CASTABLE_UTIL_H + +#include "slang-castable-list.h" + +#include "../../slang-com-helper.h" +#include "../../slang-com-ptr.h" + +#include "../core/slang-com-object.h" + +namespace Slang +{ + +/* An adapter such that types which aren't derived from ICastable, can be used as such. + +With the following caveats. +* the interfaces/objects of the adapter are checked *first*, so IUnknown will always be for the adapter +* assumes when doing a queryInterface on the contained item, it will remain in scope when released (this is *not* strict COM) +*/ +class UnknownCastableAdapter : public ComBaseObject, public IUnknownCastableAdapter +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IUnknownCastableAdapter + virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() SLANG_OVERRIDE { return m_contained; } + + UnknownCastableAdapter(ISlangUnknown* unk): + m_contained(unk) + { + SLANG_ASSERT(unk); + } + +protected: + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); + + ComPtr<ISlangUnknown> m_contained; + + // We hold a cache for a single lookup to make things a little faster + void* m_found = nullptr; + Guid m_foundGuid; +}; + +struct CastableUtil +{ + /// Given an ISlangUnkown return as a castable interface. + /// Can use UnknownCastableAdapter if can't queryInterface unk to ICastable + static ComPtr<ICastable> getCastable(ISlangUnknown* unk); +}; + +} // namespace Slang + +#endif diff --git a/source/core/slang-platform.h b/source/core/slang-platform.h index ff7f1ccd9..c8bea747f 100644 --- a/source/core/slang-platform.h +++ b/source/core/slang-platform.h @@ -7,7 +7,7 @@ namespace Slang { - enum class PlatformKind + enum class PlatformKind : uint8_t { Unknown, WinRT, @@ -48,7 +48,7 @@ namespace Slang }; }; - enum class PlatformFamily + enum class PlatformFamily : uint8_t { Unknown, Windows, diff --git a/source/core/slang-semantic-version.cpp b/source/core/slang-semantic-version.cpp index cc631d292..550ea993b 100644 --- a/source/core/slang-semantic-version.cpp +++ b/source/core/slang-semantic-version.cpp @@ -26,16 +26,16 @@ SlangResult SemanticVersion::parse(const UnownedStringSlice& value, char separat { SLANG_RETURN_ON_FAIL(StringUtil::parseInt(slices[i], ints[i])); - const Int max = (i == 0) ? 0x7fffffff : 0xffff; + const Int max = (i == 2) ? 0x7fffffff : 0xffff; if (ints[i] < 0 || ints[i] > max) { return SLANG_FAIL; } } - outVersion.m_major = uint32_t(ints[0]); + outVersion.m_major = uint16_t(ints[0]); outVersion.m_minor = uint16_t(ints[1]); - outVersion.m_patch = uint16_t(ints[2]); + outVersion.m_patch = uint32_t(ints[2]); return SLANG_OK; } @@ -50,7 +50,7 @@ void SemanticVersion::append(StringBuilder& buf) const buf << Int32(m_major) << "." << Int32(m_minor); if (m_patch != 0) { - buf << "." << Int32(m_patch); + buf << "." << UInt32(m_patch); } } @@ -90,8 +90,6 @@ void SemanticVersion::append(StringBuilder& buf) const return bestVersion; } - - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MatchSemanticVersion !!!!!!!!!!!!!!!!!!!!!!!!!!!!! /* static */SemanticVersion MatchSemanticVersion::findAnyBest(const SemanticVersion* versions, Count count, const ThisType& matchVersion) diff --git a/source/core/slang-semantic-version.h b/source/core/slang-semantic-version.h index 4d64627c2..e7f10eeed 100644 --- a/source/core/slang-semantic-version.h +++ b/source/core/slang-semantic-version.h @@ -3,6 +3,7 @@ #define SLANG_SEMANTIC_VERSION_H #include "../core/slang-basic.h" +#include "../core/slang-hash.h" namespace Slang { @@ -14,10 +15,11 @@ struct SemanticVersion typedef uint64_t IntegerType; SemanticVersion():m_major(0), m_minor(0), m_patch(0) {} + SemanticVersion(int inMajor, int inMinor = 0, int inPatch = 0): - m_major(uint32_t(inMajor)), + m_major(uint16_t(inMajor)), m_minor(uint16_t(inMinor)), - m_patch(uint16_t(inPatch)) + m_patch(uint32_t(inPatch)) {} void reset() @@ -30,20 +32,23 @@ struct SemanticVersion /// All zeros means nothing is set bool isSet() const { return m_major || m_minor || m_patch; } - IntegerType toInteger() const { return (IntegerType(m_major) << 32) | (uint32_t(m_minor) << 16) | m_patch; } + IntegerType toInteger() const { return (IntegerType(m_major) << 48) | (IntegerType(m_minor) << 32) | m_patch; } void setFromInteger(IntegerType v) { - set(int(v >> 32), int((v >> 16) & 0xffff), int(v & 0xffff)); + set(int(v >> 48), int((v >> 32) & 0xffff), int(v & 0xffffffff)); } void set(int major, int minor, int patch = 0) { SLANG_ASSERT(major >= 0 && minor >=0 && patch >= 0); - m_major = uint32_t(major); + m_major = uint16_t(major); m_minor = uint16_t(minor); - m_patch = uint16_t(patch); + m_patch = uint32_t(patch); } + /// Get hash value + HashCode getHashCode() const { return Slang::getHashCode(toInteger()); } + static SlangResult parse(const UnownedStringSlice& value, SemanticVersion& outVersion); static SlangResult parse(const UnownedStringSlice& value, char separatorChar, SemanticVersion& outVersion); @@ -61,9 +66,9 @@ struct SemanticVersion bool operator==(const ThisType& rhs) const { return toInteger() == rhs.toInteger(); } bool operator!=(const ThisType& rhs) const { return toInteger() != rhs.toInteger(); } - uint32_t m_major; + uint16_t m_major; uint16_t m_minor; - uint16_t m_patch; + uint32_t m_patch; ///< Patch number. Can actually be quite large for some code bases. }; /* Adds to the semantic versioning information for an incomplete version that can be matched */ diff --git a/source/slang/slang-artifact-output-util.cpp b/source/slang/slang-artifact-output-util.cpp index ccf49ed30..ac4138020 100644 --- a/source/slang/slang-artifact-output-util.cpp +++ b/source/slang/slang-artifact-output-util.cpp @@ -17,32 +17,28 @@ namespace Slang { -// Given a desc returns a codegen target if it can be used for disassembly -// Returns Unknown if cannot be used for generating disassembly -// -// NOTE! This returns the code gen target for the input binary, *not* the dissassembly output -static CodeGenTarget _getDisassemblyCodeGenTarget(const ArtifactDesc& desc) -{ - switch (desc.payload) - { - case ArtifactPayload::DXIL: return CodeGenTarget::DXIL; - case ArtifactPayload::DXBC: return CodeGenTarget::DXBytecode; - case ArtifactPayload::SPIRV: return CodeGenTarget::SPIRV; - default: break; - } - return CodeGenTarget::Unknown; -} - /* static */SlangResult ArtifactOutputUtil::dissassembleWithDownstream(Session* session, IArtifact* artifact, DiagnosticSink* sink, IArtifact** outArtifact) { auto desc = artifact->getDesc(); + auto assemblyDesc = desc; + assemblyDesc.kind = ArtifactKind::Assembly; + + // Check it seems like a plausbile disassembly + if (!ArtifactDescUtil::isDissassembly(desc, assemblyDesc)) + { + if (sink) + { + sink->diagnose(SourceLoc(), Diagnostics::cannotDisassemble, ArtifactDescUtil::getText(desc)); + } + return SLANG_FAIL; + } // Get the downstream compiler that can be used for this target // TODO(JS): // This could perhaps be performed in some other manner if there was more than one way to produce // disassembly from a binary. - const CodeGenTarget target = _getDisassemblyCodeGenTarget(desc); + const CodeGenTarget target = (CodeGenTarget)ArtifactDescUtil::getCompileTargetFromDesc(desc); if (target == CodeGenTarget::Unknown) { return SLANG_FAIL; @@ -63,40 +59,26 @@ static CodeGenTarget _getDisassemblyCodeGenTarget(const ArtifactDesc& desc) return SLANG_FAIL; } - ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(artifact->loadBlob(ArtifactKeep::No, blob.writeRef())); - - const auto data = blob->getBufferPointer(); - const auto dataSizeInBytes = blob->getBufferSize(); - - ComPtr<ISlangBlob> dissassemblyBlob; - SLANG_RETURN_ON_FAIL(compiler->disassemble(SlangCompileTarget(target), data, dataSizeInBytes, dissassemblyBlob.writeRef())); + SLANG_RETURN_ON_FAIL(compiler->convert(artifact, assemblyDesc, outArtifact)); - ArtifactDesc disassemblyDesc(desc); - disassemblyDesc.kind = ArtifactKind::Assembly; - - auto disassemblyArtifact = ArtifactUtil::createArtifact(disassemblyDesc); - disassemblyArtifact->addRepresentationUnknown(dissassemblyBlob); - - *outArtifact = disassemblyArtifact.detach(); return SLANG_OK; } SlangResult ArtifactOutputUtil::maybeDisassemble(Session* session, IArtifact* artifact, DiagnosticSink* sink, ComPtr<IArtifact>& outArtifact) { const auto desc = artifact->getDesc(); - if (ArtifactDescUtil::isText(artifact->getDesc())) + if (ArtifactDescUtil::isText(desc)) { // Nothing to convert return SLANG_OK; } - if (_getDisassemblyCodeGenTarget(desc) != CodeGenTarget::Unknown) - { - // Get the blob - ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(artifact->loadBlob(ArtifactKeep::No, blob.writeRef())); + auto toDesc = desc; + toDesc.kind = ArtifactKind::Assembly; + // If this likes a playsible disassebly conversion + if (ArtifactDescUtil::isDissassembly(desc, toDesc)) + { ComPtr<IArtifact> disassemblyArtifact; if (SLANG_SUCCEEDED(dissassembleWithDownstream(session, artifact, sink, disassemblyArtifact.writeRef()))) diff --git a/source/slang/slang-artifact-output-util.h b/source/slang/slang-artifact-output-util.h index 948b3ce7a..3c8b2cfc7 100644 --- a/source/slang/slang-artifact-output-util.h +++ b/source/slang/slang-artifact-output-util.h @@ -18,7 +18,7 @@ struct ArtifactOutputUtil /// Attempts to disassembly artifact into outArtifact. /// Errors are output to sink if set. If not desired pass nullptr static SlangResult dissassembleWithDownstream(Session* session, IArtifact* artifact, DiagnosticSink* sink, IArtifact** outArtifact); - + /// Disassembles if that is plausible /// Errors are output to sink if set. If not desired pass nullptr static SlangResult maybeDisassemble(Session* session, IArtifact* artifact, DiagnosticSink* sink, ComPtr<IArtifact>& outArtifact); diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 811359d71..14be426d6 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -596,6 +596,7 @@ DIAGNOSTIC(52000, Error, multiLevelBreakUnsupported, "control flow appears to re DIAGNOSTIC(52001, Warning, dxilNotFound, "dxil shared library not found, so 'dxc' output cannot be signed! Shader code will not be runnable in non-development environments.") DIAGNOSTIC(52002, Error, passThroughCompilerNotFound, "could not find a suitable pass-through compiler for '$0'.") +DIAGNOSTIC(52003, Error, cannotDisassemble, "cannot disassemble '$0'.") DIAGNOSTIC(52004, Error, unableToWriteFile, "unable to write file '$0'") DIAGNOSTIC(52005, Error, unableToReadFile, "unable to read file '$0'") |
