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 "StdVideoAV1Profile": "vk_video/vulkan_video_codec_av1std.h", 283 "StdVideoAV1Level": "vk_video/vulkan_video_codec_av1std.h", 284 "StdVideoAV1SequenceHeader": "vk_video/vulkan_video_codec_av1std.h", 285 "StdVideoDecodeAV1PictureInfo": "vk_video/vulkan_video_codec_av1std_decode.h", 286 "StdVideoDecodeAV1ReferenceInfo": "vk_video/vulkan_video_codec_av1std_decode.h", 287 "uint8_t": "vk_platform", 288 "uint16_t": "vk_platform", 289 "uint32_t": "vk_platform", 290 "uint64_t": "vk_platform", 291 "VisualID": "X11/Xlib.h", 292 "void": "vk_platform", 293 "Window": "X11/Xlib.h", 294 "wl_display": "wayland-client.h", 295 "wl_surface": "wayland-client.h", 296 "xcb_connection_t": "xcb/xcb.h", 297 "xcb_visualid_t": "xcb/xcb.h", 298 "xcb_window_t": "xcb/xcb.h", 299 "zx_handle_t": "zircon/types.h", 300} 301 302// We don't really parse defines since we don't have a full-blown compiler. 303// Instead we rely on the fact that there are very few defines in vk.xml and just verify that they match out assumptions. 304var known_defines = map[string]string{ 305 "VK_MAKE_VERSION": "// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead.\n" + 306 "#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \\\n" + 307 " ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))", 308 "VK_VERSION_MAJOR": "// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead.\n" + 309 "#define <name>VK_VERSION_MAJOR</name>(version) ((uint32_t)(version) >> 22U)", 310 "VK_VERSION_MINOR": "// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead.\n" + 311 "#define <name>VK_VERSION_MINOR</name>(version) (((uint32_t)(version) >> 12U) & 0x3FFU)", 312 "VK_VERSION_PATCH": "// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead.\n" + 313 "#define <name>VK_VERSION_PATCH</name>(version) ((uint32_t)(version) & 0xFFFU)", 314 315 "VK_MAKE_API_VERSION": "#define <name>VK_MAKE_API_VERSION</name>(variant, major, minor, patch) \\\n" + 316 " ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))", 317 "VK_API_VERSION_VARIANT": "#define <name>VK_API_VERSION_VARIANT</name>(version) ((uint32_t)(version) >> 29U)", 318 "VK_API_VERSION_MAJOR": "#define <name>VK_API_VERSION_MAJOR</name>(version) (((uint32_t)(version) >> 22U) & 0x7FU)", 319 "VK_API_VERSION_MINOR": "#define <name>VK_API_VERSION_MINOR</name>(version) (((uint32_t)(version) >> 12U) & 0x3FFU)", 320 "VK_API_VERSION_PATCH": "#define <name>VK_API_VERSION_PATCH</name>(version) ((uint32_t)(version) & 0xFFFU)", 321 322 "VKSC_API_VARIANT": "// Vulkan SC variant number\n#define <name>VKSC_API_VARIANT</name> 1", 323 "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" + 324 "//#define <name>VK_API_VERSION</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 0, 0) // Patch version should always be set to 0", 325 "VK_API_VERSION_1_0": "// Vulkan 1.0 version number\n" + 326 "#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", 327 "VK_API_VERSION_1_1": "// Vulkan 1.1 version number\n" + 328 "#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", 329 "VK_API_VERSION_1_2": "// Vulkan 1.2 version number\n" + 330 "#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", 331 "VK_API_VERSION_1_3": "// Vulkan 1.3 version number\n" + 332 "#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", 333 "VK_API_VERSION_1_4": "// Vulkan 1.4 version number\n" + 334 "#define <name>VK_API_VERSION_1_4</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 4, 0)// Patch version should always be set to 0", 335 "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", 336 "VK_HEADER_VERSION": "// Version of this file\n" + 337 "#define <name>VK_HEADER_VERSION</name> ", 338 "VK_HEADER_VERSION_COMPLETE": "// Complete version of this file\n" + 339 "#define <name>VK_HEADER_VERSION_COMPLETE</name> <type>VK_MAKE_API_VERSION</type>", 340 "VK_DEFINE_HANDLE": "\n#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;", 341 "VK_USE_64_BIT_PTR_DEFINES": "\n" + 342 "#ifndef VK_USE_64_BIT_PTR_DEFINES\n" + 343 " #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" + 344 " #define VK_USE_64_BIT_PTR_DEFINES 1\n" + 345 " #else\n" + 346 " #define VK_USE_64_BIT_PTR_DEFINES 0\n" + 347 " #endif\n" + 348 "#endif", 349 "VK_NULL_HANDLE": "\n" + 350 "#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE\n" + 351 " #if (VK_USE_64_BIT_PTR_DEFINES==1)\n" + 352 " #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L))\n" + 353 " #define VK_NULL_HANDLE nullptr\n" + 354 " #else\n" + 355 " #define VK_NULL_HANDLE ((void*)0)\n" + 356 " #endif\n" + 357 " #else\n" + 358 " #define VK_NULL_HANDLE 0ULL\n" + 359 " #endif\n" + 360 "#endif\n" + 361 "#ifndef VK_NULL_HANDLE\n" + 362 " #define VK_NULL_HANDLE 0\n" + 363 "#endif", 364} 365 366var vulkan_known_defines = map[string]string{ 367 "VK_DEFINE_HANDLE": "\n#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;", 368 "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "\n" + 369 "#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE\n" + 370 " #if (VK_USE_64_BIT_PTR_DEFINES==1)\n" + 371 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;\n" + 372 " #else\n" + 373 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;\n" + 374 " #endif\n" + 375 "#endif", 376} 377 378var vulkansc_known_defines = map[string]string{ 379 "VK_DEFINE_HANDLE": "\n#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* (object);", 380 "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "\n" + 381 "#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE\n" + 382 " #if (VK_USE_64_BIT_PTR_DEFINES==1)\n" + 383 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *(object);\n" + 384 " #else\n" + 385 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t (object);\n" + 386 " #endif\n" + 387 "#endif", 388} 389 390var known_defines_obsoleted = map[string]string{ 391 "VK_MAKE_VERSION": "// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead.\n" + 392 "#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \\\n" + 393 " ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))", 394 "VK_VERSION_MAJOR": "// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead.\n" + 395 "#define <name>VK_VERSION_MAJOR</name>(version) ((uint32_t)(version) >> 22)", 396 "VK_VERSION_MINOR": "// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead.\n" + 397 "#define <name>VK_VERSION_MINOR</name>(version) (((uint32_t)(version) >> 12) & 0x3FFU)", 398 "VK_VERSION_PATCH": "// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead.\n" + 399 "#define <name>VK_VERSION_PATCH</name>(version) ((uint32_t)(version) & 0xFFFU)", 400 "VK_MAKE_API_VERSION": "#define <name>VK_MAKE_API_VERSION</name>(variant, major, minor, patch) \\\n" + 401 " ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))", 402 "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.", 403 "VK_API_VERSION_VARIANT": "#define <name>VK_API_VERSION_VARIANT</name>(version) ((uint32_t)(version) >> 29)", 404 "VK_API_VERSION_MAJOR": "#define <name>VK_API_VERSION_MAJOR</name>(version) (((uint32_t)(version) >> 22) & 0x7FU)", 405 "VK_API_VERSION_MINOR": "#define <name>VK_API_VERSION_MINOR</name>(version) (((uint32_t)(version) >> 12) & 0x3FFU)", 406 "VK_API_VERSION_PATCH": "#define <name>VK_API_VERSION_PATCH</name>(version) ((uint32_t)(version) & 0xFFFU)", 407 "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" + 408 "//#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>(1, 0, 0) // Patch version should always be set to 0", 409 "VK_API_VERSION_1_0": "// Vulkan 1.0 version number\n" + 410 "#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_VERSION</type>(1, 0, 0)// Patch version should always be set to 0", 411 "VK_API_VERSION_1_1": "// Vulkan 1.1 version number\n" + 412 "#define <name>VK_API_VERSION_1_1</name> <type>VK_MAKE_VERSION</type>(1, 1, 0)// Patch version should always be set to 0", 413 "VK_API_VERSION_1_2": "// Vulkan 1.2 version number\n" + 414 "#define <name>VK_API_VERSION_1_2</name> <type>VK_MAKE_VERSION</type>(1, 2, 0)// Patch version should always be set to 0", 415 "VKSC_API_VERSION_1_0": "VK_MAKE_API_VERSION</type>(VKSC_API_VARIANT, 1, 0, 0)// Patch version should always be set to 0", 416 "VK_HEADER_VERSION": "// Version of this file\n" + 417 "#define <name>VK_HEADER_VERSION</name> ", 418 "VK_HEADER_VERSION_COMPLETE": "// Complete version of this file\n" + 419 "#define <name>VK_HEADER_VERSION_COMPLETE</name> <type>VK_MAKE_VERSION</type>(1, 2, VK_HEADER_VERSION)", 420 "VK_USE_64_BIT_PTR_DEFINES": "\n" + 421 "#ifndef VK_USE_64_BIT_PTR_DEFINES\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_USE_64_BIT_PTR_DEFINES 1\n" + 424 " #else\n" + 425 " #define VK_USE_64_BIT_PTR_DEFINES 0\n" + 426 " #endif\n" + 427 "#endif", 428 "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "\n#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)\n" + 429 "#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)\n" + 430 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;\n" + 431 "#else\n" + 432 " #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;\n" + 433 "#endif\n" + 434 "#endif", 435 "VK_NULL_HANDLE": "\n#define <name>VK_NULL_HANDLE</name> 0", 436 "VK_DEFINE_HANDLE": "\n#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* (object);", 437} 438 439func Unmarshal(data []byte) (*registry, error) { 440 var registry registry 441 err := xml.Unmarshal(data, ®istry) 442 if err != nil { 443 return nil, err 444 } 445 for i := range registry.Types { 446 typе := ®istry.Types[i] 447 if typе.Name == "" { 448 typе.Name, err = elementFromRawXML("name", typе.RawXML) 449 if err != nil { 450 return nil, err 451 } 452 } 453 if typе.Category == "" { 454 if requires, found := known_types[typе.Name]; !found || typе.Requires != requires { 455 return nil, errors.New("Unknown type without category: \"" + typе.Name + "\"") 456 } 457 typе.Category = "vk_platform" 458 } 459 if typе.Alias != "" || (typе.Category != "struct" && typе.Category != "union") { 460 if len(typе.Members) != 0 { 461 return nil, errors.New("Members in non-struct type : \"" + typе.Name + "\"") 462 } 463 } else { 464 for j := range typе.Members { 465 member := &typе.Members[j] 466 if member.Name == "" { 467 member.Name, err = elementFromRawXML("name", member.RawXML) 468 if err != nil { 469 return nil, err 470 } 471 } 472 if member.Type == "" { 473 member.Type, err = elementFromRawXML("type", member.RawXML) 474 if err != nil { 475 return nil, err 476 } 477 } 478 if member.Comment == "" && strings.Contains(member.RawXML, "<comment>") { 479 member.Comment, err = elementFromRawXML("comment", member.RawXML) 480 if err != nil { 481 return nil, err 482 } 483 } 484 } 485 } 486 } 487 for i := range registry.Commands { 488 command := ®istry.Commands[i] 489 if command.Name == "" { 490 command.Name, err = elementFromRawXML("name", command.Proto.RawXML) 491 if err != nil { 492 return nil, err 493 } 494 } 495 if command.Alias == "" { 496 if command.Proto.Type == "" { 497 command.Proto.Type, err = elementFromRawXML("type", command.Proto.RawXML) 498 if err != nil { 499 return nil, err 500 } 501 } 502 if command.Proto.Comment == "" && strings.Contains(command.Proto.RawXML, "<comment>") { 503 command.Proto.Type, err = elementFromRawXML("comment", command.Proto.RawXML) 504 if err != nil { 505 return nil, err 506 } 507 } 508 for j := range command.Params { 509 param := &command.Params[j] 510 if param.Name == "" { 511 param.Name, err = elementFromRawXML("name", param.RawXML) 512 if err != nil { 513 return nil, err 514 } 515 } 516 if param.Type == "" { 517 param.Type, err = elementFromRawXML("type", param.RawXML) 518 if err != nil { 519 return nil, err 520 } 521 } 522 if param.Comment == "" && strings.Contains(command.Proto.RawXML, "<comment>") { 523 param.Comment, err = elementFromRawXML("comment", param.RawXML) 524 if err != nil { 525 return nil, err 526 } 527 } 528 } 529 } 530 } 531 return ®istry, nil 532} 533 534func 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) { 535 types = vulkan_types.PlatformTypes() 536 // Note that we don't pre-calculate values for enums during initial parsing because vk.xml 537 // [ab]uses "enum" to define non-integer constants and integers defined-as-C-expression, too. 538 // E.g. "VK_LOD_CLAMP_NONE" as "1000.0f" or VK_QUEUE_FAMILY_FOREIGN_EXT as "(~0U-2)". 539 // We return "raw" string value here and only parse them on as-needed basis. 540 enum_values, enum_types, err := parseEnumValues(registry) 541 if err != nil { 542 return nil, nil, nil, nil, nil, err 543 } 544 // It's allowed in C/C++ to refer to not-yet defined type and type may even include pointer 545 // to itself. But other uses of undefined types are forbidden. Mutually directly (non-pointer) 546 // used types are *forbidden* in C/C++. 547 // Thus the graph of type uses is acyclic when pointers are excluded and we should be 548 // able to iteratively resolve all types by retrying failed types, expecting at least one 549 // type to resolve during an iteration. 550 // The first loop parsing resolves all directly (non-pointer) used types. 551 // 552 // Pointed types just became opaque, if undefined, and will be attempted to be resolved with 553 // a dedicated pass. 554 // The second loop (below) replaces opaque types referenced by pointer if they have been 555 // resolved at some point. Some types are supposed to just be opaque types and be only 556 // operated using pointers — but only platform-provided types, not vk.xml-defined types. 557 var xml_types_list []*typeInfo 558 next_xml_types_list := []*typeInfo{} 559 for index := range registry.Types { 560 next_xml_types_list = append(next_xml_types_list, ®istry.Types[index]) 561 } 562 for len(next_xml_types_list) > 0 { 563 // If next list is the same as previous one then we have some kind of loop and types couldn't be defined. 564 if len(xml_types_list) == len(next_xml_types_list) { 565 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 + "\"\"") 566 } 567 xml_types_list = next_xml_types_list 568 next_xml_types_list = []*typeInfo{} 569 for _, xml_type := range xml_types_list { 570 if _, ok := types[xml_type.Name]; ok { 571 if xml_type.Category == "vk_platform" { 572 continue 573 } 574 if xml_type.Api == "vulkansc" { 575 continue 576 } 577 return nil, nil, nil, nil, nil, errors.New("Duplicated type \"" + xml_type.Name + "\"") 578 } 579 if xml_type.Alias != "" { 580 if alias_target, ok := types[xml_type.Alias]; ok { 581 types[xml_type.Name] = cpp_types.AliasType(xml_type.Name, alias_target) 582 continue 583 } 584 next_xml_types_list = append(next_xml_types_list, xml_type) 585 continue 586 } 587 var c_type cpp_types.Type 588 switch xml_type.Category { 589 case "basetype": 590 c_type, err = vulkanBaseTypeFromXML(xml_type) 591 case "bitmask": 592 c_type, err = vulkanBitmaskTypeFromXML(xml_type, types) 593 case "define": 594 err := vulkanDefineTypeFromXML(xml_type) 595 if err != nil { 596 return nil, nil, nil, nil, nil, err 597 } 598 continue 599 case "enum": 600 c_type, err = vulkanEnumTypeFromXML(xml_type, enum_values, enum_types) 601 case "funcpointer": 602 c_type, err = vulkanFuncPoiterTypeFromXML(xml_type, types) 603 case "handle": 604 c_type, err = vulkanHandleTypeFromXML(xml_type, types) 605 case "include": 606 continue 607 case "struct": 608 c_type, err = vulkanStructTypeFromXML(xml_type, xml_type.StructExtends != "", types, enum_values) 609 case "union": 610 c_type, err = vulkanUnionTypeFromXML(xml_type, types, enum_values) 611 case "vk_platform": 612 return nil, nil, nil, nil, nil, errors.New("Unknown platform type \"" + xml_type.Name + "\"") 613 default: 614 return nil, nil, nil, nil, nil, errors.New("Unknown type category \"" + xml_type.Category + "\"") 615 } 616 // 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. 617 if err == unknownType { 618 next_xml_types_list = append(next_xml_types_list, xml_type) 619 continue 620 } 621 if err != nil { 622 return nil, nil, nil, nil, nil, err 623 } 624 types[xml_type.Name] = c_type 625 } 626 } 627 // 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. 628 for _, xml_type := range registry.Types { 629 if xml_type.Category == "struct" && xml_type.StructExtends != "" { 630 for _, name := range strings.Split(xml_type.StructExtends, ",") { 631 var extended_with *[]cpp_types.Type 632 if types[name].Kind(cpp_types.FirstArch) == cpp_types.Alias { 633 extended_with = &types[name].Elem(cpp_types.FirstArch).(*extendedStruct).extended_with 634 } else { 635 extended_with = &types[name].(*extendedStruct).extended_with 636 } 637 *extended_with = append(*extended_with, types[xml_type.Name]) 638 } 639 } 640 } 641 // Resolve potentially circular references. 642 for type_name := range types { 643 // Here we rely on the fact that there are no types in Vulkan which are stuctural in one case yet non-structural 644 // in other cases. And also there are differently-structured structural types either. 645 typе := types[type_name] 646 if typе.Kind(cpp_types.FirstArch) == cpp_types.Ptr { 647 typе = typе.Elem(cpp_types.FirstArch) 648 } 649 if typе.Kind(cpp_types.FirstArch) != cpp_types.Func && 650 typе.Kind(cpp_types.FirstArch) != cpp_types.Struct && 651 typе.Kind(cpp_types.FirstArch) != cpp_types.Union { 652 continue 653 } 654 for i := uint(0); i < typе.NumField(cpp_types.FirstArch); i++ { 655 field := typе.Field(i, cpp_types.FirstArch) 656 if field.Type().Kind(cpp_types.FirstArch) != cpp_types.Ptr { 657 continue 658 } 659 pointee_type := field.Type().Elem(cpp_types.FirstArch) 660 if pointee_type.Kind(cpp_types.FirstArch) == cpp_types.Opaque { 661 if field_type, ok := types[pointee_type.Name(cpp_types.FirstArch)]; ok && field_type.Kind(cpp_types.FirstArch) != cpp_types.Opaque { 662 field.Type().(cpp_types.ModifyablePtrType).ReplaceElem(field_type) 663 } 664 } else if pointee_type.Kind(cpp_types.FirstArch) == cpp_types.Const && 665 pointee_type.Elem(cpp_types.FirstArch).Kind(cpp_types.FirstArch) == cpp_types.Opaque { 666 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 { 667 field.Type().(cpp_types.ModifyablePtrType).ReplaceElem(cpp_types.ConstType(field_type)) 668 } 669 } 670 } 671 } 672 commands = make(map[string]cpp_types.Type) 673 for index := range registry.Commands { 674 command := registry.Commands[index] 675 // We'll link aliases below, after the final commands are constructed. 676 if command.Alias != "" { 677 continue 678 } 679 if result_type, ok := types[command.Proto.Type]; ok { 680 if space.ReplaceAllString(command.Proto.RawXML, " ") != fmt.Sprintf("<type>%s</type> <name>%s</name>", command.Proto.Type, command.Name) { 681 return nil, nil, nil, nil, nil, errors.New("Unexpected prototype \"" + command.Proto.RawXML + "\"") 682 } 683 fields_info, err := vulkanStructuralTypeMembersFromXML(command.Name, command.Params, types, enum_values) 684 if err != nil { 685 return nil, nil, nil, nil, nil, err 686 } 687 // Arrays decay into pointers when used as parameters of functions - but only one, outer, dimension. 688 // Convert arrays into pointers, leave other types intact. 689 params_info := []cpp_types.FieldInfo{} 690 for _, field_info := range fields_info { 691 if field_info.Type().Kind(cpp_types.FirstArch) == cpp_types.Array { 692 params_info = append(params_info, ExtendedField( 693 field_info.Name(), 694 cpp_types.PointerType(field_info.Type().Elem(cpp_types.FirstArch)), 695 field_info.BaseFieldInfo().(ExtendedFieldInfo).Length(), 696 field_info.BaseFieldInfo().(ExtendedFieldInfo).NestedField())) 697 } else { 698 params_info = append(params_info, field_info) 699 } 700 } 701 commands[command.Name] = cpp_types.FunctionType(result_type, params_info) 702 continue 703 } 704 return nil, nil, nil, nil, nil, errors.New("Unknown return function type \"" + command.Proto.Type + "\"") 705 } 706 // Now link aliases to the final command of the original function. 707 for index := range registry.Commands { 708 command := registry.Commands[index] 709 if command.Alias == "" { 710 continue 711 } 712 commands[command.Name] = commands[command.Alias] 713 } 714 sorted_type_names = []string{} 715 for name := range types { 716 sorted_type_names = append(sorted_type_names, name) 717 } 718 sort.Strings(sorted_type_names) 719 sorted_command_names = []string{} 720 for name := range commands { 721 sorted_command_names = append(sorted_command_names, name) 722 } 723 sort.Strings(sorted_command_names) 724 extensions = make(map[string]int64) 725 for extension_idx := range registry.Extensions { 726 extension := ®istry.Extensions[extension_idx] 727 extensions_spec := int64(-1) 728 for requires_idx := range extension.Requires { 729 requires := &extension.Requires[requires_idx] 730 for enum_field_idx := range requires.EnumFields { 731 enum_field := &requires.EnumFields[enum_field_idx] 732 if enum_field.Alias == "" && strings.HasSuffix(enum_field.Name, "_SPEC_VERSION") { 733 spec_version, err := strconv.ParseInt(enum_field.Value, 10, 32) 734 if err != nil { 735 return nil, nil, nil, nil, nil, err 736 } 737 if spec_version == -1 || extensions_spec != -1 { 738 errors.New("Couldn't find extensions SPEC_VERSION") 739 } 740 extensions_spec = spec_version 741 } 742 } 743 } 744 extensions[extension.Name] = extensions_spec 745 } 746 return sorted_type_names, types, sorted_command_names, commands, extensions, nil 747} 748 749func vulkanBaseTypeFromXML(typе *typeInfo) (cpp_types.Type, error) { 750 RawXML := strings.TrimSpace(space.ReplaceAllString(typе.RawXML, " ")) 751 if typе.Name == "CAMetalLayer" { 752 if RawXML != "#ifdef __OBJC__ @class CAMetalLayer; #else typedef void <name>CAMetalLayer</name>; #endif" { 753 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 754 } 755 return cpp_types.OpaqueType("CAMetalLayer"), nil 756 } 757 if typе.Name == "MTLDevice_id" { 758 if RawXML != "#ifdef __OBJC__ @protocol MTLDevice; typedef __unsafe_unretained id<MTLDevice> MTLDevice_id; #else typedef void* <name>MTLDevice_id</name>; #endif" { 759 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 760 } 761 return cpp_types.PointerType(cpp_types.VoidType), nil 762 } 763 if typе.Name == "MTLCommandQueue_id" { 764 if RawXML != "#ifdef __OBJC__ @protocol MTLCommandQueue; typedef __unsafe_unretained id<MTLCommandQueue> MTLCommandQueue_id; #else typedef void* <name>MTLCommandQueue_id</name>; #endif" { 765 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 766 } 767 return cpp_types.PointerType(cpp_types.VoidType), nil 768 } 769 if typе.Name == "MTLBuffer_id" { 770 if RawXML != "#ifdef __OBJC__ @protocol MTLBuffer; typedef __unsafe_unretained id<MTLBuffer> MTLBuffer_id; #else typedef void* <name>MTLBuffer_id</name>; #endif" { 771 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 772 } 773 return cpp_types.PointerType(cpp_types.VoidType), nil 774 } 775 if typе.Name == "MTLTexture_id" { 776 if RawXML != "#ifdef __OBJC__ @protocol MTLTexture; typedef __unsafe_unretained id<MTLTexture> MTLTexture_id; #else typedef void* <name>MTLTexture_id</name>; #endif" { 777 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 778 } 779 return cpp_types.PointerType(cpp_types.VoidType), nil 780 } 781 if typе.Name == "MTLSharedEvent_id" { 782 if RawXML != "#ifdef __OBJC__ @protocol MTLSharedEvent; typedef __unsafe_unretained id<MTLSharedEvent> MTLSharedEvent_id; #else typedef void* <name>MTLSharedEvent_id</name>; #endif" { 783 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 784 } 785 return cpp_types.PointerType(cpp_types.VoidType), nil 786 } 787 if typе.Name == "IOSurfaceRef" { 788 if RawXML != "typedef struct __IOSurface* <name>IOSurfaceRef</name>;" { 789 return nil, errors.New("Unexpected define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 790 } 791 return cpp_types.PointerType(cpp_types.OpaqueType("__IOSurface")), nil 792 } 793 if RawXML == fmt.Sprintf("struct <name>%s</name>;", typе.Name) { 794 return cpp_types.OpaqueType(typе.Name), nil 795 } 796 if RawXML == fmt.Sprintf("typedef <type>uint32_t</type> <name>%s</name>;", typе.Name) { 797 return cpp_types.AliasType(typе.Name, cpp_types.UInt32TType), nil 798 } 799 if RawXML == fmt.Sprintf("typedef <type>uint64_t</type> <name>%s</name>;", typе.Name) { 800 return cpp_types.AliasType(typе.Name, cpp_types.UInt64TType), nil 801 } 802 if RawXML == fmt.Sprintf("typedef <type>void</type>* <name>%s</name>;", typе.Name) { 803 return cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.VoidType)), nil 804 } 805 return nil, errors.New("Unexpected basetype \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 806} 807 808func vulkanBitmaskTypeFromXML(typе *typeInfo, types map[string]cpp_types.Type) (cpp_types.Type, error) { 809 RawXML := strings.TrimSpace(space.ReplaceAllString(typе.RawXML, " ")) 810 if RawXML == fmt.Sprintf("typedef <type>VkFlags</type> <name>%s</name>;", typе.Name) { 811 return cpp_types.AliasType(typе.Name, types["VkFlags"]), nil 812 } 813 if RawXML == fmt.Sprintf("typedef <type>VkFlags64</type> <name>%s</name>;", typе.Name) { 814 return cpp_types.AliasType(typе.Name, types["VkFlags64"]), nil 815 } 816 return nil, errors.New("Unexpected bitmask \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 817} 818 819func vulkanDefineTypeFromXML(typе *typeInfo) error { 820 if typе.Api == "vulkan" { 821 if define, ok := vulkan_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 if typе.Api == "vulkansc" { 828 if define, ok := vulkansc_known_defines[typе.Name]; ok { 829 if define != typе.RawXML { 830 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 831 } 832 return nil 833 } 834 } else { 835 if define, ok := vulkan_known_defines[typе.Name]; ok { 836 if define == typе.RawXML { 837 return nil 838 } 839 } 840 if define, ok := vulkansc_known_defines[typе.Name]; ok { 841 if define != typе.RawXML { 842 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 843 } 844 return nil 845 } 846 } 847 if define, ok := known_defines[typе.Name]; ok { 848 // Most defines are stable and since we don't parse them we just ensure they match our expectations. 849 if typе.Name != "VK_HEADER_VERSION" && typе.Name != "VK_HEADER_VERSION_COMPLETE" { 850 if define != typе.RawXML { 851 if obsolete_define, ok := known_defines_obsoleted[typе.Name]; ok { 852 if obsolete_define == typе.RawXML { 853 return nil 854 } 855 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 856 } 857 return errors.New("Unknown obsolete define \"" + typе.Name + "\"") 858 } 859 return nil 860 } 861 // Note: VK_HEADER_VERSION is updated every time vk.xml is updated thus we couldn't hardcode it. 862 // VK_HEADER_VERSION_COMPLETE is updted when new, incompatible version of Vulkan is released. 863 if !strings.HasPrefix(typе.RawXML, define) { 864 return errors.New("Unmatched define \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 865 } 866 return nil 867 } 868 return errors.New("Unknown define \"" + typе.Name + "\"") 869} 870 871func vulkanEnumTypeFromXML(typе *typeInfo, enum_values map[string]*enumFieldInfo, enum_types map[string][]*enumFieldInfo) (cpp_types.Type, error) { 872 fits_in_int32 := true 873 fits_in_uint32 := true 874 // Duplicate logic from Khronos's generator.py: use int32_t if everything fits into int32_t, 875 // then uint32_t, then int64_t. 876 basetype := cpp_types.Int32TType 877 for _, element := range enum_types[typе.Name] { 878 value, err := enumFieldValue(element, enum_values) 879 if err != nil { 880 return nil, err 881 } 882 if int64(int32(value)) != value { 883 fits_in_int32 = false 884 } 885 if int64(uint32(value)) != value { 886 fits_in_uint32 = false 887 } 888 } 889 if !fits_in_int32 { 890 if fits_in_uint32 { 891 basetype = cpp_types.UInt32TType 892 } else { 893 basetype = cpp_types.Int64TType 894 } 895 } 896 values := []cpp_types.EnumFieldInfo{} 897 for _, element := range enum_types[typе.Name] { 898 value, _ := enumFieldValue(element, enum_values) 899 values = append(values, cpp_types.EnumField(element.Name, basetype, element.Alias, value)) 900 } 901 return cpp_types.EnumType(typе.Name, basetype, values), nil 902} 903 904func vulkanFuncPoiterTypeFromXML(typе *typeInfo, types map[string]cpp_types.Type) (cpp_types.Type, error) { 905 definition := strings.TrimSpace(typе.RawXML) 906 if !strings.HasPrefix(definition, "typedef ") || 907 !strings.HasSuffix(definition, ");") || 908 strings.Count(definition, " (VKAPI_PTR *<name>") != 1 || 909 strings.Count(definition, "</name>)(") != 1 { 910 return nil, errors.New("Couldn't determine function type from \"" + definition + "\"") 911 } 912 split := strings.Split(definition[8:len(definition)-2], " (VKAPI_PTR *<name>") 913 var return_type cpp_types.Type 914 return_type_string := split[0] 915 if strings.HasSuffix(return_type_string, "*") { 916 return_typе, ok := types[return_type_string[0:len(return_type_string)-1]] 917 if !ok { 918 return nil, errors.New("Couldn't determine function type \"" + return_type_string + "\"") 919 } 920 return_type = cpp_types.PointerType(return_typе) 921 } else { 922 return_typе, ok := types[return_type_string] 923 if !ok { 924 return nil, errors.New("Couldn't determine function type \"" + return_type_string + "\"") 925 } 926 return_type = return_typе 927 } 928 parameters := strings.Split(split[1], "</name>)(")[1] 929 var parameter_types []cpp_types.FieldInfo 930 if parameters == "void" { 931 return cpp_types.PointerType(cpp_types.FunctionType(return_type, parameter_types)), nil 932 } 933 for _, parameter := range strings.Split(parameters, ",") { 934 parameter = strings.TrimSpace(parameter) 935 parameter_type_len := strings.LastIndex(parameter, " ") 936 parameter_type := strings.TrimSpace(parameter[:parameter_type_len]) 937 parameter_name := strings.TrimSpace(parameter[parameter_type_len+1:]) 938 if strings.HasPrefix(parameter_type, "<type>") && 939 strings.HasSuffix(parameter_type, "</type>") { 940 parameter_types = append( 941 parameter_types, 942 ExtendedField(parameter_name, types[parameter_type[6:len(parameter_type)-7]], 943 nil, 944 nil)) 945 } else if strings.HasPrefix(parameter_type, "const <type>") && 946 strings.HasSuffix(parameter_type, "</type>*") { 947 pointee_type_name := parameter_type[12 : len(parameter_type)-8] 948 if pointee_type, ok := types[pointee_type_name]; ok { 949 parameter_types = append( 950 parameter_types, 951 ExtendedField( 952 parameter_name, 953 cpp_types.PointerType(cpp_types.ConstType(pointee_type)), 954 nil, 955 nil)) 956 } else { 957 parameter_types = append( 958 parameter_types, 959 ExtendedField( 960 parameter_name, 961 cpp_types.PointerType(cpp_types.ConstType(cpp_types.OpaqueType(pointee_type_name))), 962 nil, 963 nil)) 964 } 965 } else if strings.HasPrefix(parameter_type, "<type>") && 966 strings.HasSuffix(parameter_type, "</type>*") { 967 pointee_type_name := parameter_type[6 : len(parameter_type)-8] 968 if pointee_type, ok := types[pointee_type_name]; ok { 969 parameter_types = append( 970 parameter_types, 971 ExtendedField( 972 parameter_name, 973 cpp_types.PointerType(pointee_type), 974 nil, 975 nil)) 976 } else { 977 parameter_types = append( 978 parameter_types, 979 ExtendedField( 980 parameter_name, 981 cpp_types.PointerType(cpp_types.OpaqueType(pointee_type_name)), 982 nil, 983 nil)) 984 } 985 } else { 986 return nil, errors.New("Couldn't determine parameter type \"" + parameter_type + "\"") 987 } 988 } 989 return cpp_types.PointerType(cpp_types.FunctionType(return_type, parameter_types)), nil 990} 991 992func vulkanHandleTypeFromXML(typе *typeInfo, types map[string]cpp_types.Type) (cpp_types.Type, error) { 993 if typе.RawXML == fmt.Sprintf("<type>VK_DEFINE_HANDLE</type>(<name>%s</name>)", typе.Name) { 994 return cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.OpaqueType(fmt.Sprintf("struct %s_T", typе.Name)))), nil 995 } else if typе.RawXML == fmt.Sprintf("<type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>%s</name>)", typе.Name) { 996 return cpp_types.ArchDependentType( 997 cpp_types.AliasType(typе.Name, cpp_types.UInt64TType), 998 cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.OpaqueType(fmt.Sprintf("struct %s_T", typе.Name)))), 999 cpp_types.AliasType(typе.Name, cpp_types.UInt64TType), 1000 cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.OpaqueType(fmt.Sprintf("struct %s_T", typе.Name)))), 1001 cpp_types.AliasType(typе.Name, cpp_types.UInt64TType), 1002 cpp_types.AliasType(typе.Name, cpp_types.PointerType(cpp_types.OpaqueType(fmt.Sprintf("struct %s_T", typе.Name))))), nil 1003 } 1004 return nil, errors.New("Unexpected handle \"" + typе.Name + "\": \"" + typе.RawXML + "\"\"") 1005} 1006 1007func vulkanStructTypeFromXML(typе *typeInfo, optional_struct bool, types map[string]cpp_types.Type, enum_values map[string]*enumFieldInfo) (cpp_types.Type, error) { 1008 fields_info, err := vulkanStructuralTypeMembersFromXML(typе.Name, typе.Members, types, enum_values) 1009 if err != nil { 1010 return nil, err 1011 } 1012 optional_enum_value := "" 1013 if optional_struct { 1014 if typе.Members[0].Type != "VkStructureType" || fields_info[0].Name() != "sType" || fields_info[1].Name() != "pNext" { 1015 return nil, errors.New("Struct extension must have first field named VkStructureType sType and second named pNext") 1016 } 1017 optional_enum_value = typе.Members[0].Value 1018 } 1019 return ExtendedStruct(cpp_types.StructType(typе.Name, fields_info), optional_struct, optional_enum_value), nil 1020} 1021 1022func vulkanUnionTypeFromXML(typе *typeInfo, types map[string]cpp_types.Type, enum_values map[string]*enumFieldInfo) (cpp_types.Type, error) { 1023 fields_info, err := vulkanStructuralTypeMembersFromXML(typе.Name, typе.Members, types, enum_values) 1024 if err != nil { 1025 return nil, err 1026 } 1027 return cpp_types.UnionType(typе.Name, fields_info), nil 1028} 1029 1030var space = regexp.MustCompile(`\s+`) 1031 1032func vulkanStructuralTypeMembersFromXML(name string, members []structuralMemberInfo, types map[string]cpp_types.Type, enum_values map[string]*enumFieldInfo) (result []cpp_types.FieldInfo, err error) { 1033 fields_info := []*extendedField{} 1034 field_map := make(map[string]*extendedField) 1035 for _, member := range members { 1036 html := strings.TrimSpace(member.RawXML) 1037 // Note: checks below count only opening tags because XML parser guarantees that closing tags are there and they 1038 // match opening tags. 1039 if member.Comment != "" { 1040 if comments := strings.Count(html, "<comment>"); comments > 1 { 1041 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1042 } else if comments == 1 { 1043 html = strings.Split(html, "<comment>")[0] + strings.Split(html, "</comment>")[1] 1044 } 1045 } 1046 if strings.Count(html, "<type>") != 1 { 1047 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1048 } 1049 text_before_type_name := strings.TrimSpace(strings.Split(html, "<type>")[0]) 1050 text_after_type_name := strings.TrimSpace(strings.Split(html, "</type>")[1]) 1051 if strings.Count(html, "<name>") > 1 { 1052 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1053 } else if strings.Count(html, "<name>") == 1 { 1054 text_after_type_name = strings.Split(text_after_type_name, "<name>")[0] + strings.Split(text_after_type_name, "</name>")[1] 1055 } 1056 text_after_type_name = strings.TrimSpace(space.ReplaceAllString(text_after_type_name, " ")) 1057 member_type, raw_type_known := types[member.Type] 1058 // TODO(b/268638193): handle comma-separated list of allowed functions. 1059 if member.Type == "VkBaseInStructure" || member.Type == "VkBaseOutStructure" { 1060 member_type = types[member.Validstructs] 1061 } 1062 if len(text_after_type_name) > 0 && text_after_type_name[0] == '*' { 1063 if raw_type_known { 1064 if text_before_type_name == "const" || text_before_type_name == "const struct" { 1065 member_type = cpp_types.ConstType(member_type) 1066 } else if text_before_type_name != "" && text_before_type_name != "struct" { 1067 return nil, errors.New("Unexpected prefix in \"" + name + "\": \"" + html + "\"\"") 1068 } 1069 } else { 1070 member_type = cpp_types.OpaqueType(member.Type) 1071 // Note that if type is opaque in C (but not C++!) if has to be prefixed with either "const struct" or "struct". 1072 // If we only see "const" or nothing then that type is not opaque and is supposed to be declared somewhere below. 1073 // Return unknownType if that happens. 1074 if text_before_type_name == "" || text_before_type_name == "const" { 1075 return nil, unknownType 1076 } else if text_before_type_name == "const struct" { 1077 member_type = cpp_types.ConstType(member_type) 1078 } else if text_before_type_name != "struct" { 1079 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1080 } 1081 } 1082 if text_after_type_name == "*" { 1083 member_type = cpp_types.PointerType(member_type) 1084 } else if text_after_type_name == "**" { 1085 member_type = cpp_types.PointerType(cpp_types.PointerType(member_type)) 1086 } else if text_after_type_name == "* const*" || text_after_type_name == "* const *" { 1087 member_type = cpp_types.PointerType(cpp_types.ConstType(cpp_types.PointerType(member_type))) 1088 } else { 1089 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1090 } 1091 } else { 1092 if !raw_type_known { 1093 return nil, unknownType 1094 } 1095 if text_before_type_name == "const" { 1096 member_type = cpp_types.ConstType(member_type) 1097 } else if text_before_type_name != "" { 1098 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1099 } 1100 // Bitfields are not actually supposed to be used in vk.xml — and it even has comment which says exactly that! 1101 // Unfortunately they are already there and couldn't be removed (backward compatibility!). 1102 // Replace "uint32_t :8" with "uint8_t" and "uint32_t :24" with "uint8_t[3]". 1103 // This is hack but provides proper layout. 1104 if text_after_type_name == ":8" { 1105 if member.Type != "uint32_t" && member.Type != "VkGeometryInstanceFlagsKHR" { 1106 return nil, errors.New("Unsupported bitfield type name \"" + name + "\": \"" + html + "\"\"") 1107 } 1108 member_type = cpp_types.UInt8TType 1109 } else if text_after_type_name == ":24" { 1110 if member.Type != "uint32_t" { 1111 return nil, errors.New("Unsupported bitfield type name \"" + name + "\": \"" + html + "\"\"") 1112 } 1113 member_type = cpp_types.ArrayType(cpp_types.UInt8TType, 3) 1114 } else { 1115 indexes := []uint{} 1116 for strings.HasSuffix(text_after_type_name, "]") { 1117 array_size_text := text_after_type_name[strings.LastIndex(text_after_type_name, "[")+1 : len(text_after_type_name)-1] 1118 text_after_type_name = text_after_type_name[0 : len(text_after_type_name)-len(array_size_text)-2] 1119 if strings.HasPrefix(array_size_text, "<enum>") { 1120 if !strings.HasSuffix(array_size_text, "</enum>") { 1121 return nil, errors.New("Unsupported array index \"" + array_size_text + "\"\"") 1122 } 1123 array_size_text = enum_values[array_size_text[6:len(array_size_text)-7]].Value 1124 } 1125 array_size, err := strconv.ParseInt(array_size_text, 10, 32) 1126 if err != nil { 1127 return nil, err 1128 } 1129 indexes = append(indexes, uint(array_size)) 1130 } 1131 for i := len(indexes) - 1; i >= 0; i-- { 1132 member_type = cpp_types.ArrayType(member_type, indexes[i]) 1133 } 1134 if text_after_type_name != "" { 1135 return nil, errors.New("Unexpected member definition in \"" + name + "\": \"" + html + "\"\"") 1136 } 1137 } 1138 } 1139 new_field := extendedField{cpp_types.Field(member.Name, member_type), nil, nil} 1140 if member.Api != "vulkansc" { 1141 fields_info = append(fields_info, &new_field) 1142 field_map[member.Name] = &new_field 1143 } 1144 } 1145 for _, member := range members { 1146 // This strange notion is used in VkAccelerationStructureBuildGeometryInfoKHR structure where only one of two fields can be non-NULL: 1147 // <member len="geometryCount,1" optional="true,false"> 1148 // We treat it as <member len="geometryCount" optional="true"> here. 1149 if strings.HasSuffix(member.Length, ",1") { 1150 if length, ok := field_map[member.Length[0:len(member.Length)-2]]; ok { 1151 field_map[member.Name].length = length 1152 } else { 1153 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1154 } 1155 // Some corner cases have len like “pAllocateInfo->descriptorSetCount”. 1156 // Currently that only have one level, structures are always input to function, 1157 // and we don't need to convert these. 1158 // 1159 // We need to detect case where that wouldn't be true in the future. 1160 // Only then would we know how to handle these. 1161 // 1162 // We parse these and pass the information to calling module because it's 1163 // not easy to see here whether types are compatible on all platforms here 1164 // or not (and there are more than a couple of such types). 1165 } else if strings.Contains(member.Length, "->") { 1166 split_length := strings.Split(member.Length, "->") 1167 if len(split_length) > 2 { 1168 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1169 } 1170 length, ok := field_map[split_length[0]] 1171 if !ok { 1172 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1173 } 1174 field_map[member.Name].length = length 1175 // Note: we are dealing with pointer to const data structure here. 1176 // That's why we dereference twice. 1177 length_type := length.Type() 1178 if length_type.Kind(cpp_types.FirstArch) != cpp_types.Ptr { 1179 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1180 } 1181 length_type = length_type.Elem(cpp_types.FirstArch) 1182 if length_type.Kind(cpp_types.FirstArch) == cpp_types.Const { 1183 length_type = length_type.Elem(cpp_types.FirstArch) 1184 } 1185 if length_type.Kind(cpp_types.FirstArch) != cpp_types.Struct && 1186 length_type.Kind(cpp_types.FirstArch) != cpp_types.Union { 1187 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1188 } 1189 for i := uint(0); i < length_type.NumField(cpp_types.FirstArch); i++ { 1190 if length_type.Field(i, cpp_types.FirstArch).Name() == split_length[1] { 1191 field_map[member.Name].nested_field = length_type.Field(i, cpp_types.FirstArch) 1192 } 1193 } 1194 if field_map[member.Name].nested_field == nil { 1195 return nil, errors.New("Unexpected field referred by len in \"" + member.Name + "\"") 1196 } 1197 // If len is too complicated it may be represented as LaTeX expression (e.g. 1198 // latexmath:[\lceil{\mathit{rasterizationSamples} \over 32}\rceil] for pSampleMask) 1199 // In these cases altlength represents for C, but it may be quite hard to parse that 1200 // too. 1201 // Thankfully for now all such complex fields pass arrays of uint{8,16,32}_t which 1202 // we never translate. Note: we currently don't translate uint64_t even if these 1203 // are not 100% compatible on all platforms. The only direction where that may 1204 // matter would be x86 (32bit) to AArch32 translation (which we don't support), 1205 // but arrays of uint{8,16,32}_t are 100% compatible on all platforums. 1206 // 1207 // Verify that it's so and ignore "len" in that case. 1208 } else if member.AltLength != "" { 1209 typе := field_map[member.Name].Type() 1210 if typе.Kind(cpp_types.FirstArch) != cpp_types.Ptr { 1211 return nil, errors.New("Unexpected altlen field in \"" + member.Name + "\"") 1212 } 1213 element_type := typе.Elem(cpp_types.FirstArch) 1214 if element_type.Kind(cpp_types.FirstArch) == cpp_types.Const { 1215 element_type = element_type.Elem(cpp_types.FirstArch) 1216 } 1217 if element_type.Kind(cpp_types.FirstArch) == cpp_types.Alias { 1218 element_type = element_type.Elem(cpp_types.FirstArch) 1219 } 1220 if element_type.Kind(cpp_types.FirstArch) != cpp_types.UInt8T && 1221 element_type.Kind(cpp_types.FirstArch) != cpp_types.UInt16T && 1222 element_type.Kind(cpp_types.FirstArch) != cpp_types.UInt32T { 1223 return nil, errors.New("Unexpected altlen field in \"" + member.Name + "\"") 1224 } 1225 // Weird case with constant 1 length. This is currently only used by GetDeviceSubpassShadingMaxWorkgroupSize, 1226 // for a VkExtent2D, which should not require translation. 1227 } else if member.Length == "1" { 1228 // TODO(b/372341855): Figure out what we really need to do in this case. 1229 } else if member.Length != "" && member.Length != "null-terminated" && !strings.HasSuffix(member.Length, ",null-terminated") { 1230 if length, ok := field_map[member.Length]; ok { 1231 field_map[member.Name].length = length 1232 } else { 1233 return nil, errors.New("Unexpected len field in \"" + member.Name + "\"") 1234 } 1235 } 1236 } 1237 result = make([]cpp_types.FieldInfo, len(fields_info)) 1238 for index, field_info := range fields_info { 1239 result[index] = field_info 1240 } 1241 return result, nil 1242} 1243 1244var unknownType = errors.New("Couldn't find type") 1245 1246func elementFromRawXML(element_name string, raw_XML string) (string, error) { 1247 opening_tag := "<" + element_name + ">" 1248 closing_tag := "</" + element_name + ">" 1249 if strings.Count(raw_XML, opening_tag) != 1 { 1250 return "", errors.New("Couldn't determine element \"" + element_name + "\" from \"" + raw_XML + "\"") 1251 } 1252 if strings.Count(raw_XML, closing_tag) != 1 { 1253 return "", errors.New("Couldn't determine element \"" + element_name + "\" from \"" + raw_XML + "\"") 1254 } 1255 return strings.Split(strings.Split( 1256 raw_XML, opening_tag)[1], closing_tag)[0], nil 1257} 1258 1259func parseEnumValues(registry *registry) (map[string]*enumFieldInfo, map[string][]*enumFieldInfo, error) { 1260 enum_values := make(map[string]*enumFieldInfo) 1261 enum_types := make(map[string][]*enumFieldInfo) 1262 1263 for enum_idx := range registry.Enums { 1264 enum := ®istry.Enums[enum_idx] 1265 for enum_field_idx := range enum.EnumFields { 1266 enum_field := &enum.EnumFields[enum_field_idx] 1267 if _, ok := enum_values[enum_field.Name]; ok { 1268 return nil, nil, errors.New("Duplicated enum value \"" + enum.Name + "\"") 1269 } 1270 enum_values[enum_field.Name] = enum_field 1271 if value, ok := enum_types[enum.Name]; ok { 1272 enum_types[enum.Name] = append(value, enum_field) 1273 } else { 1274 enum_types[enum.Name] = append([]*enumFieldInfo{}, enum_field) 1275 } 1276 } 1277 } 1278 for feature_idx := range registry.Features { 1279 feature := ®istry.Features[feature_idx] 1280 for enum_field_idx := range feature.EnumFields { 1281 enum_field := &feature.EnumFields[enum_field_idx] 1282 if enum_field.Extends != "" { 1283 if _, ok := enum_values[enum_field.Name]; ok { 1284 return nil, nil, errors.New("Duplicated enum value \"" + enum_field.Name + "\"") 1285 } 1286 enum_values[enum_field.Name] = enum_field 1287 enum_types[enum_field.Extends] = append(enum_types[enum_field.Extends], enum_field) 1288 } 1289 } 1290 } 1291 for extension_idx := range registry.Extensions { 1292 extension := ®istry.Extensions[extension_idx] 1293 for requires_idx := range extension.Requires { 1294 requires := &extension.Requires[requires_idx] 1295 for enum_field_idx := range requires.EnumFields { 1296 enum_field := &requires.EnumFields[enum_field_idx] 1297 if enum_field.ExtID == 0 { 1298 enum_field.ExtID = extension.ID 1299 } 1300 if enum_field.Extends != "" { 1301 if old_enum_filed, ok := enum_values[enum_field.Name]; ok { 1302 // Some values are declared twice, once as feature and once as extension. 1303 // It's Ok as long as values match. 1304 if enum_field.Alias != "" && enum_field.Alias == old_enum_filed.Alias { 1305 continue 1306 } 1307 if enum_field.Alias == "" || old_enum_filed.Alias == "" { 1308 continue 1309 } 1310 value, err1 := enumFieldValue(enum_field, nil) 1311 old_value, err2 := enumFieldValue(old_enum_filed, nil) 1312 if value == old_value && err1 == nil && err2 == nil { 1313 continue 1314 } 1315 return nil, nil, errors.New("Duplicated enum value \"" + enum_field.Name + "\"") 1316 } 1317 enum_values[enum_field.Name] = enum_field 1318 enum_types[enum_field.Extends] = append(enum_types[enum_field.Extends], enum_field) 1319 } 1320 } 1321 } 1322 } 1323 return enum_values, enum_types, nil 1324} 1325 1326func enumFieldValue(enum_field *enumFieldInfo, all_enum_fields map[string]*enumFieldInfo) (int64, error) { 1327 if enum_field.Value != "" { 1328 if strings.HasPrefix(enum_field.Value, "0x") { 1329 return strconv.ParseInt(enum_field.Value[2:], 16, 64) 1330 } 1331 return strconv.ParseInt(enum_field.Value, 10, 64) 1332 } 1333 if enum_field.BitPos != "" { 1334 result, err := strconv.ParseInt(enum_field.BitPos, 10, 64) 1335 if err != nil { 1336 return 0, err 1337 } 1338 return 1 << result, nil 1339 } 1340 if enum_field.Alias != "" { 1341 return enumFieldValue(all_enum_fields[enum_field.Alias], all_enum_fields) 1342 } 1343 var result = 1000000000 + (enum_field.ExtID-1)*1000 + enum_field.Offset 1344 if enum_field.Dir == "" { 1345 return result, nil 1346 } 1347 return -result, nil 1348} 1349