1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // spirv_types.h:
7 //   Strong types for SPIR-V Ids to prevent mistakes when using the builder and parser APIs.
8 //
9 
10 #ifndef COMMON_SPIRV_TYPES_H_
11 #define COMMON_SPIRV_TYPES_H_
12 
13 #include "common/FastVector.h"
14 
15 #include <vector>
16 
17 namespace angle
18 {
19 namespace spirv
20 {
21 template <typename Helper>
22 class BoxedUint32
23 {
24   public:
BoxedUint32()25     BoxedUint32() : mValue{0} {}
BoxedUint32(uint32_t value)26     explicit BoxedUint32(uint32_t value) : mValue{value} {}
27     template <typename T>
as()28     T as() const
29     {
30         return T{mValue};
31     }
32     BoxedUint32(const BoxedUint32 &other) = default;
33     BoxedUint32 &operator=(const BoxedUint32 &other) = default;
uint32_t()34     operator uint32_t() const { return mValue.value; }
35     bool operator==(const BoxedUint32 &other) const { return mValue.value == other.mValue.value; }
36     // Applicable to ids, which cannot be 0.
valid()37     bool valid() const { return static_cast<bool>(mValue.value); }
38 
39   private:
40     Helper mValue;
41 };
42 
43 struct IdRefHelper
44 {
45     uint32_t value;
46 };
47 struct LiteralIntegerHelper
48 {
49     uint32_t value;
50 };
51 
52 using IdRef = BoxedUint32<IdRefHelper>;
53 
54 template <>
uint32_t()55 inline BoxedUint32<IdRefHelper>::operator uint32_t() const
56 {
57     ASSERT(valid());
58     return mValue.value;
59 }
60 
61 // IdResult, IdResultType, IdMemorySemantics and IdScope are all translated as IdRef.  This makes
62 // the type verification weaker, but stops the API from becoming tediously verbose.
63 using IdResult          = IdRef;
64 using IdResultType      = IdRef;
65 using IdMemorySemantics = IdRef;
66 using IdScope           = IdRef;
67 using LiteralInteger    = BoxedUint32<LiteralIntegerHelper>;
68 using LiteralString     = const char *;
69 // Note: In ANGLE's use cases, all literals fit in 32 bits.
70 using LiteralContextDependentNumber = LiteralInteger;
71 // TODO(syoussefi): To be made stronger when generating SPIR-V from the translator.
72 // http://anglebug.com/4889
73 using LiteralExtInstInteger = LiteralInteger;
74 
75 struct PairLiteralIntegerIdRef
76 {
77     LiteralInteger literal;
78     IdRef id;
79 };
80 
81 struct PairIdRefLiteralInteger
82 {
83     IdRef id;
84     LiteralInteger literal;
85 };
86 
87 struct PairIdRefIdRef
88 {
89     IdRef id1;
90     IdRef id2;
91 };
92 
93 // Some instructions need 4 components.  The drivers uniform struct in ANGLE has 8 fields.  A value
94 // of 8 means almost no instruction would end up making dynamic allocations.  Notable exceptions are
95 // user-defined structs/blocks and OpEntryPoint.
96 constexpr size_t kFastVectorSize = 8;
97 
98 template <typename T>
99 using FastVectorHelper = angle::FastVector<T, kFastVectorSize>;
100 
101 using IdRefList                   = FastVectorHelper<IdRef>;
102 using LiteralIntegerList          = FastVectorHelper<LiteralInteger>;
103 using PairLiteralIntegerIdRefList = FastVectorHelper<PairLiteralIntegerIdRef>;
104 using PairIdRefLiteralIntegerList = FastVectorHelper<PairIdRefLiteralInteger>;
105 using PairIdRefIdRefList          = FastVectorHelper<PairIdRefIdRef>;
106 
107 // Id 0 is invalid in SPIR-V.
108 constexpr uint32_t kMinValidId = 1;
109 
110 // The SPIR-V blob is a sequence of uint32_t's
111 using Blob = std::vector<uint32_t>;
112 
113 // Returns whether SPIR-V is valid.  Useful for ASSERTs.  Automatically generates a warning if
114 // SPIR-V is not valid.
115 bool Validate(const Blob &blob);
116 
117 }  // namespace spirv
118 }  // namespace angle
119 
120 #endif  // COMMON_SPIRV_TYPES_H_
121