Example #1
0
    def get_module(self, name: str, filename: str,
                   directory: str) -> RIALModule:
        module = RIALModule(name=name)
        module.filename = filename
        module.triple = self.binding.get_default_triple()
        module.data_layout = str(self.target_machine.target_data)
        module.add_named_metadata('compiler', [
            'RIALC', '0.0.1', 'LLVM', '.'.join(
                [str(info) for info in self.binding.llvm_version_info])
        ])

        di_file = module.add_debug_info("DIFile", {
            "filename": filename,
            "directory": directory,
        })
        di_compile_unit = module.add_debug_info(
            "DICompileUnit", {
                "language": ir.DIToken("DW_LANG_C"),
                "file": di_file,
                "producer": "RIALC 0.1.0",
                "runtimeVersion": 1,
                "isOptimized": False,
            },
            is_distinct=True)

        return module
Example #2
0
 def _di_compile_unit(self):
     di = super()._di_compile_unit()
     operands = dict(di.operands)
     operands["language"] = ir.DIToken("DW_LANG_C_plus_plus")
     operands["producer"] = "numba-dppy"
     di.operands = tuple(operands.items())
     return di
Example #3
0
    def _var_type(self, lltype, size):
        m = self.module
        bitsize = size * 8

        int_type = (ir.IntType, )
        real_type = ir.FloatType, ir.DoubleType
        # For simple numeric types, choose the closest encoding.
        # We treat all integers as unsigned.
        if isinstance(lltype, int_type + real_type):
            mdtype = m.add_debug_info(
                "DIBasicType",
                {
                    "name":
                    str(lltype),
                    "size":
                    bitsize,
                    "encoding": (ir.DIToken("DW_ATE_unsigned") if isinstance(
                        lltype, int_type) else ir.DIToken("DW_ATE_float")),
                },
            )
        # For all other types, describe it as sequence of bytes
        else:
            count = size
            mdrange = m.add_debug_info("DISubrange", {
                "count": count,
            })
            mdbase = m.add_debug_info(
                "DIBasicType",
                {
                    "name": "byte",
                    "size": 8,
                    "encoding": ir.DIToken("DW_ATE_unsigned_char"),
                },
            )
            mdtype = m.add_debug_info(
                "DICompositeType",
                {
                    "tag": ir.DIToken("DW_TAG_array_type"),
                    "baseType": mdbase,
                    "name": str(lltype),
                    "size": bitsize,
                    "identifier": str(lltype),
                    "elements": m.add_metadata([mdrange]),
                },
            )
        return mdtype
Example #4
0
 def _di_compile_unit(self):
     return self.module.add_debug_info('DICompileUnit', {
         'language': ir.DIToken('DW_LANG_Python'),
         'file': self.difile,
         'producer': 'Numba',
         'runtimeVersion': 0,
         'isOptimized': True,
         'emissionKind': 1,  # 0-NoDebug, 1-FullDebug
     }, is_distinct=True)
Example #5
0
    def get_debug_location(func: ir.Function, component):
        if "debug_info" not in debug_env:
            return

        mod = func.module
        path = inspect.getfile(
            component.__class__) if component is not None else "<pnl_builtin>"
        d_version = mod.add_metadata(
            [ir.IntType(32)(2), "Dwarf Version",
             ir.IntType(32)(4)])
        di_version = mod.add_metadata(
            [ir.IntType(32)(2), "Debug Info Version",
             ir.IntType(32)(3)])
        flags = mod.add_named_metadata("llvm.module.flags")
        if len(flags.operands) == 0:
            flags.add(d_version)
            flags.add(di_version)
        cu = mod.add_named_metadata("llvm.dbg.cu")
        di_file = mod.add_debug_info(
            "DIFile", {
                "filename": os.path.basename(path),
                "directory": os.path.dirname(path),
            })
        di_func_type = mod.add_debug_info(
            "DISubroutineType",
            {
                # None as `null`
                "types": mod.add_metadata([None]),
            })
        di_compileunit = mod.add_debug_info(
            "DICompileUnit", {
                "language": ir.DIToken("DW_LANG_Python"),
                "file": di_file,
                "producer": "PsyNeuLink",
                "runtimeVersion": 0,
                "isOptimized": False,
            },
            is_distinct=True)
        cu.add(di_compileunit)
        di_func = mod.add_debug_info("DISubprogram", {
            "name": func.name,
            "file": di_file,
            "line": 0,
            "type": di_func_type,
            "isLocal": False,
            "unit": di_compileunit,
        },
                                     is_distinct=True)
        di_loc = mod.add_debug_info("DILocation", {
            "line": 0,
            "column": 0,
            "scope": di_func,
        })
        return di_loc
Example #6
0
    def _var_type(self, lltype, size):
        m = self.module
        bitsize = size * 8

        int_type = ir.IntType,
        real_type = ir.FloatType, ir.DoubleType
        # For simple numeric types, choose the closest encoding.
        # We treat all integers as unsigned.
        if isinstance(lltype, int_type + real_type):
            mdtype = m.add_debug_info(
                'DIBasicType', {
                    'name':
                    str(lltype),
                    'size':
                    bitsize,
                    'encoding': (ir.DIToken('DW_ATE_unsigned') if isinstance(
                        lltype, int_type) else ir.DIToken('DW_ATE_float')),
                })
        # For all other types, describe it as sequence of bytes
        else:
            count = size
            mdrange = m.add_debug_info('DISubrange', {
                'count': count,
            })
            mdbase = m.add_debug_info(
                'DIBasicType', {
                    'name': 'byte',
                    'size': 8,
                    'encoding': ir.DIToken('DW_ATE_unsigned_char'),
                })
            mdtype = m.add_debug_info(
                'DICompositeType', {
                    'tag': ir.DIToken('DW_TAG_array_type'),
                    'baseType': mdbase,
                    'name': str(lltype),
                    'size': bitsize,
                    'identifier': str(lltype),
                    'elements': m.add_metadata([mdrange]),
                })
        return mdtype
Example #7
0
 def _di_compile_unit(self):
     return self.module.add_debug_info(
         "DICompileUnit",
         {
             "language": ir.DIToken("DW_LANG_Python"),
             "file": self.difile,
             "producer": "Numba",
             "runtimeVersion": 0,
             "isOptimized": True,
             "emissionKind": 1,  # 0-NoDebug, 1-FullDebug
         },
         is_distinct=True,
     )
Example #8
0
    def add_debug_info(self, optimize: bool, filename: str):
        di_file = self.module.add_debug_info("DIFile", {
            "filename": os.path.basename(os.path.abspath(filename)),
            "directory": os.path.dirname(os.path.abspath(filename)),
        })
        di_module = self.module.add_debug_info("DICompileUnit", {
            "language": ir.DIToken("DW_LANG_Python"),
            "file": di_file,
            "producer": "Claw v0.0.1",
            "runtimeVersion": 1,
            "isOptimized": optimize,
        }, is_distinct=True)

        self.module.name = os.path.basename(os.path.abspath(filename))
        self.module.add_named_metadata('llvm.dbg.cu', [di_file, di_module])
Example #9
0
 def _di_compile_unit(self):
     return self.module.add_debug_info('DICompileUnit', {
         'language': ir.DIToken('DW_LANG_C_plus_plus'),
         'file': self.difile,
         # Numba has to pretend to be clang to ensure the prologue is skipped
         # correctly in gdb. See:
         # https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/amd64-tdep.c;h=e563d369d8cb3eb3c2f732c2fa850ec70ba8d63b;hb=a4b0231e179607e47b1cdf1fe15c5dc25e482fad#l2521
         # Note the "producer_is_llvm" call to specialise the prologue
         # handling, this is defined here:
         # https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/producer.c;h=cdfd80d904c09394febd18749bb90359b2d128cc;hb=a4b0231e179607e47b1cdf1fe15c5dc25e482fad#l124
         # and to get a match for this condition the 'producer' must start
         # with "clang ", hence the following...
         'producer': 'clang (Numba)',
         'runtimeVersion': 0,
         'isOptimized': config.OPT != 0,
         'emissionKind': 1,  # 0-NoDebug, 1-FullDebug
     }, is_distinct=True)
Example #10
0
    def _var_type(self, lltype, size, datamodel=None):
        if self._DEBUG:
            print("-->", lltype, size, datamodel,
                  getattr(datamodel, 'fe_type', 'NO FE TYPE'))
        m = self.module
        bitsize = _BYTE_SIZE * size

        int_type = ir.IntType,
        real_type = ir.FloatType, ir.DoubleType
        # For simple numeric types, choose the closest encoding.
        # We treat all integers as unsigned when there's no known datamodel.
        if isinstance(lltype, int_type + real_type):
            if datamodel is None:
                # This is probably something like an `i8*` member of a struct
                name = str(lltype)
                if isinstance(lltype, int_type):
                    ditok = 'DW_ATE_unsigned'
                else:
                    ditok = 'DW_ATE_float'
            else:
                # This is probably a known int/float scalar type
                name = str(datamodel.fe_type)
                if isinstance(datamodel.fe_type, types.Integer):
                    if datamodel.fe_type.signed:
                        ditok = 'DW_ATE_signed'
                    else:
                        ditok = 'DW_ATE_unsigned'
                else:
                    ditok = 'DW_ATE_float'
            mdtype = m.add_debug_info('DIBasicType', {
                'name': name,
                'size': bitsize,
                'encoding': ir.DIToken(ditok),
            })
        elif isinstance(datamodel, ComplexModel):
            # TODO: Is there a better way of determining "this is a complex
            # number"?
            #
            # NOTE: Commented below is the way to generate the metadata for a
            # C99 complex type that's directly supported by DWARF. Numba however
            # generates a struct with real/imag cf. CPython to give a more
            # pythonic feel to inspection.
            #
            # mdtype = m.add_debug_info('DIBasicType', {
            #  'name': f"{datamodel.fe_type} ({str(lltype)})",
            #  'size': bitsize,
            # 'encoding': ir.DIToken('DW_ATE_complex_float'),
            #})
            meta = []
            offset = 0
            for ix, name in enumerate(('real', 'imag')):
                component = lltype.elements[ix]
                component_size = self.cgctx.get_abi_sizeof(component)
                component_basetype = m.add_debug_info('DIBasicType', {
                    'name': str(component),
                    'size': _BYTE_SIZE * component_size, # bits
                    'encoding': ir.DIToken('DW_ATE_float'),
                })
                derived_type = m.add_debug_info('DIDerivedType', {
                    'tag': ir.DIToken('DW_TAG_member'),
                    'name': name,
                    'baseType': component_basetype,
                    'size': _BYTE_SIZE * component_size, # DW_TAG_member size is in bits
                    'offset': offset,
                })
                meta.append(derived_type)
                offset += (_BYTE_SIZE * component_size) # offset is in bits
            mdtype = m.add_debug_info('DICompositeType', {
                'tag': ir.DIToken('DW_TAG_structure_type'),
                'name': f"{datamodel.fe_type} ({str(lltype)})",
                'identifier': str(lltype),
                'elements': m.add_metadata(meta),
                'size': offset,
            }, is_distinct=True)
        elif isinstance(datamodel, UniTupleModel):
            element = lltype.element
            el_size = self.cgctx.get_abi_sizeof(element)
            basetype = self._var_type(element, el_size)
            name = f"{datamodel.fe_type} ({str(lltype)})"
            count = size // el_size
            mdrange = m.add_debug_info('DISubrange', {
                'count': count,
            })
            mdtype = m.add_debug_info('DICompositeType', {
                'tag': ir.DIToken('DW_TAG_array_type'),
                'baseType': basetype,
                'name': name,
                'size': bitsize,
                'identifier': str(lltype),
                'elements': m.add_metadata([mdrange]),
            })
        elif isinstance(lltype, ir.PointerType):
            model = getattr(datamodel, '_pointee_model', None)
            basetype = self._var_type(lltype.pointee,
                                      self.cgctx.get_abi_sizeof(lltype.pointee),
                                      model)
            mdtype = m.add_debug_info('DIDerivedType', {
                'tag': ir.DIToken('DW_TAG_pointer_type'),
                'baseType': basetype,
                'size': _BYTE_SIZE * self.cgctx.get_abi_sizeof(lltype)
            })
        elif isinstance(lltype, ir.LiteralStructType):
            # Struct type
            meta = []
            offset = 0
            if datamodel is None:
                name = f"Anonymous struct ({str(lltype)})"
                for field_id, element in enumerate(lltype.elements):
                    size = self.cgctx.get_abi_sizeof(element)
                    basetype = self._var_type(element, size)
                    derived_type = m.add_debug_info('DIDerivedType', {
                        'tag': ir.DIToken('DW_TAG_member'),
                        'name': f'<field {field_id}>',
                        'baseType': basetype,
                        'size': _BYTE_SIZE * size, # DW_TAG_member size is in bits
                        'offset': offset,
                    })
                    meta.append(derived_type)
                    offset += (_BYTE_SIZE * size) # offset is in bits
            else:
                name = f"{datamodel.fe_type} ({str(lltype)})"
                for element, field, model in zip(lltype.elements,
                                                 datamodel._fields,
                                                 datamodel.inner_models()):
                    size = self.cgctx.get_abi_sizeof(element)
                    basetype = self._var_type(element, size, datamodel=model)
                    derived_type = m.add_debug_info('DIDerivedType', {
                        'tag': ir.DIToken('DW_TAG_member'),
                        'name': field,
                        'baseType': basetype,
                        'size': _BYTE_SIZE * size, # DW_TAG_member size is in bits
                        'offset': offset,
                    })
                    meta.append(derived_type)
                    offset += (_BYTE_SIZE * size) # offset is in bits

            mdtype = m.add_debug_info('DICompositeType', {
                'tag': ir.DIToken('DW_TAG_structure_type'),
                'name': name,
                'identifier': str(lltype),
                'elements': m.add_metadata(meta),
                'size': offset,
            }, is_distinct=True)
        elif isinstance(lltype, ir.ArrayType):
            element = lltype.element
            el_size = self.cgctx.get_abi_sizeof(element)
            basetype = self._var_type(element, el_size)
            count = size // el_size
            mdrange = m.add_debug_info('DISubrange', {
                'count': count,
            })
            mdtype = m.add_debug_info('DICompositeType', {
                'tag': ir.DIToken('DW_TAG_array_type'),
                'baseType': basetype,
                'name': str(lltype),
                'size': bitsize,
                'identifier': str(lltype),
                'elements': m.add_metadata([mdrange]),
            })
        else:
            # For all other types, describe it as sequence of bytes
            count = size
            mdrange = m.add_debug_info('DISubrange', {
                'count': count,
            })
            mdbase = m.add_debug_info('DIBasicType', {
                'name': 'byte',
                'size': _BYTE_SIZE,
                'encoding': ir.DIToken('DW_ATE_unsigned_char'),
            })
            mdtype = m.add_debug_info('DICompositeType', {
                'tag': ir.DIToken('DW_TAG_array_type'),
                'baseType': mdbase,
                'name': str(lltype),
                'size': bitsize,
                'identifier': str(lltype),
                'elements': m.add_metadata([mdrange]),
            })

        return mdtype
Example #11
0
unop.attributes.add("uwtable")

truth_type = ir.FunctionType(int1, (ppyobj_type,))
truth = ir.Function(module, truth_type, name="truth")
truth.attributes.add("uwtable")

call_function = ir.Function(module,fnty, name="call_function")
call_function.attributes.add("uwtable")

di_file = module.add_debug_info("DIFile", {
    "filename":        "test_c.py",
    "directory":       "tests",
})

di_compileunit = module.add_debug_info("DICompileUnit", {
    "language":        ir.DIToken("DW_LANG_Python"),
    "file":            di_file,
    "producer":        "Prython",
    "runtimeVersion":  0,
    "isOptimized":     True,
  }, is_distinct=True)

module.add_named_metadata("llvm.dbg.cu").add(di_compileunit)
module.add_named_metadata("llvm.ident").add(module.add_metadata(["Prython"]))
flags = module.add_named_metadata("llvm.module.flags")
flags.add(module.add_metadata([int32(2), "Dwarf Version", int32(4)]))
flags.add(module.add_metadata([int32(2), "Debug Info Version", int32(3)]))
flags.add(module.add_metadata([int32(1), "wchar_size", int32(4)]))

############## Helper code