aboutsummaryrefslogtreecommitdiffhomepage
path: root/registry/generator.py
diff options
context:
space:
mode:
Diffstat (limited to 'registry/generator.py')
-rw-r--r--registry/generator.py75
1 files changed, 58 insertions, 17 deletions
diff --git a/registry/generator.py b/registry/generator.py
index c939f9a..e563209 100644
--- a/registry/generator.py
+++ b/registry/generator.py
@@ -2,17 +2,7 @@
#
# Copyright (c) 2013-2020 The Khronos Group Inc.
#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# SPDX-License-Identifier: Apache-2.0
"""Base class for source/header/doc generators, as well as some utility functions."""
from __future__ import unicode_literals
@@ -351,9 +341,6 @@ class OutputGenerator:
bitpos = int(value, 0)
numVal = 1 << bitpos
value = '0x%08x' % numVal
- if not self.genOpts.conventions.valid_flag_bit(bitpos):
- msg='Enum {} uses bit position {}, which may result in undefined behavior or unexpected enumerant scalar data type'
- self.logMsg('warn', msg.format(name, bitpos))
if bitpos >= 32:
value = value + 'ULL'
self.logMsg('diag', 'Enum', name, '-> bitpos [', numVal, ',', value, ']')
@@ -442,10 +429,43 @@ class OutputGenerator:
"""Generate the C declaration for an enum"""
groupElem = groupinfo.elem
+ # Determine the required bit width for the enum group.
+ # 32 is the default, which generates C enum types for the values.
+ bitwidth = 32
+
+ # If the constFlagBits preference is set, 64 is the default for bitmasks
if self.genOpts.conventions.constFlagBits and groupElem.get('type') == 'bitmask':
- return self.buildEnumCDecl_Bitmask(groupinfo, groupName)
+ bitwidth = 64
+
+ # Check for an explicitly defined bitwidth, which will override any defaults.
+ if groupElem.get('bitwidth'):
+ try:
+ bitwidth = int(groupElem.get('bitwidth'))
+ except ValueError as ve:
+ self.logMsg('error', 'Invalid value for bitwidth attribute (', groupElem.get('bitwidth'), ') for ', groupName, ' - must be an integer value\n')
+ exit(1)
+
+ # Bitmask types support 64-bit flags, so have different handling
+ if groupElem.get('type') == 'bitmask':
+
+ # Validate the bitwidth and generate values appropriately
+ # Bitmask flags up to 64-bit are generated as static const uint64_t values
+ # Bitmask flags up to 32-bit are generated as C enum values
+ if bitwidth > 64:
+ self.logMsg('error', 'Invalid value for bitwidth attribute (', groupElem.get('bitwidth'), ') for bitmask type ', groupName, ' - must be less than or equal to 64\n')
+ exit(1)
+ elif bitwidth > 32:
+ return self.buildEnumCDecl_Bitmask(groupinfo, groupName)
+ else:
+ return self.buildEnumCDecl_Enum(expand, groupinfo, groupName)
else:
- return self.buildEnumCDecl_Enum(expand, groupinfo, groupName)
+ # Validate the bitwidth and generate values appropriately
+ # Enum group types up to 32-bit are generated as C enum values
+ if bitwidth > 32:
+ self.logMsg('error', 'Invalid value for bitwidth attribute (', groupElem.get('bitwidth'), ') for enum type ', groupName, ' - must be less than or equal to 32\n')
+ exit(1)
+ else:
+ return self.buildEnumCDecl_Enum(expand, groupinfo, groupName)
def buildEnumCDecl_Bitmask(self, groupinfo, groupName):
"""Generate the C declaration for an "enum" that is actually a
@@ -455,14 +475,24 @@ class OutputGenerator:
# Prefix
body = "// Flag bits for " + flagTypeName + "\n"
+
+ # Maximum allowable value for a flag (unsigned 64-bit integer)
+ maxValidValue = 2**(64) - 1
+ minValidValue = 0
# Loop over the nested 'enum' tags.
for elem in groupElem.findall('enum'):
# Convert the value to an integer and use that to track min/max.
# Values of form -(number) are accepted but nothing more complex.
# Should catch exceptions here for more complex constructs. Not yet.
- (_, strVal) = self.enumToValue(elem, True)
+ (numVal, strVal) = self.enumToValue(elem, True)
name = elem.get('name')
+
+ # Range check for the enum value
+ if numVal is not None and (numVal > maxValidValue or numVal < minValidValue):
+ self.logMsg('error', 'Allowable range for flag types in C is [', minValidValue, ',', maxValidValue, '], but', name, 'flag has a value outside of this (', strVal, ')\n')
+ exit(1)
+
body += "static const {} {} = {};\n".format(flagTypeName, name, strVal)
# Postfix
@@ -489,6 +519,11 @@ class OutputGenerator:
# @@ Should use the type="bitmask" attribute instead
isEnum = ('FLAG_BITS' not in expandPrefix)
+
+ # Allowable range for a C enum - which is that of a signed 32-bit integer
+ maxValidValue = 2**(32 - 1) - 1
+ minValidValue = (maxValidValue * -1) - 1
+
# Get a list of nested 'enum' tags.
enums = groupElem.findall('enum')
@@ -524,6 +559,12 @@ class OutputGenerator:
else:
aliasText.append(decl)
+ # Range check for the enum value
+ if numVal is not None and (numVal > maxValidValue or numVal < minValidValue):
+ self.logMsg('error', 'Allowable range for C enum types is [', minValidValue, ',', maxValidValue, '], but', name, 'has a value outside of this (', strVal, ')\n')
+ exit(1)
+
+
# Don't track min/max for non-numbers (numVal is None)
if isEnum and numVal is not None and elem.get('extends') is None:
if minName is None: