1// 2// Copyright (C) 2024 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17package vulkan_xml 18 19import ( 20 "berberis/cpp_types" 21 "berberis/vulkan_types" 22 "encoding/xml" 23 "errors" 24 "fmt" 25 "regexp" 26 "sort" 27 "strconv" 28 "strings" 29) 30 31// Vulkan XML includes one platform entity which has many sub entities. 32// We need XMLName for root elements, but validity of all other entities 33// is guaranteed because of XML attributes. 34type registry struct { 35 XMLName xml.Name `xml:"registry"` 36 Platforms []platformInfo `xml:"platforms>platform"` 37 Tags []tagInfo `xml:"tags>tag"` 38 Types []typeInfo `xml:"types>type"` 39 Enums []enumInfo `xml:"enums"` 40 Commands []commandInfo `xml:"commands>command"` 41 Extensions []struct { 42 Name string `xml:"name,attr"` 43 ID int64 `xml:"number,attr"` 44 Requires []struct { 45 EnumFields []enumFieldInfo `xml:"enum"` 46 } `xml:"require"` 47 } `xml:"extensions>extension"` 48 Features []struct { 49 EnumFields []enumFieldInfo `xml:"enum"` 50 } `xml:"feature>require"` 51 Comments string `xml:"comment"` 52} 53 54type platformInfo struct { 55 Name string `xml:"name,attr"` 56 Comment string `xml:"comment,attr"` 57} 58 59type tagInfo struct { 60 Name string `xml:"name,attr"` 61 Author string `xml:"author,attr"` 62 Contact string `xml:"contact,attr"` 63 Comment string `xml:"comment,attr"` 64} 65 66type typeInfo struct { 67 Name string `xml:"name,attr"` 68 Category string `xml:"category,attr"` 69 Requires string `xml:"requires,attr"` 70 Alias string `xml:"alias,attr"` 71 Members []structuralMemberInfo `xml:"member"` 72 StructExtends string `xml:"structextends,attr"` 73 RawXML string `xml:",innerxml"` 74 Comment string `xml:"comment,attr"` 75 Api string `xml:"api,attr"` 76} 77 78type enumInfo struct { 79 Name string `xml:"name,attr"` 80 EnumFields []enumFieldInfo `xml:"enum"` 81} 82 83type enumFieldInfo struct { 84 Name string `xml:"name,attr"` 85 Alias string `xml:"alias,attr"` 86 Value string `xml:"value,attr"` 87 BitPos string `xml:"bitpos,attr"` 88 Dir string `xml:"dir,attr"` 89 Extends string `xml:"extends,attr"` 90 ExtID int64 `xml:"extnumber,attr"` 91 Offset int64 `xml:"offset,attr"` 92} 93 94type commandInfo struct { 95 Name string `xml:"name,attr"` 96 Alias string `xml:"alias,attr"` 97 Proto struct { 98 Type string `xml:"type,attr"` 99 RawXML string `xml:",innerxml"` 100 Comment string `xml:"comment,attr"` 101 } `xml:"proto"` 102 Params []structuralMemberInfo `xml:"param"` 103 RawXML string `xml:",innerxml"` 104} 105 106type structuralMemberInfo struct { 107 Name string `xml:"name,attr"` 108 Type string `xml:"type,attr"` 109 Value string `xml:"values,attr"` 110 Length string `xml:"len,attr"` 111 AltLength string `xml:"altlen,attr"` 112 Validstructs string `xml:"validstructs,attr"` 113 RawXML string `xml:",innerxml"` 114 Comment string `xml:"comment,attr"` 115 Api string `xml:"api,attr"` 116} 117 118type ExtendedStructInfo interface { 119 ExtendedWith() []cpp_types.Type 120 OptionalStruct() bool 121 OptionalValue() string 122} 123 124func ExtendedStruct(base_struct cpp_types.Type, optional_struct bool, optional_value string) cpp_types.Type { 125 return &extendedStruct{base_struct, []cpp_types.Type{}, optional_struct, optional_value} 126} 127 128type extendedStruct struct { 129 cpp_types.Type 130 extended_with []cpp_types.Type 131 optional_struct bool 132 optional_value string 133} 134 135func (extended_struct *extendedStruct) ExtendedWith() []cpp_types.Type { 136 return extended_struct.extended_with 137} 138 139func (extended_struct *extendedStruct) OptionalStruct() bool { 140 return extended_struct.optional_struct 141} 142 143func (extended_struct *extendedStruct) OptionalValue() string { 144 return extended_struct.optional_value 145} 146 147func ExtendedField(name string, typе cpp_types.Type, length, field cpp_types.FieldInfo) cpp_types.FieldInfo { 148 return &extendedField{cpp_types.Field(name, typе), length, field} 149} 150 151type ExtendedFieldInfo interface { 152 Length() cpp_types.FieldInfo 153 NestedField() cpp_types.FieldInfo 154} 155 156type extendedField struct { 157 cpp_types.FieldInfo 158 length cpp_types.FieldInfo 159 nested_field cpp_types.FieldInfo 160} 161 162func (field_info *extendedField) BaseFieldInfo() cpp_types.FieldInfo { 163 return field_info 164} 165 166func (field_info *extendedField) Length() cpp_types.FieldInfo { 167 return field_info.length 168} 169 170func (field_info *extendedField) NestedField() cpp_types.FieldInfo { 171 return field_info.nested_field 172} 173 174// Certain types come from platform files and vk.xml doesn't declare them. 175// Not even category name is specified, so we have no idea if these are types 176// or includes or anything else. 177var known_types = map[string]string{ 178 "_screen_context": "screen/screen.h", 179 "_screen_window": "screen/screen.h", 180 "_screen_buffer": "screen/screen.h", 181 "NvSciSyncAttrList": "nvscisync.h", 182 "NvSciSyncObj": "nvscisync.h", 183 "NvSciSyncFence": "nvscisync.h", 184 "NvSciBufAttrList": "nvscibuf.h", 185 "NvSciBufObj": "nvscibuf.h", 186 "char": "vk_platform", 187 "Display": "X11/Xlib.h", 188 "DWORD": "windows.h", 189 "float": "vk_platform", 190 "double": "vk_platform", 191 "GgpFrameToken": "ggp_c/vulkan_types.h", 192 "GgpStreamDescriptor": "ggp_c/vulkan_types.h", 193 "HANDLE": "windows.h", 194 "HINSTANCE": "windows.h", 195 "HMONITOR": "windows.h", 196 "HWND": "windows.h", 197 "IDirectFB": "directfb.h", 198 "IDirectFBSurface": "directfb.h", 199 "int": "", 200 "int8_t": "vk_platform", 201 "int16_t": "vk_platform", 202 "int32_t": "vk_platform", 203 "int64_t": "vk_platform", 204 "LPCWSTR": "windows.h", 205 "RROutput": "X11/extensions/Xrandr.h", 206 "SECURITY_ATTRIBUTES": "windows.h", 207 "size_t": "vk_platform", 208 "StdVideoDecodeH264Mvc": "vk_video/vulkan_video_codec_h264std_decode.h", 209 "StdVideoDecodeH264MvcElement": "vk_video/vulkan_video_codec_h264std_decode.h", 210 "StdVideoDecodeH264MvcElementFlags": "vk_video/vulkan_video_codec_h264std_decode.h", 211 "StdVideoDecodeH264PictureInfo": "vk_video/vulkan_video_codec_h264std_decode.h", 212 "StdVideoDecodeH264PictureInfoFlags": "vk_video/vulkan_video_codec_h264std_decode.h", 213 "StdVideoDecodeH264ReferenceInfo": "vk_video/vulkan_video_codec_h264std_decode.h", 214 "StdVideoDecodeH264ReferenceInfoFlags": "vk_video/vulkan_video_codec_h264std_decode.h", 215 "StdVideoDecodeH265PictureInfo": "vk_video/vulkan_video_codec_h265std_decode.h", 216 "StdVideoDecodeH265PictureInfoFlags": "vk_video/vulkan_video_codec_h265std_decode.h", 217 "StdVideoDecodeH265ReferenceInfo": "vk_video/vulkan_video_codec_h265std_decode.h", 218 "StdVideoDecodeH265ReferenceInfoFlags": "vk_video/vulkan_video_codec_h265std_decode.h", 219 "StdVideoEncodeH264PictureInfo": "vk_video/vulkan_video_codec_h264std_encode.h", 220 "StdVideoEncodeH264PictureInfoFlags": "vk_video/vulkan_video_codec_h264std_encode.h", 221 "StdVideoEncodeH264RefListModEntry": "vk_video/vulkan_video_codec_h264std_encode.h", 222 "StdVideoEncodeH264RefMemMgmtCtrlOperations": "vk_video/vulkan_video_codec_h264std_encode.h", 223 "StdVideoEncodeH264RefMgmtFlags": "vk_video/vulkan_video_codec_h264std_encode.h", 224 "StdVideoEncodeH264RefPicMarkingEntry": "vk_video/vulkan_video_codec_h264std_encode.h", 225 "StdVideoEncodeH264ReferenceInfo": "vk_video/vulkan_video_codec_h264std_encode.h", 226 "StdVideoEncodeH264ReferenceListsInfo": "vk_video/vulkan_video_codec_h264std_encode.h", 227 "StdVideoEncodeH264ReferenceInfoFlags": "vk_video/vulkan_video_codec_h264std_encode.h", 228 "StdVideoEncodeH264SliceHeader": "vk_video/vulkan_video_codec_h264std_encode.h", 229 "StdVideoEncodeH264SliceHeaderFlags": "vk_video/vulkan_video_codec_h264std_encode.h", 230 "StdVideoEncodeH265PictureInfo": "vk_video/vulkan_video_codec_h265std_encode.h", 231 "StdVideoEncodeH265PictureInfoFlags": "vk_video/vulkan_video_codec_h265std_encode.h", 232 "StdVideoEncodeH265ReferenceInfo": "vk_video/vulkan_video_codec_h265std_encode.h", 233 "StdVideoEncodeH265ReferenceListsInfo": "vk_video/vulkan_video_codec_h265std_encode.h", 234 "StdVideoEncodeH265ReferenceInfoFlags": "vk_video/vulkan_video_codec_h265std_encode.h", 235 "StdVideoEncodeH265ReferenceModificationFlags": "vk_video/vulkan_video_codec_h265std_encode.h", 236 "StdVideoEncodeH265ReferenceModifications": "vk_video/vulkan_video_codec_h265std_encode.h", 237 "StdVideoEncodeH265SliceHeader": "vk_video/vulkan_video_codec_h265std_encode.h", 238 "StdVideoEncodeH265SliceHeaderFlags": "vk_video/vulkan_video_codec_h265std_encode.h", 239 "StdVideoEncodeH265SliceSegmentHeader": "vk_video/vulkan_video_codec_h265std_encode.h", 240 "StdVideoEncodeH265SliceSegmentHeaderFlags": "vk_video/vulkan_video_codec_h265std_encode.h", 241 "StdVideoH264AspectRatioIdc": "vk_video/vulkan_video_codec_h264std.h", 242 "StdVideoH264CabacInitIdc": "vk_video/vulkan_video_codec_h264std.h", 243 "StdVideoH264ChromaFormatIdc": "vk_video/vulkan_video_codec_h264std.h", 244 "StdVideoH264DisableDeblockingFilterIdc": "vk_video/vulkan_video_codec_h264std.h", 245 "StdVideoH264HrdParameters": "vk_video/vulkan_video_codec_h264std.h", 246 "StdVideoH264Level": "vk_video/vulkan_video_codec_h264std.h", 247 "StdVideoH264LevelIdc": "vk_video/vulkan_video_codec_h264std.h", 248 "StdVideoH264MemMgmtControlOp": "vk_video/vulkan_video_codec_h264std.h", 249 "StdVideoH264ModificationOfPicNumsIdc": "vk_video/vulkan_video_codec_h264std.h", 250 "StdVideoH264PictureParameterSet": "vk_video/vulkan_video_codec_h264std.h", 251 "StdVideoH264PictureType": "vk_video/vulkan_video_codec_h264std.h", 252 "StdVideoH264PocType": "vk_video/vulkan_video_codec_h264std.h", 253 "StdVideoH264PpsFlags": "vk_video/vulkan_video_codec_h264std.h", 254 "StdVideoH264ProfileIdc": "vk_video/vulkan_video_codec_h264std.h", 255 "StdVideoH264ScalingLists": "vk_video/vulkan_video_codec_h264std.h", 256 "StdVideoH264SequenceParameterSet": "vk_video/vulkan_video_codec_h264std.h", 257 "StdVideoH264SequenceParameterSetVui": "vk_video/vulkan_video_codec_h264std.h", 258 "StdVideoH264SliceType": "vk_video/vulkan_video_codec_h264std.h", 259 "StdVideoH264SpsFlags": "vk_video/vulkan_video_codec_h264std.h", 260 "StdVideoH264SpsVuiFlags": "vk_video/vulkan_video_codec_h264std.h", 261 "StdVideoH264WeightedBiPredIdc": "vk_video/vulkan_video_codec_h264std.h", 262 "StdVideoH264WeightedBipredIdc": "vk_video/vulkan_video_codec_h264std.h", 263 "StdVideoH265PictureParameterSet": "vk_video/vulkan_video_codec_h265std.h", 264 "StdVideoH265DecPicBufMgr": "vk_video/vulkan_video_codec_h265std.h", 265 "StdVideoH265HrdFlags": "vk_video/vulkan_video_codec_h265std.h", 266 "StdVideoH265HrdParameters": "vk_video/vulkan_video_codec_h265std.h", 267 "StdVideoH265Level": "vk_video/vulkan_video_codec_h265std.h", 268 "StdVideoH265LevelIdc": "vk_video/vulkan_video_codec_h265std.h", 269 "StdVideoH265PictureType": "vk_video/vulkan_video_codec_h265std.h", 270 "StdVideoH265PpsFlags": "vk_video/vulkan_video_codec_h265std.h", 271 "StdVideoH265PredictorPaletteEntries": "vk_video/vulkan_video_codec_h265std.h", 272 "StdVideoH265ProfileIdc": "vk_video/vulkan_video_codec_h265std.h", 273 "StdVideoH265ScalingLists": "vk_video/vulkan_video_codec_h265std.h", 274 "StdVideoH265SequenceParameterSet": "vk_video/vulkan_video_codec_h265std.h", 275 "StdVideoH265SequenceParameterSetVui": "vk_video/vulkan_video_codec_h265std.h", 276 "StdVideoH265SliceType": "vk_video/vulkan_video_codec_h265std.h", 277 "StdVideoH265SpsFlags": "vk_video/vulkan_video_codec_h265std.h", 278 "StdVideoH265SpsVuiFlags": "vk_video/vulkan_video_codec_h265std.h", 279 "StdVideoH265SubLayerHrdParameters": "vk_video/vulkan_video_codec_h265std.h", 280 "StdVideoH265VideoParameterSet": "vk_video/vulkan_video_codec_h265std.h", 281 "StdVideoH265VpsFlags": "vk_video/vulkan_video_codec_h265std.h", 282 "uint8_t": "vk_platform", 283 "uint16_t": "vk_platform", 284 "uint32_t": "vk_platform", 285 "uint64_t": "vk_platform", 286 "VisualID": "X11/Xlib.h", 287 "void": "vk_platform", 288 "Window": "X11/Xlib.h", 289 "wl_display": "wayland-client.h", 290 "wl_surface": "wayland-client.h", 291 "xcb_connection_t": "xcb/xcb.h", 292 "xcb_visualid_t": "xcb/xcb.h", 293 "xcb_window_t": "xcb/xcb.h", 294 "zx_handle_t": "zircon/types.h", 295} 296 297// We don't really parse defines since we don't have a full-blown compiler. 298// Instead we rely on the fact that there are very few defines in vk.xml and just verify that they match out assumptions. 299var known_defines = map[string]string{ 300 "VK_MAKE_VERSION": "// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead.\n" + 301 "#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \\\n" + 302 " ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))", 303 "VK_VERSION_MAJOR": "// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead.\n" + 304 "#define <name>VK_VERSION_MAJOR</name>(version) ((uint32_t)(version) >> 22U)", 305 "VK_VERSION_MINOR": "// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead.\n" + 306 "#define <name>VK_VERSION_MINOR</name>(version) (((uint32_t)(version) >> 12U) & 0x3FFU)", 307 "VK_VERSION_PATCH": "// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead.\n" + 308 "#define <name>VK_VERSION_PATCH</name>(version) ((uint32_t)(version) & 0xFFFU)", 309 310 "VK_MAKE_API_VERSION": "#define <name>VK_MAKE_API_VERSION</name>(variant, major, minor, patch) \\\n" + 311 " ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))", 312 "VK_API_VERSION_VARIANT": "#define <name>VK_API_VERSION_VARIANT</name>(version) ((uint32_t)(version) >> 29U)", 313 "VK_API_VERSION_MAJOR": "#define <name>VK_API_VERSION_MAJOR</name>(version) (((uint32_t)(version) >> 22U) & 0x7FU)", 314 "VK_API_VERSION_MINOR": "#define <name>VK_API_VERSION_MINOR</name>(version) (((uint32_t)(version) >> 12U) & 0x3FFU)", 315 "VK_API_VERSION_PATCH": "#define <name>VK_API_VERSION_PATCH</name>(version) ((uint32_t)(version) & 0xFFFU)", 316 317 "VKSC_API_VARIANT": "// Vulkan SC variant number\n#define <name>VKSC_API_VARIANT</name> 1", 318 "VK_API_VERSION": "// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead.\n" + 319 "//#define <name>VK_API_VERSION</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 0, 0) // Patch version should always be set to 0", 320 "VK_API_VERSION_1_0": "// Vulkan 1.0 version number\n" + 321 "#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 0, 0)// Patch version should always be set to 0", 322 "VK_API_VERSION_1_1": "// Vulkan 1.1 version number\n" + 323 "#define <name>VK_API_VERSION_1_1</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 1, 0)// Patch version should always be set to 0", 324 "VK_API_VERSION_1_2": "// Vulkan 1.2 version number\n" + 325 "#define <name>VK_API_VERSION_1_2</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 2, 0)// Patch version should always be set to 0", 326 "VK_API_VERSION_1_3": "// Vulkan 1.3 version number\n" + 327 "#define <name>VK_API_VERSION_1_3</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 3, 0)// Patch version should always be set to 0", 328 "VKSC_API_VERSION_1_0": "// Vulkan SC 1.0 version number\n#define <name>VKSC_API_VERSION_1_0</name> <type>VK_MAKE_API_VERSION</type>(VKSC_API_VARIANT, 1, 0, 0)// Patch version should always be set to 0", 329 "VK_HEADER_VERSION": "// Version of this file\n" + 330 "#define <name>VK_HEADER_VERSION</name> ", 331 "VK_HEADER_VERSION_COMPLETE": "// Complete version of this file\n" + 332 "#define <name>VK_HEADER_VERSION_COMPLETE</name> <type>VK_MAKE_API_VERSION</type>", 333 "VK_DEFINE_HANDLE": "\n#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;", 334 "VK_USE_64_BIT_PTR_DEFINES": "\n" + 335 "#ifndef VK_USE_64_BIT_PTR_DEFINES\n" + 336 " #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64)\n" + 337 " #define VK_USE_64_BIT_PTR_DEFINES 1\n" + 338 " #else\n" + 339 " #define VK_USE_64_BIT_PTR_DEFINES 0\n" + 340 " #endif\n" + 341 "#endif", 342 "VK_NULL_HANDLE": "\n" + 343 "#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE\n" + 344 " #if (VK_USE_64_BIT_PTR_DEFINES==1)\n" + 345 " #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L))\n" + 346 " #define VK_NULL_HANDLE nullptr\n" + 347 " #else\n" + 348 " #define VK_NULL_HANDLE ((void*)0)\n" + 349 " #endif\n" + 350 " #else\n" + 351 " #define VK_NULL_HANDLE 0ULL\n" + 352 " #endif\n" + 353 "#endif\n" + 354 "#ifndef VK_NULL_HANDLE\n" + 355 " #define VK_NULL_HANDLE 0\n" + 356 "#endif", 357} 358 359var vulkan_known_defines = map[string]string{ 360 "VK_DEFINE_HANDLE": "\n#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;", 361 "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "\n" + 362 "#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE\n" + 363 " #if (VK_USE_64_BIT_PTR_DEFINES==1)\n" + 364 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;\n" + 365 " #else\n" + 366 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;\n" + 367 " #endif\n" + 368 "#endif", 369} 370 371var vulkansc_known_defines = map[string]string{ 372 "VK_DEFINE_HANDLE": "\n#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* (object);", 373 "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "\n" + 374 "#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE\n" + 375 " #if (VK_USE_64_BIT_PTR_DEFINES==1)\n" + 376 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *(object);\n" + 377 " #else\n" + 378 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t (object);\n" + 379 " #endif\n" + 380 "#endif", 381} 382 383var known_defines_obsoleted = map[string]string{ 384 "VK_MAKE_VERSION": "// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead.\n" + 385 "#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \\\n" + 386 " ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))", 387 "VK_VERSION_MAJOR": "// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead.\n" + 388 "#define <name>VK_VERSION_MAJOR</name>(version) ((uint32_t)(version) >> 22)", 389 "VK_VERSION_MINOR": "// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead.\n" + 390 "#define <name>VK_VERSION_MINOR</name>(version) (((uint32_t)(version) >> 12) & 0x3FFU)", 391 "VK_VERSION_PATCH": "// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead.\n" + 392 "#define <name>VK_VERSION_PATCH</name>(version) ((uint32_t)(version) & 0xFFFU)", 393 "VK_MAKE_API_VERSION": "#define <name>VK_MAKE_API_VERSION</name>(variant, major, minor, patch) \\\n" + 394 " ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))", 395 "VKSC_API_VARIANT": "// Vulkan SC variant number \n#define <name>VKSC_API_VARIANT</name> 1 // DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead.", 396 "VK_API_VERSION_VARIANT": "#define <name>VK_API_VERSION_VARIANT</name>(version) ((uint32_t)(version) >> 29)", 397 "VK_API_VERSION_MAJOR": "#define <name>VK_API_VERSION_MAJOR</name>(version) (((uint32_t)(version) >> 22) & 0x7FU)", 398 "VK_API_VERSION_MINOR": "#define <name>VK_API_VERSION_MINOR</name>(version) (((uint32_t)(version) >> 12) & 0x3FFU)", 399 "VK_API_VERSION_PATCH": "#define <name>VK_API_VERSION_PATCH</name>(version) ((uint32_t)(version) & 0xFFFU)", 400 "VK_API_VERSION": "// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead.\n" + 401 "//#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>(1, 0, 0) // Patch version should always be set to 0", 402 "VK_API_VERSION_1_0": "// Vulkan 1.0 version number\n" + 403 "#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_VERSION</type>(1, 0, 0)// Patch version should always be set to 0", 404 "VK_API_VERSION_1_1": "// Vulkan 1.1 version number\n" + 405 "#define <name>VK_API_VERSION_1_1</name> <type>VK_MAKE_VERSION</type>(1, 1, 0)// Patch version should always be set to 0", 406 "VK_API_VERSION_1_2": "// Vulkan 1.2 version number\n" + 407 "#define <name>VK_API_VERSION_1_2</name> <type>VK_MAKE_VERSION</type>(1, 2, 0)// Patch version should always be set to 0", 408 "VKSC_API_VERSION_1_0": "VK_MAKE_API_VERSION</type>(VKSC_API_VARIANT, 1, 0, 0)// Patch version should always be set to 0", 409 "VK_HEADER_VERSION": "// Version of this file\n" + 410 "#define <name>VK_HEADER_VERSION</name> ", 411 "VK_HEADER_VERSION_COMPLETE": "// Complete version of this file\n" + 412 "#define <name>VK_HEADER_VERSION_COMPLETE</name> <type>VK_MAKE_VERSION</type>(1, 2, VK_HEADER_VERSION)", 413 "VK_USE_64_BIT_PTR_DEFINES": "\n" + 414 "#ifndef VK_USE_64_BIT_PTR_DEFINES\n" + 415 " #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)\n" + 416 " #define VK_USE_64_BIT_PTR_DEFINES 1\n" + 417 " #else\n" + 418 " #define VK_USE_64_BIT_PTR_DEFINES 0\n" + 419 " #endif\n" + 420 "#endif", 421 "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "\n#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)\n" + 422 "#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)\n" + 423 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;\n" + 424 "#else\n" + 425 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;\n" + 426 "#endif\n" + 427 "#endif", 428 "VK_NULL_HANDLE": "\n#define <name>VK_NULL_HANDLE</name> 0", 429 "VK_DEFINE_HANDLE": "\n#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* (object);", 430} 431 432func Unmarshal(data []byte) (*registry, error) { 433 var registry registry 434 err := xml.Unmarshal(data, ®istry) 435 if err != nil { 436 return nil, err 437 } 438 for i := range registry.Types { 439 typе := ®istry.Types[i] 440 if typе.Name == "" { 441 typе.Name, err = elementFromRawXML("name", typе.RawXML) 442 if err != nil { 443 return nil, err 444 } 445 } 446 if typе.Category == "" { 447 if requires, found := known_types[typе.Name]; !found || typе.Requires != requires { 448 return nil, errors.New("Unknown type without category: \"" + typе.Name + "\"") 449 } 450 typе.Category = "vk_platform" 451 } 452 if typе.Alias != "" || (typе.Category != "struct" && typе.Category != "union") { 453 if len(typе.Members) != 0 { 454 return nil, errors.New("Members in non-struct type : \"" + typе.Name + "\"") 455 } 456 } else { 457 for j := range typе.Members { 458 member := &typе.Members[j] 459 if member.Name == "" { 460 member.Name, err = elementFromRawXML("name", member.RawXML) 461 if err != nil { 462 return nil, err 463 } 464 } 465 if member.Type == "" { 466 member.Type, err = elementFromRawXML("type", member.RawXML) 467 if err != nil { 468 return nil, err 469 } 470 } 471 if member.Comment == "" && strings.Contains(member.RawXML, "<comment>") { 472 member.Comment, err = elementFromRawXML("comment", member.RawXML) 473 if err != nil { 474 return nil, err 475 } 476 } 477 } 478 } 479 } 480 for i := range registry.Commands { 481 command := ®istry.Commands[i] 482 if command.Name == "" { 483 command.Name, err = elementFromRawXML("name", command.Proto.RawXML) 484 if err != nil { 485 return nil, err 486 } 487 } 488 if command.Alias == "" { 489 if command.Proto.Type == "" { 490 command.Proto.Type, err = elementFromRawXML("type", command.Proto.RawXML) 491 if err != nil { 492 return nil, err 493 } 494 } 495 if command.Proto.Comment == "" && strings.Contains(command.Proto.RawXML, "<comment>") { 496 command.Proto.Type, err = elementFromRawXML("comment", command.Proto.RawXML) 497 if err != nil { 498 return nil, err 499 } 500 } 501 for j := range command.Params { 502 param := &command.Params[j] 503 if param.Name == "" { 504 param.Name, err = elementFromRawXML("name", param.RawXML) 505 if err != nil { 506 return nil, err 507 } 508 } 509 if param.Type == "" { 510 param.Type, err = elementFromRawXML("type", param.RawXML) 511 if err != nil { 512 return nil, err 513 } 514 } 515 if param.Comment == "" && strings.Contains(command.Proto.RawXML, "<comment>") { 516 param.Comment, err = elementFromRawXML("comment", param.RawXML) 517 if err != nil { 518 return nil, err 519 } 520 } 521 } 522 } 523 } 524 return ®istry, nil 525} 526 527func VulkanTypesfromXML(registry *registry) (sorted_type_names []string, types map[string]cpp_types.Type, sorted_command_names []string, commands map[string]cpp_types.Type, extensions map[string]int64, err error) { 528 types = vulkan_types.PlatformTypes() 529 // Note that we don't pre-calculate values for enums during initial parsing because vk.xml 530 // [ab]uses "enum" to define non-integer constants and integers defined-as-C-expression, too. 531 // E.g. "VK_LOD_CLAMP_NONE" as "1000.0f" or VK_QUEUE_FAMILY_FOREIGN_EXT as "(~0U-2)". 532 // We return "raw" string value here and only parse them on as-needed basis. 533 enum_values, enum_types, err := parseEnumValues(registry) 534 if err != nil { 535 return nil, nil, nil, nil, nil, err 536 } 537 // It's allowed in C/C++ to refer to not-yet defined type and type may even include pointer 538 // to itself. But other uses of undefined types are forbidden. Mutually directly (non-pointer) 539 // used types are *forbidden* in C/C++. 540 // Thus the graph of type uses is acyclic when pointers are excluded and we should be 541 // able to iteratively resolve all types by retrying failed types, expecting at least one 542 // type to resolve during an iteration. 543 // The first loop parsing resolves all directly (non-pointer) used types. 544 // 545 // Pointed types just became opaque, if undefined, and will be attempted to be resolved with 546 // a dedicated pass. 547 // The second loop (below) replaces opaque types referenced by pointer if they have been 548 // resolved at some point. Some types are supposed to just be opaque types and be only 549 // operated using pointers — but only platform-provided types, not vk.xml-defined types. 550 var xml_types_list []*typeInfo 551 next_xml_types_list := []*typeInfo{} 552 for index := range registry.Types { 553 next_xml_types_list = append(next_xml_types_list, ®istry.Types[index]) 554 } 555 for len(next_xml_types_list) > 0 { 556 // If next list is the same as previous one then we have some kind of loop and types couldn't be defined. 557 if len(xml_types_list) == len(next_xml_types_list) { 558 return nil, nil, nil, nil, nil, errors.New("Cannot make any progress: type \"" + xml_types_list[0].Name + "\" refers to undefined type: \"" + xml_types_list[0].RawXML + "\"\"") 559 } 560 xml_types_list = next_xml_types_list 561 next_xml_types_list = []*typeInfo{} 562 for _, xml_type := range xml_types_list { 563 if _, ok := types[xml_type.Name]; ok { 564 if xml_type.Category == "vk_platform" { 565 continue 566 } 567 if xml_type.Api == "vulkansc" { 568 continue 569 } 570 return nil, nil, nil, nil, nil, errors.New("Duplicated type \"" + xml_type.Name + "\"") 571 } 572 if xml_type.Alias != "" { 573 if alias_target, ok := types[xml_type.Alias]; ok { 574 types[xml_type.Name] = cpp_types.AliasType(xml_type.Name, alias_target) 575 continue 576 } 577 next_xml_types_list = append(next_xml_types_list, xml_type) 578 continue 579 } 580 var c_type cpp_types.Type 581 switch xml_type.Category { 582 case "basetype": 583 c_type, err = vulkanBaseTypeFromXML(xml_type) 584 case "bitmask": 585 c_type, err = vulkanBitmaskTypeFromXML(xml_type, types) 586 case "define": 587 err := vulkanDefineTypeFromXML(xml_type) 588 if err != nil { 589 return nil, nil, nil, nil, nil, err 590 } 591 continue 592 case "enum": 593 c_type, err = vulkanEnumTypeFromXML(xml_type, enum_values, enum_types) 594 case "funcpointer": 595 c_type, err = vulkanFuncPoiterTypeFromXML(xml_type, types) 596 case "handle": 597 c_type, err = vulkanHandleTypeFromXML(xml_type, types) 598 case "include": 599 continue 600 case "struct": 601 c_type, err = vulkanStructTypeFromXML(xml_type, xml_type.StructExtends != "", types, enum_values) 602 case "union": 603 c_type, err = vulkanUnionTypeFromXML(xml_type, types, enum_values) 604 case "vk_platform": 605 return nil, nil, nil, nil, nil, errors.New("Unknown platform type \"" + xml_type.Name + "\"") 606 default: 607 return nil, nil, nil, nil, nil, errors.New("Unknown type category \"" + xml_type.Category + "\"") 608 } 609 // This type refers the unknown type. But it maybe because it needs some type defined further on in the xml. Defer its parsing to next pass. 610 if err == unknownType { 611 next_xml_types_list = append(next_xml_types_list, xml_type) 612 continue 613 } 614 if err != nil { 615 return nil, nil, nil, nil, nil, err 616 } 617 types[xml_type.Name] = c_type 618 } 619 } 620 // Populate extended_with info. We need to be the separate path since structs may refer other structs which are defined later in the vk.xml file. 621 for _, xml_type := range registry.Types { 622 if xml_type.Category == "struct" && xml_type.StructExtends != "" { 623 for _, name := range strings.Split(xml_type.StructExtends, ",") { 624 var extended_with *[]cpp_types.Type 625 if types[name].Kind(cpp_types.FirstArch) == cpp_types.Alias { 626 extended_with = &types[name].Elem(cpp_types.FirstArch).(*extendedStruct).extended_with 627 } else { 628 extended_with = &types[name].(*extendedStruct).extended_with 629 } 630 *extended_with = append(*extended_with, types[xml_type.Name]) 631 } 632 } 633 } 634 // Resolve potentially circular references. 635 for type_name := range types { 636 // Here we rely on the fact that there are no types in Vulkan which are stuctural in one case yet non-structural 637 // in other cases. And also there are differently-structured structural types either. 638 typе := types[type_name] 639 if typе.Kind(cpp_types.FirstArch) == cpp_types.Ptr { 640 typе = typе.Elem(cpp_types.FirstArch) 641 } 642 if typе.Kind(cpp_types.FirstArch) != cpp_types.Func && 643 typе.Kind(cpp_types.FirstArch) != cpp_types.Struct && 644 typе.Kind(cpp_types.FirstArch) != cpp_types.Union { 645 continue 646 } 647 for i := uint(0); i < typе.NumField(cpp_types.FirstArch); i++ { 648 field := typе.Field(i, cpp_types.FirstArch) 649 if field.Type().Kind(cpp_types.FirstArch) != cpp_types.Ptr { 650 continue 651 } 652 pointee_type := field.Type().Elem(cpp_types.FirstArch) 653 if pointee_type.Kind(cpp_types.FirstArch) == cpp_types.Opaque { 654 if field_type, ok := types[pointee_type.Name(cpp_types.FirstArch)]; ok && field_type.Kind(cpp_types.FirstArch) != cpp_types.Opaque { 655 field.Type().(cpp_types.ModifyablePtrType).ReplaceElem(field_type) 656 } 657 } else if pointee_type.Kind(cpp_types.FirstArch) == cpp_types.Const && 658 pointee_type.Elem(cpp_types.FirstArch).Kind(cpp_types.FirstArch) == cpp_types.Opaque { 659 if field_type, ok := types[pointee_type.Elem(cpp_types.FirstArch).Name(cpp_types.FirstArch)]; ok && field_type.Kind(cpp_types.FirstArch) != cpp_types.Opaque { 660 field.Type().(cpp_types.ModifyablePtrType).ReplaceElem(cpp_types.ConstType(field_type)) 661 } 662 } 663 } 664 } 665 commands = make(map[string]cpp_types.Type) 666 for index := range registry.Commands { 667 command := registry.Commands[index] 668 // We'll link aliases below, after the final commands are constructed. 669 if command.Alias != "" { 670 continue 671 } 672 if result_type, ok := types[command.Proto.Type]; ok { 673 if space.ReplaceAllString(command.Proto.RawXML, " ") != fmt.Sprintf("<type>%s</type> <name>%s</name>", command.Proto.Type, command.Name) { 674 return nil, nil, nil, nil, nil, errors.New("Unexpected prototype \"" + command.Proto.RawXML + "\"") 675 } 676 fields_info, err := vulkanStructuralTypeMembersFromXML(command.Name, command.Params, types, enum_values) 677 if err != nil { 678 return nil, nil, nil, nil, nil, err 679 } 680 // Arrays decay into pointers when used as parameters of functions - but only one, outer, dimension. 681 // Convert arrays into pointers, leave other types intact. 682 params_info := []cpp_types.FieldInfo{} 683 for _, field_info := range fields_info { 684 if field_info.Type().Kind(cpp_types.FirstArch) == cpp_types.Array { 685 params_info = append(params_info, ExtendedField( 686 field_info.Name(), 687 cpp_types.PointerType(field_info.Type().Elem(cpp_types.FirstArch)), 688 field_info.BaseFieldInfo().(ExtendedFieldInfo).Length(), 689 field_info.BaseFieldInfo().(ExtendedFieldInfo).NestedField())) 690 } else { 691 params_info = append(params_info, field_info) 692 } 693 } 694 commands[command.Name] = cpp_types.FunctionType(result_type, params_info) 695 continue 696 } 697 return nil, nil, nil, nil, nil, errors.New("Unknown return function type \"" + command.Proto.Type + "\"") 698 } 699 // Now link aliases to the final command of the original function. 700 for index := range registry.Commands { 701 command := registry.Commands[index] 702 if command.Alias == "" { 703 continue 704 } 705 commands[command.Name] = commands[command.Alias] 706 } 707 sorted_type_names = []string{} 708 for name := range types { 709 sorted_type_names = append(sorted_type_names, name) 710 } 711 sort.Strings(sorted_type_names) 712 sorted_command_names = []string{} 713 for name := range commands { 714 sorted_command_names = append(sorted_command_names, name) 715 } 716 sort.Strings(sorted_command_names) 717 extensions = make(map[string]int64) 718 for extension_idx := range registry.Extensions { 719 extension := ®istry.Extensions[extension_idx] 720 extensions_spec := int64(-1) 721 for requires_idx := range extension.Requires { 722 requires := &extension.Requires[requires_idx] 723 for enum_field_idx := range requires.EnumFields { 724 enum_field := &requires.EnumFields[enum_field_idx] 725 if enum_field.Alias == "" && strings.HasSuffix(enum_field.Name, "_SPEC_VERSION") { 726 spec_version, err := strconv.ParseInt(enum_field.Value, 10, 32) 727 if err != nil { 728 return nil, nil, nil, nil, nil, err 729 } 730 if spec_version == -1 || extensions_spec != -1 { 731 errors.New("Couldn't find extensions SPEC_VERSION") 732 } 733 extensions_spec = spec_version 734 } 735 } 736 } 737 extensions[extension.Name] = extensions_spec 738 } 739 return sorted_type_names, types, sorted_command_names, commands, extensions, nil 740} 741 742func vulkanBaseTypeFromXML(typе *typeInfo) (cpp_types.Type, error) { 743 RawXML := strings.TrimSpace(space.ReplaceAllString(typе.RawXML, " ")) 744 if typе.Name == "CAMetalLayer" { 745 if RawXML != "#ifdef __OBJC__ @class CAMetalLayer; #else typedef void <name>CAMetalLayer</name>; #endif" { 746 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 747 } 748 return cpp_types.OpaqueType("CAMetalLayer"), nil 749 } 750 if typе.Name == "MTLDevice_id" { 751 if RawXML != "#ifdef __OBJC__ @protocol MTLDevice; typedef id<MTLDevice> MTLDevice_id; #else typedef void* <name>MTLDevice_id</name>; #endif" { 752 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 753 } 754 return cpp_types.PointerType(cpp_types.VoidType), nil 755 } 756 if typе.Name == "MTLCommandQueue_id" { 757 if RawXML != "#ifdef __OBJC__ @protocol MTLCommandQueue; typedef id<MTLCommandQueue> MTLCommandQueue_id; #else typedef void* <name>MTLCommandQueue_id</name>; #endif" { 758 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 759 } 760 return cpp_types.PointerType(cpp_types.VoidType), nil 761 } 762 if typе.Name == "MTLBuffer_id" { 763 if RawXML != "#ifdef __OBJC__ @protocol MTLBuffer; typedef id<MTLBuffer> MTLBuffer_id; #else typedef void* <name>MTLBuffer_id</name>; #endif" { 764 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 765 } 766 return cpp_types.PointerType(cpp_types.VoidType), nil 767 } 768 if typе.Name == "MTLTexture_id" { 769 if RawXML != "#ifdef __OBJC__ @protocol MTLTexture; typedef id<MTLTexture> MTLTexture_id; #else typedef void* <name>MTLTexture_id</name>; #endif" { 770 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 771 } 772 return cpp_types.PointerType(cpp_types.VoidType), nil 773 } 774 if typе.Name == "MTLSharedEvent_id" { 775 if RawXML != "#ifdef __OBJC__ @protocol MTLSharedEvent; typedef id<MTLSharedEvent> MTLSharedEvent_id; #else typedef void* <name>MTLSharedEvent_id</name>; #endif" { 776 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 777 } 778 return cpp_types.PointerType(cpp_types.VoidType), nil 779 } 780 if typе.Name == "IOSurfaceRef" { 781 if RawXML != "typedef struct __IOSurface* <name>IOSurfaceRef</name>;" { 782 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 783 } 784 return cpp_types.PointerType(cpp_types.OpaqueType("__IOSurface")), nil 785 } 786 if RawXML == fmt.Sprintf("struct <name>%s</name>;", typе.Name) { 787 return cpp_types.OpaqueType(typе.Name), nil 788 } 789 if RawXML == fmt.Sprintf("typedef <type>uint32_t</type> <name>%s</name>;", typе.Name) { 790 return cpp_types.AliasType(typе.Name, cpp_types.UInt32TType), nil 791 } 792 if RawXML == fmt.Sprintf("typedef <type>uint64_t</type> <name>%s</name>;", typе.Name) { 793 return cpp_types.AliasType(typе.Name, cpp_types.UInt64TType), nil 794 } 795 if RawXML == fmt.Sprintf("typedef <type>void</type>* <name>%s</name>;", typе.Name) { 796 return cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.VoidType)), nil 797 } 798 return nil, errors.New("Unexpected basetype \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 799} 800 801func vulkanBitmaskTypeFromXML(typе *typeInfo, types map[string]cpp_types.Type) (cpp_types.Type, error) { 802 RawXML := strings.TrimSpace(space.ReplaceAllString(typе.RawXML, " ")) 803 if RawXML == fmt.Sprintf("typedef <type>VkFlags</type> <name>%s</name>;", typе.Name) { 804 return cpp_types.AliasType(typе.Name, types["VkFlags"]), nil 805 } 806 if RawXML == fmt.Sprintf("typedef <type>VkFlags64</type> <name>%s</name>;", typе.Name) { 807 return cpp_types.AliasType(typе.Name, types["VkFlags64"]), nil 808 } 809 return nil, errors.New("Unexpected bitmask \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 810} 811 812func vulkanDefineTypeFromXML(typе *typeInfo) error { 813 if typе.Api == "vulkan" { 814 if define, ok := vulkan_known_defines[typе.Name]; ok { 815 if define != typе.RawXML { 816 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 817 } 818 return nil 819 } 820 } else if typе.Api == "vulkansc" { 821 if define, ok := vulkansc_known_defines[typе.Name]; ok { 822 if define != typе.RawXML { 823 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 824 } 825 return nil 826 } 827 } else { 828 if define, ok := vulkan_known_defines[typе.Name]; ok { 829 if define == typе.RawXML { 830 return nil 831 } 832 } 833 if define, ok := vulkansc_known_defines[typе.Name]; ok { 834 if define != typе.RawXML { 835 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 836 } 837 return nil 838 } 839 } 840 if define, ok := known_defines[typе.Name]; ok { 841 // Most defines are stable and since we don't parse them we just ensure they match our expectations. 842 if typе.Name != "VK_HEADER_VERSION" && typе.Name != "VK_HEADER_VERSION_COMPLETE" { 843 if define != typе.RawXML { 844 if obsolete_define, ok := known_defines_obsoleted[typе.Name]; ok { 845 if obsolete_define == typе.RawXML { 846 return nil 847 } 848 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 849 } 850 return errors.New("Unknown obsolete define \"" + typе.Name + "\"") 851 } 852 return nil 853 } 854 // Note: VK_HEADER_VERSION is updated every time vk.xml is updated thus we couldn't hardcode it. 855 // VK_HEADER_VERSION_COMPLETE is updted when new, incompatible version of Vulkan is released. 856 if !strings.HasPrefix(typе.RawXML, define) { 857 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 858 } 859 return nil 860 } 861 return errors.New("Unknown define \"" + typе.Name + "\"") 862} 863 864func vulkanEnumTypeFromXML(typе *typeInfo, enum_values map[string]*enumFieldInfo, enum_types map[string][]*enumFieldInfo) (cpp_types.Type, error) { 865 fits_in_int32 := true 866 fits_in_uint32 := true 867 // Duplicate logic from Khronos's generator.py: use int32_t if everything fits into int32_t, 868 // then uint32_t, then int64_t. 869 basetype := cpp_types.Int32TType 870 for _, element := range enum_types[typе.Name] { 871 value, err := enumFieldValue(element, enum_values) 872 if err != nil { 873 return nil, err 874 } 875 if int64(int32(value)) != value { 876 fits_in_int32 = false 877 } 878 if int64(uint32(value)) != value { 879 fits_in_uint32 = false 880 } 881 } 882 if !fits_in_int32 { 883 if fits_in_uint32 { 884 basetype = cpp_types.UInt32TType 885 } else { 886 basetype = cpp_types.Int64TType 887 } 888 } 889 values := []cpp_types.EnumFieldInfo{} 890 for _, element := range enum_types[typе.Name] { 891 value, _ := enumFieldValue(element, enum_values) 892 values = append(values, cpp_types.EnumField(element.Name, basetype, element.Alias, value)) 893 } 894 return cpp_types.EnumType(typе.Name, basetype, values), nil 895} 896 897func vulkanFuncPoiterTypeFromXML(typе *typeInfo, types map[string]cpp_types.Type) (cpp_types.Type, error) { 898 definition := strings.TrimSpace(typе.RawXML) 899 if !strings.HasPrefix(definition, "typedef ") || 900 !strings.HasSuffix(definition, ");") || 901 strings.Count(definition, " (VKAPI_PTR *<name>") != 1 || 902 strings.Count(definition, "</name>)(") != 1 { 903 return nil, errors.New("Couldn't determine function type from \"" + definition + "\"") 904 } 905 split := strings.Split(definition[8:len(definition)-2], " (VKAPI_PTR *<name>") 906 var return_type cpp_types.Type 907 return_type_string := split[0] 908 if strings.HasSuffix(return_type_string, "*") { 909 return_typе, ok := types[return_type_string[0:len(return_type_string)-1]] 910 if !ok { 911 return nil, errors.New("Couldn't determine function type \"" + return_type_string + "\"") 912 } 913 return_type = cpp_types.PointerType(return_typе) 914 } else { 915 return_typе, ok := types[return_type_string] 916 if !ok { 917 return nil, errors.New("Couldn't determine function type \"" + return_type_string + "\"") 918 } 919 return_type = return_typе 920 } 921 parameters := strings.Split(split[1], "</name>)(")[1] 922 var parameter_types []cpp_types.FieldInfo 923 if parameters == "void" { 924 return cpp_types.PointerType(cpp_types.FunctionType(return_type, parameter_types)), nil 925 } 926 for _, parameter := range strings.Split(parameters, ",") { 927 parameter = strings.TrimSpace(parameter) 928 parameter_type_len := strings.LastIndex(parameter, " ") 929 parameter_type := strings.TrimSpace(parameter[:parameter_type_len]) 930 parameter_name := strings.TrimSpace(parameter[parameter_type_len+1:]) 931 if strings.HasPrefix(parameter_type, "<type>") && 932 strings.HasSuffix(parameter_type, "</type>") { 933 parameter_types = append( 934 parameter_types, 935 ExtendedField(parameter_name, types[parameter_type[6:len(parameter_type)-7]], 936 nil, 937 nil)) 938 } else if strings.HasPrefix(parameter_type, "const <type>") && 939 strings.HasSuffix(parameter_type, "</type>*") { 940 pointee_type_name := parameter_type[12 : len(parameter_type)-8] 941 if pointee_type, ok := types[pointee_type_name]; ok { 942 parameter_types = append( 943 parameter_types, 944 ExtendedField( 945 parameter_name, 946 cpp_types.PointerType(cpp_types.ConstType(pointee_type)), 947 nil, 948 nil)) 949 } else { 950 parameter_types = append( 951 parameter_types, 952 ExtendedField( 953 parameter_name, 954 cpp_types.PointerType(cpp_types.ConstType(cpp_types.OpaqueType(pointee_type_name))), 955 nil, 956 nil)) 957 } 958 } else if strings.HasPrefix(parameter_type, "<type>") && 959 strings.HasSuffix(parameter_type, "</type>*") { 960 pointee_type_name := parameter_type[6 : len(parameter_type)-8] 961 if pointee_type, ok := types[pointee_type_name]; ok { 962 parameter_types = append( 963 parameter_types, 964 ExtendedField( 965 parameter_name, 966 cpp_types.PointerType(pointee_type), 967 nil, 968 nil)) 969 } else { 970 parameter_types = append( 971 parameter_types, 972 ExtendedField( 973 parameter_name, 974 cpp_types.PointerType(cpp_types.OpaqueType(pointee_type_name)), 975 nil, 976 nil)) 977 } 978 } else { 979 return nil, errors.New("Couldn't determine parameter type \"" + parameter_type + "\"") 980 } 981 } 982 return cpp_types.PointerType(cpp_types.FunctionType(return_type, parameter_types)), nil 983} 984 985func vulkanHandleTypeFromXML(typе *typeInfo, types map[string]cpp_types.Type) (cpp_types.Type, error) { 986 if typе.RawXML == fmt.Sprintf("<type>VK_DEFINE_HANDLE</type>(<name>%s</name>)", typе.Name) { 987 return cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.OpaqueType(fmt.Sprintf("struct %s_T", typе.Name)))), nil 988 } else if typе.RawXML == fmt.Sprintf("<type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>%s</name>)", typе.Name) { 989 return cpp_types.ArchDependentType( 990 cpp_types.AliasType(typе.Name, cpp_types.UInt64TType), 991 cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.OpaqueType(fmt.Sprintf("struct %s_T", typе.Name)))), 992 cpp_types.AliasType(typе.Name, cpp_types.UInt64TType), 993 cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.OpaqueType(fmt.Sprintf("struct %s_T", typе.Name)))), 994 cpp_types.AliasType(typе.Name, cpp_types.UInt64TType), 995 cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.OpaqueType(fmt.Sprintf("struct %s_T", typе.Name))))), nil 996 } 997 return nil, errors.New("Unexpected handle \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 998} 999 1000func vulkanStructTypeFromXML(typе *typeInfo, optional_struct bool, types map[string]cpp_types.Type, enum_values map[string]*enumFieldInfo) (cpp_types.Type, error) { 1001 fields_info, err := vulkanStructuralTypeMembersFromXML(typе.Name, typе.Members, types, enum_values) 1002 if err != nil { 1003 return nil, err 1004 } 1005 optional_enum_value := "" 1006 if optional_struct { 1007 if typе.Members[0].Type != "VkStructureType" || fields_info[0].Name() != "sType" || fields_info[1].Name() != "pNext" { 1008 return nil, errors.New("Struct extension must have first field named VkStructureType sType and second named pNext") 1009 } 1010 optional_enum_value = typе.Members[0].Value 1011 } 1012 return ExtendedStruct(cpp_types.StructType(typе.Name, fields_info), optional_struct, optional_enum_value), nil 1013} 1014 1015func vulkanUnionTypeFromXML(typе *typeInfo, types map[string]cpp_types.Type, enum_values map[string]*enumFieldInfo) (cpp_types.Type, error) { 1016 fields_info, err := vulkanStructuralTypeMembersFromXML(typе.Name, typе.Members, types, enum_values) 1017 if err != nil { 1018 return nil, err 1019 } 1020 return cpp_types.UnionType(typе.Name, fields_info), nil 1021} 1022 1023var space = regexp.MustCompile(`\s+`) 1024 1025func vulkanStructuralTypeMembersFromXML(name string, members []structuralMemberInfo, types map[string]cpp_types.Type, enum_values map[string]*enumFieldInfo) (result []cpp_types.FieldInfo, err error) { 1026 fields_info := []*extendedField{} 1027 field_map := make(map[string]*extendedField) 1028 for _, member := range members { 1029 html := strings.TrimSpace(member.RawXML) 1030 // Note: checks below count only opening tags because XML parser guarantees that closing tags are there and they 1031 // match opening tags. 1032 if member.Comment != "" { 1033 if comments := strings.Count(html, "<comment>"); comments > 1 { 1034 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1035 } else if comments == 1 { 1036 html = strings.Split(html, "<comment>")[0] + strings.Split(html, "</comment>")[1] 1037 } 1038 } 1039 if strings.Count(html, "<type>") != 1 { 1040 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1041 } 1042 text_before_type_name := strings.TrimSpace(strings.Split(html, "<type>")[0]) 1043 text_after_type_name := strings.TrimSpace(strings.Split(html, "</type>")[1]) 1044 if strings.Count(html, "<name>") > 1 { 1045 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1046 } else if strings.Count(html, "<name>") == 1 { 1047 text_after_type_name = strings.Split(text_after_type_name, "<name>")[0] + strings.Split(text_after_type_name, "</name>")[1] 1048 } 1049 text_after_type_name = strings.TrimSpace(space.ReplaceAllString(text_after_type_name, " ")) 1050 member_type, raw_type_known := types[member.Type] 1051 // TODO(b/268638193): handle comma-separated list of allowed functions. 1052 if member.Type == "VkBaseInStructure" || member.Type == "VkBaseOutStructure" { 1053 member_type = types[member.Validstructs] 1054 } 1055 if len(text_after_type_name) > 0 && text_after_type_name[0] == '*' { 1056 if raw_type_known { 1057 if text_before_type_name == "const" || text_before_type_name == "const struct" { 1058 member_type = cpp_types.ConstType(member_type) 1059 } else if text_before_type_name != "" && text_before_type_name != "struct" { 1060 return nil, errors.New("Unexpected prefix in \"" + name + "\": \"" + html + "\"\"") 1061 } 1062 } else { 1063 member_type = cpp_types.OpaqueType(member.Type) 1064 // Note that if type is opaque in C (but not C++!) if has to be prefixed with either "const struct" or "struct". 1065 // If we only see "const" or nothing then that type is not opaque and is supposed to be declared somewhere below. 1066 // Return unknownType if that happens. 1067 if text_before_type_name == "" || text_before_type_name == "const" { 1068 return nil, unknownType 1069 } else if text_before_type_name == "const struct" { 1070 member_type = cpp_types.ConstType(member_type) 1071 } else if text_before_type_name != "struct" { 1072 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1073 } 1074 } 1075 if text_after_type_name == "*" { 1076 member_type = cpp_types.PointerType(member_type) 1077 } else if text_after_type_name == "**" { 1078 member_type = cpp_types.PointerType(cpp_types.PointerType(member_type)) 1079 } else if text_after_type_name == "* const*" || text_after_type_name == "* const *" { 1080 member_type = cpp_types.PointerType(cpp_types.ConstType(cpp_types.PointerType(member_type))) 1081 } else { 1082 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1083 } 1084 } else { 1085 if !raw_type_known { 1086 return nil, unknownType 1087 } 1088 if text_before_type_name == "const" { 1089 member_type = cpp_types.ConstType(member_type) 1090 } else if text_before_type_name != "" { 1091 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1092 } 1093 // Bitfields are not actually supposed to be used in vk.xml — and it even has comment which says exactly that! 1094 // Unfortunately they are already there and couldn't be removed (backward compatibility!). 1095 // Replace "uint32_t :8" with "uint8_t" and "uint32_t :24" with "uint8_t[3]". 1096 // This is hack but provides proper layout. 1097 if text_after_type_name == ":8" { 1098 if member.Type != "uint32_t" && member.Type != "VkGeometryInstanceFlagsKHR" { 1099 return nil, errors.New("Unsupported bitfield type name \"" + name + "\": \"" + html + "\"\"") 1100 } 1101 member_type = cpp_types.UInt8TType 1102 } else if text_after_type_name == ":24" { 1103 if member.Type != "uint32_t" { 1104 return nil, errors.New("Unsupported bitfield type name \"" + name + "\": \"" + html + "\"\"") 1105 } 1106 member_type = cpp_types.ArrayType(cpp_types.UInt8TType, 3) 1107 } else { 1108 indexes := []uint{} 1109 for strings.HasSuffix(text_after_type_name, "]") { 1110 array_size_text := text_after_type_name[strings.LastIndex(text_after_type_name, "[")+1 : len(text_after_type_name)-1] 1111 text_after_type_name = text_after_type_name[0 : len(text_after_type_name)-len(array_size_text)-2] 1112 if strings.HasPrefix(array_size_text, "<enum>") { 1113 if !strings.HasSuffix(array_size_text, "</enum>") { 1114 return nil, errors.New("Unsupported array index \"" + array_size_text + "\"\"") 1115 } 1116 array_size_text = enum_values[array_size_text[6:len(array_size_text)-7]].Value 1117 } 1118 array_size, err := strconv.ParseInt(array_size_text, 10, 32) 1119 if err != nil { 1120 return nil, err 1121 } 1122 indexes = append(indexes, uint(array_size)) 1123 } 1124 for i := len(indexes) - 1; i >= 0; i-- { 1125 member_type = cpp_types.ArrayType(member_type, indexes[i]) 1126 } 1127 if text_after_type_name != "" { 1128 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1129 } 1130 } 1131 } 1132 new_field := extendedField{cpp_types.Field(member.Name, member_type), nil, nil} 1133 if member.Api != "vulkansc" { 1134 fields_info = append(fields_info, &new_field) 1135 field_map[member.Name] = &new_field 1136 } 1137 } 1138 for _, member := range members { 1139 // This strange notion is used in VkAccelerationStructureBuildGeometryInfoKHR structure where only one of two fields can be non-NULL: 1140 // <member len="geometryCount,1" optional="true,false"> 1141 // We treat it as <member len="geometryCount" optional="true"> here. 1142 if strings.HasSuffix(member.Length, ",1") { 1143 if length, ok := field_map[member.Length[0:len(member.Length)-2]]; ok { 1144 field_map[member.Name].length = length 1145 } else { 1146 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1147 } 1148 // Some corner cases have len like “pAllocateInfo->descriptorSetCount”. 1149 // Currently that only have one level, structures are always input to function, 1150 // and we don't need to convert these. 1151 // 1152 // We need to detect case where that wouldn't be true in the future. 1153 // Only then would we know how to handle these. 1154 // 1155 // We parse these and pass the information to calling module because it's 1156 // not easy to see here whether types are compatible on all platforms here 1157 // or not (and there are more than a couple of such types). 1158 } else if strings.Contains(member.Length, "->") { 1159 split_length := strings.Split(member.Length, "->") 1160 if len(split_length) > 2 { 1161 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1162 } 1163 length, ok := field_map[split_length[0]] 1164 if !ok { 1165 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1166 } 1167 field_map[member.Name].length = length 1168 // Note: we are dealing with pointer to const data structure here. 1169 // That's why we dereference twice. 1170 length_type := length.Type() 1171 if length_type.Kind(cpp_types.FirstArch) != cpp_types.Ptr { 1172 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1173 } 1174 length_type = length_type.Elem(cpp_types.FirstArch) 1175 if length_type.Kind(cpp_types.FirstArch) == cpp_types.Const { 1176 length_type = length_type.Elem(cpp_types.FirstArch) 1177 } 1178 if length_type.Kind(cpp_types.FirstArch) != cpp_types.Struct && 1179 length_type.Kind(cpp_types.FirstArch) != cpp_types.Union { 1180 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1181 } 1182 for i := uint(0); i < length_type.NumField(cpp_types.FirstArch); i++ { 1183 if length_type.Field(i, cpp_types.FirstArch).Name() == split_length[1] { 1184 field_map[member.Name].nested_field = length_type.Field(i, cpp_types.FirstArch) 1185 } 1186 } 1187 if field_map[member.Name].nested_field == nil { 1188 return nil, errors.New("Unexpected field referred by len in \"" + member.Name + "\"") 1189 } 1190 // If len is too complicated it may be represented as LaTeX expression (e.g. 1191 // latexmath:[\lceil{\mathit{rasterizationSamples} \over 32}\rceil] for pSampleMask) 1192 // In these cases altlength represents for C, but it may be quite hard to parse that 1193 // too. 1194 // Thankfully for now all such complex fields pass arrays of uint{8,16,32}_t which 1195 // we never translate. Note: we currently don't translate uint64_t even if these 1196 // are not 100% compatible on all platforms. The only direction where that may 1197 // matter would be x86 (32bit) to AArch32 translation (which we don't support), 1198 // but arrays of uint{8,16,32}_t are 100% compatible on all platforums. 1199 // 1200 // Verify that it's so and ignore "len" in that case. 1201 } else if member.AltLength != "" { 1202 typе := field_map[member.Name].Type() 1203 if typе.Kind(cpp_types.FirstArch) != cpp_types.Ptr { 1204 return nil, errors.New("Unexpected altlen field in \"" + member.Name + "\"") 1205 } 1206 element_type := typе.Elem(cpp_types.FirstArch) 1207 if element_type.Kind(cpp_types.FirstArch) == cpp_types.Const { 1208 element_type = element_type.Elem(cpp_types.FirstArch) 1209 } 1210 if element_type.Kind(cpp_types.FirstArch) == cpp_types.Alias { 1211 element_type = element_type.Elem(cpp_types.FirstArch) 1212 } 1213 if element_type.Kind(cpp_types.FirstArch) != cpp_types.UInt8T && 1214 element_type.Kind(cpp_types.FirstArch) != cpp_types.UInt16T && 1215 element_type.Kind(cpp_types.FirstArch) != cpp_types.UInt32T { 1216 return nil, errors.New("Unexpected altlen field in \"" + member.Name + "\"") 1217 } 1218 } else if member.Length != "" && member.Length != "null-terminated" && !strings.HasSuffix(member.Length, ",null-terminated") { 1219 if length, ok := field_map[member.Length]; ok { 1220 field_map[member.Name].length = length 1221 } else { 1222 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1223 } 1224 } 1225 } 1226 result = make([]cpp_types.FieldInfo, len(fields_info)) 1227 for index, field_info := range fields_info { 1228 result[index] = field_info 1229 } 1230 return result, nil 1231} 1232 1233var unknownType = errors.New("Couldn't find type") 1234 1235func elementFromRawXML(element_name string, raw_XML string) (string, error) { 1236 opening_tag := "<" + element_name + ">" 1237 closing_tag := "</" + element_name + ">" 1238 if strings.Count(raw_XML, opening_tag) != 1 { 1239 return "", errors.New("Couldn't determine element \"" + element_name + "\" from \"" + raw_XML + "\"") 1240 } 1241 if strings.Count(raw_XML, closing_tag) != 1 { 1242 return "", errors.New("Couldn't determine element \"" + element_name + "\" from \"" + raw_XML + "\"") 1243 } 1244 return strings.Split(strings.Split( 1245 raw_XML, opening_tag)[1], closing_tag)[0], nil 1246} 1247 1248func parseEnumValues(registry *registry) (map[string]*enumFieldInfo, map[string][]*enumFieldInfo, error) { 1249 enum_values := make(map[string]*enumFieldInfo) 1250 enum_types := make(map[string][]*enumFieldInfo) 1251 1252 for enum_idx := range registry.Enums { 1253 enum := ®istry.Enums[enum_idx] 1254 for enum_field_idx := range enum.EnumFields { 1255 enum_field := &enum.EnumFields[enum_field_idx] 1256 if _, ok := enum_values[enum_field.Name]; ok { 1257 return nil, nil, errors.New("Duplicated enum value \"" + enum.Name + "\"") 1258 } 1259 enum_values[enum_field.Name] = enum_field 1260 if value, ok := enum_types[enum.Name]; ok { 1261 enum_types[enum.Name] = append(value, enum_field) 1262 } else { 1263 enum_types[enum.Name] = append([]*enumFieldInfo{}, enum_field) 1264 } 1265 } 1266 } 1267 for feature_idx := range registry.Features { 1268 feature := ®istry.Features[feature_idx] 1269 for enum_field_idx := range feature.EnumFields { 1270 enum_field := &feature.EnumFields[enum_field_idx] 1271 if enum_field.Extends != "" { 1272 if _, ok := enum_values[enum_field.Name]; ok { 1273 return nil, nil, errors.New("Duplicated enum value \"" + enum_field.Name + "\"") 1274 } 1275 enum_values[enum_field.Name] = enum_field 1276 enum_types[enum_field.Extends] = append(enum_types[enum_field.Extends], enum_field) 1277 } 1278 } 1279 } 1280 for extension_idx := range registry.Extensions { 1281 extension := ®istry.Extensions[extension_idx] 1282 for requires_idx := range extension.Requires { 1283 requires := &extension.Requires[requires_idx] 1284 for enum_field_idx := range requires.EnumFields { 1285 enum_field := &requires.EnumFields[enum_field_idx] 1286 if enum_field.ExtID == 0 { 1287 enum_field.ExtID = extension.ID 1288 } 1289 if enum_field.Extends != "" { 1290 if old_enum_filed, ok := enum_values[enum_field.Name]; ok { 1291 // Some values are declared twice, once as feature and once as extension. 1292 // It's Ok as long as values match. 1293 if enum_field.Alias != "" && enum_field.Alias == old_enum_filed.Alias { 1294 continue 1295 } 1296 if enum_field.Alias == "" || old_enum_filed.Alias == "" { 1297 continue 1298 } 1299 value, err1 := enumFieldValue(enum_field, nil) 1300 old_value, err2 := enumFieldValue(old_enum_filed, nil) 1301 if value == old_value && err1 == nil && err2 == nil { 1302 continue 1303 } 1304 return nil, nil, errors.New("Duplicated enum value \"" + enum_field.Name + "\"") 1305 } 1306 enum_values[enum_field.Name] = enum_field 1307 enum_types[enum_field.Extends] = append(enum_types[enum_field.Extends], enum_field) 1308 } 1309 } 1310 } 1311 } 1312 return enum_values, enum_types, nil 1313} 1314 1315func enumFieldValue(enum_field *enumFieldInfo, all_enum_fields map[string]*enumFieldInfo) (int64, error) { 1316 if enum_field.Value != "" { 1317 if strings.HasPrefix(enum_field.Value, "0x") { 1318 return strconv.ParseInt(enum_field.Value[2:], 16, 64) 1319 } 1320 return strconv.ParseInt(enum_field.Value, 10, 64) 1321 } 1322 if enum_field.BitPos != "" { 1323 result, err := strconv.ParseInt(enum_field.BitPos, 10, 64) 1324 if err != nil { 1325 return 0, err 1326 } 1327 return 1 << result, nil 1328 } 1329 if enum_field.Alias != "" { 1330 return enumFieldValue(all_enum_fields[enum_field.Alias], all_enum_fields) 1331 } 1332 var result = 1000000000 + (enum_field.ExtID-1)*1000 + enum_field.Offset 1333 if enum_field.Dir == "" { 1334 return result, nil 1335 } 1336 return -result, nil 1337} 1338