180 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- 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);
 | |
| }
 |