Beispiel #1
0
    def eval_callable(self, ctx, merged_args, var_buffer):
        # initialize the local ctx of the function for execution
        if self.return_type is None:
            return None
        # methods can return values, we need to generate a new constant
        # we generate the name based on the input arguments
        # var_name = ""
        # for arg in merged_args.values():
        #     arg = ctx.resolve_expr(arg.p4_val)
        #     # fold runtime-known values
        #     if isinstance(arg, z3.AstRef):
        #         arg = z3.simplify(arg)
        #     # elif isinstance(arg, list):
        #     #     for idx, member in enumerate(arg):
        #     #         arg[idx] = z3.simplify(member)

        #     # Because we do not know what the extern is doing
        #     # we initiate a new z3 const and
        #     # just overwrite all reference types
        #     # input arguments influence the output behavior
        #     # add the input value to the return constant
        #     var_name += str(arg)
        # If we return something, instantiate the type and return it
        # we merge the name
        # FIXME: We do not consider call order
        # and assume that externs are stateless
        return_instance = ctx.gen_instance(self.name, self.return_type)
        # a returned header may or may not be valid
        if isinstance(return_instance, StructInstance):
            propagate_validity_bit(return_instance)
        return return_instance
Beispiel #2
0
    def initialize(self, ctx):
        # clear the flat names
        self.flat_names = []
        flat_args = []
        idx = 0
        for z3_arg_name, z3_arg_type in self.members:
            z3_arg_type = ctx.resolve_type(z3_arg_type)
            if isinstance(z3_arg_type, P4ComplexType):
                member_cls = z3_arg_type.instantiate(f"{self.name}.{idx}")
                propagate_validity_bit(member_cls)
                for sub_member in z3_arg_type.flat_names:
                    flat_args.append((str(idx), sub_member.p4_type))
                    self.flat_names.append(
                        P4Member(z3_arg_name, sub_member.name))
                    idx += 1
                # this is a complex datatype, create a P4ComplexType
                ctx.set_or_add_var(z3_arg_name, member_cls, True)
            else:
                flat_args.append((str(idx), z3_arg_type))
                self.flat_names.append(z3_arg_name)
                idx += 1
        z3_type = z3.Datatype(self.name)
        z3_type.declare(f"mk_{self.name}", *flat_args)
        self.z3_type = z3_type.create()
        self.const = z3.Const(self.name, self.z3_type)

        for type_idx, arg_name in enumerate(self.flat_names):
            member_constructor = self.z3_type.accessor(0, type_idx)
            ctx.set_or_add_var(arg_name, member_constructor(self.const), True)
Beispiel #3
0
    def assign_values(self, ctx, method_args):
        for param_name, arg in method_args.items():
            arg_mode, arg_ref, arg_expr, p4_src_type = arg
            # infer the type
            try:
                p4_type = ctx.resolve_type(p4_src_type)
            except KeyError:
                # This is dynamic type inference based on arguments
                # FIXME Check this hack.
                if isinstance(arg_expr, list):
                    # synthesize a list type from the input list
                    # this mostly just a dummy
                    # FIXME: Need to get the actual sub-types
                    p4_type = ListType("tuple", ctx, arg_expr)
                else:
                    p4_type = arg_expr.sort()
                ctx.add_type(p4_src_type, p4_type)

            if arg_mode not in ("out", "inout"):
                # this value is read-only so we do not care
                # however, we still used it to potentially infer a type
                continue

            arg_name = f"{self.name}_{param_name}"
            arg_expr = ctx.gen_instance(arg_name, p4_type)

            if isinstance(arg_expr, StructInstance):
                # # In the case that the instance is a complex type make sure
                # # to propagate the variable through all its members
                # bind_const = z3.Const(arg_name, arg_expr.z3_type)
                # arg_expr.bind(bind_const)
                # we do not know whether the expression is valid afterwards
                propagate_validity_bit(arg_expr)
            # (in)outs are left-values so the arg_ref must be a string
            ctx.set_or_add_var(arg_ref, arg_expr)