diff options
Diffstat (limited to 'source/compiler-core')
22 files changed, 482 insertions, 84 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); |
