185 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/STLExtras.h"10#include "llvm/ADT/StringExtras.h"11#include "llvm/BinaryFormat/Dwarf.h"12#include "llvm/MC/MCAsmInfo.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCDwarf.h"15#include "llvm/MC/MCRegisterInfo.h"16#include "llvm/MC/MCTargetOptions.h"17#include "llvm/MC/TargetRegistry.h"18#include "llvm/Support/TargetSelect.h"19#include "gtest/gtest.h"20 21using namespace llvm;22 23namespace {24struct Context {25 static constexpr char TripleName[] = "x86_64-pc-linux";26 Triple TT;27 std::unique_ptr<MCRegisterInfo> MRI;28 std::unique_ptr<MCAsmInfo> MAI;29 std::unique_ptr<MCContext> Ctx;30 31 Context() : TT(TripleName) {32 llvm::InitializeAllTargetInfos();33 llvm::InitializeAllTargetMCs();34 llvm::InitializeAllDisassemblers();35 36 // If we didn't build x86, do not run the test.37 std::string Error;38 const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);39 if (!TheTarget)40 return;41 42 MRI.reset(TheTarget->createMCRegInfo(TT));43 MCTargetOptions MCOptions;44 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TT, MCOptions));45 Ctx = std::make_unique<MCContext>(TT, MAI.get(), MRI.get(),46 /*MSTI=*/nullptr);47 }48 49 operator bool() { return Ctx.get(); }50 operator MCContext &() { return *Ctx; };51};52 53Context &getContext() {54 static Context Ctxt;55 return Ctxt;56}57}58 59void verifyEncoding(MCDwarfLineTableParams Params, int LineDelta, int AddrDelta,60 ArrayRef<uint8_t> ExpectedEncoding) {61 SmallString<16> Buffer;62 MCDwarfLineAddr::encode(getContext(), Params, LineDelta, AddrDelta,63 Buffer);64 EXPECT_EQ(ExpectedEncoding, arrayRefFromStringRef(Buffer));65}66 67TEST(DwarfLineTables, TestDefaultParams) {68 if (!getContext())69 GTEST_SKIP();70 71 MCDwarfLineTableParams Params;72 73 // Minimal line offset expressible through extended opcode, 0 addr delta74 const uint8_t Encoding0[] = {13}; // Special opcode Addr += 0, Line += -575 verifyEncoding(Params, -5, 0, Encoding0);76 77 // Maximal line offset expressible through extended opcode,78 const uint8_t Encoding1[] = {26}; // Special opcode Addr += 0, Line += +879 verifyEncoding(Params, 8, 0, Encoding1);80 81 // Random value in the middle of the special ocode range82 const uint8_t Encoding2[] = {146}; // Special opcode Addr += 9, Line += 283 verifyEncoding(Params, 2, 9, Encoding2);84 85 // Minimal line offset expressible through extended opcode, max addr delta86 const uint8_t Encoding3[] = {251}; // Special opcode Addr += 17, Line += -587 verifyEncoding(Params, -5, 17, Encoding3);88 89 // Biggest special opcode90 const uint8_t Encoding4[] = {255}; // Special opcode Addr += 17, Line += -191 verifyEncoding(Params, -1, 17, Encoding4);92 93 // Line delta outside of the special opcode range, address delta in range94 const uint8_t Encoding5[] = {dwarf::DW_LNS_advance_line, 9,95 158}; // Special opcode Addr += 10, Line += 096 verifyEncoding(Params, 9, 10, Encoding5);97 98 // Address delta outside of the special opcode range, but small99 // enough to do DW_LNS_const_add_pc + special opcode.100 const uint8_t Encoding6[] = {dwarf::DW_LNS_const_add_pc, // pc += 17101 62}; // Special opcode Addr += 3, Line += 2102 verifyEncoding(Params, 2, 20, Encoding6);103 104 // Address delta big enough to require the use of DW_LNS_advance_pc105 // Line delta in special opcode range106 const uint8_t Encoding7[] = {dwarf::DW_LNS_advance_pc, 100,107 20}; // Special opcode Addr += 0, Line += 2108 verifyEncoding(Params, 2, 100, Encoding7);109 110 // No special opcode possible.111 const uint8_t Encoding8[] = {dwarf::DW_LNS_advance_line, 20,112 dwarf::DW_LNS_advance_pc, 100,113 dwarf::DW_LNS_copy};114 verifyEncoding(Params, 20, 100, Encoding8);115}116 117TEST(DwarfLineTables, TestCustomParams) {118 if (!getContext())119 GTEST_SKIP();120 121 // Some tests against the example values given in the standard.122 MCDwarfLineTableParams Params;123 Params.DWARF2LineOpcodeBase = 13;124 Params.DWARF2LineBase = -3;125 Params.DWARF2LineRange = 12;126 127 // Minimal line offset expressible through extended opcode, 0 addr delta128 const uint8_t Encoding0[] = {13}; // Special opcode Addr += 0, Line += -5129 verifyEncoding(Params, -3, 0, Encoding0);130 131 // Maximal line offset expressible through extended opcode,132 const uint8_t Encoding1[] = {24}; // Special opcode Addr += 0, Line += +8133 verifyEncoding(Params, 8, 0, Encoding1);134 135 // Random value in the middle of the special ocode range136 const uint8_t Encoding2[] = {126}; // Special opcode Addr += 9, Line += 2137 verifyEncoding(Params, 2, 9, Encoding2);138 139 // Minimal line offset expressible through extended opcode, max addr delta140 const uint8_t Encoding3[] = {253}; // Special opcode Addr += 20, Line += -3141 verifyEncoding(Params, -3, 20, Encoding3);142 143 // Biggest special opcode144 const uint8_t Encoding4[] = {255}; // Special opcode Addr += 17, Line += -1145 verifyEncoding(Params, -1, 20, Encoding4);146 147 // Line delta outside of the special opcode range, address delta in range148 const uint8_t Encoding5[] = {dwarf::DW_LNS_advance_line, 9,149 136}; // Special opcode Addr += 10, Line += 0150 verifyEncoding(Params, 9, 10, Encoding5);151 152 // Address delta outside of the special opcode range, but small153 // enough to do DW_LNS_const_add_pc + special opcode.154 const uint8_t Encoding6[] = {dwarf::DW_LNS_const_add_pc, // pc += 20155 138}; // Special opcode Addr += 10, Line += 2156 verifyEncoding(Params, 2, 30, Encoding6);157 158 // Address delta big enough to require the use of DW_LNS_advance_pc159 // Line delta in special opcode range160 const uint8_t Encoding7[] = {dwarf::DW_LNS_advance_pc, 100,161 18}; // Special opcode Addr += 0, Line += 2162 verifyEncoding(Params, 2, 100, Encoding7);163 164 // No special opcode possible.165 const uint8_t Encoding8[] = {dwarf::DW_LNS_advance_line, 20,166 dwarf::DW_LNS_advance_pc, 100,167 dwarf::DW_LNS_copy};168 verifyEncoding(Params, 20, 100, Encoding8);169}170 171TEST(DwarfLineTables, TestCustomParams2) {172 if (!getContext())173 GTEST_SKIP();174 175 // Corner case param values.176 MCDwarfLineTableParams Params;177 Params.DWARF2LineOpcodeBase = 13;178 Params.DWARF2LineBase = 1;179 Params.DWARF2LineRange = 255;180 181 const uint8_t Encoding0[] = {dwarf::DW_LNS_advance_line, 248, 1,182 dwarf::DW_LNS_copy};183 verifyEncoding(Params, 248, 0, Encoding0);184}185