diff --git a/llvm/debuginfo.py b/llvm/debuginfo.py new file mode 100644 index 0000000..7f2c16e --- /dev/null +++ b/llvm/debuginfo.py @@ -0,0 +1,81 @@ +""" +Support for debug info metadata. +""" + +import functools + +import llvm.core +from llvm import _dwarf + +int32_t = llvm.core.Type.int(32) +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): + """ + !0 = metadata !{ + i32, ;; Tag = 17 + LLVMDebugVersion (DW_TAG_compile_unit) + i32, ;; Unused field. + i32, ;; DWARF language identifier (ex. DW_LANG_C89) + metadata, ;; Source file name + metadata, ;; Source file directory (includes trailing slash) + metadata ;; Producer (ex. "4.0.1 LLVM (LLVM research group)") + i1, ;; True if this is a main compile unit. + i1, ;; True if this is optimized. + metadata, ;; Flags + i32 ;; Runtime version + metadata ;; List of enums types + metadata ;; List of retained types + metadata ;; List of subprograms + metadata ;; List of global variables + } + """ + + def __init__(self, langid, source_filename, source_filedir, + producer, is_main=False, is_optimized=False, + compile_flags=None, runtime_version=0, enum_types=None, + retained_types=None, subprograms=None, global_vars=None): + self.langid = langid + self.source_filename = source_filename + self.source_filedir = source_filedir + self.producer = producer + self.is_main = is_main + self.is_optimized = is_optimized + self.compile_flags = compile_flags + self.runtime_version = runtime_version + self.enum_types = enum_types + self.retained_types = retained_types + self.subprograms = subprograms + self.global_vars = global_vars + + 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_compile_unit + + _dwarf.LLVMDebugVersion), # tag + i32(0), # unused + i32(self.langid), # Language identifier + mstr(self.source_filename), + mstr(self.source_filedir), + mstr(self.producer), + i1(self.is_main), + i1(self.is_optimized), + mstr(self.compile_flags or ""), + md(self.enum_types or []), + md(self.retained_types or []), + md(self.subprograms or []), + md(self.global_vars or []), + ] + + 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 ----" + + return node diff --git a/test/test_debuginfo.py b/test/test_debuginfo.py index d2f156b..3641d22 100644 --- a/test/test_debuginfo.py +++ b/test/test_debuginfo.py @@ -2,7 +2,7 @@ import os import unittest from llvm.core import * -from llvm import _dwarf +from llvm import _dwarf, debuginfo class TestDebugInfo(unittest.TestCase): @@ -24,7 +24,33 @@ class TestDebugInfo(unittest.TestCase): # print sorted([constname for constname in dwarf_constants # if constname.startswith("DW_LANG_")]) + def test_debug_info_compile_unit(self): + mod = Module.new('test_debug_info') + fty = Type.function(Type.float(), [Type.float()]) + square = mod.add_function(fty, 'square') + bb = square.append_basic_block('entry') + bldr = Builder.new(bb) + + info = debuginfo.CompileUnitDescriptor( + _dwarf.DW_LANG_Python, + "test_debug_info.py", + os.path.expanduser("~/"), + "my_cool_compiler", + ) + + info.build_metadata(mod) + + value = square.args[0] + result = bldr.fmul(value, value) + bldr.ret(result) + +# info.build_metadata(mod) + print mod +# modstr = str(mod) +# print modstr + # self.assertIn("my_cool_compiler", modstr) if __name__ == '__main__': # TestDebugInfo("test_dwarf_constants").debug() - unittest.main() \ No newline at end of file + TestDebugInfo("test_debug_info_compile_unit").debug() +# unittest.main() \ No newline at end of file