Ejemplo n.º 1
0
    def gen_typedef(self):
        """
        Generates an internal typedef definition for this function.

        :param typedef_name: Overrides automatic type name generation w/ value.
        """
        _tmp, tmp = None, None

        # Fix for an insiduous bug with string identifiers (e.g. int_fast32_t)
        _tmp = self.func_decl.type.type.type\
            if isinstance(self.func_decl.type.type, TypeDecl) else\
            IdentifierType(names=self.func_decl.type.type.names)

        # Use TypeDecl/PtrDecl depending on whether return value is a pointer
        tmp = PtrDecl([], TypeDecl(self.typedef_name, [], _tmp))\
            if self.ret_var.ptr else TypeDecl(self.typedef_name, [], _tmp)

        _tmp_fdecl = PtrDecl([], FuncDecl(self.param_list, tmp))

        # Update base type so its registered a MyriadCType subclass
        self.base_type = type(self.typedef_name, (MyriadCType, ),
                              {'mtype': IdentifierType([self.typedef_name])})()

        # Create typedef so its registered by the pycparser AST
        self.fun_typedef = Typedef(name=self.typedef_name,
                                   quals=[],
                                   storage=['typedef'],
                                   type=_tmp_fdecl,
                                   coord=None)
Ejemplo n.º 2
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)
Ejemplo n.º 3
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=[]))
Ejemplo n.º 4
0
def translate_FunDecl(c_ast):
    args = []
    if c_ast.args is not None:
        for a in c_ast.args.params:
            args.append(translate_Decl(a))

    subst = unify(
        c_ast.type,
        TypeDecl(Var("declname"), [], IdentifierType(Var("ret_type"))))

    name = subst.lookup("declname")
    ret_type = subst.lookup("ret_type")
    return (name, args, ret_type)
Ejemplo n.º 5
0
    def _generateTypeDefForDecl(self, decl: Decl) -> str:
        typedefs = ""
        for param in filter(lambda p: utils.is_function_pointer_type(p.type),
                            decl.type.args.params):
            name = utils.create_typedef_name_for_fnc_ptr(decl, param)

            param.type.type.type.declname = name
            typedef = Typedef(name, param.quals, ["typedef"], param.type)

            param.type = TypeDecl(param.name, param.type.quals, None,
                                  IdentifierType([name]))
            typedefs += f"{self.cGen.visit_Typedef(typedef)};\n"
        return typedefs
Ejemplo n.º 6
0
def translate_typ(c_ast):
    if isinstance(c_ast, FuncDecl):
        return translate_FunDecl(c_ast)
    elif isinstance(c_ast, TypeDecl):
        pat = TypeDecl(Var("declname"), [], IdentifierType(Var("names")))
        t = unify(pat, c_ast)
        return t.lookup("names")
    elif isinstance(c_ast, ArrayDecl):
        pat = ArrayDecl(Var("element_type"), Var("dim", True), [])
        t = unify(pat, c_ast)
        elem_typ = translate_typ(t.lookup("element_type"))
        return (elem_typ, t.lookup("dim", None))
    else:
        NYI(c_ast)
Ejemplo n.º 7
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
Ejemplo n.º 8
0
def basic_type(name: Union[str, List[str]]) -> TypeDecl:
    names = [name] if isinstance(name, str) else name
    idtype = IdentifierType(names=names)
    return TypeDecl(declname=None, quals=[], type=idtype)
Ejemplo n.º 9
0
def basic_type(names: List[str]) -> TypeDecl:
    idtype = IdentifierType(names=names)
    return TypeDecl(declname=None, quals=[], type=idtype)
Ejemplo n.º 10
0
def basic_type(name: str) -> TypeDecl:
    idtype = IdentifierType(names=[name])
    return TypeDecl(declname=None, quals=[], type=idtype)
Ejemplo n.º 11
0
def print_header(message):
    generator = CGenerator()
    parser = CParser()

    def del_spaces(name):
        if name.startswith('(extension in '):
            idx = name.index('):')
            name = '_extension_in_' + name[14:idx] + "__" + name[idx + 2:]

        # file private types
        if ' in _' in name:
            idx = name.index(' in _')
            end = name.index(')', idx)
            start = name.rindex('(', None, idx)
            namespace = name[:start]
            if '>' in namespace:
                namespace = mangle_name(namespace[:-1]) + '.'
            name = namespace + name[start + 1:idx] + name[end + 1:]
        return name

    def mangle_name(human):
        if human in ('void*', 'voidp', 'Metadata*'):
            return human
        if human == '()':
            return 'void'

        info = types[human]
        if 'getGenericParams' in info and info['getGenericParams']:
            name = remove_generic(human)
        else:
            name = human

        if name.startswith('?Unknown type of'):
            name = name.replace('?Unknown type of ', 'XXX_unknown_type_of_')

        if name.startswith("Static #"):
            spl = name.split(' ', 4)
            return "_static_no" + spl[1][1:] + "_in_" + spl[
                3] + "__func" + str(hash(spl[4]))[1:]
        name = del_spaces(name)

        outp = f'swift_{info["kind"]}__'

        if info['kind'] == "Tuple":
            elems = []
            for e in info['tupleElements']:
                name = mangle_name(e['type'])
                if e['label']:
                    name += "__as_" + e['label']
                elems.append(name)
            outp += "with__" + "__and__".join(elems)
        elif info['kind'] == "Existential":
            protos = []
            for p in info['protocols']:
                protos.append(
                    del_spaces(script.exports.demangle(p)).replace(".", "__"))
            if info['isClassBounded']:
                protos.append("Swift__AnyObject")
            if protos:
                outp += "conforming_to__" + "__and__".join(protos)
            else:
                outp += "Any"
            if info.get('getSuperclassConstraint'):
                outp += "__inheriting_from_" + mangle_name(
                    info['getSuperclassConstraint'])
        elif info['kind'] == 'Function':
            return "func_" + str(hash(name))[1:]
        else:
            outp += name.replace(".", "_")

        if 'getGenericParams' in info and info['getGenericParams']:
            gen_params = [
                mangle_name(param) for param in info['getGenericParams']
            ]
            outp += "__of__" + "__and__".join(gen_params)

        return outp

    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

    #print("#include <stdint.h>")
    print("#pragma pack(1)")
    print("typedef void *voidp;")
    print("typedef struct Metadata_s Metadata;")
    types = json.loads(message)

    req_graph = {}
    ptr_types = {'void*', 'voidp', 'Metadata*'}
    ctypes = {}

    for name, info in types.items():
        pad_count = 0
        decls = []
        prev_end = 0
        ctype = None
        parent_name = name
        if info['kind'] == "Tuple":
            for i, elem in enumerate(info['tupleElements']):
                make_decl(elem['label'] or f'_{i}', elem['offset'],
                          elem['type'])
            ctype = Struct(mangle_name(name) + "_s", decls)
        elif info['kind'] == "ObjCClassWrapper":
            print(
                f'typedef struct {mangle_name(name)}_s *{mangle_name(name)};')
        elif info['kind'] in ("Struct", "Class"):
            if info['kind'] == 'Class':
                make_decl('_isa', '0x0', 'Metadata*')
                #make_decl('_refCounts', hex(pointer_size), 'size_t')

            for i, field in enumerate(info['fields']):
                make_decl(field['name'], field['offset'], field['type'])
            ctype = Struct(mangle_name(name) + "_s", decls)

            if info['kind'] == 'Class':
                ctype = PtrDecl(None, ctype)
        elif info['kind'] == "Existential":
            if info['isClassBounded'] or info.get(
                    'getSuperclassConstraint'):  # class existential container
                make_decl(f'heap_object', -1, 'void*')
            else:  # opaque existential container
                decls.append(
                    parser.parse("void *heapObjectOrInlineData0;").ext[0])
                for i in range(1, 3):
                    decls.append(
                        parser.parse(
                            "void *nothingOrInlineData{};".format(i)).ext[0])
                make_decl("dynamicType", -1, "Metadata*")
            for i in range(info['witnessTableCount']):
                make_decl(f'_witnessTable{i + 1}', -1, 'void*')
            ctype = Struct(mangle_name(name) + "_s", decls)
        elif info['kind'] in ("Enum", "Optional"):
            if info['enumCases'] and info['enumCases'][0]['name'] is None:
                # C-like enum
                # we don't have case names or values, so just generate a typedef to an int type
                print(
                    f"typedef uint{int(info['size'], 16) * 8}_t {mangle_name(name)};"
                )
            elif len(info['enumCases']) == 0:
                ctype = Struct(mangle_name(name) + "_s", decls)
            elif len(info['enumCases']) == 1 and info['enumCases'][0]['type']:
                make_decl(info['enumCases'][0]['name'], 0,
                          info['enumCases'][0]['type'])
                ctype = Struct(mangle_name(name) + "_s", decls)
            else:
                print(
                    f'typedef struct {mangle_name(name)}_s {{ char _data[{info["size"]}]; }} {mangle_name(name)};'
                )
        elif info['kind'] == 'Opaque':
            if 'getCType' in info:
                ctype_names = {
                    'pointer': 'void*',
                    'int8': 'int8_t',
                    'int16': 'int16_t',
                    'int32': 'int32_t',
                    'int64': 'int64_t',
                    'int64': 'int64_t',
                }
                print(
                    f'typedef {ctype_names[info["getCType"]]} {mangle_name(name)};'
                )
            elif name == 'Builtin.NativeObject':
                print(f'typedef void *{mangle_name(name)};')
            else:
                print(f'typedef char {mangle_name(name)}[{info["size"]}];')
        elif info['kind'] == 'Function':
            print(f"typedef void *func_{str(hash(name))[1:]};"
                  )  # TODO: proper names
        else:
            print(f'typedef char {mangle_name(name)}[{info["size"]}];')

        if ctype:
            type_decl = TypeDecl(mangle_name(name), None, ctype)
            ctypes[name] = type_decl
            type_decl_forward = Struct(mangle_name(name) + "_s", [])
            if isinstance(type_decl, PtrDecl):
                ptr_types.add(name)
                type_decl_forward = PtrDecl(None, type_decl_forward)
                print(
                    generator.visit(
                        Typedef(mangle_name(name), None, ['typedef'],
                                type_decl_forward)) + ";")

    for name in ptr_types:
        req_graph.pop(name, None)

    for name in top_sort(req_graph):
        if name in ctypes:
            print(f"\n// {name}")
            print(
                generator.visit(
                    Typedef(mangle_name(name), None, ['typedef'],
                            ctypes[name])) + ";")
Ejemplo n.º 12
0
 def touch_declaration_node(self):
     return FuncDecl(args=None,
                     type=TypeDecl(declname=self.c_touch_name,
                                   quals=[], type=IdentifierType(names=['void'])))
Ejemplo n.º 13
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)
Ejemplo n.º 14
0
def do_parse_struct(struct: Union[ca.Struct, ca.Union],
                    typemap: TypeMap) -> Struct:
    is_union = isinstance(struct, ca.Union)
    assert struct.decls is not None, "enforced by caller"
    assert struct.decls, "Empty structs are not valid C"

    fields: Dict[int, List[StructField]] = defaultdict(list)
    union_size = 0
    align = 1
    offset = 0
    bit_offset = 0
    has_bitfields = False
    for decl in struct.decls:
        if not isinstance(decl, ca.Decl):
            continue
        field_name = f"{struct.name}.{decl.name}"
        type = decl.type

        if decl.bitsize is not None:
            # A bitfield "type a : b;" has the following effects on struct layout:
            # - align the struct as if it contained a 'type' field.
            # - allocate the next 'b' bits of the struct, going from high bits to low
            #   within each byte.
            # - ensure that 'a' can be loaded using a single load of the size given by
            #   'type' (lw/lh/lb, unsigned counterparts). If it straddles a 'type'
            #   alignment boundary, skip all bits up to that boundary and then use the
            #   next 'b' bits from there instead.
            has_bitfields = True
            width = parse_constant_int(decl.bitsize, typemap)
            ssize, salign, substr = parse_struct_member(type,
                                                        field_name,
                                                        typemap,
                                                        allow_unsized=False)
            align = max(align, salign)
            if width == 0:
                continue
            if ssize != salign or substr is not None:
                raise DecompFailure(
                    f"Bitfield {field_name} is not of primitive type")
            if width > ssize * 8:
                raise DecompFailure(
                    f"Width of bitfield {field_name} exceeds its type")
            if is_union:
                union_size = max(union_size, ssize)
            else:
                if offset // ssize != (offset +
                                       (bit_offset + width - 1) // 8) // ssize:
                    bit_offset = 0
                    offset = (offset + ssize) & -ssize
                bit_offset += width
                offset += bit_offset // 8
                bit_offset &= 7
            continue

        if not is_union and bit_offset != 0:
            bit_offset = 0
            offset += 1

        if decl.name is not None:
            ssize, salign, substr = parse_struct_member(type,
                                                        field_name,
                                                        typemap,
                                                        allow_unsized=False)
            align = max(align, salign)
            offset = (offset + salign - 1) & -salign
            fields[offset].append(
                StructField(
                    type=type,
                    size=ssize,
                    name=decl.name,
                ))
            if is_union:
                union_size = max(union_size, ssize)
            else:
                offset += ssize
        elif isinstance(type,
                        (ca.Struct, ca.Union)) and type.decls is not None:
            substr = parse_struct(type, typemap)
            if type.name is not None:
                # Struct defined within another, which is silly but valid C.
                # parse_struct already makes sure it gets defined in the global
                # namespace, so no more to do here.
                pass
            else:
                # C extension: anonymous struct/union, whose members are flattened
                align = max(align, substr.align)
                offset = (offset + substr.align - 1) & -substr.align
                for off, sfields in substr.fields.items():
                    for field in sfields:
                        fields[offset + off].append(field)
                if is_union:
                    union_size = max(union_size, substr.size)
                else:
                    offset += substr.size
        elif isinstance(type, ca.Enum):
            parse_enum(type, typemap)

    if not is_union and bit_offset != 0:
        bit_offset = 0
        offset += 1

    # If there is a typedef for this struct, prefer using that name
    if struct in typemap.struct_typedefs:
        ctype = typemap.struct_typedefs[struct]
    elif struct.name and struct.name in typemap.struct_typedefs:
        ctype = typemap.struct_typedefs[struct.name]
    else:
        ctype = TypeDecl(declname=None, quals=[], type=struct, align=[])

    size = union_size if is_union else offset
    size = (size + align - 1) & -align
    return Struct(type=ctype,
                  fields=fields,
                  has_bitfields=has_bitfields,
                  size=size,
                  align=align)
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