summaryrefslogtreecommitdiffstats
path: root/source/compiler-core/slang-spirv-core-grammar.h
blob: 87ac898d881afb5e005178359cb15da5ba627b98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#pragma once

#include "../core/slang-dictionary.h"
#include "../core/slang-smart-pointer.h"
#include "../core/slang-string-slice-pool.h"
#include "../core/slang-string.h"

#include <optional>
#include <spirv/unified1/NonSemanticShaderDebugInfo100.h>
#include <spirv/unified1/spirv.h>

namespace Slang
{
using SpvWord = uint32_t;
class DiagnosticSink;
class SourceView;

struct SPIRVCoreGrammarInfo : public RefObject
{
    static RefPtr<SPIRVCoreGrammarInfo> loadFromJSON(SourceView& source, DiagnosticSink& sink);
    static RefPtr<SPIRVCoreGrammarInfo>& getEmbeddedVersion();
    static inline void freeEmbeddedGrammerInfo() { getEmbeddedVersion() = nullptr; }

    template<typename K, typename T>
    struct Lookup
    {
        std::optional<T> lookup(const K& name) const
        {
            T ret;
            if (embedded ? embedded(name, ret) : dict.tryGetValue(name, ret))
                return ret;
            else
                return std::nullopt;
        }

        bool (*embedded)(const K&, T&) = nullptr;
        Dictionary<K, T> dict;
    };

    struct OperandKind
    {
        uint8_t index;
        SLANG_COMPONENTWISE_HASHABLE_1;
        SLANG_COMPONENTWISE_EQUALITY_1(OperandKind);
    };

    struct QualifiedEnumName
    {
        OperandKind kind;
        UnownedStringSlice name;
        SLANG_COMPONENTWISE_HASHABLE_2;
        SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumName);
    };

    struct QualifiedEnumValue
    {
        OperandKind kind;
        SpvWord value;
        SLANG_COMPONENTWISE_HASHABLE_2;
        SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumValue);
    };

    struct OpInfo
    {
        enum Class
        {
            // Unrecognized instructions go in here
            Other,

            // Adding to this? Don't forget to update the embedding generator
            Miscellaneous,
            Debug,
            Annotation,
            Extension,
            ModeSetting,
            TypeDeclaration,
            ConstantCreation,
            Memory,
            Function,
            Image,
            Conversion,
            Composite,
            Arithmetic,
            Bit,
            Relational_and_Logical,
            Derivative,
            ControlFlow,
            Atomic,
            Primitive,
            Barrier,
            Group,
            DeviceSideEnqueue,
            Pipe,
            NonUniform,
            Reserved,
        };
        constexpr static int8_t kNoResultTypeId = -1;
        constexpr static int8_t kNoResultId = -1;

        Class class_;
        // -1 or 0
        int8_t resultTypeIndex = kNoResultTypeId;
        // -1 or 0 or 1
        int8_t resultIdIndex = kNoResultId;
        // The range of valid operand counts for this instruction,
        // including any result type and id. Multi-word operands count as a
        // single operand.
        uint16_t minOperandCount;
        uint16_t maxOperandCount;
        // when looking up an operand type, clamp to this number-1 to
        // account for variable length operands at the end
        uint16_t numOperandTypes;
        const OperandKind* operandTypes;
    };

    //
    // Our tables:
    //

    // Instruction name to opcode
    Lookup<UnownedStringSlice, SpvOp> opcodes;
    // Capability name to value
    Lookup<UnownedStringSlice, SpvCapability> capabilities;
    // String-qualified enum name (one with the type prefix) to value
    Lookup<UnownedStringSlice, SpvWord> allEnumsWithTypePrefix;
    // kind * enum name to value
    Lookup<QualifiedEnumName, SpvWord> allEnums;
    // kine * enum value to unqualified name
    Lookup<QualifiedEnumValue, UnownedStringSlice> allEnumNames;
    // Any other information on instructions
    Lookup<SpvOp, OpInfo> opInfos;
    // Opcode to instruction name
    Lookup<SpvOp, UnownedStringSlice> opNames;
    // Operand kind string to numeric id
    Lookup<UnownedStringSlice, OperandKind> operandKinds;
    // Operand kind id to string
    Lookup<OperandKind, UnownedStringSlice> operandKindNames;
    // Operand kind to the "un-id" version of itself, for example IdMemorySemantics to
    // MemorySemantics
    Lookup<OperandKind, OperandKind> operandKindUnderneathIds;

private:
    // If this is loaded from JSON, we keep the strings around instead of
    // copying them as dictionary keys
    StringSlicePool strings = StringSlicePool(StringSlicePool::Style::Empty);
    List<OperandKind> operandTypesStorage;
};
} // namespace Slang