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)) &lt;&lt; 22U) | (((uint32_t)(minor)) &lt;&lt; 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) &gt;&gt; 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) &gt;&gt; 12U) &amp; 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) &amp; 0xFFFU)",
309
310	"VK_MAKE_API_VERSION": "#define <name>VK_MAKE_API_VERSION</name>(variant, major, minor, patch) \\\n" +
311		"    ((((uint32_t)(variant)) &lt;&lt; 29U) | (((uint32_t)(major)) &lt;&lt; 22U) | (((uint32_t)(minor)) &lt;&lt; 12U) | ((uint32_t)(patch)))",
312	"VK_API_VERSION_VARIANT": "#define <name>VK_API_VERSION_VARIANT</name>(version) ((uint32_t)(version) &gt;&gt; 29U)",
313	"VK_API_VERSION_MAJOR":   "#define <name>VK_API_VERSION_MAJOR</name>(version) (((uint32_t)(version) &gt;&gt; 22U) &amp; 0x7FU)",
314	"VK_API_VERSION_MINOR":   "#define <name>VK_API_VERSION_MINOR</name>(version) (((uint32_t)(version) &gt;&gt; 12U) &amp; 0x3FFU)",
315	"VK_API_VERSION_PATCH":   "#define <name>VK_API_VERSION_PATCH</name>(version) ((uint32_t)(version) &amp; 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__) &amp;&amp; !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) &amp;&amp; __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) &amp;&amp; (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) &amp;&amp; (_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)) &lt;&lt; 22) | (((uint32_t)(minor)) &lt;&lt; 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) &gt;&gt; 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) &gt;&gt; 12) &amp; 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) &amp; 0xFFFU)",
393	"VK_MAKE_API_VERSION": "#define <name>VK_MAKE_API_VERSION</name>(variant, major, minor, patch) \\\n" +
394		"    ((((uint32_t)(variant)) &lt;&lt; 29) | (((uint32_t)(major)) &lt;&lt; 22) | (((uint32_t)(minor)) &lt;&lt; 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) &gt;&gt; 29)",
397	"VK_API_VERSION_MAJOR":   "#define <name>VK_API_VERSION_MAJOR</name>(version) (((uint32_t)(version) &gt;&gt; 22) &amp; 0x7FU)",
398	"VK_API_VERSION_MINOR":   "#define <name>VK_API_VERSION_MINOR</name>(version) (((uint32_t)(version) &gt;&gt; 12) &amp; 0x3FFU)",
399	"VK_API_VERSION_PATCH":   "#define <name>VK_API_VERSION_PATCH</name>(version) ((uint32_t)(version) &amp; 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__) &amp;&amp; !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__) &amp;&amp; !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, &registry)
435	if err != nil {
436		return nil, err
437	}
438	for i := range registry.Types {
439		typе := &registry.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 := &registry.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 &registry, 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, &registry.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 := &registry.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&lt;MTLDevice&gt; 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&lt;MTLCommandQueue&gt; 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&lt;MTLBuffer&gt; 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&lt;MTLTexture&gt; 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&lt;MTLSharedEvent&gt; 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 := &registry.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 := &registry.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 := &registry.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