diff --git a/llvm/debuginfo.py b/llvm/debuginfo.py index c9f6a2b..7afd563 100644 --- a/llvm/debuginfo.py +++ b/llvm/debuginfo.py @@ -13,7 +13,36 @@ bool_t = llvm.core.Type.int(1) i32 = functools.partial(llvm.core.Constant.int, int32_t) i1 = functools.partial(llvm.core.Constant.int, bool_t) -class CompileUnitDescriptor(object): +class DebugInfoBase(object): + def __init__(self): + self.metadata_cache = {} + + def get_metadata(self, llvm_module): + """ + Get an existing metadata node for the given LLVM module, or build + one from this instance. + """ + if llvm_module in self.metadata_cache: + node = self.metadata_cache[llvm_module] + else: + node = self.build_metadata(llvm_module) + self.metadata_cache[llvm_module] = node + + return node + + def build_metadata(self, llvm_module): + "Build a metadata node for the given LLVM module" + raise NotImplementedError + + def define(self, llvm_module): + """ + Define this debug descriptor as named debug metadata for the module. + """ + md = self.get_metadata(llvm_module) + llvm.core.MetaData.add_named_operand(llvm_module, "dbg", md) + + +class CompileUnitDescriptor(DebugInfoBase): """ !0 = metadata !{ i32, ;; Tag = 17 + LLVMDebugVersion (DW_TAG_compile_unit) @@ -37,6 +66,7 @@ class CompileUnitDescriptor(object): producer, is_main=False, is_optimized=False, compile_flags=None, runtime_version=0, enum_types=None, retained_types=None, subprograms=None, global_vars=None): + super(CompileUnitDescriptor, self).__init__() self.langid = langid self.source_filename = source_filename self.source_filedir = source_filedir @@ -71,14 +101,42 @@ class CompileUnitDescriptor(object): md(self.global_vars or []), ] -# for op in operands: -# print op + return md(operands) - node = llvm.core.MetaData.get(llvm_module, operands) - llvm.core.MetaData.add_named_operand(llvm_module, "dbg", node) -# print "printing metadata compile unit..." -# print node -# print "---- done ----" +class FileDescriptor(DebugInfoBase): + """ + !0 = metadata !{ + i32, ;; Tag = 41 + LLVMDebugVersion (DW_TAG_file_type) + metadata, ;; Source file name + metadata, ;; Source file directory (includes trailing slash) + metadata ;; Unused + } + """ + + def __init__(self, source_filename, source_filedir, compile_unit_descriptor): + super(FileDescriptor, self).__init__() + self.source_filename = source_filename + self.source_filedir = source_filedir + self.compile_unit_descriptor = compile_unit_descriptor + + @classmethod + def from_compileunit(cls, compile_unit_descriptor): + return cls(compile_unit_descriptor.source_filename, + compile_unit_descriptor.source_filedir, + compile_unit_descriptor) + + def build_metadata(self, llvm_module): + md = functools.partial(llvm.core.MetaData.get, llvm_module) + mstr = functools.partial(llvm.core.MetaDataString.get, llvm_module) + + operands = [ + i32(_dwarf.DW_TAG_file_type + _dwarf.LLVMDebugVersion), + mstr(self.source_filename), + mstr(self.source_filedir), + self.compile_unit_descriptor.get_metadata(llvm_module), + ] + + return md(operands) + - return node diff --git a/test/test_debuginfo.py b/test/test_debuginfo.py index 86cbe2d..4dc0f13 100644 --- a/test/test_debuginfo.py +++ b/test/test_debuginfo.py @@ -42,13 +42,15 @@ class TestDebugInfo(unittest.TestCase): "my_cool_compiler", ) - info.build_metadata(mod) + filedesc = debuginfo.FileDescriptor.from_compileunit(info) + filedesc.define(mod) value = square.args[0] result = bldr.fmul(value, value) bldr.ret(result) # print mod + modstr = str(mod) self.assertIn("my_cool_compiler", modstr) self.assertIn("test_debug_info.py", modstr)