summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/MC/MCDwarf.cpp7
-rw-r--r--llvm/unittests/MC/CMakeLists.txt1
-rw-r--r--llvm/unittests/MC/DwarfLineTables.cpp179
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);
+}
OpenPOWER on IntegriCloud