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
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
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
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)
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
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
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, )
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])
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)
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
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