• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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