#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
struct Context {
const char *TripleName = "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();
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
if (!TheTarget)
return;
MRI.reset(TheTarget->createMCRegInfo(TripleName));
MCTargetOptions MCOptions;
MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(), MRI.get(),
nullptr);
}
operator bool() { return Ctx.get(); }
operator MCContext &() { return *Ctx; };
};
Context &getContext() {
static Context Ctxt;
return Ctxt;
}
}
void verifyEncoding(MCDwarfLineTableParams Params, int LineDelta, int AddrDelta,
ArrayRef<uint8_t> ExpectedEncoding) {
SmallString<16> Buffer;
raw_svector_ostream EncodingOS(Buffer);
MCDwarfLineAddr::Encode(getContext(), Params, LineDelta, AddrDelta,
EncodingOS);
EXPECT_EQ(ExpectedEncoding, arrayRefFromStringRef(Buffer));
}
TEST(DwarfLineTables, TestDefaultParams) {
if (!getContext())
return;
MCDwarfLineTableParams Params;
const uint8_t Encoding0[] = {13}; verifyEncoding(Params, -5, 0, Encoding0);
const uint8_t Encoding1[] = {26}; verifyEncoding(Params, 8, 0, Encoding1);
const uint8_t Encoding2[] = {146}; verifyEncoding(Params, 2, 9, Encoding2);
const uint8_t Encoding3[] = {251}; verifyEncoding(Params, -5, 17, Encoding3);
const uint8_t Encoding4[] = {255}; verifyEncoding(Params, -1, 17, Encoding4);
const uint8_t Encoding5[] = {dwarf::DW_LNS_advance_line, 9,
158}; verifyEncoding(Params, 9, 10, Encoding5);
const uint8_t Encoding6[] = {dwarf::DW_LNS_const_add_pc, 62}; verifyEncoding(Params, 2, 20, Encoding6);
const uint8_t Encoding7[] = {dwarf::DW_LNS_advance_pc, 100,
20}; verifyEncoding(Params, 2, 100, Encoding7);
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 (!getContext())
return;
MCDwarfLineTableParams Params;
Params.DWARF2LineOpcodeBase = 13;
Params.DWARF2LineBase = -3;
Params.DWARF2LineRange = 12;
const uint8_t Encoding0[] = {13}; verifyEncoding(Params, -3, 0, Encoding0);
const uint8_t Encoding1[] = {24}; verifyEncoding(Params, 8, 0, Encoding1);
const uint8_t Encoding2[] = {126}; verifyEncoding(Params, 2, 9, Encoding2);
const uint8_t Encoding3[] = {253}; verifyEncoding(Params, -3, 20, Encoding3);
const uint8_t Encoding4[] = {255}; verifyEncoding(Params, -1, 20, Encoding4);
const uint8_t Encoding5[] = {dwarf::DW_LNS_advance_line, 9,
136}; verifyEncoding(Params, 9, 10, Encoding5);
const uint8_t Encoding6[] = {dwarf::DW_LNS_const_add_pc, 138}; verifyEncoding(Params, 2, 30, Encoding6);
const uint8_t Encoding7[] = {dwarf::DW_LNS_advance_pc, 100,
18}; verifyEncoding(Params, 2, 100, Encoding7);
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 (!getContext())
return;
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);
}