Raw File
diagnostics.h
#ifndef RASTER_RENDERER_COMPILE_ERROR_H
#define RASTER_RENDERER_COMPILE_ERROR_H

#include "../core/basic.h"

#include "source-loc.h"
#include "token.h"

#include "../../slang.h"

namespace Slang
{
    enum class Severity
    {
        Note,
        Warning,
        Error,
        Fatal,
        Internal,
    };

    // TODO(tfoley): move this into a source file...
    inline const char* getSeverityName(Severity severity)
    {
        switch (severity)
        {
        case Severity::Note:        return "note";
        case Severity::Warning:     return "warning";
        case Severity::Error:       return "error";
        case Severity::Fatal:       return "fatal error";
        case Severity::Internal:    return "internal error";
        default:                    return "unknown error";
        }
    }

    // A structure to be used in static data describing different
    // diagnostic messages.
    struct DiagnosticInfo
    {
        int id;
        Severity severity;
        char const* messageFormat;
    };

    class Diagnostic
    {
    public:
        String Message;
        SourceLoc loc;
        int ErrorID;
        Severity severity;

        Diagnostic()
        {
            ErrorID = -1;
        }
        Diagnostic(
            const String & msg,
            int id,
            const SourceLoc & pos,
            Severity severity)
            : severity(severity)
        {
            Message = msg;
            ErrorID = id;
            loc = pos;
        }
    };

    class Name;
    class Decl;
    class Type;
    struct TypeExp;
    struct QualType;

    enum class CodeGenTarget;
    enum class Stage : SlangStage;
    enum class ProfileVersion;

    void printDiagnosticArg(StringBuilder& sb, char const* str);
    void printDiagnosticArg(StringBuilder& sb, int val);
    void printDiagnosticArg(StringBuilder& sb, UInt val);
    void printDiagnosticArg(StringBuilder& sb, Slang::String const& str);
    void printDiagnosticArg(StringBuilder& sb, Slang::UnownedStringSlice const& str);
    void printDiagnosticArg(StringBuilder& sb, Name* name);
    void printDiagnosticArg(StringBuilder& sb, Decl* decl);
    void printDiagnosticArg(StringBuilder& sb, Type* type);
    void printDiagnosticArg(StringBuilder& sb, TypeExp const& type);
    void printDiagnosticArg(StringBuilder& sb, QualType const& type);
    void printDiagnosticArg(StringBuilder& sb, TokenType tokenType);
    void printDiagnosticArg(StringBuilder& sb, Token const& token);
    void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val);
    void printDiagnosticArg(StringBuilder& sb, Stage val);
    void printDiagnosticArg(StringBuilder& sb, ProfileVersion val);

    template<typename T>
    void printDiagnosticArg(StringBuilder& sb, RefPtr<T> ptr)
    {
        printDiagnosticArg(sb, ptr.Ptr());
    }

    inline SourceLoc const& getDiagnosticPos(SourceLoc const& pos) { return pos;  }

    class SyntaxNode;
    SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax);
    SourceLoc const& getDiagnosticPos(Token const& token);
    SourceLoc const& getDiagnosticPos(TypeExp const& typeExp);

    struct IRInst;
    SourceLoc const& getDiagnosticPos(IRInst* inst);

    template<typename T>
    SourceLoc getDiagnosticPos(RefPtr<T> const& ptr)
    {
        return getDiagnosticPos(ptr.Ptr());
    }

    struct DiagnosticArg
    {
        void* data;
        void (*printFunc)(StringBuilder&, void*);

        template<typename T>
        struct Helper
        {
            static void printFunc(StringBuilder& sb, void* data) { printDiagnosticArg(sb, *(T*)data); }
        };

        template<typename T>
        DiagnosticArg(T const& arg)
            : data((void*)&arg)
            , printFunc(&Helper<T>::printFunc)
        {}
    };

    class DiagnosticSink
    {
    public:
        // The source manager to use when mapping source locations to file+line info
        SourceManager*  sourceManager;

        StringBuilder outputBuffer;
//            List<Diagnostic> diagnostics;
        int errorCount = 0;

        SlangDiagnosticCallback callback            = nullptr;
        void*                   callbackUserData    = nullptr;

/*
        void Error(int id, const String & msg, const SourceLoc & pos)
        {
            diagnostics.Add(Diagnostic(msg, id, pos, Severity::Error));
            errorCount++;
        }

        void Warning(int id, const String & msg, const SourceLoc & pos)
        {
            diagnostics.Add(Diagnostic(msg, id, pos, Severity::Warning));
        }
*/
        int GetErrorCount() { return errorCount; }

        void diagnoseDispatch(SourceLoc const& pos, DiagnosticInfo const& info)
        {
            diagnoseImpl(pos, info, 0, NULL);
        }

        void diagnoseDispatch(SourceLoc const& pos, DiagnosticInfo const& info, DiagnosticArg const& arg0)
        {
            DiagnosticArg const* args[] = { &arg0 };
            diagnoseImpl(pos, info, 1, args);
        }

        void diagnoseDispatch(SourceLoc const& pos, DiagnosticInfo const& info, DiagnosticArg const& arg0, DiagnosticArg const& arg1)
        {
            DiagnosticArg const* args[] = { &arg0, &arg1 };
            diagnoseImpl(pos, info, 2, args);
        }

        void diagnoseDispatch(SourceLoc const& pos, DiagnosticInfo const& info, DiagnosticArg const& arg0, DiagnosticArg const& arg1, DiagnosticArg const& arg2)
        {
            DiagnosticArg const* args[] = { &arg0, &arg1, &arg2 };
            diagnoseImpl(pos, info, 3, args);
        }

        void diagnoseDispatch(SourceLoc const& pos, DiagnosticInfo const& info, DiagnosticArg const& arg0, DiagnosticArg const& arg1, DiagnosticArg const& arg2, DiagnosticArg const& arg3)
        {
            DiagnosticArg const* args[] = { &arg0, &arg1, &arg2, &arg3 };
            diagnoseImpl(pos, info, 4, args);
        }

        template<typename P, typename... Args>
        void diagnose(P const& pos, DiagnosticInfo const& info, Args const&... args )
        {
            diagnoseDispatch(getDiagnosticPos(pos), info, args...);
        }

        void diagnoseImpl(SourceLoc const& pos, DiagnosticInfo const& info, int argCount, DiagnosticArg const* const* args);

        // Add a diagnostic with raw text
        // (used when we get errors from a downstream compiler)
        void diagnoseRaw(
            Severity    severity,
            char const* message);
    };

    namespace Diagnostics
    {
#define DIAGNOSTIC(id, severity, name, messageFormat) extern const DiagnosticInfo name;
#include "diagnostic-defs.h"
    }
}

#ifdef _DEBUG
#define SLANG_INTERNAL_ERROR(sink, pos) \
    (sink)->diagnose(Slang::SourceLoc(__LINE__, 0, 0, __FILE__), Slang::Diagnostics::internalCompilerError)
#define SLANG_UNIMPLEMENTED(sink, pos, what) \
    (sink)->diagnose(Slang::SourceLoc(__LINE__, 0, 0, __FILE__), Slang::Diagnostics::unimplemented, what)

#else
#define SLANG_INTERNAL_ERROR(sink, pos) \
    (sink)->diagnose(pos, Slang::Diagnostics::internalCompilerError)
#define SLANG_UNIMPLEMENTED(sink, pos, what) \
    (sink)->diagnose(pos, Slang::Diagnostics::unimplemented, what)

#endif

#define SLANG_DIAGNOSE_UNEXPECTED(sink, pos, message) \
    (sink)->diagnose(pos, Slang::Diagnostics::unexpected, message)

#endif
back to top