diff options
| -rw-r--r-- | llvm/lib/MC/MCDwarf.cpp | 7 | ||||
| -rw-r--r-- | llvm/unittests/MC/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/unittests/MC/DwarfLineTables.cpp | 179 | 
3 files changed, 185 insertions, 2 deletions
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index f2de2fc7255..e3e5f239ef6 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -452,7 +452,8 @@ void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params,    // If the line increment is out of range of a special opcode, we must encode    // it with DW_LNS_advance_line. -  if (Temp >= Params.DWARF2LineRange) { +  if (Temp >= Params.DWARF2LineRange || +      Temp + Params.DWARF2LineOpcodeBase > 255) {      OS << char(dwarf::DW_LNS_advance_line);      encodeSLEB128(LineDelta, OS); @@ -494,8 +495,10 @@ void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params,    if (NeedCopy)      OS << char(dwarf::DW_LNS_copy); -  else +  else { +    assert(Temp <= 255 && "Buggy special opcode encoding.");      OS << char(Temp); +  }  }  // Utility function to write a tuple for .debug_abbrev. diff --git a/llvm/unittests/MC/CMakeLists.txt b/llvm/unittests/MC/CMakeLists.txt index f83eaf4779f..9d68e783a55 100644 --- a/llvm/unittests/MC/CMakeLists.txt +++ b/llvm/unittests/MC/CMakeLists.txt @@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS  add_llvm_unittest(MCTests    Disassembler.cpp +  DwarfLineTables.cpp    StringTableBuilderTest.cpp    YAMLTest.cpp    ) diff --git a/llvm/unittests/MC/DwarfLineTables.cpp b/llvm/unittests/MC/DwarfLineTables.cpp new file mode 100644 index 00000000000..4bfb5acea03 --- /dev/null +++ b/llvm/unittests/MC/DwarfLineTables.cpp @@ -0,0 +1,179 @@ +//===- llvm/unittest/MC/DwarfLineTables.cpp ------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Dwarf.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { +struct Context { +  const char *Triple = "x86_64-pc-linux"; +  std::unique_ptr<MCRegisterInfo> MRI; +  std::unique_ptr<MCAsmInfo> MAI; +  std::unique_ptr<MCContext> Ctx; + +  Context() { +    llvm::InitializeAllTargetInfos(); +    llvm::InitializeAllTargetMCs(); +    llvm::InitializeAllDisassemblers(); + +    // If we didn't build x86, do not run the test. +    std::string Error; +    const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); +    if (!TheTarget) +      return; + +    MRI.reset(TheTarget->createMCRegInfo(Triple)); +    MAI.reset(TheTarget->createMCAsmInfo(*MRI, Triple)); +    Ctx = llvm::make_unique<MCContext>(MAI.get(), MRI.get(), nullptr); +  } + +  operator bool() { return Ctx.get(); } +  operator MCContext &() { return *Ctx; }; +}; + +Context Ctxt; +} + +void verifyEncoding(MCDwarfLineTableParams Params, int LineDelta, int AddrDelta, +                    ArrayRef<uint8_t> ExpectedEncoding) { +  SmallString<16> Buffer; +  raw_svector_ostream EncodingOS(Buffer); +  MCDwarfLineAddr::Encode(Ctxt, Params, LineDelta, AddrDelta, EncodingOS); +  ArrayRef<uint8_t> Encoding(reinterpret_cast<uint8_t *>(Buffer.data()), +                             Buffer.size()); +  EXPECT_EQ(ExpectedEncoding, Encoding); +} + +TEST(DwarfLineTables, TestDefaultParams) { +  if (!Ctxt) +    return; + +  MCDwarfLineTableParams Params; + +  // Minimal line offset expressible through extended opcode, 0 addr delta +  const uint8_t Encoding0[] = {13}; // Special opcode Addr += 0, Line += -5 +  verifyEncoding(Params, -5, 0, Encoding0); + +  // Maximal line offset expressible through extended opcode, +  const uint8_t Encoding1[] = {26}; // Special opcode Addr += 0, Line += +8 +  verifyEncoding(Params, 8, 0, Encoding1); + +  // Random value in the middle of the special ocode range +  const uint8_t Encoding2[] = {146}; // Special opcode Addr += 9, Line += 2 +  verifyEncoding(Params, 2, 9, Encoding2); + +  // Minimal line offset expressible through extended opcode, max addr delta +  const uint8_t Encoding3[] = {251}; // Special opcode Addr += 17, Line += -5 +  verifyEncoding(Params, -5, 17, Encoding3); + +  // Biggest special opcode +  const uint8_t Encoding4[] = {255}; // Special opcode Addr += 17, Line += -1 +  verifyEncoding(Params, -1, 17, Encoding4); + +  // Line delta outside of the special opcode range, address delta in range +  const uint8_t Encoding5[] = {dwarf::DW_LNS_advance_line, 9, +                               158}; // Special opcode Addr += 10, Line += 0 +  verifyEncoding(Params, 9, 10, Encoding5); + +  // Address delta outside of the special opcode range, but small +  // enough to do DW_LNS_const_add_pc + special opcode. +  const uint8_t Encoding6[] = {dwarf::DW_LNS_const_add_pc, // pc += 17 +                               62}; // Special opcode Addr += 3, Line += 2 +  verifyEncoding(Params, 2, 20, Encoding6); + +  // Address delta big enough to require the use of DW_LNS_advance_pc +  // Line delta in special opcode range +  const uint8_t Encoding7[] = {dwarf::DW_LNS_advance_pc, 100, +                               20}; // Special opcode Addr += 0, Line += 2 +  verifyEncoding(Params, 2, 100, Encoding7); + +  // No special opcode possible. +  const uint8_t Encoding8[] = {dwarf::DW_LNS_advance_line, 20, +                               dwarf::DW_LNS_advance_pc, 100, +                               dwarf::DW_LNS_copy}; +  verifyEncoding(Params, 20, 100, Encoding8); +} + +TEST(DwarfLineTables, TestCustomParams) { +  if (!Ctxt) +    return; + +  // Some tests against the example values given in the standard. +  MCDwarfLineTableParams Params; +  Params.DWARF2LineOpcodeBase = 13; +  Params.DWARF2LineBase = -3; +  Params.DWARF2LineRange = 12; + +  // Minimal line offset expressible through extended opcode, 0 addr delta +  const uint8_t Encoding0[] = {13}; // Special opcode Addr += 0, Line += -5 +  verifyEncoding(Params, -3, 0, Encoding0); + +  // Maximal line offset expressible through extended opcode, +  const uint8_t Encoding1[] = {24}; // Special opcode Addr += 0, Line += +8 +  verifyEncoding(Params, 8, 0, Encoding1); + +  // Random value in the middle of the special ocode range +  const uint8_t Encoding2[] = {126}; // Special opcode Addr += 9, Line += 2 +  verifyEncoding(Params, 2, 9, Encoding2); + +  // Minimal line offset expressible through extended opcode, max addr delta +  const uint8_t Encoding3[] = {253}; // Special opcode Addr += 20, Line += -3 +  verifyEncoding(Params, -3, 20, Encoding3); + +  // Biggest special opcode +  const uint8_t Encoding4[] = {255}; // Special opcode Addr += 17, Line += -1 +  verifyEncoding(Params, -1, 20, Encoding4); + +  // Line delta outside of the special opcode range, address delta in range +  const uint8_t Encoding5[] = {dwarf::DW_LNS_advance_line, 9, +                               136}; // Special opcode Addr += 10, Line += 0 +  verifyEncoding(Params, 9, 10, Encoding5); + +  // Address delta outside of the special opcode range, but small +  // enough to do DW_LNS_const_add_pc + special opcode. +  const uint8_t Encoding6[] = {dwarf::DW_LNS_const_add_pc, // pc += 20 +                               138}; // Special opcode Addr += 10, Line += 2 +  verifyEncoding(Params, 2, 30, Encoding6); + +  // Address delta big enough to require the use of DW_LNS_advance_pc +  // Line delta in special opcode range +  const uint8_t Encoding7[] = {dwarf::DW_LNS_advance_pc, 100, +                               18}; // Special opcode Addr += 0, Line += 2 +  verifyEncoding(Params, 2, 100, Encoding7); + +  // No special opcode possible. +  const uint8_t Encoding8[] = {dwarf::DW_LNS_advance_line, 20, +                               dwarf::DW_LNS_advance_pc, 100, +                               dwarf::DW_LNS_copy}; +  verifyEncoding(Params, 20, 100, Encoding8); +} + +TEST(DwarfLineTables, TestCustomParams2) { +  if (!Ctxt) +    return; + +  // Corner case param values. +  MCDwarfLineTableParams Params; +  Params.DWARF2LineOpcodeBase = 13; +  Params.DWARF2LineBase = 1; +  Params.DWARF2LineRange = 255; + +  const uint8_t Encoding0[] = {dwarf::DW_LNS_advance_line, 248, 1, +                               dwarf::DW_LNS_copy}; +  verifyEncoding(Params, 248, 0, Encoding0); +}  | 

