diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 6fc48ee6e2d..4e0599e8890 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -35,7 +35,7 @@ namespace llvm { /// IncrementFunctionNumber(). /// unsigned FunctionNumber; - + protected: /// Output stream on which we're printing assembly code. /// @@ -165,6 +165,7 @@ namespace llvm { AsmPrinter(std::ostream &o, TargetMachine &TM); + public: /// SwitchSection - Switch to the specified section of the executable if we /// are not already in it! If GV is non-null and if the global has an /// explicitly requested section, we switch to the section indicated for the @@ -175,6 +176,7 @@ namespace llvm { /// void SwitchSection(const char *NewSection, const GlobalValue *GV); + protected: /// getFunctionNumber - Return a unique ID for the current function. /// unsigned getFunctionNumber() const { return FunctionNumber; } @@ -229,6 +231,43 @@ namespace llvm { private: void EmitXXStructorList(Constant *List); + + public: + /// getCommentString - get the comment string. + /// + const char *getCommentString() { + return CommentString; + } + + /// getData8bitsDirective - get the 8-bit data directive string. + /// + const char *getData8bitsDirective() { + return Data8bitsDirective; + } + + /// getData16bitsDirective - get the 16-bit data directive string. + /// + const char *getData16bitsDirective() { + return Data16bitsDirective; + } + + /// getData32bitsDirective - get the 32-bit data directive string. + /// + const char *getData32bitsDirective() { + return Data32bitsDirective; + } + + /// getData64bitsDirective - get the 64-bit data directive string. + /// + const char *getData64bitsDirective() { + return Data64bitsDirective; + } + + /// getPrivateGlobalPrefix - get private label prefix. + /// + const char *getPrivateGlobalPrefix() { + return PrivateGlobalPrefix; + } }; } diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h index 6dc83fff4ce..effead39406 100644 --- a/include/llvm/CodeGen/DwarfWriter.h +++ b/include/llvm/CodeGen/DwarfWriter.h @@ -14,11 +14,14 @@ #ifndef LLVM_CODEGEN_DWARFPRINTER_H #define LLVM_CODEGEN_DWARFPRINTER_H +#include +#include "llvm/CodeGen/MachineDebugInfo.h" + namespace llvm { - //===----------------------------------------------------------------------===// + //===--------------------------------------------------------------------===// // Dwarf constants as gleaned from the DWARF Debugging Information Format V.3 - // reference manual http://dwarf.freestandards.org. + // reference manual http://dwarf.freestandards.org . // enum dwarf_constants { // Tags @@ -422,6 +425,141 @@ namespace llvm { DW_CFA_lo_user = 0x1c, DW_CFA_hi_user = 0x3f }; + + // Forward declarations. + // + class AsmPrinter; + + //===--------------------------------------------------------------------===// + // DwarfWriter - emits dwarf debug and exception handling directives. + // + class DwarfWriter { + + protected: + + /// O - Stream to .s file. + /// + std::ostream &O; + + /// Asm - Target of dwarf emission. + /// + AsmPrinter *Asm; + + /// DebugInfo - Collected debug information. + /// + MachineDebugInfo &DebugInfo; + + /// hasLEB128 - True if target asm supports leb128 directives. + /// + bool hasLEB128; /// Defaults to false. + + /// needsSet - True if target asm can't compute addresses on data + /// directives. + bool needsSet; /// Defaults to false. + + /// DwarfAbbrevSection - section directive arg for dwarf abbrev. + /// + const char *DwarfAbbrevSection; /// Defaults to ".debug_abbrev". + + /// DwarfInfoSection - section directive arg for dwarf info. + /// + const char *DwarfInfoSection; /// Defaults to ".debug_info". + + /// DwarfLineSection - section directive arg for dwarf info. + /// + const char *DwarfLineSection; /// Defaults to ".debug_line". + + public: + + // Ctor. + DwarfWriter(std::ostream &o, AsmPrinter *ap, MachineDebugInfo &di) + : O(o) + , Asm(ap) + , DebugInfo(di) + , hasLEB128(false) + , needsSet(false) + , DwarfAbbrevSection(".debug_abbrev") + , DwarfInfoSection(".debug_info") + , DwarfLineSection(".debug_line") + {} + + /// EmitHex - Emit a hexidecimal string to the output stream. + /// + void EmitHex(unsigned Value) { + O << "0x" + << std::hex + << Value + << std::dec; + } + + /// EmitComment - Emit a simple string comment. + /// + void EmitComment(const char *Comment) { + O << "\t" + << Asm->getCommentString() + << " " + << Comment + << "\n"; + } + + /// EmitULEB128 - Emit a series of hexidecimal values (separated by commas) + /// representing an unsigned leb128 value. + /// + void EmitULEB128(unsigned Value) { + do { + unsigned Byte = Value & 0x7f; + Value >>= 7; + if (Value) Byte |= 0x80; + EmitHex(Byte); + if (Value) O << ", "; + } while (Value); + } + + /// EmitSLEB128 - Emit a series of hexidecimal values (separated by commas) + /// representing a signed leb128 value. + /// + void EmitSLEB128(int Value) { + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + unsigned Byte = Value & 0x7f; + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + EmitHex(Byte); + if (IsMore) O << ", "; + } while (IsMore); + } + + /// EmitLabelName - Emit label name for internal use by dwarf. + /// + void EmitLabelName(const char *Tag, int Num) { + O << Asm->getPrivateGlobalPrefix() + << "debug_" + << Tag + << Num; + } + + /// EmitLabel - Emit location label for internal use by dwarf. + /// + void EmitLabel(const char *Tag, int Num) { + EmitLabelName(Tag, Num); + O << ":\n"; + } + + // Defined elsewhere + + void EmitULEB128Bytes(unsigned Value, std::string Comment); + void EmitSLEB128Bytes(int Value, std::string Comment); + + void BeginModule(); + void EndModule(); + + void BeginFunction(); + void EndFunction(); + }; + } // end llvm namespace diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp index 5fdfbfd5a30..475928250e5 100644 --- a/lib/CodeGen/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter.cpp @@ -16,6 +16,7 @@ #include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineDebugInfo.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetMachine.h" diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp index dcfb6e4e0ef..2fc65e6f956 100644 --- a/lib/CodeGen/DwarfWriter.cpp +++ b/lib/CodeGen/DwarfWriter.cpp @@ -12,4 +12,99 @@ //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/Support/CommandLine.h" + + +namespace llvm { + +static cl::opt +DwarfVerbose("dwarf-verbose", cl::Hidden, + cl::desc("Add comments to dwarf directives.")); + +/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an +/// unsigned leb128 value. +/// +void DwarfWriter::EmitULEB128Bytes(unsigned Value, std::string Comment) { + if (hasLEB128) { + O << "\t.uleb128\t" + << Value; + } else { + O << Asm->getData8bitsDirective(); + EmitULEB128(Value); + } + if (DwarfVerbose) { + O << "\t" + << Asm->getCommentString() + << " " + << Comment + << " " + << Value; + } + O << "\n"; +} + +/// EmitSLEB128Bytes - Emit an assembler byte data directive to compose a +/// signed leb128 value. +/// +void DwarfWriter::EmitSLEB128Bytes(int Value, std::string Comment) { + if (hasLEB128) { + O << "\t.sleb128\t" + << Value; + } else { + O << Asm->getData8bitsDirective(); + EmitSLEB128(Value); + } + if (DwarfVerbose) { + O << "\t" + << Asm->getCommentString() + << " " + << Comment + << " " + << Value; + } + O << "\n"; +} + +/// BeginModule - Emit all dwarf sections that should come prior to the content. +/// +void DwarfWriter::BeginModule() { + EmitComment("Dwarf Begin Module"); + + // define base addresses for dwarf sections + Asm->SwitchSection(DwarfAbbrevSection, 0); + EmitLabel("abbrev", 0); + Asm->SwitchSection(DwarfInfoSection, 0); + EmitLabel("info", 0); + Asm->SwitchSection(DwarfLineSection, 0); + EmitLabel("line", 0); +} + +/// EndModule - Emit all dwarf sections that should come after the content. +/// +void DwarfWriter::EndModule() { + EmitComment("Dwarf End Module"); + // Print out dwarf file info + std::vector Sources = DebugInfo.getSourceFiles(); + for (unsigned i = 0, N = Sources.size(); i < N; i++) { + O << "\t; .file\t" << (i + 1) << "," << "\"" << Sources[i] << "\"" << "\n"; + } +} + + +/// BeginFunction - Emit pre-function debug information. +/// +void DwarfWriter::BeginFunction() { + EmitComment("Dwarf Begin Function"); +} + +/// EndFunction - Emit post-function debug information. +/// +void DwarfWriter::EndFunction() { + EmitComment("Dwarf End Function"); +} + + +} // End llvm namespace + diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index f75e4aae227..12b5f447759 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -25,6 +25,7 @@ #include "llvm/Module.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineDebugInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" @@ -205,13 +206,33 @@ namespace { virtual bool doFinalization(Module &M) = 0; }; + /// DarwinDwarfWriter - Dwarf debug info writer customized for Darwin/Mac OS X + /// + struct DarwinDwarfWriter : public DwarfWriter { + // Ctor. + DarwinDwarfWriter(std::ostream &o, AsmPrinter *ap, MachineDebugInfo &di) + : DwarfWriter(o, ap, di) + { + hasLEB128 = false; + needsSet = true; + DwarfAbbrevSection = ".section __DWARFA,__debug_abbrev,regular,debug"; + DwarfInfoSection = ".section __DWARFA,__debug_info,regular,debug"; + DwarfLineSection = ".section __DWARFA,__debug_line,regular,debug"; + } + }; + /// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS /// X /// struct DarwinAsmPrinter : public PPCAsmPrinter { + + DarwinDwarfWriter DW; DarwinAsmPrinter(std::ostream &O, TargetMachine &TM) - : PPCAsmPrinter(O, TM) { + : PPCAsmPrinter(O, TM), + // FIXME - MachineDebugInfo needs a proper location + DW(O, this, getMachineDebugInfo()) + { CommentString = ";"; GlobalPrefix = "_"; PrivateGlobalPrefix = "L"; // Marker for constant pool idxs @@ -397,12 +418,8 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { SetupMachineFunction(MF); O << "\n\n"; - // Print out dwarf file info - MachineDebugInfo &DebugInfo = MF.getDebugInfo(); - std::vector Sources = DebugInfo.getSourceFiles(); - for (unsigned i = 0, N = Sources.size(); i < N; i++) { - O << "\t; .file\t" << (i + 1) << "," << "\"" << Sources[i] << "\"" << "\n"; - } + // Emit pre-function debug information. + DW.BeginFunction(); // Print out constants referenced by the function EmitConstantPool(MF.getConstantPool()); @@ -449,6 +466,9 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } } + // Emit post-function debug information. + DW.EndFunction(); + // We didn't modify anything. return false; } @@ -461,6 +481,9 @@ bool DarwinAsmPrinter::doInitialization(Module &M) { // Darwin wants symbols to be quoted if they have complex names. Mang->setUseQuotes(true); + + // Emit initial debug information. + DW.BeginModule(); return false; } @@ -583,6 +606,9 @@ bool DarwinAsmPrinter::doFinalization(Module &M) { // code that does this, it is always safe to set. O << "\t.subsections_via_symbols\n"; + // Emit initial debug information. + DW.EndModule(); + AsmPrinter::doFinalization(M); return false; // success } @@ -592,7 +618,7 @@ bool DarwinAsmPrinter::doFinalization(Module &M) { /// bool AIXAsmPrinter::runOnMachineFunction(MachineFunction &MF) { SetupMachineFunction(MF); - + // Print out constants referenced by the function EmitConstantPool(MF.getConstantPool()); diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index c92122ec7d8..3115a57a902 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -80,7 +80,7 @@ bool PPCTargetMachine::addPassesToEmitFile(PassManager &PM, CodeGenFileType FileType, bool Fast) { if (FileType != TargetMachine::AssemblyFile) return true; - + // Run loop strength reduction before anything else. if (!Fast) PM.add(createLoopStrengthReducePass());