# Copyright (c) Barefoot Networks, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from p4_hlir.hlir import p4_conditional_node, p4_expression from p4_hlir.hlir import p4_header_instance, p4_field from programSerializer import ProgramSerializer from compilationException import CompilationException import ebpfProgram import ebpfInstance class EbpfConditional(object): @staticmethod def translate(op): if op == "not": return "!" elif op == "or": return "||" elif op == "and": return "&&" return op def __init__(self, p4conditional, program): assert isinstance(p4conditional, p4_conditional_node) assert isinstance(program, ebpfProgram.EbpfProgram) self.hlirconditional = p4conditional self.name = p4conditional.name def emitNode(self, node, serializer, program): if isinstance(node, p4_expression): self.emitExpression(node, serializer, program, False) elif node is None: pass elif isinstance(node, int): serializer.append(node) elif isinstance(node, p4_header_instance): header = program.getInstance(node.name) assert isinstance(header, ebpfInstance.EbpfHeader) # TODO: stacks? serializer.appendFormat( "{0}.{1}", program.headerStructName, header.name) elif isinstance(node, p4_field): instance = node.instance einstance = program.getInstance(instance.name) if isinstance(einstance, ebpfInstance.EbpfHeader): base = program.headerStructName else: base = program.metadataStructName serializer.appendFormat( "{0}.{1}.{2}", base, einstance.name, node.name) else: raise CompilationException(True, "{0} Unexpected expression ", node) def emitExpression(self, expression, serializer, program, toplevel): assert isinstance(serializer, ProgramSerializer) assert isinstance(program, ebpfProgram.EbpfProgram) assert isinstance(expression, p4_expression) assert isinstance(toplevel, bool) left = expression.left op = expression.op right = expression.right assert isinstance(op, str) if op == "valid": self.emitNode(right, serializer, program) serializer.append(".valid") return if not toplevel: serializer.append("(") self.emitNode(left, serializer, program) op = EbpfConditional.translate(op) serializer.append(op) self.emitNode(right, serializer, program) if not toplevel: serializer.append(")") def generateCode(self, serializer, program, nextNode): assert isinstance(serializer, ProgramSerializer) assert isinstance(program, ebpfProgram.EbpfProgram) serializer.emitIndent() serializer.blockStart() trueBranch = self.hlirconditional.next_[True] if trueBranch is None: trueBranch = nextNode falseBranch = self.hlirconditional.next_[False] if falseBranch is None: falseBranch = nextNode serializer.emitIndent() serializer.appendFormat("{0}:", program.getLabel(self.hlirconditional)) serializer.newline() serializer.emitIndent() serializer.append("if (") self.emitExpression( self.hlirconditional.condition, serializer, program, True) serializer.appendLine(")") serializer.increaseIndent() label = program.getLabel(trueBranch) serializer.emitIndent() serializer.appendFormat("goto {0};", label) serializer.newline() serializer.decreaseIndent() serializer.emitIndent() serializer.appendLine("else") serializer.increaseIndent() label = program.getLabel(falseBranch) serializer.emitIndent() serializer.appendFormat("goto {0};", label) serializer.newline() serializer.decreaseIndent() serializer.blockEnd(True)