DwarfLineTables.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //===- llvm/unittest/MC/DwarfLineTables.cpp ------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ADT/STLExtras.h"
  9. #include "llvm/BinaryFormat/Dwarf.h"
  10. #include "llvm/MC/MCAsmInfo.h"
  11. #include "llvm/MC/MCContext.h"
  12. #include "llvm/MC/MCDwarf.h"
  13. #include "llvm/MC/MCRegisterInfo.h"
  14. #include "llvm/Support/TargetRegistry.h"
  15. #include "llvm/Support/TargetSelect.h"
  16. #include "gtest/gtest.h"
  17. using namespace llvm;
  18. namespace {
  19. struct Context {
  20. const char *Triple = "x86_64-pc-linux";
  21. std::unique_ptr<MCRegisterInfo> MRI;
  22. std::unique_ptr<MCAsmInfo> MAI;
  23. std::unique_ptr<MCContext> Ctx;
  24. Context() {
  25. llvm::InitializeAllTargetInfos();
  26. llvm::InitializeAllTargetMCs();
  27. llvm::InitializeAllDisassemblers();
  28. // If we didn't build x86, do not run the test.
  29. std::string Error;
  30. const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  31. if (!TheTarget)
  32. return;
  33. MRI.reset(TheTarget->createMCRegInfo(Triple));
  34. MAI.reset(TheTarget->createMCAsmInfo(*MRI, Triple));
  35. Ctx = std::make_unique<MCContext>(MAI.get(), MRI.get(), nullptr);
  36. }
  37. operator bool() { return Ctx.get(); }
  38. operator MCContext &() { return *Ctx; };
  39. };
  40. Context &getContext() {
  41. static Context Ctxt;
  42. return Ctxt;
  43. }
  44. }
  45. void verifyEncoding(MCDwarfLineTableParams Params, int LineDelta, int AddrDelta,
  46. ArrayRef<uint8_t> ExpectedEncoding) {
  47. SmallString<16> Buffer;
  48. raw_svector_ostream EncodingOS(Buffer);
  49. MCDwarfLineAddr::Encode(getContext(), Params, LineDelta, AddrDelta,
  50. EncodingOS);
  51. EXPECT_EQ(ExpectedEncoding, arrayRefFromStringRef(Buffer));
  52. }
  53. TEST(DwarfLineTables, TestDefaultParams) {
  54. if (!getContext())
  55. return;
  56. MCDwarfLineTableParams Params;
  57. // Minimal line offset expressible through extended opcode, 0 addr delta
  58. const uint8_t Encoding0[] = {13}; // Special opcode Addr += 0, Line += -5
  59. verifyEncoding(Params, -5, 0, Encoding0);
  60. // Maximal line offset expressible through extended opcode,
  61. const uint8_t Encoding1[] = {26}; // Special opcode Addr += 0, Line += +8
  62. verifyEncoding(Params, 8, 0, Encoding1);
  63. // Random value in the middle of the special ocode range
  64. const uint8_t Encoding2[] = {146}; // Special opcode Addr += 9, Line += 2
  65. verifyEncoding(Params, 2, 9, Encoding2);
  66. // Minimal line offset expressible through extended opcode, max addr delta
  67. const uint8_t Encoding3[] = {251}; // Special opcode Addr += 17, Line += -5
  68. verifyEncoding(Params, -5, 17, Encoding3);
  69. // Biggest special opcode
  70. const uint8_t Encoding4[] = {255}; // Special opcode Addr += 17, Line += -1
  71. verifyEncoding(Params, -1, 17, Encoding4);
  72. // Line delta outside of the special opcode range, address delta in range
  73. const uint8_t Encoding5[] = {dwarf::DW_LNS_advance_line, 9,
  74. 158}; // Special opcode Addr += 10, Line += 0
  75. verifyEncoding(Params, 9, 10, Encoding5);
  76. // Address delta outside of the special opcode range, but small
  77. // enough to do DW_LNS_const_add_pc + special opcode.
  78. const uint8_t Encoding6[] = {dwarf::DW_LNS_const_add_pc, // pc += 17
  79. 62}; // Special opcode Addr += 3, Line += 2
  80. verifyEncoding(Params, 2, 20, Encoding6);
  81. // Address delta big enough to require the use of DW_LNS_advance_pc
  82. // Line delta in special opcode range
  83. const uint8_t Encoding7[] = {dwarf::DW_LNS_advance_pc, 100,
  84. 20}; // Special opcode Addr += 0, Line += 2
  85. verifyEncoding(Params, 2, 100, Encoding7);
  86. // No special opcode possible.
  87. const uint8_t Encoding8[] = {dwarf::DW_LNS_advance_line, 20,
  88. dwarf::DW_LNS_advance_pc, 100,
  89. dwarf::DW_LNS_copy};
  90. verifyEncoding(Params, 20, 100, Encoding8);
  91. }
  92. TEST(DwarfLineTables, TestCustomParams) {
  93. if (!getContext())
  94. return;
  95. // Some tests against the example values given in the standard.
  96. MCDwarfLineTableParams Params;
  97. Params.DWARF2LineOpcodeBase = 13;
  98. Params.DWARF2LineBase = -3;
  99. Params.DWARF2LineRange = 12;
  100. // Minimal line offset expressible through extended opcode, 0 addr delta
  101. const uint8_t Encoding0[] = {13}; // Special opcode Addr += 0, Line += -5
  102. verifyEncoding(Params, -3, 0, Encoding0);
  103. // Maximal line offset expressible through extended opcode,
  104. const uint8_t Encoding1[] = {24}; // Special opcode Addr += 0, Line += +8
  105. verifyEncoding(Params, 8, 0, Encoding1);
  106. // Random value in the middle of the special ocode range
  107. const uint8_t Encoding2[] = {126}; // Special opcode Addr += 9, Line += 2
  108. verifyEncoding(Params, 2, 9, Encoding2);
  109. // Minimal line offset expressible through extended opcode, max addr delta
  110. const uint8_t Encoding3[] = {253}; // Special opcode Addr += 20, Line += -3
  111. verifyEncoding(Params, -3, 20, Encoding3);
  112. // Biggest special opcode
  113. const uint8_t Encoding4[] = {255}; // Special opcode Addr += 17, Line += -1
  114. verifyEncoding(Params, -1, 20, Encoding4);
  115. // Line delta outside of the special opcode range, address delta in range
  116. const uint8_t Encoding5[] = {dwarf::DW_LNS_advance_line, 9,
  117. 136}; // Special opcode Addr += 10, Line += 0
  118. verifyEncoding(Params, 9, 10, Encoding5);
  119. // Address delta outside of the special opcode range, but small
  120. // enough to do DW_LNS_const_add_pc + special opcode.
  121. const uint8_t Encoding6[] = {dwarf::DW_LNS_const_add_pc, // pc += 20
  122. 138}; // Special opcode Addr += 10, Line += 2
  123. verifyEncoding(Params, 2, 30, Encoding6);
  124. // Address delta big enough to require the use of DW_LNS_advance_pc
  125. // Line delta in special opcode range
  126. const uint8_t Encoding7[] = {dwarf::DW_LNS_advance_pc, 100,
  127. 18}; // Special opcode Addr += 0, Line += 2
  128. verifyEncoding(Params, 2, 100, Encoding7);
  129. // No special opcode possible.
  130. const uint8_t Encoding8[] = {dwarf::DW_LNS_advance_line, 20,
  131. dwarf::DW_LNS_advance_pc, 100,
  132. dwarf::DW_LNS_copy};
  133. verifyEncoding(Params, 20, 100, Encoding8);
  134. }
  135. TEST(DwarfLineTables, TestCustomParams2) {
  136. if (!getContext())
  137. return;
  138. // Corner case param values.
  139. MCDwarfLineTableParams Params;
  140. Params.DWARF2LineOpcodeBase = 13;
  141. Params.DWARF2LineBase = 1;
  142. Params.DWARF2LineRange = 255;
  143. const uint8_t Encoding0[] = {dwarf::DW_LNS_advance_line, 248, 1,
  144. dwarf::DW_LNS_copy};
  145. verifyEncoding(Params, 248, 0, Encoding0);
  146. }