diff --git a/llvmlite/ir/module.py b/llvmlite/ir/module.py index 464f91ec3..3b7eeca67 100644 --- a/llvmlite/ir/module.py +++ b/llvmlite/ir/module.py @@ -42,6 +42,15 @@ def _fix_di_operands(self, operands): fixed_ops.append((name, op)) return fixed_ops + def str_ditok_operands(self, operands): + str_ops = [] + for name, op in operands: + if name == 'encoding' and isinstance(op, values.DIToken): + # use string value instead of address of object + op = op.value + str_ops.append((name, op)) + return str_ops + def add_metadata(self, operands): """ Add an unnamed metadata to the module with the given *operands* @@ -73,7 +82,8 @@ def add_debug_info(self, kind, operands, is_distinct=False): an instruction. """ operands = tuple(sorted(self._fix_di_operands(operands.items()))) - key = (kind, operands, is_distinct) + str_op_key = tuple(sorted(self.str_ditok_operands(operands))) + key = (kind, str_op_key, is_distinct) if key not in self._metadatacache: n = len(self.metadata) di = values.DIValue(self, is_distinct, kind, operands, name=str(n)) diff --git a/llvmlite/tests/test_ir.py b/llvmlite/tests/test_ir.py index 5b29aa82f..2d2407f5b 100644 --- a/llvmlite/tests/test_ir.py +++ b/llvmlite/tests/test_ir.py @@ -490,6 +490,71 @@ def test_debug_info_2(self): '"foo")', strmod) self.assert_valid_ir(mod) + def test_debug_info_3(self): + # Identical DIBasicType metadata nodes should be merged + mod = self.module() + di1 = mod.add_debug_info("DIBasicType", { + "name": "i8", + "size": 8, + "encoding": ir.DIToken("DW_ATE_unsigned") + }) + di2 = mod.add_debug_info("DIBasicType", { + "name": "i8", + "size": 8, + "encoding": ir.DIToken("DW_ATE_unsigned") + }) + di3 = mod.add_debug_info("DIBasicType", { + "name": "i32", + "size": 32, + "encoding": ir.DIToken("DW_ATE_unsigned") + }) + di4 = mod.add_debug_info("DIBasicType", { + "name": "i8", + "size": 8, + "encoding": ir.DIToken("DW_ATE_unsigned") + }) + di5 = mod.add_debug_info("DIBasicType", { + "name": "i8", + "size": 8, + "encoding": ir.DIToken("DW_ATE_unsigned") + }) + di6 = mod.add_debug_info("DIBasicType", { + "name": "i32", + "size": 32, + "encoding": ir.DIToken("DW_ATE_unsigned") + }) + di7 = mod.add_debug_info("DIBasicType", { + "name": "i64", + "size": 64, + "encoding": ir.DIToken("DW_ATE_signed") + }) + di8 = mod.add_debug_info("DIBasicType", { + "name": "i64", + "size": 64, + "encoding": ir.DIToken("DW_ATE_signed") + }) + di9 = mod.add_debug_info("DIBasicType", { + "name": "i64", + "size": 64, + "encoding": ir.DIToken("DW_ATE_signed") + }) + self.assertIs(di1, di2) + self.assertIs(di1, di4) + self.assertIs(di1, di5) + self.assertIs(di3, di6) + self.assertIs(di7, di8) + self.assertIs(di7, di9) + self.assertEqual(len({di1, di2, di3, di4, di5, di6, di7, di8, di9}), 3) + # Check output + strmod = str(mod) + self.assert_ir_line('!0 = !DIBasicType(encoding: DW_ATE_unsigned, ' + 'name: "i8", size: 8)', strmod) + self.assert_ir_line('!1 = !DIBasicType(encoding: DW_ATE_unsigned, ' + 'name: "i32", size: 32)', strmod) + self.assert_ir_line('!2 = !DIBasicType(encoding: DW_ATE_signed, ' + 'name: "i64", size: 64)', strmod) + self.assert_valid_ir(mod) + def test_debug_info_gvar(self): # This test defines a module with a global variable named 'gvar'. # When the module is compiled and linked with a main function, gdb can