示例#1
0
    def __init__(self, field: Decl, ast, tag, annotation_types):
        self.field = field
        self.field_name = field.name

        field_type = type(field.type)
        if field_type == TypeDecl:
            decl_type = type(field.type.type)
            if decl_type == IdentifierType:
                self.c_type = field.type.type.names[0]
                self.type = FieldType.NORMAL
            elif decl_type == Struct:
                self.type = FieldType.STRUCT
                self.c_type = field.type.type.name
                self.struct = struct_by_name(ast, self.c_type)
                self.fields_and_annotations = walk_struct(ast, tag, self.struct, annotation_types)
            elif decl_type == CEnum:
                self.type = FieldType.ENUM
                self.c_type = field.type.type.name
                self.enum = enum_by_name(ast, self.c_type)
            else:
                field.show()
                assert False, ("TypeDecl type %s not handled" % decl_type)
        elif field_type == PtrDecl:
            self.c_type = field.type.type.type.names[0]
            self.type = FieldType.POINTER
        else:
            assert False, ("field type %s not handled" % (type(field.type)))
示例#2
0
def translate_Decl(c_ast):
    pat = Decl(Var("name"), [], [], [], Var("type"), Var("init", True), None)
    subst = unify(pat, c_ast)
    if subst is None:
        pat.show()
        c_ast.show()
    name = subst.lookup("name")
    raw_typ = subst.lookup("type")
    raw_init = subst.lookup("init")

    typ = translate_typ(raw_typ)
    if raw_init is not None:
        init = translate_exp(raw_init)
    else:
        init = None

    return (name, typ, init)
示例#3
0
 def gen_memo_flag_node(self,self_touch):
     val = 'true' if self_touch else 'false'
     type_ = TypeDecl(declname = self.memo_flag_name,
                      quals=[], type=IdentifierType(names=['bool']))
     return Decl(name=self.entity, quals=[],
                 storage=[], funcspec=[],
                 type= type_, init=ID(name=val),
                 bitsize=None)
示例#4
0
文件: c_types.py 项目: ethteck/mips3c
 def anonymize_param(param: ca.Decl) -> ca.Typename:
     param = copy.deepcopy(param)
     param.name = None
     set_decl_name(param)
     return ca.Typename(name=None,
                        quals=param.quals,
                        type=param.type,
                        align=[])
示例#5
0
 def touch_definition_node(self):
     type_ = FuncDecl(args=None,
                      type=TypeDecl(declname=self.c_touch_name,
                                    quals=[], type=IdentifierType(names=['void'])))
     return FuncDef(decl=Decl(name=self.c_touch_name,
                              quals=[], storage=[],
                              funcspec=[], type=type_,
                              init=None, bitsize=None),
                    param_decls=None, body=Compound(block_items=[]))
示例#6
0
 def void_ptr_ptr(cls, ident: str):
     """ Special method for generating a void** (corner case)"""
     obj = cls(ident, MVoid, True)
     obj.ptr_decl = PtrDecl(quals=[], type=obj.ptr_decl)
     obj.decl = Decl(name=obj.ident,
                     quals=obj.quals,
                     storage=obj.storage,
                     funcspec=[],
                     type=obj.ptr_decl,
                     init=obj.init,
                     bitsize=None)
     return obj
示例#7
0
    def __init__(self,
                 struct_name: str,
                 members: OrderedDict = None,
                 storage: list = None):
        """
        Initializes a new struct type.

        :param str struct_name: Type name of the struct.
        :param OrderedDict members: _MyriadBase-derived members of the struct
        :param list storage: List of C AST storage qualifiers (e.g. "const")
        :raises AssertionError: if members are not _MyriadBase subclassed
        """

        # Make sure we got the right parameter types
        assert_list_type(list(members.values()), _MyriadBase)

        #: Struct type identifier, i.e. the name after 'struct' in C.
        self.struct_name = struct_name

        #: Ordered members of the struct, derived from _MyriadBase.
        self.members = OrderedDict()

        members = OrderedDict() if members is None else members

        # Store member type information for introspection. Non-ordered.
        self.member_type_info = {}
        for scalar in members.values():
            self.member_type_info[scalar.ident] = scalar

        # Set struct members using ordered dict: order matters for memory!
        sorted_members = [members[idx].decl for idx in members.keys()]
        members = {v.ident: v.decl for v in members.values()}
        for member_ident, member in members.items():
            self.members[member_ident] = member

        #: pycparser C AST struct node.
        self.struct_c_ast = Struct(self.struct_name, sorted_members)

        #: Programmatically-generated base type for run-time checking.
        self.base_type = type(self.struct_name, (MyriadCType, ),
                              {'mtype': Struct(self.struct_name, None)})()

        # Manually build declaration to pass to super constructor
        _tmp_decl = Decl(name=None,
                         quals=[],
                         storage=[],
                         funcspec=[],
                         type=self.struct_c_ast,
                         init=None,
                         bitsize=None)
        super().__init__(None, _tmp_decl, storage=storage)
示例#8
0
    def make_decl(name, offset, type_name):
        nonlocal decls, pad_count, parser, prev_end

        if isinstance(offset, str):
            assert offset[:2] == '0x'
            offset = int(offset, 16)

        if prev_end < offset:
            pad_str = f"char _padding{pad_count}[{offset - prev_end}];"
            decls.append(parser.parse(pad_str).ext[0])
            pad_count += 1

        type_decl = TypeDecl(name.replace(".", "__"), None,
                             IdentifierType([mangle_name(type_name)]))
        decls.append(Decl(None, None, None, None, type_decl, None, None))

        req_graph.setdefault(type_name, set()).add(parent_name)

        if offset != -1:
            size = pointer_size if type_name.endswith('*') else int(
                types[type_name]['size'], 16)
            prev_end = offset + size
示例#9
0
    def __init__(self,
                 ident: str,
                 args_list: OrderedDict = None,
                 ret_var: MyriadScalar = None,
                 storage: list = None,
                 fun_def=None):
        """
        Initializes a new MyriadFunction.

        :param str ident: Name of the function to be created.

        :param args_list: Ordered dict of identifiers:_MyriadBase fxn args
        :type args_list: OrderedDict or None

        :param ret_var: Return value as a MyriadScalar
        :type ret_var: MyriadScalar or None

        :param storage: C AST storage qualifiers (e.g. "const")
        :type storage: list or None

        :param fun_def: Function definition in form of a string or template

        :raise AssertionError: if args_list has non-_MyriadBase members
        """

        # Always call super first
        super().__init__(ident)

        # --------------------------------------------
        # Set return value; none is given, assume void
        # --------------------------------------------
        if ret_var is None:
            ret_var = MyriadScalar(self.ident, MVoid)

        #: Return value for the function as a MyriadScalar, default MVoid.
        self.ret_var = ret_var

        # --------------------------------------------
        #  Create internal representation of args list
        # --------------------------------------------

        # Make sure we got the right parameter types
        if args_list is not None and len(args_list) > 0:
            assert_list_type(list(args_list.values()), _MyriadBase)

        #: Stores the MyriadScalars as ordered parameters.
        self.args_list = OrderedDict() if args_list is None else args_list

        #: Stores the scalar's declarations in a C AST object.
        self.param_list = ParamList([v.decl for v in self.args_list.values()])

        # ------------------------------------------
        # Create internal c_ast function declaration
        # ------------------------------------------
        _tmp_decl = copy.deepcopy(self.ret_var.decl.type)

        # Make sure we override the identifier in our copy
        if isinstance(_tmp_decl, PtrDecl):
            _tmp_decl.type.declname = self.ident
        else:
            _tmp_decl.declname = self.ident

        #: C AST function declaration with parameter list and return type.
        self.func_decl = FuncDecl(self.param_list, _tmp_decl)

        self.decl = Decl(name=self.ident,
                         quals=[],
                         storage=storage,
                         funcspec=[],
                         type=self.func_decl,
                         init=None,
                         bitsize=None)

        #: C AST typedef, must be generated using gen_typedef.
        self.fun_typedef = None
        #: Typedef name defaults to ident + "_t"
        self.typedef_name = self.ident + "_t"
        #: Underlying MyriadCType for this function (based on typedef).
        self.base_type = None

        # Automaticall generate typedef depending on function type
        self.gen_typedef()

        #: Function definition represented as a string.
        self.fun_def = fun_def
示例#10
0
    def __init__(self,
                 ident: str,
                 base_type: MyriadCType,
                 ptr: bool = False,
                 quals: list = None,
                 storage: list = None,
                 arr_id: str = None,
                 init=None):
        """
        Initializes a scalar variable, i.e. a base type, a pointer type, or an
        array type containing the base scalar type (variable/fixed length).

        :param str ident: Name of the scalar variable to be created.
        :param MyriadCType base_type: Underlying C AST base type (e.g. MInt).
        :param bool ptr: Indicates whether this is a pointer.
        :param list quals: C AST scope qualifiers (e.g. "static")
        :param list storage: C AST storage qualifiers (e.g. "const")
        :param str arr_id: Array length ID specifier (None if this isn't one)
        :param init: Initial value given to this scalar # TODO: NOT IMPLEMENTED
        """
        # Always call super first
        super().__init__(ident, quals=quals, storage=storage)

        #: Represents the underlying C type via a MyriadCType subclass.
        self.base_type = base_type

        #: Indicates if this is a pointer (or an array of pointers).
        self.ptr = ptr

        #: Indicates whether this is actually an array of this scalar type
        self.arr_id = arr_id

        #: Underlying C AST type declaration, used for C generation.
        self.type_decl = TypeDecl(declname=self.ident,
                                  quals=self.quals,
                                  type=self.base_type.mtype)

        #: Optional pointer declaration, used for scalar pointers.
        self.ptr_decl = PtrDecl(quals=[], type=self.type_decl)

        #: Optional array declaration, used for scalar arrays
        self.arr_decl = None
        if self.arr_id is not None:
            # Array of scalars or array of pointers (first arg is base type)
            self.arr_decl = ArrayDecl(self.ptr_decl if ptr else self.type_decl,
                                      dim=ID(name=self.arr_id),
                                      dim_quals=[])

        # TODO: Process init in some way
        #: Initial value of this scalar at the C level.
        self.init = init
        if init is not None:
            warn("Setting init is deprecated", DeprecationWarning)

        # Override superclass and re-initialize internal top-level declaration
        # Order of choosing declaration:
        # 1. If it's an array declaration (aka arr_id isn't None), use that
        # 2. Otherwise:
        #    a) If ptr is true, use the ptr declaration
        #    b) Otherwise, use the regular type declaration
        if self.arr_id is None:
            self.decl = Decl(name=self.ident,
                             quals=self.quals,
                             storage=self.storage,
                             funcspec=[],
                             type=self.ptr_decl if ptr else self.type_decl,
                             init=self.init,
                             bitsize=None)
        else:
            self.decl = Decl(name=self.ident,
                             quals=self.quals,
                             storage=self.storage,
                             funcspec=[],
                             type=self.arr_decl,
                             init=None,
                             bitsize=None)
示例#11
0
    def visit_Decl(self, node: c_ast.Decl):
        logger.debug(f'Line {str(node.coord.line)}: {generate(node)}')

        # ignore the FuncDecl node since it's already preprocessed
        if isinstance(node.type, c_ast.FuncDecl):
            return
        # TODO - Enhancement: Array Declaration support
        elif not isinstance(node.type, c_ast.TypeDecl):
            raise NotImplementedError(
                f'Declaration type {node.type} currently not supported for statement: {generate(node)}'
            )

        # if declarations are in function body, store distance into type system
        assert isinstance(node.type, c_ast.TypeDecl)
        # if no initial value is given, default to (0, 0)
        if not node.init:
            self._type_system.update_distance(node.name, '0', '0')
        # else update the distance to the distance of initial value (T-Asgn)
        elif isinstance(
                node.init,
            (c_ast.Constant, c_ast.BinaryOp, c_ast.BinaryOp, c_ast.UnaryOp)):
            self._assign(c_ast.ID(name=node.name), node.init, node)
        # if it is random variable declaration (T-Laplace)
        elif isinstance(node.init, c_ast.FuncCall):
            if self._enable_shadow and self._pc:
                raise ValueError(
                    'Cannot have random variable assignment in shadow-diverging branches'
                )
            self._random_variables.add(node.name)
            logger.debug(f'Random variables: {self._random_variables}')

            # set the random variable distance
            self._type_system.update_distance(node.name, '*', '0')

            if self._enable_shadow:
                # since we have to dynamically switch (the aligned distances) to shadow version, we have to guard the
                # switch with the selector
                shadow_type_system = deepcopy(self._type_system)
                for name, _, shadow_distance, _, _ in shadow_type_system.variables(
                ):
                    # skip the distance of custom holes
                    if constants.HOLE in name:
                        continue
                    shadow_type_system.update_distance(name, shadow_distance,
                                                       shadow_distance)
                self._type_system.merge(shadow_type_system)

            if self._loop_level == 0:
                to_inserts = []

                if self._enable_shadow:
                    # insert distance updates for normal variables
                    distance_update_statements = []
                    for name, align, shadow, _, _ in self._type_system.variables(
                    ):
                        if align == '*' and name not in self._parameters and name != node.name:
                            shadow_distance = f'{constants.SHADOW_DISTANCE}_{name}' if shadow == '*' else shadow
                            distance_update_statements.append(
                                parse(
                                    f'{constants.ALIGNED_DISTANCE}_{name} = {shadow_distance};'
                                ))
                    distance_update = c_ast.If(cond=parse(
                        f'{constants.SELECTOR}_{node.name} == {constants.SELECT_SHADOW}'
                    ),
                                               iftrue=c_ast.Compound(
                                                   block_items=
                                                   distance_update_statements),
                                               iffalse=None)
                    to_inserts.append(distance_update)

                # insert distance template for the variable
                distance = parse(
                    f'{constants.ALIGNED_DISTANCE}_{node.name} = {constants.RANDOM_DISTANCE}_{node.name}'
                )
                to_inserts.append(distance)

                # insert cost variable update statement
                scale = generate(node.init.args.exprs[0])
                cost = expr_simplify(
                    f'(Abs({constants.ALIGNED_DISTANCE}_{node.name}) * (1 / ({scale})))'
                )
                # calculate v_epsilon by combining normal cost and sampling cost
                if self._enable_shadow:
                    previous_cost = \
                        f'(({constants.SELECTOR}_{node.name} == {constants.SELECT_ALIGNED}) ? {constants.V_EPSILON} : 0)'
                else:
                    previous_cost = constants.V_EPSILON

                v_epsilon = parse(
                    f'{constants.V_EPSILON} = {previous_cost} + {cost}')
                to_inserts.append(v_epsilon)

                # transform sampling command to havoc command
                node.init = parse(
                    f'{constants.SAMPLE_ARRAY}[{constants.SAMPLE_INDEX}]')
                to_inserts.append(
                    parse(
                        f'{constants.SAMPLE_INDEX} = {constants.SAMPLE_INDEX} + 1;'
                    ))

                self._insert_at(node, to_inserts)
        else:
            raise NotImplementedError(
                f'Initial value currently not supported: {node.init}')

        logger.debug(f'types: {self._type_system}')
def identify_nested(ast_tree):
    ast = ast_tree
    old_stdout = sys.stdout
    sys.stdout = mystdout = StringIO()
    aux_ast = duplicate_element(ast)
    list = []
    extern_while = get_extern_while_body(aux_ast)
    identify_nested_algorithms_bodies(extern_while, list)

    labelname_inner = config.variables_2['round']
    rounds_list_inner = config.rounds_list_2
    delete_round_phase_inner = config.delete_round_phase
    message_inner = config.msg_structure_fields_2
    variables_inner = config.variables_2

    if list:
        list.reverse()
        labels = config.rounds_list_2
        labels.append('ERR_ROUND')
        code = None
        cop = duplicate_element(ast)
        if len(list) >= config.number_of_nested_algorithms:
            extern = get_extern_while_body(cop)
            if isinstance(extern.block_items[0], If):
                myif = extern.block_items[0]
                list1 = []
                list2 = []
                aux1 = []
                aux2 = []
                identify_nested_algorithms_bodies(extern.block_items[0].iftrue,
                                                  list1)
                if list1:
                    sys.stdout = old_stdout

                    for elem in list1:
                        conditii = []
                        whiles_to_if(elem.stmt, conditii)
                        identify_recv_exits(elem.stmt, conditii)
                        remove_mbox(elem.stmt, config.mailbox_2,
                                    config.clean_mailbox_2)
                        aux1 = elem.stmt

                        parent = find_parent(ast, elem)
                        index = parent.block_items.index(elem)
                        parent.block_items.remove(elem)
                        coord = elem.coord
                        new_id = ID("inner_algorithm", coord)
                        func = FuncCall(new_id, None, coord)
                        assign_unique_coord(func, coord)
                        parent.block_items.insert(index, func)

                identify_nested_algorithms_bodies(
                    extern.block_items[0].iffalse, list2)
                if list2:
                    for elem in list2:
                        conditii = []
                        whiles_to_if(elem.stmt, conditii)
                        identify_recv_exits(elem.stmt, conditii)
                        remove_mbox(elem.stmt, config.mailbox_2,
                                    config.clean_mailbox_2)
                        aux2 = elem.stmt

                        parent = find_parent(ast, elem)
                        index = parent.block_items.index(elem)
                        parent.block_items.remove(elem)
                        coord = elem.coord
                        new_id = ID("inner_algorithm", coord)
                        func = FuncCall(new_id, None, coord)
                        assign_unique_coord(func, coord)
                        parent.block_items.insert(index, func)
                if aux1 and aux2:
                    myif.iftrue = None
                    myif.iffalse = None
                    myif.iftrue = aux1
                    myif.iffalse = aux2

                    trees_dict, trees_paths_dict, is_job = get_paths_trees(
                        cop, labels, labels, config.variables_2['round'])

                    print_rounds(labels, trees_dict, trees_paths_dict,
                                 config.variables_2['round'], is_job,
                                 delete_round_phase_inner, message_inner,
                                 variables_inner, rounds_list_inner[0])

                    code = mystdout.getvalue()
                    sys.stdout = old_stdout

                    return ast, code

        else:
            for elem in list:
                # print generator.visit(elem), "AAAAAAAAAAA"
                conditii = []
                whiles_to_if(elem.stmt, conditii)

                identify_recv_exits(elem.stmt, conditii)
                remove_mbox(elem.stmt, config.mailbox_2,
                            config.clean_mailbox_2)
                # print generator.visit(elem)
                trees_dict, trees_paths_dict, is_job = get_paths_trees(
                    elem.stmt, labels, labels, config.variables_2['round'])
                # print_code(trees_dict, trees_paths_dict, labels)

                print_rounds(labels, trees_dict, trees_paths_dict,
                             config.variables_2['round'], is_job,
                             delete_round_phase_inner, message_inner,
                             variables_inner, rounds_list_inner[0])
                parent = find_parent(ast, elem)
                index = parent.block_items.index(elem)
                parent.block_items.remove(elem)

                coord = elem.coord

                new_id = ID("inner_algorithm", coord)
                func = FuncCall(new_id, None, coord)
                assign_unique_coord(func, coord)
                parent.block_items.insert(index, func)
                # print generator.visit(parent.block_items[index])
                # print generator.visit(ast)
                # print generator.visit(func)

                funcdecl = FuncDecl(
                    None,
                    TypeDecl('inner_algorithm', None, IdentifierType(['int'])))
                decl = Decl('inner_algorithm', None, None, None, funcdecl,
                            None, None)
                funcdef = FuncDef(decl, None, None)
                code = mystdout.getvalue()
                funcdef.body = Compound([code])

                # print generator.visit(ast)

            sys.stdout = old_stdout
            return ast, code
    else:
        sys.stdout = old_stdout
        print "pe else"
        return ast_tree