1# Copyright (c) Barefoot Networks, Inc. 2# Licensed under the Apache License, Version 2.0 (the "License") 3 4from p4_hlir.hlir import p4_conditional_node, p4_expression 5from p4_hlir.hlir import p4_header_instance, p4_field 6from programSerializer import ProgramSerializer 7from compilationException import CompilationException 8import ebpfProgram 9import ebpfInstance 10 11 12class EbpfConditional(object): 13 @staticmethod 14 def translate(op): 15 if op == "not": 16 return "!" 17 elif op == "or": 18 return "||" 19 elif op == "and": 20 return "&&" 21 return op 22 23 def __init__(self, p4conditional, program): 24 assert isinstance(p4conditional, p4_conditional_node) 25 assert isinstance(program, ebpfProgram.EbpfProgram) 26 self.hlirconditional = p4conditional 27 self.name = p4conditional.name 28 29 def emitNode(self, node, serializer, program): 30 if isinstance(node, p4_expression): 31 self.emitExpression(node, serializer, program, False) 32 elif node is None: 33 pass 34 elif isinstance(node, int): 35 serializer.append(node) 36 elif isinstance(node, p4_header_instance): 37 header = program.getInstance(node.name) 38 assert isinstance(header, ebpfInstance.EbpfHeader) 39 # TODO: stacks? 40 serializer.appendFormat( 41 "{0}.{1}", program.headerStructName, header.name) 42 elif isinstance(node, p4_field): 43 instance = node.instance 44 einstance = program.getInstance(instance.name) 45 if isinstance(einstance, ebpfInstance.EbpfHeader): 46 base = program.headerStructName 47 else: 48 base = program.metadataStructName 49 serializer.appendFormat( 50 "{0}.{1}.{2}", base, einstance.name, node.name) 51 else: 52 raise CompilationException(True, "{0} Unexpected expression ", node) 53 54 def emitExpression(self, expression, serializer, program, toplevel): 55 assert isinstance(serializer, ProgramSerializer) 56 assert isinstance(program, ebpfProgram.EbpfProgram) 57 assert isinstance(expression, p4_expression) 58 assert isinstance(toplevel, bool) 59 left = expression.left 60 op = expression.op 61 right = expression.right 62 63 assert isinstance(op, str) 64 65 if op == "valid": 66 self.emitNode(right, serializer, program) 67 serializer.append(".valid") 68 return 69 70 if not toplevel: 71 serializer.append("(") 72 self.emitNode(left, serializer, program) 73 op = EbpfConditional.translate(op) 74 serializer.append(op) 75 self.emitNode(right, serializer, program) 76 if not toplevel: 77 serializer.append(")") 78 79 def generateCode(self, serializer, program, nextNode): 80 assert isinstance(serializer, ProgramSerializer) 81 assert isinstance(program, ebpfProgram.EbpfProgram) 82 serializer.emitIndent() 83 serializer.blockStart() 84 85 trueBranch = self.hlirconditional.next_[True] 86 if trueBranch is None: 87 trueBranch = nextNode 88 falseBranch = self.hlirconditional.next_[False] 89 if falseBranch is None: 90 falseBranch = nextNode 91 92 serializer.emitIndent() 93 serializer.appendFormat("{0}:", program.getLabel(self.hlirconditional)) 94 serializer.newline() 95 96 serializer.emitIndent() 97 serializer.append("if (") 98 self.emitExpression( 99 self.hlirconditional.condition, serializer, program, True) 100 serializer.appendLine(")") 101 102 serializer.increaseIndent() 103 label = program.getLabel(trueBranch) 104 serializer.emitIndent() 105 serializer.appendFormat("goto {0};", label) 106 serializer.newline() 107 serializer.decreaseIndent() 108 109 serializer.emitIndent() 110 serializer.appendLine("else") 111 serializer.increaseIndent() 112 label = program.getLabel(falseBranch) 113 serializer.emitIndent() 114 serializer.appendFormat("goto {0};", label) 115 serializer.newline() 116 serializer.decreaseIndent() 117 118 serializer.blockEnd(True) 119