1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef SRC_PROGRAM_ID_H_
16 #define SRC_PROGRAM_ID_H_
17
18 #include <stdint.h>
19 #include <iostream>
20 #include <utility>
21
22 #include "src/debug.h"
23
24 namespace tint {
25
26 /// If 1 then checks are enabled that AST nodes are not leaked from one program
27 /// to another.
28 /// TODO(bclayton): We'll want to disable this in production builds. For now we
29 /// always check.
30 #define TINT_CHECK_FOR_CROSS_PROGRAM_LEAKS 1
31
32 /// A ProgramID is a unique identifier of a Program.
33 /// ProgramID can be used to ensure that objects referenced by the Program are
34 /// owned exclusively by that Program and have accidentally not leaked from
35 /// another Program.
36 class ProgramID {
37 public:
38 /// Constructor
39 ProgramID();
40
41 /// @returns a new. globally unique ProgramID
42 static ProgramID New();
43
44 /// Equality operator
45 /// @param rhs the other ProgramID
46 /// @returns true if the ProgramIDs are equal
47 bool operator==(const ProgramID& rhs) const { return val == rhs.val; }
48
49 /// Inequality operator
50 /// @param rhs the other ProgramID
51 /// @returns true if the ProgramIDs are not equal
52 bool operator!=(const ProgramID& rhs) const { return val != rhs.val; }
53
54 /// @returns the numerical identifier value
Value()55 uint32_t Value() const { return val; }
56
57 /// @returns true if this ProgramID is valid
58 operator bool() const { return val != 0; }
59
60 private:
61 explicit ProgramID(uint32_t);
62
63 uint32_t val = 0;
64 };
65
66 /// A simple pass-through function for ProgramID. Intended to be overloaded for
67 /// other types.
68 /// @param id a ProgramID
69 /// @returns id. Simple pass-through function
ProgramIDOf(ProgramID id)70 inline ProgramID ProgramIDOf(ProgramID id) {
71 return id;
72 }
73
74 /// Writes the ProgramID to the std::ostream.
75 /// @param out the std::ostream to write to
76 /// @param id the program identifier to write
77 /// @returns out so calls can be chained
78 inline std::ostream& operator<<(std::ostream& out, ProgramID id) {
79 out << "Program<" << id.Value() << ">";
80 return out;
81 }
82
83 namespace detail {
84
85 /// AssertProgramIDsEqual is called by TINT_ASSERT_PROGRAM_IDS_EQUAL() and
86 /// TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID() to assert that the ProgramIDs
87 /// `a` and `b` are equal.
88 void AssertProgramIDsEqual(ProgramID a,
89 ProgramID b,
90 bool if_valid,
91 diag::System system,
92 const char* msg,
93 const char* file,
94 size_t line);
95
96 } // namespace detail
97
98 /// TINT_ASSERT_PROGRAM_IDS_EQUAL(SYSTEM, A, B) is a macro that asserts that the
99 /// program identifiers for A and B are equal.
100 ///
101 /// TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(SYSTEM, A, B) is a macro that asserts
102 /// that the program identifiers for A and B are equal, if both A and B have
103 /// valid program identifiers.
104 #if TINT_CHECK_FOR_CROSS_PROGRAM_LEAKS
105 #define TINT_ASSERT_PROGRAM_IDS_EQUAL(system, a, b) \
106 detail::AssertProgramIDsEqual( \
107 ProgramIDOf(a), ProgramIDOf(b), false, tint::diag::System::system, \
108 "TINT_ASSERT_PROGRAM_IDS_EQUAL(" #system "," #a ", " #b ")", __FILE__, \
109 __LINE__)
110 #define TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(system, a, b) \
111 detail::AssertProgramIDsEqual( \
112 ProgramIDOf(a), ProgramIDOf(b), true, tint::diag::System::system, \
113 "TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(" #system ", " #a ", " #b ")", \
114 __FILE__, __LINE__)
115 #else
116 #define TINT_ASSERT_PROGRAM_IDS_EQUAL(a, b) \
117 do { \
118 } while (false)
119 #define TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(a, b) \
120 do { \
121 } while (false)
122 #endif
123
124 } // namespace tint
125
126 #endif // SRC_PROGRAM_ID_H_
127