6565class db_dxil_enum_value (object ):
6666 "A representation for a value in an enumeration type"
6767
68- def __init__ (self , name , value , doc ):
69- self .name = name # Name (identifier)
68+ def __init__ (self , value , name , doc ):
7069 self .value = value # Numeric value
70+ self .name = name # Name (identifier)
7171 self .doc = doc # Documentation string
7272 self .category = None
7373
@@ -78,14 +78,19 @@ class db_dxil_enum(object):
7878 def __init__ (self , name , doc , valNameDocTuples = ()):
7979 self .name = name
8080 self .doc = doc
81- self .values = [
82- db_dxil_enum_value (n , v , d ) for v , n , d in valNameDocTuples
83- ] # Note transmutation
81+ self .values = [db_dxil_enum_value (* args ) for args in valNameDocTuples ]
8482 self .is_internal = False # whether this is never serialized
83+ self .last_value_name = None # optional last value name for dense enums
84+ self .dxil_version_info = {} # version info for this enum
8585
8686 def value_names (self ):
8787 return [i .name for i in self .values ]
8888
89+ def add_value (self , * args ):
90+ v = db_dxil_enum_value (* args )
91+ self .values .append (v )
92+ return v
93+
8994
9095class db_dxil_inst (object ):
9196 "A representation for a DXIL instruction"
@@ -344,16 +349,20 @@ def __init__(self):
344349 self .passes = [] # inventory of available passes (db_dxil_pass)
345350 self .name_idx = {} # DXIL instructions by name
346351 self .enum_idx = {} # enumerations by name
347- self .dxil_version_info = {}
348352 # list of counters for instructions and dxil ops,
349353 # starting with extra ones specified here
350354 self .counters = extra_counters
351355 self .next_dxil_op_id = 0 # next available DXIL op ID
352356
357+ # Add the OpCode enum type, which will also track version info.
358+ OpCodeEnum = self .add_enum_type (
359+ "OpCode" , "Enumeration for operations specified by DXIL"
360+ )
361+ OpCodeEnum .last_value_name = "NumOpCodes"
362+
353363 self .populate_llvm_instructions ()
354364 self .call_instr = self .get_instr_by_llvm_name ("CallInst" )
355365 self .populate_dxil_operations ()
356- self .build_indices ()
357366 self .populate_extended_docs ()
358367 self .populate_categories_and_models ()
359368 self .build_opcode_enum ()
@@ -362,7 +371,6 @@ def __init__(self):
362371 self .populate_passes ()
363372 self .build_valrules ()
364373 self .build_semantics ()
365- self .build_indices ()
366374 self .populate_counters ()
367375
368376 def __str__ (self ):
@@ -374,43 +382,37 @@ def next_id(self):
374382 self .next_dxil_op_id += 1
375383 return val
376384
377- def add_enum_type (self , name , doc , valNameDocTuples ):
378- "Adds a new enumeration type with name/value/doc tuples"
379- self .enums .append (db_dxil_enum (name , doc , valNameDocTuples ))
380-
381- def build_indices (self ):
382- "Build a name_idx dictionary with instructions and an enum_idx dictionary with enumeration types"
383- self .name_idx = {}
384- for i in self .instr :
385- self .name_idx [i .name ] = i
386- self .enum_idx = {}
387- for i in self .enums :
388- self .enum_idx [i .name ] = i
385+ def add_enum_type (self , name , doc , valNameDocTuples = ()):
386+ "Adds a new enumeration type with optional name/value/doc tuples"
387+ assert name not in self .enum_idx , "Enumeration type %s already exists" % (name )
388+ enum = db_dxil_enum (name , doc , valNameDocTuples )
389+ self .enum_idx [enum .name ] = enum
390+ self .enums .append (enum )
391+ return enum
389392
390393 def build_opcode_enum (self ):
391394 # Build enumeration from instructions
392- OpCodeEnum = db_dxil_enum (
393- "OpCode" , "Enumeration for operations specified by DXIL"
394- )
395+ OpCodeEnum = self . enum_idx [ "OpCode" ]
396+
397+ # Keep track of last seen class/category pairs for OpCodeClass
395398 class_dict = {}
396399 class_dict ["LlvmInst" ] = "LLVM Instructions"
397400 for i in self .instr :
398401 if i .is_dxil_op :
399- v = db_dxil_enum_value (i .dxil_op , i .dxil_opid , i .doc )
402+ v = OpCodeEnum . add_value (i .dxil_opid , i .dxil_op , i .doc )
400403 v .category = i .category
401404 class_dict [i .dxil_class ] = i .category
402- OpCodeEnum . values . append ( v )
403- self . enums . append ( OpCodeEnum )
404- OpCodeClass = db_dxil_enum (
405+
406+ # Build OpCodeClass enum
407+ OpCodeClass = self . add_enum_type (
405408 "OpCodeClass" ,
406409 "Groups for DXIL operations with equivalent function templates" ,
407410 )
408411 OpCodeClass .is_internal = True
412+ OpCodeClass .last_value_name = "NumOpClasses"
409413 for k , v in iter (class_dict .items ()):
410- ev = db_dxil_enum_value ( k , 0 , None )
414+ ev = OpCodeClass . add_value ( 0 , k , None )
411415 ev .category = v
412- OpCodeClass .values .append (ev )
413- self .enums .append (OpCodeClass )
414416
415417 def mark_disallowed_operations (self ):
416418 # Disallow indirect branching, unreachable instructions and support for exception unwinding.
@@ -436,9 +438,7 @@ def verify_dense(self, it, pred, name_proj):
436438 val = i_val
437439
438440 def set_op_count_for_version (self , major , minor ):
439- info = self .dxil_version_info .setdefault ((major , minor ), dict ())
440- info ["NumOpCodes" ] = self .next_dxil_op_id
441- info ["NumOpClasses" ] = len (set ([op .dxil_class for op in self .instr ]))
441+ self .enum_idx ["OpCode" ].dxil_version_info [(major , minor )] = self .next_dxil_op_id
442442 return self .next_dxil_op_id
443443
444444 def populate_categories_and_models (self ):
@@ -5890,7 +5890,6 @@ def UFI(name, **mappings):
58905890 )
58915891
58925892 # Set interesting properties.
5893- self .build_indices ()
58945893 for (
58955894 i
58965895 ) in "CalculateLOD,DerivCoarseX,DerivCoarseY,DerivFineX,DerivFineY,Sample,SampleBias,SampleCmp,SampleCmpBias" .split (
@@ -7024,7 +7023,7 @@ def add_pass(name, type_name, doc, opts):
70247023 self .pass_idx_args .add (anarg .name )
70257024
70267025 def build_semantics (self ):
7027- SemanticKind = db_dxil_enum (
7026+ SemanticKind = self . add_enum_type (
70287027 "SemanticKind" ,
70297028 "Semantic kind; Arbitrary or specific system value." ,
70307029 [
@@ -7064,8 +7063,7 @@ def build_semantics(self):
70647063 (33 , "Invalid" , "" ),
70657064 ],
70667065 )
7067- self .enums .append (SemanticKind )
7068- SigPointKind = db_dxil_enum (
7066+ SigPointKind = self .add_enum_type (
70697067 "SigPointKind" ,
70707068 "Signature Point is more specific than shader stage or signature as it is unique in both stage and item dimensionality or frequency." ,
70717069 [
@@ -7112,8 +7110,7 @@ def build_semantics(self):
71127110 (21 , "Invalid" , "" ),
71137111 ],
71147112 )
7115- self .enums .append (SigPointKind )
7116- PackingKind = db_dxil_enum (
7113+ self .add_enum_type (
71177114 "PackingKind" ,
71187115 "Kind of signature point" ,
71197116 [
@@ -7126,7 +7123,7 @@ def build_semantics(self):
71267123 ],
71277124 )
71287125
7129- Float32DenormMode = db_dxil_enum (
7126+ self . add_enum_type (
71307127 "Float32DenormMode" ,
71317128 "float32 denorm behavior" ,
71327129 [
@@ -7140,7 +7137,6 @@ def build_semantics(self):
71407137 (7 , "Reserve7" , "Reserved Value. Not used for now" ),
71417138 ],
71427139 )
7143- self .enums .append (Float32DenormMode )
71447140
71457141 SigPointCSV = """
71467142 SigPoint, Related, ShaderKind, PackingKind, SignatureKind
@@ -7178,8 +7174,7 @@ def build_semantics(self):
71787174 assert False and "SigPointKind does not align with SigPointCSV row labels"
71797175 self .sigpoint_table = table
71807176
7181- self .enums .append (PackingKind )
7182- SemanticInterpretationKind = db_dxil_enum (
7177+ self .add_enum_type (
71837178 "SemanticInterpretationKind" ,
71847179 "Defines how a semantic is interpreted at a particular SignaturePoint" ,
71857180 [
@@ -7208,7 +7203,6 @@ def build_semantics(self):
72087203 (9 , "Invalid" , "" ),
72097204 ],
72107205 )
7211- self .enums .append (SemanticInterpretationKind )
72127206
72137207 # The following has SampleIndex, Coverage, and InnerCoverage as loaded with instructions rather than from the signature
72147208 SemanticInterpretationCSV = """
@@ -8483,14 +8477,13 @@ def build_valrules(self):
84838477 "UNI" : "Uniform analysis" ,
84848478 "DECL" : "Declaration" ,
84858479 }
8486- valrule_enum = db_dxil_enum ("ValidationRule" , "Known validation rules" )
8480+ valrule_enum = self . add_enum_type ("ValidationRule" , "Known validation rules" )
84878481 valrule_enum .is_internal = True
84888482 for vr in self .val_rules :
84898483 vr .category = cat_names [vr .group_name ]
8490- vrval = db_dxil_enum_value (vr .enum_name , vr .rule_id , vr .doc )
8484+ vrval = valrule_enum . add_value (vr .rule_id , vr .enum_name , vr .doc )
84918485 vrval .category = vr .category
84928486 vrval .err_msg = vr .err_msg
8493- valrule_enum .values .append (vrval )
84948487 self .enums .append (valrule_enum )
84958488
84968489 def populate_counters (self ):
@@ -8517,6 +8510,14 @@ def add_valrule_msg(self, name, desc, err_msg):
85178510 db_dxil_valrule (name , len (self .val_rules ), err_msg = err_msg , doc = desc )
85188511 )
85198512
8513+ def add_inst (self , i ):
8514+ if i .name != "UDiv" :
8515+ # These should not overlap, but UDiv is a known collision.
8516+ assert i .name not in self .name_idx , f"Duplicate instruction name: { i .name } "
8517+ self .name_idx [i .name ] = i
8518+ self .instr .append (i )
8519+ return i
8520+
85208521 def add_llvm_instr (
85218522 self , kind , llvm_id , name , llvm_name , doc , oload_types , op_params , ** props
85228523 ):
@@ -8529,7 +8530,7 @@ def add_llvm_instr(
85298530 oload_types = oload_types ,
85308531 )
85318532 i .props = props
8532- self .instr . append (i )
8533+ return self .add_inst (i )
85338534
85348535 def add_dxil_op (
85358536 self , name , code_class , doc , oload_types , fn_attr , op_params , ** props
@@ -8549,7 +8550,7 @@ def add_dxil_op(
85498550 fn_attr = fn_attr ,
85508551 )
85518552 i .props = props
8552- self .instr . append (i )
8553+ return self .add_inst (i )
85538554
85548555 def add_dxil_op_reserved (self , name ):
85558556 # The return value is parameter 0, insert the opcode as 1.
@@ -8566,7 +8567,7 @@ def add_dxil_op_reserved(self, name):
85668567 oload_types = "v" ,
85678568 fn_attr = "" ,
85688569 )
8569- self .instr . append (i )
8570+ return self .add_inst (i )
85708571
85718572 def reserve_dxil_op_range (self , group_name , count , start_reserved_id = 0 ):
85728573 "Reserve a range of dxil opcodes for future use; returns next id"
0 commit comments