예제 #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)
예제 #2
0
def pointer_decay(type: Type, typemap: TypeMap) -> SimpleType:
    real_type = resolve_typedefs(type, typemap)
    if isinstance(real_type, ArrayDecl):
        return PtrDecl(quals=[], type=real_type.type)
    if isinstance(real_type, FuncDecl):
        return PtrDecl(quals=[], type=type)
    if isinstance(real_type, TypeDecl) and isinstance(real_type.type, c_ast.Enum):
        return basic_type("int")
    assert not isinstance(
        type, (ArrayDecl, FuncDecl)
    ), "resolve_typedefs can't hide arrays/functions"
    return type
예제 #3
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
예제 #4
0
def pointer(type: Type) -> Type:
    return PtrDecl(quals=[], type=type)
예제 #5
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])) + ";")
예제 #6
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)