summaryrefslogtreecommitdiff
path: root/tests/preprocessor
AgeCommit message (Expand)Author
2020-08-18Support for float atomics on RWByteAddressBuffer (#1502)jsmall-nvidia
2020-07-10Fix a preprocessor bug affecting X-macros (#1436)Tim Foley
2020-01-31Fix for a macro expansion bug (#1192)Tim Foley
2020-01-24Fix for infinite recursion with macro invocation (#1177)jsmall-nvidia
2019-08-19Testing using a 'naked' ISlangFileSystemExt option. (#1026)jsmall-nvidia
2019-08-15A more convoluted #pragma once file identity test, using relative paths. (#1021)jsmall-nvidia
2019-03-02#include not using search paths (#873)jsmall-nvidia
2019-02-13Ignore expression if hit #if when skipping. (#844)jsmall-nvidia
2019-01-21Path simplification/hash mode, plus bug fixes (#788)jsmall-nvidia
2019-01-17Feature/hash for source identity (#786)jsmall-nvidia
2018-10-16Feature/include refactor (#675)jsmall-nvidia
2018-08-27Add basic support for #pragma once (#630)Tim Foley
2018-05-11Add tests for custom #error and #warning messages (#562)Tim Foley
2018-01-26Fix handling of errors in imported modules (#387)Tim Foley
2017-10-09Preprocessor: fix `undef` and redefinition (#204)Tim Foley
2017-08-10Make source location lightweightTim Foley
2017-07-10Cleanups for test cases:Tim Foley
2017-06-26Make `#import` work with preprocessor macrosTim Foley
2017-06-14AppVeyor: Run tests as part of AppVeyor buildsTim Foley
2017-06-12Add test case for escaped newlines.Tim Foley
2017-06-12Rename tests from `*.spire` to `*.slang`Tim Foley
2017-06-09Initial import of code.Tim Foley
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 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