1212793Sdim//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===// 2212793Sdim// 3212793Sdim// The LLVM Compiler Infrastructure 4212793Sdim// 5212793Sdim// This file is distributed under the University of Illinois Open Source 6212793Sdim// License. See LICENSE.TXT for details. 7212793Sdim// 8212793Sdim//===----------------------------------------------------------------------===// 9212793Sdim 10226633Sdim#include "llvm/MC/MCDwarf.h" 11249423Sdim#include "llvm/ADT/Hashing.h" 12249423Sdim#include "llvm/ADT/SmallString.h" 13249423Sdim#include "llvm/ADT/Twine.h" 14249423Sdim#include "llvm/Config/config.h" 15218893Sdim#include "llvm/MC/MCAsmInfo.h" 16226633Sdim#include "llvm/MC/MCContext.h" 17249423Sdim#include "llvm/MC/MCExpr.h" 18226633Sdim#include "llvm/MC/MCObjectFileInfo.h" 19226633Sdim#include "llvm/MC/MCObjectWriter.h" 20226633Sdim#include "llvm/MC/MCRegisterInfo.h" 21218893Sdim#include "llvm/MC/MCStreamer.h" 22218893Sdim#include "llvm/MC/MCSymbol.h" 23212793Sdim#include "llvm/Support/Debug.h" 24218893Sdim#include "llvm/Support/ErrorHandling.h" 25239462Sdim#include "llvm/Support/LEB128.h" 26234353Sdim#include "llvm/Support/Path.h" 27234353Sdim#include "llvm/Support/SourceMgr.h" 28249423Sdim#include "llvm/Support/raw_ostream.h" 29212793Sdimusing namespace llvm; 30212793Sdim 31218893Sdim// Given a special op, return the address skip amount (in units of 32218893Sdim// DWARF2_LINE_MIN_INSN_LENGTH. 33218893Sdim#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) 34218893Sdim 35218893Sdim// The maximum address skip amount that can be encoded with a special op. 36224145Sdim#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) 37218893Sdim 38218893Sdim// First special line opcode - leave room for the standard opcodes. 39218893Sdim// Note: If you want to change this, you'll have to update the 40239462Sdim// "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit(). 41224145Sdim#define DWARF2_LINE_OPCODE_BASE 13 42218893Sdim 43218893Sdim// Minimum line offset in a special line info. opcode. This value 44218893Sdim// was chosen to give a reasonable range of values. 45224145Sdim#define DWARF2_LINE_BASE -5 46218893Sdim 47218893Sdim// Range of line offsets in a special line info. opcode. 48224145Sdim#define DWARF2_LINE_RANGE 14 49218893Sdim 50218893Sdim// Define the architecture-dependent minimum instruction length (in bytes). 51218893Sdim// This value should be rather too small than too big. 52224145Sdim#define DWARF2_LINE_MIN_INSN_LENGTH 1 53218893Sdim 54218893Sdim// Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting, 55218893Sdim// this routine is a nop and will be optimized away. 56224145Sdimstatic inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) { 57218893Sdim if (DWARF2_LINE_MIN_INSN_LENGTH == 1) 58218893Sdim return AddrDelta; 59218893Sdim if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) { 60218893Sdim // TODO: report this error, but really only once. 61218893Sdim ; 62218893Sdim } 63218893Sdim return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH; 64218893Sdim} 65218893Sdim 66218893Sdim// 67218893Sdim// This is called when an instruction is assembled into the specified section 68218893Sdim// and if there is information from the last .loc directive that has yet to have 69218893Sdim// a line entry made for it is made. 70218893Sdim// 71218893Sdimvoid MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) { 72218893Sdim if (!MCOS->getContext().getDwarfLocSeen()) 73218893Sdim return; 74218893Sdim 75218893Sdim // Create a symbol at in the current section for use in the line entry. 76218893Sdim MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol(); 77218893Sdim // Set the value of the symbol to use for the MCLineEntry. 78218893Sdim MCOS->EmitLabel(LineSym); 79218893Sdim 80218893Sdim // Get the current .loc info saved in the context. 81218893Sdim const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc(); 82218893Sdim 83218893Sdim // Create a (local) line entry with the symbol and the current .loc info. 84218893Sdim MCLineEntry LineEntry(LineSym, DwarfLoc); 85218893Sdim 86218893Sdim // clear DwarfLocSeen saying the current .loc info is now used. 87218893Sdim MCOS->getContext().ClearDwarfLocSeen(); 88218893Sdim 89218893Sdim // Get the MCLineSection for this section, if one does not exist for this 90218893Sdim // section create it. 91218893Sdim const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = 92218893Sdim MCOS->getContext().getMCLineSections(); 93218893Sdim MCLineSection *LineSection = MCLineSections.lookup(Section); 94218893Sdim if (!LineSection) { 95218893Sdim // Create a new MCLineSection. This will be deleted after the dwarf line 96218893Sdim // table is created using it by iterating through the MCLineSections 97218893Sdim // DenseMap. 98218893Sdim LineSection = new MCLineSection; 99218893Sdim // Save a pointer to the new LineSection into the MCLineSections DenseMap. 100218893Sdim MCOS->getContext().addMCLineSection(Section, LineSection); 101218893Sdim } 102218893Sdim 103218893Sdim // Add the line entry to this section's entries. 104249423Sdim LineSection->addLineEntry(LineEntry, 105249423Sdim MCOS->getContext().getDwarfCompileUnitID()); 106218893Sdim} 107218893Sdim 108218893Sdim// 109218893Sdim// This helper routine returns an expression of End - Start + IntVal . 110239462Sdim// 111218893Sdimstatic inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, 112218893Sdim const MCSymbol &Start, 113218893Sdim const MCSymbol &End, 114218893Sdim int IntVal) { 115218893Sdim MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 116218893Sdim const MCExpr *Res = 117218893Sdim MCSymbolRefExpr::Create(&End, Variant, MCOS.getContext()); 118218893Sdim const MCExpr *RHS = 119218893Sdim MCSymbolRefExpr::Create(&Start, Variant, MCOS.getContext()); 120218893Sdim const MCExpr *Res1 = 121218893Sdim MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext()); 122218893Sdim const MCExpr *Res2 = 123218893Sdim MCConstantExpr::Create(IntVal, MCOS.getContext()); 124218893Sdim const MCExpr *Res3 = 125218893Sdim MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext()); 126218893Sdim return Res3; 127218893Sdim} 128218893Sdim 129218893Sdim// 130218893Sdim// This emits the Dwarf line table for the specified section from the entries 131218893Sdim// in the LineSection. 132218893Sdim// 133218893Sdimstatic inline void EmitDwarfLineTable(MCStreamer *MCOS, 134218893Sdim const MCSection *Section, 135249423Sdim const MCLineSection *LineSection, 136249423Sdim unsigned CUID) { 137249423Sdim // This LineSection does not contain any LineEntry for the given Compile Unit. 138249423Sdim if (!LineSection->containEntriesForID(CUID)) 139249423Sdim return; 140249423Sdim 141218893Sdim unsigned FileNum = 1; 142218893Sdim unsigned LastLine = 1; 143218893Sdim unsigned Column = 0; 144218893Sdim unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 145218893Sdim unsigned Isa = 0; 146218893Sdim MCSymbol *LastLabel = NULL; 147218893Sdim 148218893Sdim // Loop through each MCLineEntry and encode the dwarf line number table. 149218893Sdim for (MCLineSection::const_iterator 150249423Sdim it = LineSection->getMCLineEntries(CUID).begin(), 151249423Sdim ie = LineSection->getMCLineEntries(CUID).end(); it != ie; ++it) { 152218893Sdim 153218893Sdim if (FileNum != it->getFileNum()) { 154218893Sdim FileNum = it->getFileNum(); 155218893Sdim MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1); 156218893Sdim MCOS->EmitULEB128IntValue(FileNum); 157218893Sdim } 158218893Sdim if (Column != it->getColumn()) { 159218893Sdim Column = it->getColumn(); 160218893Sdim MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); 161218893Sdim MCOS->EmitULEB128IntValue(Column); 162218893Sdim } 163218893Sdim if (Isa != it->getIsa()) { 164218893Sdim Isa = it->getIsa(); 165218893Sdim MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); 166218893Sdim MCOS->EmitULEB128IntValue(Isa); 167218893Sdim } 168218893Sdim if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 169218893Sdim Flags = it->getFlags(); 170218893Sdim MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); 171218893Sdim } 172218893Sdim if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK) 173218893Sdim MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); 174218893Sdim if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END) 175218893Sdim MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); 176218893Sdim if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 177218893Sdim MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); 178218893Sdim 179218893Sdim int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine; 180218893Sdim MCSymbol *Label = it->getLabel(); 181218893Sdim 182218893Sdim // At this point we want to emit/create the sequence to encode the delta in 183218893Sdim // line numbers and the increment of the address from the previous Label 184218893Sdim // and the current Label. 185224145Sdim const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo(); 186224145Sdim MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 187224145Sdim asmInfo.getPointerSize()); 188218893Sdim 189218893Sdim LastLine = it->getLine(); 190218893Sdim LastLabel = Label; 191218893Sdim } 192218893Sdim 193218893Sdim // Emit a DW_LNE_end_sequence for the end of the section. 194218893Sdim // Using the pointer Section create a temporary label at the end of the 195218893Sdim // section and use that and the LastLabel to compute the address delta 196218893Sdim // and use INT64_MAX as the line delta which is the signal that this is 197218893Sdim // actually a DW_LNE_end_sequence. 198218893Sdim 199218893Sdim // Switch to the section to be able to create a symbol at its end. 200251662Sdim // TODO: keep track of the last subsection so that this symbol appears in the 201251662Sdim // correct place. 202218893Sdim MCOS->SwitchSection(Section); 203218893Sdim 204218893Sdim MCContext &context = MCOS->getContext(); 205218893Sdim // Create a symbol at the end of the section. 206218893Sdim MCSymbol *SectionEnd = context.CreateTempSymbol(); 207218893Sdim // Set the value of the symbol, as we are at the end of the section. 208218893Sdim MCOS->EmitLabel(SectionEnd); 209218893Sdim 210239462Sdim // Switch back the dwarf line section. 211226633Sdim MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); 212218893Sdim 213224145Sdim const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo(); 214224145Sdim MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, 215224145Sdim asmInfo.getPointerSize()); 216218893Sdim} 217218893Sdim 218218893Sdim// 219218893Sdim// This emits the Dwarf file and the line tables. 220218893Sdim// 221234353Sdimconst MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) { 222218893Sdim MCContext &context = MCOS->getContext(); 223218893Sdim // Switch to the section where the table will be emitted into. 224226633Sdim MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); 225218893Sdim 226249423Sdim const DenseMap<unsigned, MCSymbol *> &MCLineTableSymbols = 227249423Sdim MCOS->getContext().getMCLineTableSymbols(); 228249423Sdim // CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does 229249423Sdim // not exist, CUID will be 0 and MCLineTableSymbols will be empty. 230249423Sdim // Handle Compile Unit 0, the line table start symbol is the section symbol. 231249423Sdim const MCSymbol *LineStartSym = EmitCU(MCOS, 0); 232249423Sdim // Handle the rest of the Compile Units. 233249423Sdim for (unsigned Is = 1, Ie = MCLineTableSymbols.size(); Is < Ie; Is++) 234249423Sdim EmitCU(MCOS, Is); 235249423Sdim 236249423Sdim // Now delete the MCLineSections that were created in MCLineEntry::Make() 237249423Sdim // and used to emit the line table. 238249423Sdim const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = 239249423Sdim MCOS->getContext().getMCLineSections(); 240249423Sdim for (DenseMap<const MCSection *, MCLineSection *>::const_iterator it = 241249423Sdim MCLineSections.begin(), ie = MCLineSections.end(); it != ie; 242249423Sdim ++it) 243249423Sdim delete it->second; 244249423Sdim 245249423Sdim return LineStartSym; 246249423Sdim} 247249423Sdim 248249423Sdimconst MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { 249249423Sdim MCContext &context = MCOS->getContext(); 250249423Sdim 251249423Sdim // Create a symbol at the beginning of the line table. 252249423Sdim MCSymbol *LineStartSym = MCOS->getContext().getMCLineTableSymbol(CUID); 253249423Sdim if (!LineStartSym) 254249423Sdim LineStartSym = context.CreateTempSymbol(); 255249423Sdim // Set the value of the symbol, as we are at the start of the line table. 256218893Sdim MCOS->EmitLabel(LineStartSym); 257218893Sdim 258218893Sdim // Create a symbol for the end of the section (to be set when we get there). 259218893Sdim MCSymbol *LineEndSym = context.CreateTempSymbol(); 260218893Sdim 261218893Sdim // The first 4 bytes is the total length of the information for this 262218893Sdim // compilation unit (not including these 4 bytes for the length). 263218893Sdim MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym,4), 264218893Sdim 4); 265218893Sdim 266218893Sdim // Next 2 bytes is the Version, which is Dwarf 2. 267218893Sdim MCOS->EmitIntValue(2, 2); 268218893Sdim 269218893Sdim // Create a symbol for the end of the prologue (to be set when we get there). 270218893Sdim MCSymbol *ProEndSym = context.CreateTempSymbol(); // Lprologue_end 271218893Sdim 272218893Sdim // Length of the prologue, is the next 4 bytes. Which is the start of the 273218893Sdim // section to the end of the prologue. Not including the 4 bytes for the 274218893Sdim // total length, the 2 bytes for the version, and these 4 bytes for the 275218893Sdim // length of the prologue. 276218893Sdim MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, 277249423Sdim (4 + 2 + 4)), 4, 0); 278218893Sdim 279218893Sdim // Parameters of the state machine, are next. 280218893Sdim MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); 281218893Sdim MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); 282218893Sdim MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); 283218893Sdim MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); 284218893Sdim MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1); 285218893Sdim 286218893Sdim // Standard opcode lengths 287218893Sdim MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy 288218893Sdim MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc 289218893Sdim MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line 290218893Sdim MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file 291218893Sdim MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column 292218893Sdim MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt 293218893Sdim MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block 294218893Sdim MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc 295218893Sdim MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc 296218893Sdim MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end 297218893Sdim MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin 298218893Sdim MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa 299218893Sdim 300218893Sdim // Put out the directory and file tables. 301218893Sdim 302218893Sdim // First the directory table. 303249423Sdim const SmallVectorImpl<StringRef> &MCDwarfDirs = 304249423Sdim context.getMCDwarfDirs(CUID); 305218893Sdim for (unsigned i = 0; i < MCDwarfDirs.size(); i++) { 306249423Sdim MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName 307249423Sdim MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string 308218893Sdim } 309218893Sdim MCOS->EmitIntValue(0, 1); // Terminate the directory list 310218893Sdim 311218893Sdim // Second the file table. 312249423Sdim const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = 313249423Sdim MCOS->getContext().getMCDwarfFiles(CUID); 314218893Sdim for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { 315249423Sdim MCOS->EmitBytes(MCDwarfFiles[i]->getName()); // FileName 316249423Sdim MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string 317218893Sdim // the Directory num 318218893Sdim MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex()); 319218893Sdim MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0) 320218893Sdim MCOS->EmitIntValue(0, 1); // filesize (always 0) 321218893Sdim } 322218893Sdim MCOS->EmitIntValue(0, 1); // Terminate the file list 323218893Sdim 324218893Sdim // This is the end of the prologue, so set the value of the symbol at the 325218893Sdim // end of the prologue (that was used in a previous expression). 326218893Sdim MCOS->EmitLabel(ProEndSym); 327218893Sdim 328218893Sdim // Put out the line tables. 329218893Sdim const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = 330218893Sdim MCOS->getContext().getMCLineSections(); 331218893Sdim const std::vector<const MCSection *> &MCLineSectionOrder = 332218893Sdim MCOS->getContext().getMCLineSectionOrder(); 333218893Sdim for (std::vector<const MCSection*>::const_iterator it = 334224145Sdim MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie; 335218893Sdim ++it) { 336218893Sdim const MCSection *Sec = *it; 337218893Sdim const MCLineSection *Line = MCLineSections.lookup(Sec); 338249423Sdim EmitDwarfLineTable(MCOS, Sec, Line, CUID); 339218893Sdim } 340218893Sdim 341218893Sdim if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines() 342218893Sdim && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) { 343218893Sdim // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures 344239462Sdim // it requires: 345218893Sdim // total_length >= prologue_length + 10 346218893Sdim // We are 4 bytes short, since we have total_length = 51 and 347218893Sdim // prologue_length = 45 348218893Sdim 349218893Sdim // The regular end_sequence should be sufficient. 350218893Sdim MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0); 351218893Sdim } 352218893Sdim 353218893Sdim // This is the end of the section, so set the value of the symbol at the end 354218893Sdim // of this section (that was used in a previous expression). 355218893Sdim MCOS->EmitLabel(LineEndSym); 356234353Sdim 357234353Sdim return LineStartSym; 358218893Sdim} 359218893Sdim 360218893Sdim/// Utility function to write the encoding to an object writer. 361218893Sdimvoid MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta, 362218893Sdim uint64_t AddrDelta) { 363218893Sdim SmallString<256> Tmp; 364218893Sdim raw_svector_ostream OS(Tmp); 365218893Sdim MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); 366218893Sdim OW->WriteBytes(OS.str()); 367218893Sdim} 368218893Sdim 369218893Sdim/// Utility function to emit the encoding to a streamer. 370218893Sdimvoid MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, 371218893Sdim uint64_t AddrDelta) { 372218893Sdim SmallString<256> Tmp; 373218893Sdim raw_svector_ostream OS(Tmp); 374218893Sdim MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); 375249423Sdim MCOS->EmitBytes(OS.str()); 376218893Sdim} 377218893Sdim 378218893Sdim/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. 379218893Sdimvoid MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta, 380218893Sdim raw_ostream &OS) { 381218893Sdim uint64_t Temp, Opcode; 382218893Sdim bool NeedCopy = false; 383218893Sdim 384218893Sdim // Scale the address delta by the minimum instruction length. 385218893Sdim AddrDelta = ScaleAddrDelta(AddrDelta); 386218893Sdim 387218893Sdim // A LineDelta of INT64_MAX is a signal that this is actually a 388239462Sdim // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the 389218893Sdim // end_sequence to emit the matrix entry. 390218893Sdim if (LineDelta == INT64_MAX) { 391218893Sdim if (AddrDelta == MAX_SPECIAL_ADDR_DELTA) 392218893Sdim OS << char(dwarf::DW_LNS_const_add_pc); 393218893Sdim else { 394218893Sdim OS << char(dwarf::DW_LNS_advance_pc); 395239462Sdim encodeULEB128(AddrDelta, OS); 396218893Sdim } 397218893Sdim OS << char(dwarf::DW_LNS_extended_op); 398218893Sdim OS << char(1); 399218893Sdim OS << char(dwarf::DW_LNE_end_sequence); 400218893Sdim return; 401218893Sdim } 402218893Sdim 403218893Sdim // Bias the line delta by the base. 404218893Sdim Temp = LineDelta - DWARF2_LINE_BASE; 405218893Sdim 406218893Sdim // If the line increment is out of range of a special opcode, we must encode 407218893Sdim // it with DW_LNS_advance_line. 408218893Sdim if (Temp >= DWARF2_LINE_RANGE) { 409218893Sdim OS << char(dwarf::DW_LNS_advance_line); 410239462Sdim encodeSLEB128(LineDelta, OS); 411218893Sdim 412218893Sdim LineDelta = 0; 413218893Sdim Temp = 0 - DWARF2_LINE_BASE; 414218893Sdim NeedCopy = true; 415218893Sdim } 416218893Sdim 417218893Sdim // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode. 418218893Sdim if (LineDelta == 0 && AddrDelta == 0) { 419218893Sdim OS << char(dwarf::DW_LNS_copy); 420218893Sdim return; 421218893Sdim } 422218893Sdim 423218893Sdim // Bias the opcode by the special opcode base. 424218893Sdim Temp += DWARF2_LINE_OPCODE_BASE; 425218893Sdim 426218893Sdim // Avoid overflow when addr_delta is large. 427218893Sdim if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) { 428218893Sdim // Try using a special opcode. 429218893Sdim Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE; 430218893Sdim if (Opcode <= 255) { 431218893Sdim OS << char(Opcode); 432218893Sdim return; 433218893Sdim } 434218893Sdim 435218893Sdim // Try using DW_LNS_const_add_pc followed by special op. 436218893Sdim Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; 437218893Sdim if (Opcode <= 255) { 438218893Sdim OS << char(dwarf::DW_LNS_const_add_pc); 439218893Sdim OS << char(Opcode); 440218893Sdim return; 441218893Sdim } 442218893Sdim } 443218893Sdim 444218893Sdim // Otherwise use DW_LNS_advance_pc. 445218893Sdim OS << char(dwarf::DW_LNS_advance_pc); 446239462Sdim encodeULEB128(AddrDelta, OS); 447218893Sdim 448218893Sdim if (NeedCopy) 449218893Sdim OS << char(dwarf::DW_LNS_copy); 450218893Sdim else 451218893Sdim OS << char(Temp); 452218893Sdim} 453218893Sdim 454212793Sdimvoid MCDwarfFile::print(raw_ostream &OS) const { 455212793Sdim OS << '"' << getName() << '"'; 456212793Sdim} 457212793Sdim 458243830Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 459212793Sdimvoid MCDwarfFile::dump() const { 460212793Sdim print(dbgs()); 461212793Sdim} 462243830Sdim#endif 463218893Sdim 464234353Sdim// Utility function to write a tuple for .debug_abbrev. 465234353Sdimstatic void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) { 466234353Sdim MCOS->EmitULEB128IntValue(Name); 467234353Sdim MCOS->EmitULEB128IntValue(Form); 468234353Sdim} 469234353Sdim 470234353Sdim// When generating dwarf for assembly source files this emits 471234353Sdim// the data for .debug_abbrev section which contains three DIEs. 472234353Sdimstatic void EmitGenDwarfAbbrev(MCStreamer *MCOS) { 473234353Sdim MCContext &context = MCOS->getContext(); 474234353Sdim MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); 475234353Sdim 476234353Sdim // DW_TAG_compile_unit DIE abbrev (1). 477234353Sdim MCOS->EmitULEB128IntValue(1); 478234353Sdim MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); 479234353Sdim MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); 480234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); 481234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); 482234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); 483234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); 484234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); 485234353Sdim StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); 486234353Sdim if (!DwarfDebugFlags.empty()) 487234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string); 488234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string); 489234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2); 490234353Sdim EmitAbbrev(MCOS, 0, 0); 491234353Sdim 492234353Sdim // DW_TAG_label DIE abbrev (2). 493234353Sdim MCOS->EmitULEB128IntValue(2); 494234353Sdim MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label); 495234353Sdim MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); 496234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); 497234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4); 498234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4); 499234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); 500234353Sdim EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag); 501234353Sdim EmitAbbrev(MCOS, 0, 0); 502234353Sdim 503234353Sdim // DW_TAG_unspecified_parameters DIE abbrev (3). 504234353Sdim MCOS->EmitULEB128IntValue(3); 505234353Sdim MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters); 506234353Sdim MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1); 507234353Sdim EmitAbbrev(MCOS, 0, 0); 508234353Sdim 509234353Sdim // Terminate the abbreviations for this compilation unit. 510234353Sdim MCOS->EmitIntValue(0, 1); 511234353Sdim} 512234353Sdim 513234353Sdim// When generating dwarf for assembly source files this emits the data for 514234353Sdim// .debug_aranges section. Which contains a header and a table of pairs of 515234353Sdim// PointerSize'ed values for the address and size of section(s) with line table 516234353Sdim// entries (just the default .text in our case) and a terminating pair of zeros. 517249423Sdimstatic void EmitGenDwarfAranges(MCStreamer *MCOS, 518249423Sdim const MCSymbol *InfoSectionSymbol) { 519234353Sdim MCContext &context = MCOS->getContext(); 520234353Sdim 521234353Sdim // Create a symbol at the end of the section that we are creating the dwarf 522234353Sdim // debugging info to use later in here as part of the expression to calculate 523234353Sdim // the size of the section for the table. 524234353Sdim MCOS->SwitchSection(context.getGenDwarfSection()); 525234353Sdim MCSymbol *SectionEndSym = context.CreateTempSymbol(); 526234353Sdim MCOS->EmitLabel(SectionEndSym); 527234353Sdim context.setGenDwarfSectionEndSym(SectionEndSym); 528234353Sdim 529234353Sdim MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); 530234353Sdim 531234353Sdim // This will be the length of the .debug_aranges section, first account for 532234353Sdim // the size of each item in the header (see below where we emit these items). 533234353Sdim int Length = 4 + 2 + 4 + 1 + 1; 534234353Sdim 535234353Sdim // Figure the padding after the header before the table of address and size 536234353Sdim // pairs who's values are PointerSize'ed. 537234353Sdim const MCAsmInfo &asmInfo = context.getAsmInfo(); 538234353Sdim int AddrSize = asmInfo.getPointerSize(); 539234353Sdim int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1)); 540234353Sdim if (Pad == 2 * AddrSize) 541234353Sdim Pad = 0; 542234353Sdim Length += Pad; 543234353Sdim 544234353Sdim // Add the size of the pair of PointerSize'ed values for the address and size 545234353Sdim // of the one default .text section we have in the table. 546234353Sdim Length += 2 * AddrSize; 547234353Sdim // And the pair of terminating zeros. 548234353Sdim Length += 2 * AddrSize; 549234353Sdim 550234353Sdim 551234353Sdim // Emit the header for this section. 552234353Sdim // The 4 byte length not including the 4 byte value for the length. 553234353Sdim MCOS->EmitIntValue(Length - 4, 4); 554234353Sdim // The 2 byte version, which is 2. 555234353Sdim MCOS->EmitIntValue(2, 2); 556234353Sdim // The 4 byte offset to the compile unit in the .debug_info from the start 557249423Sdim // of the .debug_info. 558249423Sdim if (InfoSectionSymbol) 559249423Sdim MCOS->EmitSymbolValue(InfoSectionSymbol, 4); 560249423Sdim else 561249423Sdim MCOS->EmitIntValue(0, 4); 562234353Sdim // The 1 byte size of an address. 563234353Sdim MCOS->EmitIntValue(AddrSize, 1); 564234353Sdim // The 1 byte size of a segment descriptor, we use a value of zero. 565234353Sdim MCOS->EmitIntValue(0, 1); 566234353Sdim // Align the header with the padding if needed, before we put out the table. 567234353Sdim for(int i = 0; i < Pad; i++) 568234353Sdim MCOS->EmitIntValue(0, 1); 569234353Sdim 570234353Sdim // Now emit the table of pairs of PointerSize'ed values for the section(s) 571234353Sdim // address and size, in our case just the one default .text section. 572234353Sdim const MCExpr *Addr = MCSymbolRefExpr::Create( 573234353Sdim context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); 574234353Sdim const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, 575234353Sdim *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0); 576234353Sdim MCOS->EmitAbsValue(Addr, AddrSize); 577234353Sdim MCOS->EmitAbsValue(Size, AddrSize); 578234353Sdim 579234353Sdim // And finally the pair of terminating zeros. 580234353Sdim MCOS->EmitIntValue(0, AddrSize); 581234353Sdim MCOS->EmitIntValue(0, AddrSize); 582234353Sdim} 583234353Sdim 584234353Sdim// When generating dwarf for assembly source files this emits the data for 585234353Sdim// .debug_info section which contains three parts. The header, the compile_unit 586234353Sdim// DIE and a list of label DIEs. 587234353Sdimstatic void EmitGenDwarfInfo(MCStreamer *MCOS, 588234353Sdim const MCSymbol *AbbrevSectionSymbol, 589234353Sdim const MCSymbol *LineSectionSymbol) { 590234353Sdim MCContext &context = MCOS->getContext(); 591234353Sdim 592239462Sdim MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); 593234353Sdim 594234353Sdim // Create a symbol at the start and end of this section used in here for the 595234353Sdim // expression to calculate the length in the header. 596234353Sdim MCSymbol *InfoStart = context.CreateTempSymbol(); 597234353Sdim MCOS->EmitLabel(InfoStart); 598234353Sdim MCSymbol *InfoEnd = context.CreateTempSymbol(); 599234353Sdim 600234353Sdim // First part: the header. 601234353Sdim 602234353Sdim // The 4 byte total length of the information for this compilation unit, not 603234353Sdim // including these 4 bytes. 604234353Sdim const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); 605234353Sdim MCOS->EmitAbsValue(Length, 4); 606234353Sdim 607234353Sdim // The 2 byte DWARF version, which is 2. 608234353Sdim MCOS->EmitIntValue(2, 2); 609234353Sdim 610234353Sdim // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev, 611234353Sdim // it is at the start of that section so this is zero. 612234353Sdim if (AbbrevSectionSymbol) { 613234353Sdim MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4); 614234353Sdim } else { 615234353Sdim MCOS->EmitIntValue(0, 4); 616234353Sdim } 617234353Sdim 618234353Sdim const MCAsmInfo &asmInfo = context.getAsmInfo(); 619234353Sdim int AddrSize = asmInfo.getPointerSize(); 620234353Sdim // The 1 byte size of an address. 621234353Sdim MCOS->EmitIntValue(AddrSize, 1); 622234353Sdim 623234353Sdim // Second part: the compile_unit DIE. 624234353Sdim 625234353Sdim // The DW_TAG_compile_unit DIE abbrev (1). 626234353Sdim MCOS->EmitULEB128IntValue(1); 627234353Sdim 628234353Sdim // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section, 629234353Sdim // which is at the start of that section so this is zero. 630234353Sdim if (LineSectionSymbol) { 631234353Sdim MCOS->EmitSymbolValue(LineSectionSymbol, 4); 632234353Sdim } else { 633234353Sdim MCOS->EmitIntValue(0, 4); 634234353Sdim } 635234353Sdim 636234353Sdim // AT_low_pc, the first address of the default .text section. 637234353Sdim const MCExpr *Start = MCSymbolRefExpr::Create( 638234353Sdim context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); 639234353Sdim MCOS->EmitAbsValue(Start, AddrSize); 640234353Sdim 641234353Sdim // AT_high_pc, the last address of the default .text section. 642234353Sdim const MCExpr *End = MCSymbolRefExpr::Create( 643234353Sdim context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context); 644234353Sdim MCOS->EmitAbsValue(End, AddrSize); 645234353Sdim 646234353Sdim // AT_name, the name of the source file. Reconstruct from the first directory 647234353Sdim // and file table entries. 648249423Sdim const SmallVectorImpl<StringRef> &MCDwarfDirs = 649234353Sdim context.getMCDwarfDirs(); 650234353Sdim if (MCDwarfDirs.size() > 0) { 651249423Sdim MCOS->EmitBytes(MCDwarfDirs[0]); 652249423Sdim MCOS->EmitBytes("/"); 653234353Sdim } 654249423Sdim const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = 655234353Sdim MCOS->getContext().getMCDwarfFiles(); 656249423Sdim MCOS->EmitBytes(MCDwarfFiles[1]->getName()); 657234353Sdim MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 658234353Sdim 659234353Sdim // AT_comp_dir, the working directory the assembly was done in. 660249423Sdim MCOS->EmitBytes(context.getCompilationDir()); 661234353Sdim MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 662234353Sdim 663234353Sdim // AT_APPLE_flags, the command line arguments of the assembler tool. 664234353Sdim StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); 665234353Sdim if (!DwarfDebugFlags.empty()){ 666249423Sdim MCOS->EmitBytes(DwarfDebugFlags); 667234353Sdim MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 668234353Sdim } 669234353Sdim 670234353Sdim // AT_producer, the version of the assembler tool. 671249423Sdim StringRef DwarfDebugProducer = context.getDwarfDebugProducer(); 672249423Sdim if (!DwarfDebugProducer.empty()){ 673249423Sdim MCOS->EmitBytes(DwarfDebugProducer); 674249423Sdim } 675249423Sdim else { 676249423Sdim MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM ")); 677249423Sdim MCOS->EmitBytes(StringRef(PACKAGE_VERSION)); 678249423Sdim MCOS->EmitBytes(StringRef(")")); 679249423Sdim } 680234353Sdim MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 681234353Sdim 682234353Sdim // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2 683234353Sdim // draft has no standard code for assembler. 684234353Sdim MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2); 685234353Sdim 686234353Sdim // Third part: the list of label DIEs. 687234353Sdim 688234353Sdim // Loop on saved info for dwarf labels and create the DIEs for them. 689234353Sdim const std::vector<const MCGenDwarfLabelEntry *> &Entries = 690234353Sdim MCOS->getContext().getMCGenDwarfLabelEntries(); 691234353Sdim for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it = 692234353Sdim Entries.begin(), ie = Entries.end(); it != ie; 693234353Sdim ++it) { 694234353Sdim const MCGenDwarfLabelEntry *Entry = *it; 695234353Sdim 696234353Sdim // The DW_TAG_label DIE abbrev (2). 697234353Sdim MCOS->EmitULEB128IntValue(2); 698234353Sdim 699234353Sdim // AT_name, of the label without any leading underbar. 700249423Sdim MCOS->EmitBytes(Entry->getName()); 701234353Sdim MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 702234353Sdim 703234353Sdim // AT_decl_file, index into the file table. 704234353Sdim MCOS->EmitIntValue(Entry->getFileNumber(), 4); 705234353Sdim 706234353Sdim // AT_decl_line, source line number. 707234353Sdim MCOS->EmitIntValue(Entry->getLineNumber(), 4); 708234353Sdim 709234353Sdim // AT_low_pc, start address of the label. 710234353Sdim const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry->getLabel(), 711234353Sdim MCSymbolRefExpr::VK_None, context); 712234353Sdim MCOS->EmitAbsValue(AT_low_pc, AddrSize); 713234353Sdim 714234353Sdim // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype. 715234353Sdim MCOS->EmitIntValue(0, 1); 716234353Sdim 717234353Sdim // The DW_TAG_unspecified_parameters DIE abbrev (3). 718234353Sdim MCOS->EmitULEB128IntValue(3); 719234353Sdim 720234353Sdim // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's. 721234353Sdim MCOS->EmitIntValue(0, 1); 722234353Sdim } 723234353Sdim // Deallocate the MCGenDwarfLabelEntry classes that saved away the info 724234353Sdim // for the dwarf labels. 725234353Sdim for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it = 726234353Sdim Entries.begin(), ie = Entries.end(); it != ie; 727234353Sdim ++it) { 728234353Sdim const MCGenDwarfLabelEntry *Entry = *it; 729234353Sdim delete Entry; 730234353Sdim } 731234353Sdim 732234353Sdim // Add the NULL DIE terminating the Compile Unit DIE's. 733234353Sdim MCOS->EmitIntValue(0, 1); 734234353Sdim 735234353Sdim // Now set the value of the symbol at the end of the info section. 736234353Sdim MCOS->EmitLabel(InfoEnd); 737234353Sdim} 738234353Sdim 739234353Sdim// 740234353Sdim// When generating dwarf for assembly source files this emits the Dwarf 741234353Sdim// sections. 742234353Sdim// 743234353Sdimvoid MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) { 744234353Sdim // Create the dwarf sections in this order (.debug_line already created). 745234353Sdim MCContext &context = MCOS->getContext(); 746234353Sdim const MCAsmInfo &AsmInfo = context.getAsmInfo(); 747249423Sdim bool CreateDwarfSectionSymbols = 748249423Sdim AsmInfo.doesDwarfUseRelocationsAcrossSections(); 749249423Sdim if (!CreateDwarfSectionSymbols) 750249423Sdim LineSectionSymbol = NULL; 751249423Sdim MCSymbol *AbbrevSectionSymbol = NULL; 752249423Sdim MCSymbol *InfoSectionSymbol = NULL; 753234353Sdim MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); 754249423Sdim if (CreateDwarfSectionSymbols) { 755249423Sdim InfoSectionSymbol = context.CreateTempSymbol(); 756249423Sdim MCOS->EmitLabel(InfoSectionSymbol); 757249423Sdim } 758234353Sdim MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); 759249423Sdim if (CreateDwarfSectionSymbols) { 760234353Sdim AbbrevSectionSymbol = context.CreateTempSymbol(); 761234353Sdim MCOS->EmitLabel(AbbrevSectionSymbol); 762234353Sdim } 763234353Sdim MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); 764234353Sdim 765234353Sdim // If there are no line table entries then do not emit any section contents. 766234353Sdim if (context.getMCLineSections().empty()) 767234353Sdim return; 768234353Sdim 769234353Sdim // Output the data for .debug_aranges section. 770249423Sdim EmitGenDwarfAranges(MCOS, InfoSectionSymbol); 771234353Sdim 772234353Sdim // Output the data for .debug_abbrev section. 773234353Sdim EmitGenDwarfAbbrev(MCOS); 774234353Sdim 775234353Sdim // Output the data for .debug_info section. 776234353Sdim EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol); 777234353Sdim} 778234353Sdim 779234353Sdim// 780234353Sdim// When generating dwarf for assembly source files this is called when symbol 781234353Sdim// for a label is created. If this symbol is not a temporary and is in the 782234353Sdim// section that dwarf is being generated for, save the needed info to create 783234353Sdim// a dwarf label. 784234353Sdim// 785234353Sdimvoid MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, 786234353Sdim SourceMgr &SrcMgr, SMLoc &Loc) { 787234353Sdim // We won't create dwarf labels for temporary symbols or symbols not in 788234353Sdim // the default text. 789234353Sdim if (Symbol->isTemporary()) 790234353Sdim return; 791234353Sdim MCContext &context = MCOS->getContext(); 792251662Sdim if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) 793234353Sdim return; 794234353Sdim 795234353Sdim // The dwarf label's name does not have the symbol name's leading 796234353Sdim // underbar if any. 797234353Sdim StringRef Name = Symbol->getName(); 798234353Sdim if (Name.startswith("_")) 799234353Sdim Name = Name.substr(1, Name.size()-1); 800234353Sdim 801234353Sdim // Get the dwarf file number to be used for the dwarf label. 802234353Sdim unsigned FileNumber = context.getGenDwarfFileNumber(); 803234353Sdim 804234353Sdim // Finding the line number is the expensive part which is why we just don't 805234353Sdim // pass it in as for some symbols we won't create a dwarf label. 806234353Sdim int CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); 807234353Sdim unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer); 808234353Sdim 809234353Sdim // We create a temporary symbol for use for the AT_high_pc and AT_low_pc 810234353Sdim // values so that they don't have things like an ARM thumb bit from the 811234353Sdim // original symbol. So when used they won't get a low bit set after 812234353Sdim // relocation. 813234353Sdim MCSymbol *Label = context.CreateTempSymbol(); 814234353Sdim MCOS->EmitLabel(Label); 815234353Sdim 816234353Sdim // Create and entry for the info and add it to the other entries. 817239462Sdim MCGenDwarfLabelEntry *Entry = 818234353Sdim new MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label); 819234353Sdim MCOS->getContext().addMCGenDwarfLabelEntry(Entry); 820234353Sdim} 821234353Sdim 822218893Sdimstatic int getDataAlignmentFactor(MCStreamer &streamer) { 823218893Sdim MCContext &context = streamer.getContext(); 824224145Sdim const MCAsmInfo &asmInfo = context.getAsmInfo(); 825249423Sdim int size = asmInfo.getCalleeSaveStackSlotSize(); 826224145Sdim if (asmInfo.isStackGrowthDirectionUp()) 827218893Sdim return size; 828224145Sdim else 829224145Sdim return -size; 830218893Sdim} 831218893Sdim 832221345Sdimstatic unsigned getSizeForEncoding(MCStreamer &streamer, 833221345Sdim unsigned symbolEncoding) { 834221345Sdim MCContext &context = streamer.getContext(); 835221345Sdim unsigned format = symbolEncoding & 0x0f; 836221345Sdim switch (format) { 837234353Sdim default: llvm_unreachable("Unknown Encoding"); 838221345Sdim case dwarf::DW_EH_PE_absptr: 839221345Sdim case dwarf::DW_EH_PE_signed: 840224145Sdim return context.getAsmInfo().getPointerSize(); 841221345Sdim case dwarf::DW_EH_PE_udata2: 842221345Sdim case dwarf::DW_EH_PE_sdata2: 843221345Sdim return 2; 844221345Sdim case dwarf::DW_EH_PE_udata4: 845221345Sdim case dwarf::DW_EH_PE_sdata4: 846221345Sdim return 4; 847221345Sdim case dwarf::DW_EH_PE_udata8: 848221345Sdim case dwarf::DW_EH_PE_sdata8: 849221345Sdim return 8; 850221345Sdim } 851221345Sdim} 852221345Sdim 853221345Sdimstatic void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, 854224145Sdim unsigned symbolEncoding, const char *comment = 0) { 855221345Sdim MCContext &context = streamer.getContext(); 856221345Sdim const MCAsmInfo &asmInfo = context.getAsmInfo(); 857221345Sdim const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol, 858221345Sdim symbolEncoding, 859221345Sdim streamer); 860221345Sdim unsigned size = getSizeForEncoding(streamer, symbolEncoding); 861224145Sdim if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment); 862221345Sdim streamer.EmitAbsValue(v, size); 863221345Sdim} 864221345Sdim 865221345Sdimstatic void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, 866221345Sdim unsigned symbolEncoding) { 867221345Sdim MCContext &context = streamer.getContext(); 868221345Sdim const MCAsmInfo &asmInfo = context.getAsmInfo(); 869221345Sdim const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol, 870221345Sdim symbolEncoding, 871221345Sdim streamer); 872221345Sdim unsigned size = getSizeForEncoding(streamer, symbolEncoding); 873221345Sdim streamer.EmitValue(v, size); 874221345Sdim} 875221345Sdim 876221345Sdimstatic const MachineLocation TranslateMachineLocation( 877226633Sdim const MCRegisterInfo &MRI, 878221345Sdim const MachineLocation &Loc) { 879221345Sdim unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? 880221345Sdim MachineLocation::VirtualFP : 881226633Sdim unsigned(MRI.getDwarfRegNum(Loc.getReg(), true)); 882221345Sdim const MachineLocation &NewLoc = Loc.isReg() ? 883221345Sdim MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); 884221345Sdim return NewLoc; 885221345Sdim} 886221345Sdim 887221345Sdimnamespace { 888221345Sdim class FrameEmitterImpl { 889221345Sdim int CFAOffset; 890221345Sdim int CIENum; 891221345Sdim bool UsingCFI; 892223017Sdim bool IsEH; 893223017Sdim const MCSymbol *SectionStart; 894221345Sdim public: 895226633Sdim FrameEmitterImpl(bool usingCFI, bool isEH) 896226633Sdim : CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH), 897226633Sdim SectionStart(0) {} 898221345Sdim 899226633Sdim void setSectionStart(const MCSymbol *Label) { SectionStart = Label; } 900226633Sdim 901224145Sdim /// EmitCompactUnwind - Emit the unwind information in a compact way. If 902224145Sdim /// we're successful, return 'true'. Otherwise, return 'false' and it will 903224145Sdim /// emit the normal CIE and FDE. 904251662Sdim void EmitCompactUnwind(MCStreamer &streamer, 905224145Sdim const MCDwarfFrameInfo &frame); 906224145Sdim 907221345Sdim const MCSymbol &EmitCIE(MCStreamer &streamer, 908221345Sdim const MCSymbol *personality, 909221345Sdim unsigned personalityEncoding, 910221345Sdim const MCSymbol *lsda, 911234353Sdim bool IsSignalFrame, 912221345Sdim unsigned lsdaEncoding); 913221345Sdim MCSymbol *EmitFDE(MCStreamer &streamer, 914221345Sdim const MCSymbol &cieStart, 915223017Sdim const MCDwarfFrameInfo &frame); 916221345Sdim void EmitCFIInstructions(MCStreamer &streamer, 917221345Sdim const std::vector<MCCFIInstruction> &Instrs, 918221345Sdim MCSymbol *BaseLabel); 919221345Sdim void EmitCFIInstruction(MCStreamer &Streamer, 920221345Sdim const MCCFIInstruction &Instr); 921221345Sdim }; 922224145Sdim 923224145Sdim} // end anonymous namespace 924224145Sdim 925224145Sdimstatic void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding, 926224145Sdim StringRef Prefix) { 927224145Sdim if (Streamer.isVerboseAsm()) { 928234353Sdim const char *EncStr; 929224145Sdim switch (Encoding) { 930234353Sdim default: EncStr = "<unknown encoding>"; break; 931234353Sdim case dwarf::DW_EH_PE_absptr: EncStr = "absptr"; break; 932234353Sdim case dwarf::DW_EH_PE_omit: EncStr = "omit"; break; 933234353Sdim case dwarf::DW_EH_PE_pcrel: EncStr = "pcrel"; break; 934234353Sdim case dwarf::DW_EH_PE_udata4: EncStr = "udata4"; break; 935234353Sdim case dwarf::DW_EH_PE_udata8: EncStr = "udata8"; break; 936234353Sdim case dwarf::DW_EH_PE_sdata4: EncStr = "sdata4"; break; 937234353Sdim case dwarf::DW_EH_PE_sdata8: EncStr = "sdata8"; break; 938234353Sdim case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: 939234353Sdim EncStr = "pcrel udata4"; 940234353Sdim break; 941234353Sdim case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: 942234353Sdim EncStr = "pcrel sdata4"; 943234353Sdim break; 944234353Sdim case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: 945234353Sdim EncStr = "pcrel udata8"; 946234353Sdim break; 947234353Sdim case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: 948234353Sdim EncStr = "screl sdata8"; 949234353Sdim break; 950224145Sdim case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4: 951224145Sdim EncStr = "indirect pcrel udata4"; 952234353Sdim break; 953224145Sdim case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4: 954224145Sdim EncStr = "indirect pcrel sdata4"; 955234353Sdim break; 956224145Sdim case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8: 957224145Sdim EncStr = "indirect pcrel udata8"; 958234353Sdim break; 959224145Sdim case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8: 960224145Sdim EncStr = "indirect pcrel sdata8"; 961234353Sdim break; 962224145Sdim } 963224145Sdim 964224145Sdim Streamer.AddComment(Twine(Prefix) + " = " + EncStr); 965224145Sdim } 966224145Sdim 967224145Sdim Streamer.EmitIntValue(Encoding, 1); 968221345Sdim} 969221345Sdim 970221345Sdimvoid FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, 971221345Sdim const MCCFIInstruction &Instr) { 972218893Sdim int dataAlignmentFactor = getDataAlignmentFactor(Streamer); 973224145Sdim bool VerboseAsm = Streamer.isVerboseAsm(); 974218893Sdim 975218893Sdim switch (Instr.getOperation()) { 976249423Sdim case MCCFIInstruction::OpRegister: { 977249423Sdim unsigned Reg1 = Instr.getRegister(); 978249423Sdim unsigned Reg2 = Instr.getRegister2(); 979249423Sdim if (VerboseAsm) { 980249423Sdim Streamer.AddComment("DW_CFA_register"); 981249423Sdim Streamer.AddComment(Twine("Reg1 ") + Twine(Reg1)); 982249423Sdim Streamer.AddComment(Twine("Reg2 ") + Twine(Reg2)); 983249423Sdim } 984249423Sdim Streamer.EmitIntValue(dwarf::DW_CFA_register, 1); 985249423Sdim Streamer.EmitULEB128IntValue(Reg1); 986249423Sdim Streamer.EmitULEB128IntValue(Reg2); 987249423Sdim return; 988249423Sdim } 989249423Sdim case MCCFIInstruction::OpUndefined: { 990249423Sdim unsigned Reg = Instr.getRegister(); 991249423Sdim if (VerboseAsm) { 992249423Sdim Streamer.AddComment("DW_CFA_undefined"); 993249423Sdim Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 994249423Sdim } 995249423Sdim Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1); 996249423Sdim Streamer.EmitULEB128IntValue(Reg); 997249423Sdim return; 998249423Sdim } 999249423Sdim case MCCFIInstruction::OpAdjustCfaOffset: 1000249423Sdim case MCCFIInstruction::OpDefCfaOffset: { 1001249423Sdim const bool IsRelative = 1002249423Sdim Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset; 1003218893Sdim 1004249423Sdim if (VerboseAsm) 1005249423Sdim Streamer.AddComment("DW_CFA_def_cfa_offset"); 1006249423Sdim Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); 1007218893Sdim 1008249423Sdim if (IsRelative) 1009249423Sdim CFAOffset += Instr.getOffset(); 1010249423Sdim else 1011249423Sdim CFAOffset = -Instr.getOffset(); 1012221345Sdim 1013249423Sdim if (VerboseAsm) 1014249423Sdim Streamer.AddComment(Twine("Offset " + Twine(CFAOffset))); 1015249423Sdim Streamer.EmitULEB128IntValue(CFAOffset); 1016218893Sdim 1017249423Sdim return; 1018249423Sdim } 1019249423Sdim case MCCFIInstruction::OpDefCfa: { 1020249423Sdim if (VerboseAsm) 1021249423Sdim Streamer.AddComment("DW_CFA_def_cfa"); 1022249423Sdim Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); 1023218893Sdim 1024249423Sdim if (VerboseAsm) 1025249423Sdim Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister())); 1026249423Sdim Streamer.EmitULEB128IntValue(Instr.getRegister()); 1027249423Sdim 1028249423Sdim CFAOffset = -Instr.getOffset(); 1029249423Sdim 1030249423Sdim if (VerboseAsm) 1031249423Sdim Streamer.AddComment(Twine("Offset " + Twine(CFAOffset))); 1032249423Sdim Streamer.EmitULEB128IntValue(CFAOffset); 1033249423Sdim 1034249423Sdim return; 1035249423Sdim } 1036249423Sdim 1037249423Sdim case MCCFIInstruction::OpDefCfaRegister: { 1038249423Sdim if (VerboseAsm) 1039249423Sdim Streamer.AddComment("DW_CFA_def_cfa_register"); 1040249423Sdim Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); 1041249423Sdim 1042249423Sdim if (VerboseAsm) 1043249423Sdim Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister())); 1044249423Sdim Streamer.EmitULEB128IntValue(Instr.getRegister()); 1045249423Sdim 1046249423Sdim return; 1047249423Sdim } 1048249423Sdim 1049249423Sdim case MCCFIInstruction::OpOffset: 1050249423Sdim case MCCFIInstruction::OpRelOffset: { 1051249423Sdim const bool IsRelative = 1052249423Sdim Instr.getOperation() == MCCFIInstruction::OpRelOffset; 1053249423Sdim 1054249423Sdim unsigned Reg = Instr.getRegister(); 1055249423Sdim int Offset = Instr.getOffset(); 1056221345Sdim if (IsRelative) 1057221345Sdim Offset -= CFAOffset; 1058221345Sdim Offset = Offset / dataAlignmentFactor; 1059221345Sdim 1060218893Sdim if (Offset < 0) { 1061224145Sdim if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf"); 1062218893Sdim Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); 1063224145Sdim if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 1064218893Sdim Streamer.EmitULEB128IntValue(Reg); 1065224145Sdim if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); 1066218893Sdim Streamer.EmitSLEB128IntValue(Offset); 1067218893Sdim } else if (Reg < 64) { 1068224145Sdim if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") + 1069224145Sdim Twine(Reg) + ")"); 1070218893Sdim Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); 1071224145Sdim if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); 1072221345Sdim Streamer.EmitULEB128IntValue(Offset); 1073218893Sdim } else { 1074224145Sdim if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended"); 1075218893Sdim Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); 1076224145Sdim if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 1077221345Sdim Streamer.EmitULEB128IntValue(Reg); 1078224145Sdim if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); 1079221345Sdim Streamer.EmitULEB128IntValue(Offset); 1080218893Sdim } 1081218893Sdim return; 1082218893Sdim } 1083249423Sdim case MCCFIInstruction::OpRememberState: 1084224145Sdim if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state"); 1085218893Sdim Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); 1086218893Sdim return; 1087249423Sdim case MCCFIInstruction::OpRestoreState: 1088224145Sdim if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state"); 1089218893Sdim Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); 1090218893Sdim return; 1091249423Sdim case MCCFIInstruction::OpSameValue: { 1092249423Sdim unsigned Reg = Instr.getRegister(); 1093224145Sdim if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value"); 1094221345Sdim Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); 1095224145Sdim if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 1096221345Sdim Streamer.EmitULEB128IntValue(Reg); 1097221345Sdim return; 1098218893Sdim } 1099249423Sdim case MCCFIInstruction::OpRestore: { 1100249423Sdim unsigned Reg = Instr.getRegister(); 1101234353Sdim if (VerboseAsm) { 1102234353Sdim Streamer.AddComment("DW_CFA_restore"); 1103234353Sdim Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 1104234353Sdim } 1105234353Sdim Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); 1106234353Sdim return; 1107221345Sdim } 1108249423Sdim case MCCFIInstruction::OpEscape: 1109234353Sdim if (VerboseAsm) Streamer.AddComment("Escape bytes"); 1110249423Sdim Streamer.EmitBytes(Instr.getValues()); 1111234353Sdim return; 1112234353Sdim } 1113218893Sdim llvm_unreachable("Unhandled case in switch"); 1114218893Sdim} 1115218893Sdim 1116218893Sdim/// EmitFrameMoves - Emit frame instructions to describe the layout of the 1117218893Sdim/// frame. 1118221345Sdimvoid FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, 1119221345Sdim const std::vector<MCCFIInstruction> &Instrs, 1120221345Sdim MCSymbol *BaseLabel) { 1121218893Sdim for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { 1122218893Sdim const MCCFIInstruction &Instr = Instrs[i]; 1123218893Sdim MCSymbol *Label = Instr.getLabel(); 1124218893Sdim // Throw out move if the label is invalid. 1125218893Sdim if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. 1126218893Sdim 1127218893Sdim // Advance row if new location. 1128218893Sdim if (BaseLabel && Label) { 1129218893Sdim MCSymbol *ThisSym = Label; 1130218893Sdim if (ThisSym != BaseLabel) { 1131224145Sdim if (streamer.isVerboseAsm()) streamer.AddComment("DW_CFA_advance_loc4"); 1132218893Sdim streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); 1133218893Sdim BaseLabel = ThisSym; 1134218893Sdim } 1135218893Sdim } 1136218893Sdim 1137218893Sdim EmitCFIInstruction(streamer, Instr); 1138218893Sdim } 1139218893Sdim} 1140218893Sdim 1141224145Sdim/// EmitCompactUnwind - Emit the unwind information in a compact way. If we're 1142224145Sdim/// successful, return 'true'. Otherwise, return 'false' and it will emit the 1143224145Sdim/// normal CIE and FDE. 1144251662Sdimvoid FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, 1145224145Sdim const MCDwarfFrameInfo &Frame) { 1146224145Sdim MCContext &Context = Streamer.getContext(); 1147226633Sdim const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); 1148224145Sdim bool VerboseAsm = Streamer.isVerboseAsm(); 1149224145Sdim 1150224145Sdim // range-start range-length compact-unwind-enc personality-func lsda 1151224145Sdim // _foo LfooEnd-_foo 0x00000023 0 0 1152224145Sdim // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab1 1153224145Sdim // 1154224145Sdim // .section __LD,__compact_unwind,regular,debug 1155224145Sdim // 1156224145Sdim // # compact unwind for _foo 1157224145Sdim // .quad _foo 1158224145Sdim // .set L1,LfooEnd-_foo 1159224145Sdim // .long L1 1160224145Sdim // .long 0x01010001 1161224145Sdim // .quad 0 1162224145Sdim // .quad 0 1163224145Sdim // 1164224145Sdim // # compact unwind for _bar 1165224145Sdim // .quad _bar 1166224145Sdim // .set L2,LbarEnd-_bar 1167224145Sdim // .long L2 1168224145Sdim // .long 0x01020011 1169224145Sdim // .quad __gxx_personality 1170224145Sdim // .quad except_tab1 1171224145Sdim 1172226633Sdim uint32_t Encoding = Frame.CompactUnwindEncoding; 1173251662Sdim if (!Encoding) return; 1174251662Sdim bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly()); 1175224145Sdim 1176224145Sdim // The encoding needs to know we have an LSDA. 1177251662Sdim if (!DwarfEHFrameOnly && Frame.Lsda) 1178224145Sdim Encoding |= 0x40000000; 1179224145Sdim 1180224145Sdim // Range Start 1181226633Sdim unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI); 1182224145Sdim unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); 1183224145Sdim if (VerboseAsm) Streamer.AddComment("Range Start"); 1184224145Sdim Streamer.EmitSymbolValue(Frame.Function, Size); 1185224145Sdim 1186224145Sdim // Range Length 1187224145Sdim const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, 1188224145Sdim *Frame.End, 0); 1189224145Sdim if (VerboseAsm) Streamer.AddComment("Range Length"); 1190224145Sdim Streamer.EmitAbsValue(Range, 4); 1191224145Sdim 1192224145Sdim // Compact Encoding 1193224145Sdim Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); 1194234353Sdim if (VerboseAsm) Streamer.AddComment("Compact Unwind Encoding: 0x" + 1195234353Sdim Twine::utohexstr(Encoding)); 1196224145Sdim Streamer.EmitIntValue(Encoding, Size); 1197224145Sdim 1198224145Sdim // Personality Function 1199224145Sdim Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr); 1200224145Sdim if (VerboseAsm) Streamer.AddComment("Personality Function"); 1201251662Sdim if (!DwarfEHFrameOnly && Frame.Personality) 1202224145Sdim Streamer.EmitSymbolValue(Frame.Personality, Size); 1203224145Sdim else 1204224145Sdim Streamer.EmitIntValue(0, Size); // No personality fn 1205224145Sdim 1206224145Sdim // LSDA 1207224145Sdim Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); 1208224145Sdim if (VerboseAsm) Streamer.AddComment("LSDA"); 1209251662Sdim if (!DwarfEHFrameOnly && Frame.Lsda) 1210224145Sdim Streamer.EmitSymbolValue(Frame.Lsda, Size); 1211224145Sdim else 1212224145Sdim Streamer.EmitIntValue(0, Size); // No LSDA 1213224145Sdim} 1214224145Sdim 1215221345Sdimconst MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, 1216221345Sdim const MCSymbol *personality, 1217221345Sdim unsigned personalityEncoding, 1218221345Sdim const MCSymbol *lsda, 1219234353Sdim bool IsSignalFrame, 1220221345Sdim unsigned lsdaEncoding) { 1221218893Sdim MCContext &context = streamer.getContext(); 1222226633Sdim const MCRegisterInfo &MRI = context.getRegisterInfo(); 1223226633Sdim const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); 1224224145Sdim bool verboseAsm = streamer.isVerboseAsm(); 1225218893Sdim 1226221345Sdim MCSymbol *sectionStart; 1227226633Sdim if (MOFI->isFunctionEHFrameSymbolPrivate() || !IsEH) 1228221345Sdim sectionStart = context.CreateTempSymbol(); 1229221345Sdim else 1230221345Sdim sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); 1231218893Sdim 1232224145Sdim streamer.EmitLabel(sectionStart); 1233221345Sdim CIENum++; 1234221345Sdim 1235224145Sdim MCSymbol *sectionEnd = context.CreateTempSymbol(); 1236218893Sdim 1237218893Sdim // Length 1238218893Sdim const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, 1239218893Sdim *sectionEnd, 4); 1240224145Sdim if (verboseAsm) streamer.AddComment("CIE Length"); 1241221345Sdim streamer.EmitAbsValue(Length, 4); 1242218893Sdim 1243218893Sdim // CIE ID 1244223017Sdim unsigned CIE_ID = IsEH ? 0 : -1; 1245224145Sdim if (verboseAsm) streamer.AddComment("CIE ID Tag"); 1246223017Sdim streamer.EmitIntValue(CIE_ID, 4); 1247218893Sdim 1248218893Sdim // Version 1249224145Sdim if (verboseAsm) streamer.AddComment("DW_CIE_VERSION"); 1250218893Sdim streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); 1251218893Sdim 1252218893Sdim // Augmentation String 1253218893Sdim SmallString<8> Augmentation; 1254223017Sdim if (IsEH) { 1255224145Sdim if (verboseAsm) streamer.AddComment("CIE Augmentation"); 1256223017Sdim Augmentation += "z"; 1257223017Sdim if (personality) 1258223017Sdim Augmentation += "P"; 1259223017Sdim if (lsda) 1260223017Sdim Augmentation += "L"; 1261223017Sdim Augmentation += "R"; 1262234353Sdim if (IsSignalFrame) 1263234353Sdim Augmentation += "S"; 1264249423Sdim streamer.EmitBytes(Augmentation.str()); 1265223017Sdim } 1266218893Sdim streamer.EmitIntValue(0, 1); 1267218893Sdim 1268218893Sdim // Code Alignment Factor 1269224145Sdim if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor"); 1270218893Sdim streamer.EmitULEB128IntValue(1); 1271218893Sdim 1272218893Sdim // Data Alignment Factor 1273224145Sdim if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor"); 1274218893Sdim streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); 1275218893Sdim 1276218893Sdim // Return Address Register 1277224145Sdim if (verboseAsm) streamer.AddComment("CIE Return Address Column"); 1278226633Sdim streamer.EmitULEB128IntValue(MRI.getDwarfRegNum(MRI.getRARegister(), true)); 1279218893Sdim 1280218893Sdim // Augmentation Data Length (optional) 1281218893Sdim 1282221345Sdim unsigned augmentationLength = 0; 1283223017Sdim if (IsEH) { 1284223017Sdim if (personality) { 1285223017Sdim // Personality Encoding 1286223017Sdim augmentationLength += 1; 1287223017Sdim // Personality 1288223017Sdim augmentationLength += getSizeForEncoding(streamer, personalityEncoding); 1289223017Sdim } 1290223017Sdim if (lsda) 1291223017Sdim augmentationLength += 1; 1292223017Sdim // Encoding of the FDE pointers 1293221345Sdim augmentationLength += 1; 1294221345Sdim 1295224145Sdim if (verboseAsm) streamer.AddComment("Augmentation Size"); 1296223017Sdim streamer.EmitULEB128IntValue(augmentationLength); 1297221345Sdim 1298223017Sdim // Augmentation Data (optional) 1299223017Sdim if (personality) { 1300223017Sdim // Personality Encoding 1301224145Sdim EmitEncodingByte(streamer, personalityEncoding, 1302224145Sdim "Personality Encoding"); 1303223017Sdim // Personality 1304224145Sdim if (verboseAsm) streamer.AddComment("Personality"); 1305223017Sdim EmitPersonality(streamer, *personality, personalityEncoding); 1306223017Sdim } 1307224145Sdim 1308223017Sdim if (lsda) 1309224145Sdim EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding"); 1310224145Sdim 1311223017Sdim // Encoding of the FDE pointers 1312226633Sdim EmitEncodingByte(streamer, MOFI->getFDEEncoding(UsingCFI), 1313224145Sdim "FDE Encoding"); 1314218893Sdim } 1315218893Sdim 1316218893Sdim // Initial Instructions 1317218893Sdim 1318226633Sdim const MCAsmInfo &MAI = context.getAsmInfo(); 1319226633Sdim const std::vector<MachineMove> &Moves = MAI.getInitialFrameState(); 1320218893Sdim std::vector<MCCFIInstruction> Instructions; 1321218893Sdim 1322218893Sdim for (int i = 0, n = Moves.size(); i != n; ++i) { 1323218893Sdim MCSymbol *Label = Moves[i].getLabel(); 1324218893Sdim const MachineLocation &Dst = 1325226633Sdim TranslateMachineLocation(MRI, Moves[i].getDestination()); 1326218893Sdim const MachineLocation &Src = 1327226633Sdim TranslateMachineLocation(MRI, Moves[i].getSource()); 1328249423Sdim 1329249423Sdim if (Dst.isReg()) { 1330249423Sdim assert(Dst.getReg() == MachineLocation::VirtualFP); 1331249423Sdim assert(!Src.isReg()); 1332249423Sdim MCCFIInstruction Inst = 1333249423Sdim MCCFIInstruction::createDefCfa(Label, Src.getReg(), -Src.getOffset()); 1334249423Sdim Instructions.push_back(Inst); 1335249423Sdim } else { 1336249423Sdim assert(Src.isReg()); 1337249423Sdim unsigned Reg = Src.getReg(); 1338249423Sdim int Offset = Dst.getOffset(); 1339249423Sdim MCCFIInstruction Inst = 1340249423Sdim MCCFIInstruction::createOffset(Label, Reg, Offset); 1341249423Sdim Instructions.push_back(Inst); 1342249423Sdim } 1343218893Sdim } 1344218893Sdim 1345218893Sdim EmitCFIInstructions(streamer, Instructions, NULL); 1346218893Sdim 1347218893Sdim // Padding 1348224145Sdim streamer.EmitValueToAlignment(IsEH 1349224145Sdim ? 4 : context.getAsmInfo().getPointerSize()); 1350218893Sdim 1351218893Sdim streamer.EmitLabel(sectionEnd); 1352218893Sdim return *sectionStart; 1353218893Sdim} 1354218893Sdim 1355221345SdimMCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, 1356221345Sdim const MCSymbol &cieStart, 1357223017Sdim const MCDwarfFrameInfo &frame) { 1358218893Sdim MCContext &context = streamer.getContext(); 1359218893Sdim MCSymbol *fdeStart = context.CreateTempSymbol(); 1360218893Sdim MCSymbol *fdeEnd = context.CreateTempSymbol(); 1361226633Sdim const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); 1362224145Sdim bool verboseAsm = streamer.isVerboseAsm(); 1363218893Sdim 1364226633Sdim if (IsEH && frame.Function && !MOFI->isFunctionEHFrameSymbolPrivate()) { 1365224145Sdim MCSymbol *EHSym = 1366224145Sdim context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh")); 1367221345Sdim streamer.EmitEHSymAttributes(frame.Function, EHSym); 1368221345Sdim streamer.EmitLabel(EHSym); 1369221345Sdim } 1370221345Sdim 1371218893Sdim // Length 1372218893Sdim const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); 1373224145Sdim if (verboseAsm) streamer.AddComment("FDE Length"); 1374221345Sdim streamer.EmitAbsValue(Length, 4); 1375218893Sdim 1376218893Sdim streamer.EmitLabel(fdeStart); 1377223017Sdim 1378218893Sdim // CIE Pointer 1379223017Sdim const MCAsmInfo &asmInfo = context.getAsmInfo(); 1380223017Sdim if (IsEH) { 1381223017Sdim const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, 1382223017Sdim 0); 1383224145Sdim if (verboseAsm) streamer.AddComment("FDE CIE Offset"); 1384223017Sdim streamer.EmitAbsValue(offset, 4); 1385239462Sdim } else if (!asmInfo.doesDwarfUseRelocationsAcrossSections()) { 1386223017Sdim const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, 1387223017Sdim cieStart, 0); 1388223017Sdim streamer.EmitAbsValue(offset, 4); 1389223017Sdim } else { 1390223017Sdim streamer.EmitSymbolValue(&cieStart, 4); 1391223017Sdim } 1392224145Sdim 1393218893Sdim // PC Begin 1394239462Sdim unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding(UsingCFI) 1395239462Sdim : (unsigned)dwarf::DW_EH_PE_absptr; 1396239462Sdim unsigned PCSize = getSizeForEncoding(streamer, PCEncoding); 1397239462Sdim EmitSymbol(streamer, *frame.Begin, PCEncoding, "FDE initial location"); 1398218893Sdim 1399218893Sdim // PC Range 1400218893Sdim const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, 1401218893Sdim *frame.End, 0); 1402224145Sdim if (verboseAsm) streamer.AddComment("FDE address range"); 1403239462Sdim streamer.EmitAbsValue(Range, PCSize); 1404218893Sdim 1405223017Sdim if (IsEH) { 1406223017Sdim // Augmentation Data Length 1407223017Sdim unsigned augmentationLength = 0; 1408218893Sdim 1409223017Sdim if (frame.Lsda) 1410223017Sdim augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); 1411221345Sdim 1412224145Sdim if (verboseAsm) streamer.AddComment("Augmentation size"); 1413223017Sdim streamer.EmitULEB128IntValue(augmentationLength); 1414221345Sdim 1415223017Sdim // Augmentation Data 1416223017Sdim if (frame.Lsda) 1417224145Sdim EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding, 1418224145Sdim "Language Specific Data Area"); 1419223017Sdim } 1420221345Sdim 1421218893Sdim // Call Frame Instructions 1422218893Sdim EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); 1423218893Sdim 1424218893Sdim // Padding 1425239462Sdim streamer.EmitValueToAlignment(PCSize); 1426218893Sdim 1427218893Sdim return fdeEnd; 1428218893Sdim} 1429218893Sdim 1430218893Sdimnamespace { 1431218893Sdim struct CIEKey { 1432234353Sdim static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false); } 1433234353Sdim static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false); } 1434218893Sdim 1435218893Sdim CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_, 1436234353Sdim unsigned LsdaEncoding_, bool IsSignalFrame_) : 1437234353Sdim Personality(Personality_), PersonalityEncoding(PersonalityEncoding_), 1438234353Sdim LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_) { 1439218893Sdim } 1440218893Sdim const MCSymbol* Personality; 1441218893Sdim unsigned PersonalityEncoding; 1442218893Sdim unsigned LsdaEncoding; 1443234353Sdim bool IsSignalFrame; 1444218893Sdim }; 1445218893Sdim} 1446218893Sdim 1447218893Sdimnamespace llvm { 1448218893Sdim template <> 1449218893Sdim struct DenseMapInfo<CIEKey> { 1450218893Sdim static CIEKey getEmptyKey() { 1451218893Sdim return CIEKey::getEmptyKey(); 1452218893Sdim } 1453218893Sdim static CIEKey getTombstoneKey() { 1454218893Sdim return CIEKey::getTombstoneKey(); 1455218893Sdim } 1456218893Sdim static unsigned getHashValue(const CIEKey &Key) { 1457234353Sdim return static_cast<unsigned>(hash_combine(Key.Personality, 1458234353Sdim Key.PersonalityEncoding, 1459234353Sdim Key.LsdaEncoding, 1460234353Sdim Key.IsSignalFrame)); 1461218893Sdim } 1462218893Sdim static bool isEqual(const CIEKey &LHS, 1463218893Sdim const CIEKey &RHS) { 1464218893Sdim return LHS.Personality == RHS.Personality && 1465218893Sdim LHS.PersonalityEncoding == RHS.PersonalityEncoding && 1466234353Sdim LHS.LsdaEncoding == RHS.LsdaEncoding && 1467234353Sdim LHS.IsSignalFrame == RHS.IsSignalFrame; 1468218893Sdim } 1469218893Sdim }; 1470218893Sdim} 1471218893Sdim 1472224145Sdimvoid MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, 1473224145Sdim bool UsingCFI, 1474224145Sdim bool IsEH) { 1475224145Sdim MCContext &Context = Streamer.getContext(); 1476226633Sdim MCObjectFileInfo *MOFI = 1477226633Sdim const_cast<MCObjectFileInfo*>(Context.getObjectFileInfo()); 1478226633Sdim FrameEmitterImpl Emitter(UsingCFI, IsEH); 1479226633Sdim ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos(); 1480226633Sdim 1481226633Sdim // Emit the compact unwind info if available. 1482251662Sdim if (IsEH && MOFI->getCompactUnwindSection()) { 1483251662Sdim unsigned NumFrameInfos = Streamer.getNumFrameInfos(); 1484251662Sdim bool SectionEmitted = false; 1485251662Sdim 1486251662Sdim if (NumFrameInfos) { 1487251662Sdim for (unsigned i = 0; i < NumFrameInfos; ++i) { 1488251662Sdim const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i); 1489251662Sdim if (Frame.CompactUnwindEncoding == 0) continue; 1490251662Sdim if (!SectionEmitted) { 1491251662Sdim Streamer.SwitchSection(MOFI->getCompactUnwindSection()); 1492251662Sdim Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize()); 1493251662Sdim SectionEmitted = true; 1494251662Sdim } 1495226633Sdim Emitter.EmitCompactUnwind(Streamer, Frame); 1496251662Sdim } 1497226633Sdim } 1498251662Sdim } 1499226633Sdim 1500226633Sdim const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() : 1501226633Sdim *MOFI->getDwarfFrameSection(); 1502224145Sdim Streamer.SwitchSection(&Section); 1503224145Sdim MCSymbol *SectionStart = Context.CreateTempSymbol(); 1504224145Sdim Streamer.EmitLabel(SectionStart); 1505226633Sdim Emitter.setSectionStart(SectionStart); 1506221345Sdim 1507224145Sdim MCSymbol *FDEEnd = NULL; 1508218893Sdim DenseMap<CIEKey, const MCSymbol*> CIEStarts; 1509218893Sdim 1510223017Sdim const MCSymbol *DummyDebugKey = NULL; 1511226633Sdim for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { 1512226633Sdim const MCDwarfFrameInfo &Frame = FrameArray[i]; 1513224145Sdim CIEKey Key(Frame.Personality, Frame.PersonalityEncoding, 1514234353Sdim Frame.LsdaEncoding, Frame.IsSignalFrame); 1515224145Sdim const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; 1516224145Sdim if (!CIEStart) 1517224145Sdim CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality, 1518224145Sdim Frame.PersonalityEncoding, Frame.Lsda, 1519234353Sdim Frame.IsSignalFrame, 1520224145Sdim Frame.LsdaEncoding); 1521224145Sdim 1522224145Sdim FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame); 1523224145Sdim 1524218893Sdim if (i != n - 1) 1525224145Sdim Streamer.EmitLabel(FDEEnd); 1526218893Sdim } 1527218893Sdim 1528224145Sdim Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize()); 1529224145Sdim if (FDEEnd) 1530224145Sdim Streamer.EmitLabel(FDEEnd); 1531218893Sdim} 1532218893Sdim 1533218893Sdimvoid MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, 1534218893Sdim uint64_t AddrDelta) { 1535218893Sdim SmallString<256> Tmp; 1536218893Sdim raw_svector_ostream OS(Tmp); 1537223017Sdim MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS); 1538249423Sdim Streamer.EmitBytes(OS.str()); 1539218893Sdim} 1540218893Sdim 1541218893Sdimvoid MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, 1542223017Sdim raw_ostream &OS) { 1543218893Sdim // FIXME: Assumes the code alignment factor is 1. 1544218893Sdim if (AddrDelta == 0) { 1545223017Sdim } else if (isUIntN(6, AddrDelta)) { 1546218893Sdim uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; 1547218893Sdim OS << Opcode; 1548223017Sdim } else if (isUInt<8>(AddrDelta)) { 1549218893Sdim OS << uint8_t(dwarf::DW_CFA_advance_loc1); 1550218893Sdim OS << uint8_t(AddrDelta); 1551223017Sdim } else if (isUInt<16>(AddrDelta)) { 1552218893Sdim // FIXME: check what is the correct behavior on a big endian machine. 1553218893Sdim OS << uint8_t(dwarf::DW_CFA_advance_loc2); 1554218893Sdim OS << uint8_t( AddrDelta & 0xff); 1555218893Sdim OS << uint8_t((AddrDelta >> 8) & 0xff); 1556218893Sdim } else { 1557218893Sdim // FIXME: check what is the correct behavior on a big endian machine. 1558218893Sdim assert(isUInt<32>(AddrDelta)); 1559218893Sdim OS << uint8_t(dwarf::DW_CFA_advance_loc4); 1560218893Sdim OS << uint8_t( AddrDelta & 0xff); 1561218893Sdim OS << uint8_t((AddrDelta >> 8) & 0xff); 1562218893Sdim OS << uint8_t((AddrDelta >> 16) & 0xff); 1563218893Sdim OS << uint8_t((AddrDelta >> 24) & 0xff); 1564218893Sdim 1565218893Sdim } 1566218893Sdim} 1567