<s> from collections import defaultdict , OrderedDict <EOL> from p4_hlir . hlir import parse_call , p4_field , p4_parse_value_set , P4_DEFAULT , p4_parse_state , p4_table , p4_conditional_node , p4_parser_exception , p4_header_instance , P4_NEXT <EOL> import ebpfProgram <EOL> import ebpfInstance <EOL> import ebpfType <EOL> import ebpfStructType <EOL> from topoSorting import Graph <EOL> from programSerializer import ProgramSerializer <EOL> def produce_parser_topo_sorting ( hlir ) : <EOL> header_graph = Graph ( ) <EOL> def walk_rec ( hlir , parse_state , prev_hdr_node , tag_stacks_index ) : <EOL> assert ( isinstance ( parse_state , p4_parse_state ) ) <EOL> for call in parse_state . call_sequence : <EOL> call_type = call [ <NUM_LIT:0> ] <EOL> if call_type == parse_call . extract : <EOL> hdr = call [ <NUM_LIT:1> ] <EOL> if hdr . virtual : <EOL> base_name = hdr . base_name <EOL> current_index = tag_stacks_index [ base_name ] <EOL> if current_index > hdr . max_index : <EOL> return <EOL> tag_stacks_index [ base_name ] += <NUM_LIT:1> <EOL> name = base_name + "<STR_LIT>" % current_index <EOL> hdr = hlir . p4_header_instances [ name ] <EOL> if hdr not in header_graph : <EOL> header_graph . add_node ( hdr ) <EOL> hdr_node = header_graph . get_node ( hdr ) <EOL> if prev_hdr_node : <EOL> prev_hdr_node . add_edge_to ( hdr_node ) <EOL> else : <EOL> header_graph . root = hdr <EOL> prev_hdr_node = hdr_node <EOL> for branch_case , next_state in parse_state . branch_to . items ( ) : <EOL> if not next_state : <EOL> continue <EOL> if not isinstance ( next_state , p4_parse_state ) : <EOL> continue <EOL> walk_rec ( hlir , next_state , prev_hdr_node , tag_stacks_index . copy ( ) ) <EOL> start_state = hlir . p4_parse_states [ "<STR_LIT:start>" ] <EOL> walk_rec ( hlir , start_state , None , defaultdict ( int ) ) <EOL> header_topo_sorting = header_graph . produce_topo_sorting ( ) <EOL> return header_topo_sorting <EOL> class EbpfDeparser ( object ) : <EOL> def __init__ ( self , hlir ) : <EOL> header_topo_sorting = produce_parser_topo_sorting ( hlir ) <EOL> self . headerOrder = [ hdr . name for hdr in header_topo_sorting ] <EOL> def serialize ( self , serializer , program ) : <EOL> assert isinstance ( serializer , ProgramSerializer ) <EOL> assert isinstance ( program , ebpfProgram . EbpfProgram ) <EOL> serializer . emitIndent ( ) <EOL> serializer . blockStart ( ) <EOL> serializer . emitIndent ( ) <EOL> serializer . appendLine ( "<STR_LIT>" ) <EOL> serializer . emitIndent ( ) <EOL> serializer . appendFormat ( "<STR_LIT>" , program . offsetVariableName ) <EOL> serializer . newline ( ) <EOL> for h in self . headerOrder : <EOL> header = program . getHeaderInstance ( h ) <EOL> self . serializeHeaderEmit ( header , serializer , program ) <EOL> serializer . blockEnd ( True ) <EOL> def serializeHeaderEmit ( self , header , serializer , program ) : <EOL> assert isinstance ( header , ebpfInstance . EbpfHeader ) <EOL> assert isinstance ( serializer , ProgramSerializer ) <EOL> assert isinstance ( program , ebpfProgram . EbpfProgram ) <EOL> p4header = header . hlirInstance <EOL> assert isinstance ( p4header , p4_header_instance ) <EOL> serializer . emitIndent ( ) <EOL> serializer . appendFormat ( "<STR_LIT>" , <EOL> program . headerStructName , header . name ) <EOL> serializer . blockStart ( ) <EOL> if ebpfProgram . EbpfProgram . isArrayElementInstance ( p4header ) : <EOL> ebpfStack = program . getStackInstance ( p4header . base_name ) <EOL> assert isinstance ( ebpfStack , ebpfInstance . EbpfHeaderStack ) <EOL> if isinstance ( p4header . index , int ) : <EOL> index = "<STR_LIT:[>" + str ( headerInstance . index ) + "<STR_LIT:]>" <EOL> elif p4header . index is P4_NEXT : <EOL> index = "<STR_LIT:[>" + ebpfStack . indexVar + "<STR_LIT:]>" <EOL> else : <EOL> raise CompilationException ( <EOL> True , "<STR_LIT>" , <EOL> p4header . index ) <EOL> basetype = ebpfStack . basetype <EOL> else : <EOL> ebpfHeader = program . getHeaderInstance ( p4header . name ) <EOL> basetype = ebpfHeader . type <EOL> index = "<STR_LIT>" <EOL> alignment = <NUM_LIT:0> <EOL> for field in basetype . fields : <EOL> assert isinstance ( field , ebpfStructType . EbpfField ) <EOL> self . serializeFieldEmit ( serializer , p4header . base_name , <EOL> index , field , alignment , program ) <EOL> alignment += field . widthInBits ( ) <EOL> alignment = alignment % <NUM_LIT:8> <EOL> serializer . blockEnd ( True ) <EOL> def serializeFieldEmit ( self , serializer , name , index , <EOL> field , alignment , program ) : <EOL> assert isinstance ( index , str ) <EOL> assert isinstance ( name , str ) <EOL> assert isinstance ( field , ebpfStructType . EbpfField ) <EOL> assert isinstance ( serializer , ProgramSerializer ) <EOL> assert isinstance ( alignment , int ) <EOL> assert isinstance ( program , ebpfProgram . EbpfProgram ) <EOL> if field . name == "<STR_LIT>" : <EOL> return <EOL> fieldToEmit = ( program . headerStructName + "<STR_LIT:.>" + name + <EOL> index + "<STR_LIT:.>" + field . name ) <EOL> width = field . widthInBits ( ) <EOL> if width <= <NUM_LIT:32> : <EOL> store = self . generatePacketStore ( fieldToEmit , <NUM_LIT:0> , alignment , <EOL> width , program ) <EOL> serializer . emitIndent ( ) <EOL> serializer . appendLine ( store ) <EOL> else : <EOL> b = ( width + <NUM_LIT:7> ) / <NUM_LIT:8> <EOL> for i in range ( <NUM_LIT:0> , b ) : <EOL> serializer . emitIndent ( ) <EOL> store = self . generatePacketStore ( fieldToEmit + "<STR_LIT:[>" + str ( i ) + "<STR_LIT:]>" , <EOL> i , <EOL> alignment , <EOL> <NUM_LIT:8> , program ) <EOL> serializer . appendLine ( store ) <EOL> serializer . emitIndent ( ) <EOL> serializer . appendFormat ( "<STR_LIT>" , <EOL> program . offsetVariableName , width ) <EOL> serializer . newline ( ) <EOL> def generatePacketStore ( self , value , offset , alignment , width , program ) : <EOL> assert width > <NUM_LIT:0> <EOL> assert alignment < <NUM_LIT:8> <EOL> assert isinstance ( width , int ) <EOL> assert isinstance ( alignment , int ) <EOL> return "<STR_LIT>" . format ( <EOL> program . packetName , <EOL> program . offsetVariableName , <EOL> offset , <EOL> alignment , <EOL> width , <EOL> value <EOL> ) </s>
