diff options
Diffstat (limited to 'source/slang/slang-pass-through.cpp')
| -rw-r--r-- | source/slang/slang-pass-through.cpp | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/source/slang/slang-pass-through.cpp b/source/slang/slang-pass-through.cpp new file mode 100644 index 000000000..268cbc98f --- /dev/null +++ b/source/slang/slang-pass-through.cpp @@ -0,0 +1,275 @@ +// slang-pass-through.cpp +#include "slang-pass-through.h" + +#include "../core/slang-type-text-util.h" +#include "compiler-core/slang-slice-allocator.h" +#include "slang-compiler.h" + +namespace Slang +{ + +void printDiagnosticArg(StringBuilder& sb, PassThroughMode val) +{ + sb << TypeTextUtil::getPassThroughName(SlangPassThrough(val)); +} + +SourceLanguage getDefaultSourceLanguageForDownstreamCompiler(PassThroughMode compiler) +{ + switch (compiler) + { + case PassThroughMode::None: + { + return SourceLanguage::Unknown; + } + case PassThroughMode::Fxc: + case PassThroughMode::Dxc: + { + return SourceLanguage::HLSL; + } + case PassThroughMode::Glslang: + { + return SourceLanguage::GLSL; + } + case PassThroughMode::LLVM: + case PassThroughMode::Clang: + case PassThroughMode::VisualStudio: + case PassThroughMode::Gcc: + case PassThroughMode::GenericCCpp: + { + // These could ingest C, but we only have this function to work out a + // 'default' language to ingest. + return SourceLanguage::CPP; + } + case PassThroughMode::NVRTC: + { + return SourceLanguage::CUDA; + } + case PassThroughMode::Tint: + { + return SourceLanguage::WGSL; + } + case PassThroughMode::SpirvDis: + { + return SourceLanguage::SPIRV; + } + case PassThroughMode::MetalC: + { + return SourceLanguage::Metal; + } + default: + break; + } + SLANG_ASSERT(!"Unknown compiler"); + return SourceLanguage::Unknown; +} + +PassThroughMode getDownstreamCompilerRequiredForTarget(CodeGenTarget target) +{ + switch (target) + { + // Don't *require* a downstream compiler for source output + case CodeGenTarget::GLSL: + case CodeGenTarget::HLSL: + case CodeGenTarget::CUDASource: + case CodeGenTarget::CPPSource: + case CodeGenTarget::HostCPPSource: + case CodeGenTarget::PyTorchCppBinding: + case CodeGenTarget::CSource: + case CodeGenTarget::Metal: + case CodeGenTarget::WGSL: + { + return PassThroughMode::None; + } + case CodeGenTarget::None: + { + return PassThroughMode::None; + } + case CodeGenTarget::WGSLSPIRVAssembly: + case CodeGenTarget::SPIRVAssembly: + case CodeGenTarget::SPIRV: + { + return PassThroughMode::SpirvDis; + } + case CodeGenTarget::DXBytecode: + case CodeGenTarget::DXBytecodeAssembly: + { + return PassThroughMode::Fxc; + } + case CodeGenTarget::DXIL: + case CodeGenTarget::DXILAssembly: + { + return PassThroughMode::Dxc; + } + case CodeGenTarget::MetalLib: + case CodeGenTarget::MetalLibAssembly: + { + return PassThroughMode::MetalC; + } + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::ShaderSharedLibrary: + case CodeGenTarget::HostExecutable: + case CodeGenTarget::HostHostCallable: + case CodeGenTarget::HostSharedLibrary: + { + // We need some C/C++ compiler + return PassThroughMode::GenericCCpp; + } + case CodeGenTarget::PTX: + { + return PassThroughMode::NVRTC; + } + case CodeGenTarget::WGSLSPIRV: + { + return PassThroughMode::Tint; + } + default: + break; + } + + SLANG_ASSERT(!"Unhandled target"); + return PassThroughMode::None; +} + + +void reportExternalCompileError( + const char* compilerName, + Severity severity, + SlangResult res, + const UnownedStringSlice& diagnostic, + DiagnosticSink* sink) +{ + StringBuilder builder; + if (compilerName) + { + builder << compilerName << ": "; + } + + if (SLANG_FAILED(res) && res != SLANG_FAIL) + { + { + char tmp[17]; + sprintf_s(tmp, SLANG_COUNT_OF(tmp), "0x%08x", uint32_t(res)); + builder << "Result(" << tmp << ") "; + } + + PlatformUtil::appendResult(res, builder); + } + + if (diagnostic.getLength() > 0) + { + builder.append(diagnostic); + if (!diagnostic.endsWith("\n")) + { + builder.append("\n"); + } + } + + sink->diagnoseRaw(severity, builder.getUnownedSlice()); +} + +void reportExternalCompileError( + const char* compilerName, + SlangResult res, + const UnownedStringSlice& diagnostic, + DiagnosticSink* sink) +{ + // TODO(tfoley): need a better policy for how we translate diagnostics + // back into the Slang world (although we should always try to generate + // HLSL that doesn't produce any diagnostics...) + reportExternalCompileError( + compilerName, + SLANG_FAILED(res) ? Severity::Error : Severity::Warning, + res, + diagnostic, + sink); +} + +static Severity _getDiagnosticSeverity(ArtifactDiagnostic::Severity severity) +{ + switch (severity) + { + case ArtifactDiagnostic::Severity::Warning: + return Severity::Warning; + case ArtifactDiagnostic::Severity::Info: + return Severity::Note; + default: + return Severity::Error; + } +} + +SlangResult passthroughDownstreamDiagnostics( + DiagnosticSink* sink, + IDownstreamCompiler* compiler, + IArtifact* artifact) +{ + auto diagnostics = findAssociatedRepresentation<IArtifactDiagnostics>(artifact); + + if (!diagnostics) + return SLANG_OK; + + if (diagnostics->getCount()) + { + StringBuilder compilerText; + DownstreamCompilerUtil::appendAsText(compiler->getDesc(), compilerText); + + StringBuilder builder; + + auto const diagnosticCount = diagnostics->getCount(); + for (Index i = 0; i < diagnosticCount; ++i) + { + const auto& diagnostic = *diagnostics->getAt(i); + + builder.clear(); + + const Severity severity = _getDiagnosticSeverity(diagnostic.severity); + + if (diagnostic.filePath.count == 0 && diagnostic.location.line == 0 && + severity == Severity::Note) + { + // If theres no filePath line number and it's info, output severity and text alone + builder << getSeverityName(severity) << " : "; + } + else + { + if (diagnostic.filePath.count) + { + builder << asStringSlice(diagnostic.filePath); + } + + if (diagnostic.location.line) + { + builder << "(" << diagnostic.location.line << ")"; + } + + builder << ": "; + + if (diagnostic.stage == ArtifactDiagnostic::Stage::Link) + { + builder << "link "; + } + + builder << getSeverityName(severity); + builder << " " << asStringSlice(diagnostic.code) << ": "; + } + + builder << asStringSlice(diagnostic.text); + reportExternalCompileError( + compilerText.getBuffer(), + severity, + SLANG_OK, + builder.getUnownedSlice(), + sink); + } + } + + // If any errors are emitted, then we are done + if (diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error)) + { + return SLANG_FAIL; + } + + return SLANG_OK; +} + + +} // namespace Slang |
