annotate win64-msvc/include/capnp/raw-schema.h @ 166:cbd6d7e562c7

Merge build update
author Chris Cannam <cannam@all-day-breakfast.com>
date Thu, 31 Oct 2019 13:36:58 +0000
parents b4bfdf10c4b3
children
rev   line source
cannam@148 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@148 2 // Licensed under the MIT License:
cannam@148 3 //
cannam@148 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@148 5 // of this software and associated documentation files (the "Software"), to deal
cannam@148 6 // in the Software without restriction, including without limitation the rights
cannam@148 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@148 8 // copies of the Software, and to permit persons to whom the Software is
cannam@148 9 // furnished to do so, subject to the following conditions:
cannam@148 10 //
cannam@148 11 // The above copyright notice and this permission notice shall be included in
cannam@148 12 // all copies or substantial portions of the Software.
cannam@148 13 //
cannam@148 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@148 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@148 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@148 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@148 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@148 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@148 20 // THE SOFTWARE.
cannam@148 21
cannam@148 22 #ifndef CAPNP_RAW_SCHEMA_H_
cannam@148 23 #define CAPNP_RAW_SCHEMA_H_
cannam@148 24
cannam@148 25 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
cannam@148 26 #pragma GCC system_header
cannam@148 27 #endif
cannam@148 28
cannam@148 29 #include "common.h" // for uint and friends
cannam@148 30
cannam@148 31 #if _MSC_VER
cannam@148 32 #include <atomic>
cannam@148 33 #endif
cannam@148 34
cannam@148 35 namespace capnp {
cannam@148 36 namespace _ { // private
cannam@148 37
cannam@148 38 struct RawSchema;
cannam@148 39
cannam@148 40 struct RawBrandedSchema {
cannam@148 41 // Represents a combination of a schema and bindings for its generic parameters.
cannam@148 42 //
cannam@148 43 // Note that while we generate one `RawSchema` per type, we generate a `RawBrandedSchema` for
cannam@148 44 // every _instance_ of a generic type -- or, at least, every instance that is actually used. For
cannam@148 45 // generated-code types, we use template magic to initialize these.
cannam@148 46
cannam@148 47 const RawSchema* generic;
cannam@148 48 // Generic type which we're branding.
cannam@148 49
cannam@148 50 struct Binding {
cannam@148 51 uint8_t which; // Numeric value of one of schema::Type::Which.
cannam@148 52
cannam@148 53 bool isImplicitParameter;
cannam@148 54 // For AnyPointer, true if it's an implicit method parameter.
cannam@148 55
cannam@148 56 uint16_t listDepth; // Number of times to wrap the base type in List().
cannam@148 57
cannam@148 58 uint16_t paramIndex;
cannam@148 59 // For AnyPointer. If it's a type parameter (scopeId is non-zero) or it's an implicit parameter
cannam@148 60 // (isImplicitParameter is true), then this is the parameter index. Otherwise this is a numeric
cannam@148 61 // value of one of schema::Type::AnyPointer::Unconstrained::Which.
cannam@148 62
cannam@148 63 union {
cannam@148 64 const RawBrandedSchema* schema; // for struct, enum, interface
cannam@148 65 uint64_t scopeId; // for AnyPointer, if it's a type parameter
cannam@148 66 };
cannam@148 67
cannam@148 68 Binding() = default;
cannam@148 69 inline constexpr Binding(uint8_t which, uint16_t listDepth, const RawBrandedSchema* schema)
cannam@148 70 : which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(0),
cannam@148 71 schema(schema) {}
cannam@148 72 inline constexpr Binding(uint8_t which, uint16_t listDepth,
cannam@148 73 uint64_t scopeId, uint16_t paramIndex)
cannam@148 74 : which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(paramIndex),
cannam@148 75 scopeId(scopeId) {}
cannam@148 76 inline constexpr Binding(uint8_t which, uint16_t listDepth, uint16_t implicitParamIndex)
cannam@148 77 : which(which), isImplicitParameter(true), listDepth(listDepth),
cannam@148 78 paramIndex(implicitParamIndex), scopeId(0) {}
cannam@148 79 };
cannam@148 80
cannam@148 81 struct Scope {
cannam@148 82 uint64_t typeId;
cannam@148 83 // Type ID whose parameters are being bound.
cannam@148 84
cannam@148 85 const Binding* bindings;
cannam@148 86 uint bindingCount;
cannam@148 87 // Bindings for those parameters.
cannam@148 88
cannam@148 89 bool isUnbound;
cannam@148 90 // This scope is unbound, in the sense of SchemaLoader::getUnbound().
cannam@148 91 };
cannam@148 92
cannam@148 93 const Scope* scopes;
cannam@148 94 // Array of enclosing scopes for which generic variables have been bound, sorted by type ID.
cannam@148 95
cannam@148 96 struct Dependency {
cannam@148 97 uint location;
cannam@148 98 const RawBrandedSchema* schema;
cannam@148 99 };
cannam@148 100
cannam@148 101 const Dependency* dependencies;
cannam@148 102 // Map of branded schemas for dependencies of this type, given our brand. Only dependencies that
cannam@148 103 // are branded are included in this map; if a dependency is missing, use its `defaultBrand`.
cannam@148 104
cannam@148 105 uint32_t scopeCount;
cannam@148 106 uint32_t dependencyCount;
cannam@148 107
cannam@148 108 enum class DepKind {
cannam@148 109 // Component of a Dependency::location. Specifies what sort of dependency this is.
cannam@148 110
cannam@148 111 INVALID,
cannam@148 112 // Mostly defined to ensure that zero is not a valid location.
cannam@148 113
cannam@148 114 FIELD,
cannam@148 115 // Binding needed for a field's type. The index is the field index (NOT ordinal!).
cannam@148 116
cannam@148 117 METHOD_PARAMS,
cannam@148 118 // Bindings needed for a method's params type. The index is the method number.
cannam@148 119
cannam@148 120 METHOD_RESULTS,
cannam@148 121 // Bindings needed for a method's results type. The index is the method ordinal.
cannam@148 122
cannam@148 123 SUPERCLASS,
cannam@148 124 // Bindings needed for a superclass type. The index is the superclass's index in the
cannam@148 125 // "extends" list.
cannam@148 126
cannam@148 127 CONST_TYPE
cannam@148 128 // Bindings needed for the type of a constant. The index is zero.
cannam@148 129 };
cannam@148 130
cannam@148 131 static inline uint makeDepLocation(DepKind kind, uint index) {
cannam@148 132 // Make a number representing the location of a particular dependency within its parent
cannam@148 133 // schema.
cannam@148 134
cannam@148 135 return (static_cast<uint>(kind) << 24) | index;
cannam@148 136 }
cannam@148 137
cannam@148 138 class Initializer {
cannam@148 139 public:
cannam@148 140 virtual void init(const RawBrandedSchema* generic) const = 0;
cannam@148 141 };
cannam@148 142
cannam@148 143 const Initializer* lazyInitializer;
cannam@148 144 // Lazy initializer, invoked by ensureInitialized().
cannam@148 145
cannam@148 146 inline void ensureInitialized() const {
cannam@148 147 // Lazy initialization support. Invoke to ensure that initialization has taken place. This
cannam@148 148 // is required in particular when traversing the dependency list. RawSchemas for compiled-in
cannam@148 149 // types are always initialized; only dynamically-loaded schemas may be lazy.
cannam@148 150
cannam@148 151 #if __GNUC__
cannam@148 152 const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE);
cannam@148 153 #elif _MSC_VER
cannam@148 154 const Initializer* i = *static_cast<Initializer const* const volatile*>(&lazyInitializer);
cannam@148 155 std::atomic_thread_fence(std::memory_order_acquire);
cannam@148 156 #else
cannam@148 157 #error "Platform not supported"
cannam@148 158 #endif
cannam@148 159 if (i != nullptr) i->init(this);
cannam@148 160 }
cannam@148 161
cannam@148 162 inline bool isUnbound() const;
cannam@148 163 // Checks if this schema is the result of calling SchemaLoader::getUnbound(), in which case
cannam@148 164 // binding lookups need to be handled specially.
cannam@148 165 };
cannam@148 166
cannam@148 167 struct RawSchema {
cannam@148 168 // The generated code defines a constant RawSchema for every compiled declaration.
cannam@148 169 //
cannam@148 170 // This is an internal structure which could change in the future.
cannam@148 171
cannam@148 172 uint64_t id;
cannam@148 173
cannam@148 174 const word* encodedNode;
cannam@148 175 // Encoded SchemaNode, readable via readMessageUnchecked<schema::Node>(encodedNode).
cannam@148 176
cannam@148 177 uint32_t encodedSize;
cannam@148 178 // Size of encodedNode, in words.
cannam@148 179
cannam@148 180 const RawSchema* const* dependencies;
cannam@148 181 // Pointers to other types on which this one depends, sorted by ID. The schemas in this table
cannam@148 182 // may be uninitialized -- you must call ensureInitialized() on the one you wish to use before
cannam@148 183 // using it.
cannam@148 184 //
cannam@148 185 // TODO(someday): Make this a hashtable.
cannam@148 186
cannam@148 187 const uint16_t* membersByName;
cannam@148 188 // Indexes of members sorted by name. Used to implement name lookup.
cannam@148 189 // TODO(someday): Make this a hashtable.
cannam@148 190
cannam@148 191 uint32_t dependencyCount;
cannam@148 192 uint32_t memberCount;
cannam@148 193 // Sizes of above tables.
cannam@148 194
cannam@148 195 const uint16_t* membersByDiscriminant;
cannam@148 196 // List of all member indexes ordered by discriminant value. Those which don't have a
cannam@148 197 // discriminant value are listed at the end, in order by ordinal.
cannam@148 198
cannam@148 199 const RawSchema* canCastTo;
cannam@148 200 // Points to the RawSchema of a compiled-in type to which it is safe to cast any DynamicValue
cannam@148 201 // with this schema. This is null for all compiled-in types; it is only set by SchemaLoader on
cannam@148 202 // dynamically-loaded types.
cannam@148 203
cannam@148 204 class Initializer {
cannam@148 205 public:
cannam@148 206 virtual void init(const RawSchema* schema) const = 0;
cannam@148 207 };
cannam@148 208
cannam@148 209 const Initializer* lazyInitializer;
cannam@148 210 // Lazy initializer, invoked by ensureInitialized().
cannam@148 211
cannam@148 212 inline void ensureInitialized() const {
cannam@148 213 // Lazy initialization support. Invoke to ensure that initialization has taken place. This
cannam@148 214 // is required in particular when traversing the dependency list. RawSchemas for compiled-in
cannam@148 215 // types are always initialized; only dynamically-loaded schemas may be lazy.
cannam@148 216
cannam@148 217 #if __GNUC__
cannam@148 218 const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE);
cannam@148 219 #elif _MSC_VER
cannam@148 220 const Initializer* i = *static_cast<Initializer const* const volatile*>(&lazyInitializer);
cannam@148 221 std::atomic_thread_fence(std::memory_order_acquire);
cannam@148 222 #else
cannam@148 223 #error "Platform not supported"
cannam@148 224 #endif
cannam@148 225 if (i != nullptr) i->init(this);
cannam@148 226 }
cannam@148 227
cannam@148 228 RawBrandedSchema defaultBrand;
cannam@148 229 // Specifies the brand to use for this schema if no generic parameters have been bound to
cannam@148 230 // anything. Generally, in the default brand, all generic parameters are treated as if they were
cannam@148 231 // bound to `AnyPointer`.
cannam@148 232 };
cannam@148 233
cannam@148 234 inline bool RawBrandedSchema::isUnbound() const {
cannam@148 235 // The unbound schema is the only one that has no scopes but is not the default schema.
cannam@148 236 return scopeCount == 0 && this != &generic->defaultBrand;
cannam@148 237 }
cannam@148 238
cannam@148 239 } // namespace _ (private)
cannam@148 240 } // namespace capnp
cannam@148 241
cannam@148 242 #endif // CAPNP_RAW_SCHEMA_H_