Change some methods in MCDwarf.cpp to be able to handle an arbitrary

MCStreamer instead of just MCObjectStreamer. Address changes cannot
be as efficient as we have to use DW_LNE_set_addres, but at least
most of the logic is shared.

This will be used so that, with CodeGen still using EmitDwarfLocDirective,
llvm-gcc is able to produce debug_line sections without needing an
assembler that supports .loc.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119777 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2010-11-19 02:26:16 +00:00
parent 602890dd8e
commit 195a0ce484
9 changed files with 128 additions and 43 deletions

View File

@ -167,7 +167,7 @@ namespace llvm {
// This is called when an instruction is assembled into the specified // This is called when an instruction is assembled into the specified
// section and if there is information from the last .loc directive that // section and if there is information from the last .loc directive that
// has yet to have a line entry made for it is made. // has yet to have a line entry made for it is made.
static void Make(MCObjectStreamer *MCOS, const MCSection *Section); static void Make(MCStreamer *MCOS, const MCSection *Section);
}; };
/// MCLineSection - Instances of this class represent the line information /// MCLineSection - Instances of this class represent the line information
@ -205,7 +205,8 @@ namespace llvm {
// //
// This emits the Dwarf file and the line tables. // This emits the Dwarf file and the line tables.
// //
static void Emit(MCObjectStreamer *MCOS, const MCSection *DwarfLineSection); static void Emit(MCStreamer *MCOS, const MCSection *DwarfLineSection,
MCSectionData *DLS, int PointerSize);
}; };
class MCDwarfLineAddr { class MCDwarfLineAddr {
@ -214,7 +215,7 @@ namespace llvm {
static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
/// Utility function to emit the encoding to a streamer. /// Utility function to emit the encoding to a streamer.
static void Emit(MCObjectStreamer *MCOS, static void Emit(MCStreamer *MCOS,
int64_t LineDelta,uint64_t AddrDelta); int64_t LineDelta,uint64_t AddrDelta);
/// Utility function to compute the size of the encoding. /// Utility function to compute the size of the encoding.

View File

@ -28,6 +28,7 @@ namespace llvm {
class MCSymbol; class MCSymbol;
class StringRef; class StringRef;
class TargetAsmBackend; class TargetAsmBackend;
class TargetLoweringObjectFile;
class Twine; class Twine;
class raw_ostream; class raw_ostream;
class formatted_raw_ostream; class formatted_raw_ostream;
@ -388,6 +389,14 @@ namespace llvm {
MCCodeEmitter *CE = 0, MCCodeEmitter *CE = 0,
bool ShowInst = false); bool ShowInst = false);
MCStreamer *createAsmStreamerNoLoc(MCContext &Ctx, formatted_raw_ostream &OS,
bool isLittleEndian, bool isVerboseAsm,
const TargetLoweringObjectFile *TLOF,
int PointerSize,
MCInstPrinter *InstPrint = 0,
MCCodeEmitter *CE = 0,
bool ShowInst = false);
/// createMachOStreamer - Create a machine code streamer which will generate /// createMachOStreamer - Create a machine code streamer which will generate
/// Mach-O format object files. /// Mach-O format object files.
/// ///

View File

@ -104,6 +104,7 @@ protected: // Can only create subclasses.
const MCAsmInfo *AsmInfo; const MCAsmInfo *AsmInfo;
unsigned MCRelaxAll : 1; unsigned MCRelaxAll : 1;
unsigned MCUseLoc : 1;
public: public:
virtual ~TargetMachine(); virtual ~TargetMachine();
@ -169,6 +170,12 @@ public:
/// relaxed. /// relaxed.
void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } void setMCRelaxAll(bool Value) { MCRelaxAll = Value; }
/// hasMCUseLoc - Check whether we should use dwarf's .loc directive.
bool hasMCUseLoc() const { return MCUseLoc; }
/// setMCUseLoc - Set whether all we should use dwarf's .loc directive.
void setMCUseLoc(bool Value) { MCUseLoc = Value; }
/// getRelocationModel - Returns the code generation relocation model. The /// getRelocationModel - Returns the code generation relocation model. The
/// choices are static, PIC, and dynamic-no-pic, and target default. /// choices are static, PIC, and dynamic-no-pic, and target default.
static Reloc::Model getRelocationModel(); static Reloc::Model getRelocationModel();

View File

@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/GCStrategy.h"
#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetOptions.h"
#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCStreamer.h"
@ -144,11 +145,28 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
if (ShowMCEncoding) if (ShowMCEncoding)
MCE = getTarget().createCodeEmitter(*this, *Context); MCE = getTarget().createCodeEmitter(*this, *Context);
AsmStreamer.reset(getTarget().createAsmStreamer(*Context, Out, const TargetLoweringObjectFile &TLOF =
getTargetLowering()->getObjFileLowering();
int PointerSize = getTargetData()->getPointerSize();
MCStreamer *S;
if (hasMCUseLoc())
S = getTarget().createAsmStreamer(*Context, Out,
getTargetData()->isLittleEndian(), getTargetData()->isLittleEndian(),
getVerboseAsm(), getVerboseAsm(),
InstPrinter, MCE, InstPrinter,
ShowMCInst)); MCE,
ShowMCInst);
else
S = createAsmStreamerNoLoc(*Context, Out,
getTargetData()->isLittleEndian(),
getVerboseAsm(),
&TLOF,
PointerSize,
InstPrinter,
MCE,
ShowMCInst);
AsmStreamer.reset(S);
break; break;
} }
case CGFT_ObjectFile: { case CGFT_ObjectFile: {

View File

@ -23,6 +23,7 @@
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h" #include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm; using namespace llvm;
namespace { namespace {
@ -36,16 +37,21 @@ class MCAsmStreamer : public MCStreamer {
SmallString<128> CommentToEmit; SmallString<128> CommentToEmit;
raw_svector_ostream CommentStream; raw_svector_ostream CommentStream;
const TargetLoweringObjectFile *TLOF;
int PointerSize;
unsigned IsLittleEndian : 1; unsigned IsLittleEndian : 1;
unsigned IsVerboseAsm : 1; unsigned IsVerboseAsm : 1;
unsigned ShowInst : 1; unsigned ShowInst : 1;
public: public:
MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer, bool isLittleEndian, bool isVerboseAsm,
MCCodeEmitter *emitter, bool showInst) const TargetLoweringObjectFile *tlof, int pointerSize,
MCInstPrinter *printer, MCCodeEmitter *emitter, bool showInst)
: MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()),
InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit), InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit),
TLOF(tlof), PointerSize(pointerSize),
IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm), IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm),
ShowInst(showInst) { ShowInst(showInst) {
if (InstPrinter && IsVerboseAsm) if (InstPrinter && IsVerboseAsm)
@ -637,9 +643,11 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
} }
bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){
if (!TLOF) {
OS << "\t.file\t" << FileNo << ' '; OS << "\t.file\t" << FileNo << ' ';
PrintQuotedString(Filename, OS); PrintQuotedString(Filename, OS);
EmitEOL(); EmitEOL();
}
return this->MCStreamer::EmitDwarfFileDirective(FileNo, Filename); return this->MCStreamer::EmitDwarfFileDirective(FileNo, Filename);
} }
@ -647,6 +655,11 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags, unsigned Column, unsigned Flags,
unsigned Isa, unsigned Isa,
unsigned Discriminator) { unsigned Discriminator) {
this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
Isa, Discriminator);
if (TLOF)
return;
OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
if (Flags & DWARF2_FLAG_BASIC_BLOCK) if (Flags & DWARF2_FLAG_BASIC_BLOCK)
OS << " basic_block"; OS << " basic_block";
@ -670,8 +683,6 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
if (Discriminator) if (Discriminator)
OS << "discriminator " << Discriminator; OS << "discriminator " << Discriminator;
EmitEOL(); EmitEOL();
return this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
Isa, Discriminator);
} }
void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) {
@ -755,6 +766,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) {
void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
assert(CurSection && "Cannot emit contents before setting section!"); assert(CurSection && "Cannot emit contents before setting section!");
if (TLOF)
MCLineEntry::Make(this, getCurrentSection());
// Show the encoding in a comment if we have a code emitter. // Show the encoding in a comment if we have a code emitter.
if (Emitter) if (Emitter)
AddEncodingComment(Inst); AddEncodingComment(Inst);
@ -784,6 +798,11 @@ void MCAsmStreamer::EmitRawText(StringRef String) {
} }
void MCAsmStreamer::Finish() { void MCAsmStreamer::Finish() {
// Dump out the dwarf file & directory tables and line tables.
if (getContext().hasDwarfFiles() && TLOF) {
MCDwarfFileTable::Emit(this, TLOF->getDwarfLineSection(), NULL,
PointerSize);
}
} }
MCStreamer *llvm::createAsmStreamer(MCContext &Context, MCStreamer *llvm::createAsmStreamer(MCContext &Context,
@ -792,5 +811,18 @@ MCStreamer *llvm::createAsmStreamer(MCContext &Context,
bool isVerboseAsm, MCInstPrinter *IP, bool isVerboseAsm, MCInstPrinter *IP,
MCCodeEmitter *CE, bool ShowInst) { MCCodeEmitter *CE, bool ShowInst) {
return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm,
IP, CE, ShowInst); NULL, 0, IP, CE, ShowInst);
}
MCStreamer *llvm::createAsmStreamerNoLoc(MCContext &Context,
formatted_raw_ostream &OS,
bool isLittleEndian,
bool isVerboseAsm,
const TargetLoweringObjectFile *TLOF,
int PointerSize,
MCInstPrinter *IP,
MCCodeEmitter *CE, bool ShowInst) {
return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm,
TLOF, PointerSize, IP, CE, ShowInst);
} }

View File

@ -60,7 +60,7 @@ static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta)
// and if there is information from the last .loc directive that has yet to have // and if there is information from the last .loc directive that has yet to have
// a line entry made for it is made. // a line entry made for it is made.
// //
void MCLineEntry::Make(MCObjectStreamer *MCOS, const MCSection *Section) { void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) {
if (!MCOS->getContext().getDwarfLocSeen()) if (!MCOS->getContext().getDwarfLocSeen())
return; return;
@ -99,7 +99,7 @@ void MCLineEntry::Make(MCObjectStreamer *MCOS, const MCSection *Section) {
// //
// This helper routine returns an expression of End - Start + IntVal . // This helper routine returns an expression of End - Start + IntVal .
// //
static inline const MCExpr *MakeStartMinusEndExpr(MCObjectStreamer *MCOS, static inline const MCExpr *MakeStartMinusEndExpr(MCStreamer *MCOS,
MCSymbol *Start, MCSymbol *Start,
MCSymbol *End, int IntVal) { MCSymbol *End, int IntVal) {
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
@ -120,33 +120,33 @@ static inline const MCExpr *MakeStartMinusEndExpr(MCObjectStreamer *MCOS,
// This emits an "absolute" address used in the start of a dwarf line number // This emits an "absolute" address used in the start of a dwarf line number
// table. This will result in a relocatation entry for the address. // table. This will result in a relocatation entry for the address.
// //
static inline void EmitDwarfSetAddress(MCObjectStreamer *MCOS, static inline void EmitDwarfSetAddress(MCStreamer *MCOS,
MCSymbol *Symbol) { MCSymbol *Symbol,
int PointerSize) {
MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
int sizeof_address = MCOS->getAssembler().getBackend().getPointerSize(); MCOS->EmitULEB128IntValue(PointerSize + 1);
MCOS->EmitULEB128IntValue(sizeof_address + 1);
MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1); MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
MCOS->EmitSymbolValue(Symbol, sizeof_address); MCOS->EmitSymbolValue(Symbol, PointerSize);
} }
// //
// This emits the Dwarf line table for the specified section from the entries // This emits the Dwarf line table for the specified section from the entries
// in the LineSection. // in the LineSection.
// //
static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS, static inline void EmitDwarfLineTable(MCStreamer *MCOS,
const MCSection *Section, const MCSection *Section,
MCLineSection *LineSection, MCLineSection *LineSection,
const MCSection *DwarfLineSection) { const MCSection *DwarfLineSection,
MCSectionData *DLS,
int PointerSize) {
unsigned FileNum = 1; unsigned FileNum = 1;
unsigned LastLine = 1; unsigned LastLine = 1;
unsigned Column = 0; unsigned Column = 0;
unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
unsigned Isa = 0; unsigned Isa = 0;
MCSymbol *LastLabel = NULL; MCSymbol *LastLabel = NULL;
MCSectionData &DLS =
MCOS->getAssembler().getOrCreateSectionData(*DwarfLineSection);
// Loop through each MCLineEntry and encode the dwarf line number table. // Loop through each MCLineEntry and encode the dwarf line number table.
for (MCLineSection::iterator for (MCLineSection::iterator
@ -185,9 +185,9 @@ static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS,
// At this point we want to emit/create the sequence to encode the delta in // At this point we want to emit/create the sequence to encode the delta in
// line numbers and the increment of the address from the previous Label // line numbers and the increment of the address from the previous Label
// and the current Label. // and the current Label.
if (LastLabel == NULL) { if (LastLabel == NULL || DLS == NULL) {
// emit the sequence to set the address // emit the sequence to set the address
EmitDwarfSetAddress(MCOS, Label); EmitDwarfSetAddress(MCOS, Label, PointerSize);
// emit the sequence for the LineDelta (from 1) and a zero address delta. // emit the sequence for the LineDelta (from 1) and a zero address delta.
MCDwarfLineAddr::Emit(MCOS, LineDelta, 0); MCDwarfLineAddr::Emit(MCOS, LineDelta, 0);
} }
@ -196,7 +196,7 @@ static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS,
// this Label (plus 0). // this Label (plus 0).
const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, Label,0); const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, Label,0);
// Create a Dwarf Line fragment for the LineDelta and AddrDelta. // Create a Dwarf Line fragment for the LineDelta and AddrDelta.
new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, &DLS); new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, DLS);
} }
LastLine = it->getLine(); LastLine = it->getLine();
@ -218,19 +218,29 @@ static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS,
// Switch back the the dwarf line section. // Switch back the the dwarf line section.
MCOS->SwitchSection(DwarfLineSection); MCOS->SwitchSection(DwarfLineSection);
if (DLS == NULL) {
// emit the sequence to set the address
EmitDwarfSetAddress(MCOS, SectionEnd, PointerSize);
// emit the sequence for the LineDelta (from 1) and a zero address delta.
MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0);
} else {
// Create an expression for the address delta from the LastLabel and this // Create an expression for the address delta from the LastLabel and this
// SectionEnd label. // SectionEnd label.
const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, SectionEnd, const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, SectionEnd,
0); 0);
// Create a Dwarf Line fragment for the LineDelta and AddrDelta. // Create a Dwarf Line fragment for the LineDelta and AddrDelta.
new MCDwarfLineAddrFragment(INT64_MAX, *AddrDelta, &DLS); new MCDwarfLineAddrFragment(INT64_MAX, *AddrDelta, DLS);
}
} }
// //
// This emits the Dwarf file and the line tables. // This emits the Dwarf file and the line tables.
// //
void MCDwarfFileTable::Emit(MCObjectStreamer *MCOS, void MCDwarfFileTable::Emit(MCStreamer *MCOS,
const MCSection *DwarfLineSection) { const MCSection *DwarfLineSection,
MCSectionData *DLS,
int PointerSize) {
// Switch to the section where the table will be emitted into. // Switch to the section where the table will be emitted into.
MCOS->SwitchSection(DwarfLineSection); MCOS->SwitchSection(DwarfLineSection);
@ -315,7 +325,8 @@ void MCDwarfFileTable::Emit(MCObjectStreamer *MCOS,
MCOS->getContext().getMCLineSections(); MCOS->getContext().getMCLineSections();
for (DenseMap<const MCSection *, MCLineSection *>::iterator it = for (DenseMap<const MCSection *, MCLineSection *>::iterator it =
MCLineSections.begin(), ie = MCLineSections.end(); it != ie; ++it) { MCLineSections.begin(), ie = MCLineSections.end(); it != ie; ++it) {
EmitDwarfLineTable(MCOS, it->first, it->second, DwarfLineSection); EmitDwarfLineTable(MCOS, it->first, it->second, DwarfLineSection, DLS,
PointerSize);
// Now delete the MCLineSections that were created in MCLineEntry::Make() // Now delete the MCLineSections that were created in MCLineEntry::Make()
// and used to emit the line table. // and used to emit the line table.
@ -345,7 +356,7 @@ void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta,
} }
/// Utility function to emit the encoding to a streamer. /// Utility function to emit the encoding to a streamer.
void MCDwarfLineAddr::Emit(MCObjectStreamer *MCOS, int64_t LineDelta, void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta,
uint64_t AddrDelta) { uint64_t AddrDelta) {
SmallString<256> Tmp; SmallString<256> Tmp;
raw_svector_ostream OS(Tmp); raw_svector_ostream OS(Tmp);

View File

@ -490,7 +490,10 @@ void MCELFStreamer::Finish() {
const MCSection *DwarfLineSection = const MCSection *DwarfLineSection =
getContext().getELFSection(".debug_line", 0, 0, getContext().getELFSection(".debug_line", 0, 0,
SectionKind::getDataRelLocal()); SectionKind::getDataRelLocal());
MCDwarfFileTable::Emit(this, DwarfLineSection); MCSectionData &DLS =
getAssembler().getOrCreateSectionData(*DwarfLineSection);
int PointerSize = getAssembler().getBackend().getPointerSize();
MCDwarfFileTable::Emit(this, DwarfLineSection, &DLS, PointerSize);
} }
for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(), for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),

View File

@ -414,7 +414,10 @@ void MCMachOStreamer::Finish() {
"__debug_line", "__debug_line",
MCSectionMachO::S_ATTR_DEBUG, MCSectionMachO::S_ATTR_DEBUG,
0, SectionKind::getDataRelLocal()); 0, SectionKind::getDataRelLocal());
MCDwarfFileTable::Emit(this, DwarfLineSection); MCSectionData &DLS =
getAssembler().getOrCreateSectionData(*DwarfLineSection);
int PointerSize = getAssembler().getBackend().getPointerSize();
MCDwarfFileTable::Emit(this, DwarfLineSection, &DLS, PointerSize);
} }
// We have to set the fragment atom associations so we can relax properly for // We have to set the fragment atom associations so we can relax properly for

View File

@ -219,7 +219,8 @@ FunctionSections("ffunction-sections",
TargetMachine::TargetMachine(const Target &T) TargetMachine::TargetMachine(const Target &T)
: TheTarget(T), AsmInfo(0), : TheTarget(T), AsmInfo(0),
MCRelaxAll(false) { MCRelaxAll(false),
MCUseLoc(true) {
// Typically it will be subtargets that will adjust FloatABIType from Default // Typically it will be subtargets that will adjust FloatABIType from Default
// to Soft or Hard. // to Soft or Hard.
if (UseSoftFloat) if (UseSoftFloat)