DIEHash: Use DW_FORM_sdata for integers, per spec.
authorDavid Blaikie <dblaikie@gmail.com>
Wed, 16 Oct 2013 23:36:20 +0000 (23:36 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Wed, 16 Oct 2013 23:36:20 +0000 (23:36 +0000)
This allows us to produce the same hash as GCC for at least some simple
examples.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192855 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/DIEHash.cpp
lib/CodeGen/AsmPrinter/DIEHash.h
test/DebugInfo/X86/fission-hash.ll
unittests/CodeGen/DIEHashTest.cpp

index bf02daac517dcefe2f9a47838de8a52c3a14defe..9a26e727bd99a12877159a0fe5ce29eef0fa4148 100644 (file)
@@ -68,6 +68,20 @@ void DIEHash::addULEB128(uint64_t Value) {
   } while (Value != 0);
 }
 
+void DIEHash::addSLEB128(int64_t Value) {
+  DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
+  bool More;
+  do {
+    uint8_t Byte = Value & 0x7f;
+    Value >>= 7;
+    More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
+              ((Value == -1) && ((Byte & 0x40) != 0))));
+    if (More)
+      Byte |= 0x80; // Mark this byte to show that more bytes will follow.
+    Hash.update(Byte);
+  } while (More);
+}
+
 /// \brief Including \p Parent adds the context of Parent to the hash..
 void DIEHash::addParentContext(DIE *Parent) {
 
@@ -277,15 +291,20 @@ void DIEHash::hashAttribute(AttrEntry Attr) {
   // Add the letter A to the hash.
   addULEB128('A');
 
-  // Then the attribute code and form.
+  // Then the attribute code.
   addULEB128(Desc->getAttribute());
-  addULEB128(Desc->getForm());
+
+  // To ensure reproducibility of the signature, the set of forms used in the
+  // signature computation is limited to the following: DW_FORM_sdata,
+  // DW_FORM_flag, DW_FORM_string, and DW_FORM_block.
 
   // TODO: Add support for additional forms.
   switch (Desc->getForm()) {
-  // TODO: We'll want to add DW_FORM_string here if we start emitting them
-  // again.
+  case dwarf::DW_FORM_string:
+    llvm_unreachable(
+        "Add support for DW_FORM_string if we ever start emitting them again");
   case dwarf::DW_FORM_strp:
+    addULEB128(dwarf::DW_FORM_string);
     addString(cast<DIEString>(Value)->getString());
     break;
   case dwarf::DW_FORM_data1:
@@ -293,7 +312,8 @@ void DIEHash::hashAttribute(AttrEntry Attr) {
   case dwarf::DW_FORM_data4:
   case dwarf::DW_FORM_data8:
   case dwarf::DW_FORM_udata:
-    addULEB128(cast<DIEInteger>(Value)->getValue());
+    addULEB128(dwarf::DW_FORM_sdata);
+    addSLEB128((int64_t)cast<DIEInteger>(Value)->getValue());
     break;
   }
 }
index b792aeab6ce6cdd34021164b20b20e3f4f9f60e0..78238e19ab3c3e6e8a0ba4606d0d3a5ee6d18fc7 100644 (file)
@@ -106,6 +106,9 @@ private:
   /// \brief Encodes and adds \param Value to the hash as a ULEB128.
   void addULEB128(uint64_t Value);
 
+  /// \brief Encodes and adds \param Value to the hash as a SLEB128.
+  void addSLEB128(int64_t Value);
+
   /// \brief Adds \param Str to the hash and includes a NULL byte.
   void addString(StringRef Str);
 
index 1cfbf4439fbac02cfcd83bc7e20aa6421f2f3385..969b21c4d8d6a3a99792a75d9f06d09620c518f6 100644 (file)
@@ -3,8 +3,8 @@
 
 ; The source is an empty file.
 
-; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x2410f0bbc44241ed)
-; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x2410f0bbc44241ed)
+; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x63fc20b98dd69e2d)
+; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x63fc20b98dd69e2d)
 
 !llvm.dbg.cu = !{!0}
 !llvm.module.flags = !{!3}
index 91b03224f0a6fba9539cebb047696d9ec4996a28..92b6d7686cfbe4209c3674a709b65a314f844c42 100644 (file)
@@ -23,6 +23,22 @@ TEST(DIEHashData1Test, DIEHash) {
   DIEInteger Size(4);
   Die.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Size);
   uint64_t MD5Res = Hash.computeTypeSignature(&Die);
-  ASSERT_EQ(0x4F68EF1039F8D2BULL, MD5Res);
+  ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res);
+}
+
+TEST(DIEHashTrivialTypeTest, DIEHash) {
+  // A complete, but simple, type containing no members and defined on the first
+  // line of a file.
+  DIE FooType(dwarf::DW_TAG_structure_type);
+  DIEInteger One(1);
+  FooType.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+  // Line and file number are ignored.
+  FooType.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One);
+  FooType.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One);
+  uint64_t MD5Res = DIEHash().computeTypeSignature(&FooType);
+
+  // The exact same hash GCC produces for this DIE.
+  ASSERT_EQ(0x715305ce6cfd9ad1ULL, MD5Res);
 }
 }