From 89b9372605db2ce3b0085c84089e389f7bc1fbdd Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 10 Dec 2010 07:39:47 +0000 Subject: [PATCH] Fixed version of 121434 with no new memory leaks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121471 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineModuleInfo.h | 3 +- include/llvm/MC/MCContext.h | 7 +- include/llvm/MC/MCDwarf.h | 18 +- include/llvm/MC/MCObjectStreamer.h | 3 +- include/llvm/MC/MCStreamer.h | 39 +++- include/llvm/Target/TargetAsmBackend.h | 4 - include/llvm/Target/TargetAsmInfo.h | 75 +++++++ include/llvm/Target/TargetRegistry.h | 9 +- lib/CodeGen/ELFWriter.cpp | 3 +- lib/CodeGen/LLVMTargetMachine.cpp | 31 +-- lib/CodeGen/MachineModuleInfo.cpp | 7 +- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 2 +- lib/MC/MCAsmStreamer.cpp | 63 +++--- lib/MC/MCContext.cpp | 8 +- lib/MC/MCDisassembler/EDDisassembler.cpp | 2 +- lib/MC/MCDwarf.cpp | 210 +++++++++++++++++-- lib/MC/MCELFStreamer.cpp | 11 +- lib/MC/MCLoggingStreamer.cpp | 5 +- lib/MC/MCMachOStreamer.cpp | 10 +- lib/MC/MCNullStreamer.cpp | 4 +- lib/MC/MCObjectStreamer.cpp | 14 +- lib/MC/MCStreamer.cpp | 58 ++++- lib/Target/CBackend/CBackend.cpp | 2 +- lib/Target/CMakeLists.txt | 1 + lib/Target/PTX/PTXMCAsmStreamer.cpp | 25 ++- lib/Target/PTX/PTXTargetMachine.cpp | 2 +- lib/Target/TargetAsmInfo.cpp | 27 +++ lib/Target/X86/X86AsmBackend.cpp | 23 -- test/MC/ELF/cfi.s | 41 ++++ test/MC/ELF/empty-dwarf-lines.s | 2 +- tools/llvm-mc/llvm-mc.cpp | 17 +- tools/lto/LTOCodeGenerator.cpp | 2 +- tools/lto/LTOModule.cpp | 2 +- 33 files changed, 554 insertions(+), 176 deletions(-) create mode 100644 include/llvm/Target/TargetAsmInfo.h create mode 100644 lib/Target/TargetAsmInfo.cpp create mode 100644 test/MC/ELF/cfi.s diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index febb9dd990b..9ea27b4b027 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -170,7 +170,8 @@ public: VariableDbgInfoMapTy VariableDbgInfo; MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL. - MachineModuleInfo(const MCAsmInfo &MAI); // Real constructor. + // Real constructor. + MachineModuleInfo(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); ~MachineModuleInfo(); bool doInitialization(); diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 7968e1e27d9..7b26d549377 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -29,6 +29,7 @@ namespace llvm { class MCLineSection; class StringRef; class Twine; + class TargetAsmInfo; class MCSectionMachO; class MCSectionELF; @@ -42,6 +43,8 @@ namespace llvm { /// The MCAsmInfo for this target. const MCAsmInfo &MAI; + const TargetAsmInfo *TAI; + /// Symbols - Bindings of names to symbols. StringMap Symbols; @@ -99,11 +102,13 @@ namespace llvm { MCSymbol *CreateSymbol(StringRef Name); public: - explicit MCContext(const MCAsmInfo &MAI); + explicit MCContext(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); ~MCContext(); const MCAsmInfo &getAsmInfo() const { return MAI; } + const TargetAsmInfo &getTargetAsmInfo() const { return *TAI; } + /// @name Symbol Management /// @{ diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 46177be2303..81e06514281 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -22,6 +22,7 @@ #include namespace llvm { + class MachineMove; class MCContext; class MCSection; class MCSectionData; @@ -208,7 +209,7 @@ namespace llvm { // // This emits the Dwarf file and the line tables. // - static void Emit(MCStreamer *MCOS, const MCSection *DwarfLineSection); + static void Emit(MCStreamer *MCOS); }; class MCDwarfLineAddr { @@ -224,6 +225,21 @@ namespace llvm { static void Write(MCObjectWriter *OW, int64_t LineDelta, uint64_t AddrDelta); }; + + struct MCDwarfFrameInfo { + MCSymbol *Begin; + MCSymbol *End; + const MCSymbol *Personality; + const MCSymbol *Lsda; + }; + + class MCDwarfFrameEmitter { + public: + // + // This emits the frame info section. + // + static void Emit(MCStreamer &streamer); + }; } // end namespace llvm #endif diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index c6dd96068ff..17ba09e3a0b 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -59,7 +59,8 @@ public: /// @{ virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace); virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index d4c759d248c..00c1600b324 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -16,6 +16,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" namespace llvm { class MCAsmInfo; @@ -48,6 +49,9 @@ namespace llvm { MCStreamer(const MCStreamer&); // DO NOT IMPLEMENT MCStreamer &operator=(const MCStreamer&); // DO NOT IMPLEMENT + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool isPCRel, unsigned AddrSpace); + protected: MCStreamer(MCContext &Ctx); @@ -59,11 +63,23 @@ namespace llvm { /// is kept up to date by SwitchSection. const MCSection *PrevSection; + std::vector FrameInfos; + MCDwarfFrameInfo *getCurrentFrameInfo(); + void EnsureValidFrame(); + public: virtual ~MCStreamer(); MCContext &getContext() const { return Context; } + unsigned getNumFrameInfos() { + return FrameInfos.size(); + } + + const MCDwarfFrameInfo &getFrameInfo(unsigned i) { + return FrameInfos[i]; + } + /// @name Assembly File Formatting. /// @{ @@ -241,8 +257,13 @@ namespace llvm { /// @param Value - The value to emit. /// @param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - virtual void EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace = 0) = 0; + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) = 0; + + void EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace = 0); + + void EmitPCRelValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace = 0); /// EmitIntValue - Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. @@ -275,6 +296,9 @@ namespace llvm { void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, unsigned AddrSpace = 0); + void EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace = 0); + /// EmitGPRel32Value - Emit the expression @p Value into the output as a /// gprel32 (32-bit GP relative) value. /// @@ -405,19 +429,12 @@ namespace llvm { /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint = 0, MCCodeEmitter *CE = 0, 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 /// Mach-O format object files. /// diff --git a/include/llvm/Target/TargetAsmBackend.h b/include/llvm/Target/TargetAsmBackend.h index 4805e1966f2..e204a5fed57 100644 --- a/include/llvm/Target/TargetAsmBackend.h +++ b/include/llvm/Target/TargetAsmBackend.h @@ -21,7 +21,6 @@ class MCObjectWriter; class MCSection; template class SmallVectorImpl; -class Target; class raw_ostream; /// TargetAsmBackend - Generic interface to target specific assembler backends. @@ -81,9 +80,6 @@ public: return true; } - /// getPointerSize - Get the pointer size in bytes. - virtual unsigned getPointerSize() const = 0; - /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h new file mode 100644 index 00000000000..cfe60e671a6 --- /dev/null +++ b/include/llvm/Target/TargetAsmInfo.h @@ -0,0 +1,75 @@ +//===-- llvm/Target/TargetAsmInfo.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to provide the information necessary for producing assembly files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETASMINFO_H +#define LLVM_TARGET_TARGETASMINFO_H + +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class MCSection; + class MCContext; + class TargetMachine; + class TargetLoweringObjectFile; + +class TargetAsmInfo { + unsigned PointerSize; + bool IsLittleEndian; + TargetFrameInfo::StackDirection StackDir; + const TargetRegisterInfo *TRI; + std::vector InitialFrameState; + const TargetLoweringObjectFile *TLOF; + +public: + explicit TargetAsmInfo(const TargetMachine &TM); + + /// getPointerSize - Get the pointer size in bytes. + unsigned getPointerSize() const { + return PointerSize; + } + + /// islittleendian - True if the target is little endian. + bool isLittleEndian() const { + return IsLittleEndian; + } + + TargetFrameInfo::StackDirection getStackGrowthDirection() const { + return StackDir; + } + + const MCSection *getDwarfLineSection() const { + return TLOF->getDwarfLineSection(); + } + + const MCSection *getEHFrameSection() const { + return TLOF->getEHFrameSection(); + } + + unsigned getDwarfRARegNum(bool isEH) const { + return TRI->getDwarfRegNum(TRI->getRARegister(), isEH); + } + + const std::vector &getInitialFrameState() const { + return InitialFrameState; + } + + int getDwarfRegNum(unsigned RegNum, bool isEH) const { + return TRI->getDwarfRegNum(RegNum, isEH); + } +}; + +} +#endif diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index abffb5852a6..fe2146b8d8f 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -42,7 +42,8 @@ namespace llvm { class formatted_raw_ostream; MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint, MCCodeEmitter *CE, bool ShowInst); @@ -90,8 +91,8 @@ namespace llvm { bool RelaxAll); typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint, MCCodeEmitter *CE, bool ShowInst); @@ -318,13 +319,13 @@ namespace llvm { /// createAsmStreamer - Create a target specific MCStreamer. MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint, MCCodeEmitter *CE, bool ShowInst) const { // AsmStreamerCtorFn is default to llvm::createAsmStreamer - return AsmStreamerCtorFn(Ctx, OS, isLittleEndian, isVerboseAsm, + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, InstPrint, CE, ShowInst); } diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index d14728d8a36..2da62449320 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -45,6 +45,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetELFWriterInfo.h" #include "llvm/Target/TargetLowering.h" @@ -64,7 +65,7 @@ char ELFWriter::ID = 0; ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) : MachineFunctionPass(ID), O(o), TM(tm), - OutContext(*new MCContext(*TM.getMCAsmInfo())), + OutContext(*new MCContext(*TM.getMCAsmInfo(), new TargetAsmInfo(tm))), TLOF(TM.getTargetLowering()->getObjFileLowering()), is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64), isLittleEndian(TM.getTargetData()->isLittleEndian()), diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 5954f62da95..af94365218c 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -24,6 +24,7 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Transforms/Scalar.h" @@ -145,27 +146,12 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, if (ShowMCEncoding) MCE = getTarget().createCodeEmitter(*this, *Context); - const TargetLoweringObjectFile &TLOF = - getTargetLowering()->getObjFileLowering(); - int PointerSize = getTargetData()->getPointerSize(); - - MCStreamer *S; - if (hasMCUseLoc()) - S = getTarget().createAsmStreamer(*Context, Out, - getTargetData()->isLittleEndian(), - getVerboseAsm(), - InstPrinter, - MCE, - ShowMCInst); - else - S = createAsmStreamerNoLoc(*Context, Out, - getTargetData()->isLittleEndian(), - getVerboseAsm(), - &TLOF, - PointerSize, - InstPrinter, - MCE, - ShowMCInst); + MCStreamer *S = getTarget().createAsmStreamer(*Context, Out, + getVerboseAsm(), + hasMCUseLoc(), + InstPrinter, + MCE, + ShowMCInst); AsmStreamer.reset(S); break; } @@ -344,7 +330,8 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, // Install a MachineModuleInfo class, which is an immutable pass that holds // all the per-module stuff we're generating, including MCContext. - MachineModuleInfo *MMI = new MachineModuleInfo(*getMCAsmInfo()); + TargetAsmInfo *TAI = new TargetAsmInfo(*this); + MachineModuleInfo *MMI = new MachineModuleInfo(*getMCAsmInfo(), TAI); PM.add(MMI); OutContext = &MMI->getContext(); // Return the MCContext specifically by-ref. diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index 79622e8df3e..fadc594efcb 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -253,8 +253,9 @@ void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) { //===----------------------------------------------------------------------===// -MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI) -: ImmutablePass(ID), Context(MAI), +MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI, + const TargetAsmInfo *TAI) +: ImmutablePass(ID), Context(MAI, TAI), ObjFileMMI(0), CurCallSite(0), CallsEHReturn(0), CallsUnwindInit(0), DbgInfoAvailable(false), CallsExternalVAFunctionWithFloatingPointArguments(false) { @@ -266,7 +267,7 @@ MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI) } MachineModuleInfo::MachineModuleInfo() -: ImmutablePass(ID), Context(*(MCAsmInfo*)0) { +: ImmutablePass(ID), Context(*(MCAsmInfo*)0, NULL) { assert(0 && "This MachineModuleInfo constructor should never be called, MMI " "should always be explicitly constructed by LLVMTargetMachine"); abort(); diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 944ed26f542..abc01a28776 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -135,7 +135,7 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, SectionKind::getReadOnly()); EHFrameSection = getContext().getELFSection(".eh_frame", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC |MCSectionELF::SHF_WRITE, + MCSectionELF::SHF_ALLOC, SectionKind::getDataRel()); // Debug Info Sections. diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index ce85e462b3d..a1c02208a0b 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetAsmInfo.h" using namespace llvm; namespace { @@ -37,32 +38,26 @@ class MCAsmStreamer : public MCStreamer { SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; - const TargetLoweringObjectFile *TLOF; - int PointerSize; - - unsigned IsLittleEndian : 1; unsigned IsVerboseAsm : 1; unsigned ShowInst : 1; + unsigned UseLoc : 1; bool needsSet(const MCExpr *Value); public: MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, - bool isLittleEndian, bool isVerboseAsm, - const TargetLoweringObjectFile *tlof, int pointerSize, + bool isVerboseAsm, + bool useLoc, MCInstPrinter *printer, MCCodeEmitter *emitter, bool showInst) : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit), - TLOF(tlof), PointerSize(pointerSize), - IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm), - ShowInst(showInst) { + IsVerboseAsm(isVerboseAsm), + ShowInst(showInst), UseLoc(useLoc) { if (InstPrinter && IsVerboseAsm) InstPrinter->setCommentStream(CommentStream); } ~MCAsmStreamer() {} - bool isLittleEndian() const { return IsLittleEndian; } - inline void EmitEOL() { // If we don't have any comments, just emit a \n. if (!IsVerboseAsm) { @@ -152,7 +147,8 @@ public: virtual void EmitBytes(StringRef Data, unsigned AddrSpace); - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace); virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace = 0); @@ -307,7 +303,8 @@ void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { void MCAsmStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label) { - EmitDwarfSetLineAddr(LineDelta, Label, PointerSize); + EmitDwarfSetLineAddr(LineDelta, Label, + getContext().getTargetAsmInfo().getPointerSize()); } void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, @@ -512,9 +509,10 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace); } -void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { +void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) { assert(CurSection && "Cannot emit contents before setting section!"); + assert(!isPCRel && "Cannot emit pc relative relocations!"); const char *Directive = 0; switch (Size) { default: break; @@ -528,7 +526,7 @@ void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, int64_t IntValue; if (!Value->EvaluateAsAbsolute(IntValue)) report_fatal_error("Don't know how to emit this value."); - if (isLittleEndian()) { + if (getContext().getTargetAsmInfo().isLittleEndian()) { EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); } else { @@ -662,7 +660,7 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) { } bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ - if (!TLOF) { + if (UseLoc) { OS << "\t.file\t" << FileNo << ' '; PrintQuotedString(Filename, OS); EmitEOL(); @@ -676,7 +674,7 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Discriminator) { this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, Isa, Discriminator); - if (TLOF) + if (!UseLoc) return; OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; @@ -829,7 +827,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { unsigned Bit = (Code[i] >> j) & 1; unsigned FixupBit; - if (IsLittleEndian) + if (getContext().getTargetAsmInfo().isLittleEndian()) FixupBit = i * 8 + j; else FixupBit = i * 8 + (7-j); @@ -855,7 +853,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { assert(CurSection && "Cannot emit contents before setting section!"); - if (TLOF) + if (!UseLoc) MCLineEntry::Make(this, getCurrentSection()); // Show the encoding in a comment if we have a code emitter. @@ -888,28 +886,15 @@ void MCAsmStreamer::EmitRawText(StringRef String) { void MCAsmStreamer::Finish() { // Dump out the dwarf file & directory tables and line tables. - if (getContext().hasDwarfFiles() && TLOF) - MCDwarfFileTable::Emit(this, TLOF->getDwarfLineSection()); + if (getContext().hasDwarfFiles() && !UseLoc) + MCDwarfFileTable::Emit(this); } MCStreamer *llvm::createAsmStreamer(MCContext &Context, formatted_raw_ostream &OS, - bool isLittleEndian, - bool isVerboseAsm, MCInstPrinter *IP, + bool isVerboseAsm, bool useLoc, + MCInstPrinter *IP, MCCodeEmitter *CE, bool ShowInst) { - return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, - 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); + return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc, + IP, CE, ShowInst); } diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index a1bc9d8b6f5..839c08d8a26 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -15,6 +15,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCLabel.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" using namespace llvm; @@ -24,8 +25,9 @@ typedef StringMap ELFUniqueMapTy; typedef StringMap COFFUniqueMapTy; -MCContext::MCContext(const MCAsmInfo &mai) : MAI(mai), NextUniqueID(0), - CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0) { +MCContext::MCContext(const MCAsmInfo &mai, const TargetAsmInfo *tai) : + MAI(mai), TAI(tai), NextUniqueID(0), + CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0) { MachOUniquingMap = 0; ELFUniquingMap = 0; COFFUniquingMap = 0; @@ -48,6 +50,8 @@ MCContext::~MCContext() { // If the stream for the .secure_log_unique directive was created free it. delete (raw_ostream*)SecureLog; + + delete TAI; } //===----------------------------------------------------------------------===// diff --git a/lib/MC/MCDisassembler/EDDisassembler.cpp b/lib/MC/MCDisassembler/EDDisassembler.cpp index 697b3d9c051..2fd14db2a45 100644 --- a/lib/MC/MCDisassembler/EDDisassembler.cpp +++ b/lib/MC/MCDisassembler/EDDisassembler.cpp @@ -354,7 +354,7 @@ int EDDisassembler::parseInst(SmallVectorImpl &operands, SourceMgr sourceMgr; sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over - MCContext context(*AsmInfo); + MCContext context(*AsmInfo, NULL); OwningPtr streamer(createNullStreamer(context)); OwningPtr genericParser(createMCAsmParser(*Tgt, sourceMgr, context, *streamer, diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index d7540ce077d..c1de31bf069 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" using namespace llvm; // Given a special op, return the address skip amount (in units of @@ -125,8 +126,7 @@ static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, // static inline void EmitDwarfLineTable(MCStreamer *MCOS, const MCSection *Section, - const MCLineSection *LineSection, - const MCSection *DwarfLineSection) { + const MCLineSection *LineSection) { unsigned FileNum = 1; unsigned LastLine = 1; unsigned Column = 0; @@ -185,13 +185,15 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // Switch to the section to be able to create a symbol at its end. MCOS->SwitchSection(Section); + + MCContext &context = MCOS->getContext(); // Create a symbol at the end of the section. - MCSymbol *SectionEnd = MCOS->getContext().CreateTempSymbol(); + MCSymbol *SectionEnd = context.CreateTempSymbol(); // Set the value of the symbol, as we are at the end of the section. MCOS->EmitLabel(SectionEnd); // Switch back the the dwarf line section. - MCOS->SwitchSection(DwarfLineSection); + MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection()); MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd); } @@ -199,18 +201,18 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // // This emits the Dwarf file and the line tables. // -void MCDwarfFileTable::Emit(MCStreamer *MCOS, - const MCSection *DwarfLineSection) { +void MCDwarfFileTable::Emit(MCStreamer *MCOS) { + MCContext &context = MCOS->getContext(); // Switch to the section where the table will be emitted into. - MCOS->SwitchSection(DwarfLineSection); + MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection()); // Create a symbol at the beginning of this section. - MCSymbol *LineStartSym = MCOS->getContext().CreateTempSymbol(); + MCSymbol *LineStartSym = context.CreateTempSymbol(); // Set the value of the symbol, as we are at the start of the section. MCOS->EmitLabel(LineStartSym); // Create a symbol for the end of the section (to be set when we get there). - MCSymbol *LineEndSym = MCOS->getContext().CreateTempSymbol(); + MCSymbol *LineEndSym = context.CreateTempSymbol(); // The first 4 bytes is the total length of the information for this // compilation unit (not including these 4 bytes for the length). @@ -221,7 +223,7 @@ void MCDwarfFileTable::Emit(MCStreamer *MCOS, MCOS->EmitIntValue(2, 2); // Create a symbol for the end of the prologue (to be set when we get there). - MCSymbol *ProEndSym = MCOS->getContext().CreateTempSymbol(); // Lprologue_end + MCSymbol *ProEndSym = context.CreateTempSymbol(); // Lprologue_end // Length of the prologue, is the next 4 bytes. Which is the start of the // section to the end of the prologue. Not including the 4 bytes for the @@ -256,7 +258,7 @@ void MCDwarfFileTable::Emit(MCStreamer *MCOS, // First the directory table. const std::vector &MCDwarfDirs = - MCOS->getContext().getMCDwarfDirs(); + context.getMCDwarfDirs(); for (unsigned i = 0; i < MCDwarfDirs.size(); i++) { MCOS->EmitBytes(MCDwarfDirs[i], 0); // the DirectoryName MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string @@ -290,7 +292,7 @@ void MCDwarfFileTable::Emit(MCStreamer *MCOS, ++it) { const MCSection *Sec = *it; const MCLineSection *Line = MCLineSections.lookup(Sec); - EmitDwarfLineTable(MCOS, Sec, Line, DwarfLineSection); + EmitDwarfLineTable(MCOS, Sec, Line); // Now delete the MCLineSections that were created in MCLineEntry::Make() // and used to emit the line table. @@ -425,3 +427,187 @@ void MCDwarfFile::dump() const { print(dbgs()); } +static int getDataAlignmentFactor(MCStreamer &streamer) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + int size = asmInfo.getPointerSize(); + if (asmInfo.getStackGrowthDirection() == TargetFrameInfo::StackGrowsUp) + return size; + else + return -size; +} + +/// EmitFrameMoves - Emit frame instructions to describe the layout of the +/// frame. +static void EmitFrameMoves(MCStreamer &streamer, + const std::vector &Moves, + MCSymbol *BaseLabel, bool isEH) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + int dataAlignmentFactor = getDataAlignmentFactor(streamer); + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + MCSymbol *Label = Move.getLabel(); + // Throw out move if the label is invalid. + if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabel && Label) { + MCSymbol *ThisSym = Label; + if (ThisSym != BaseLabel) { + streamer.EmitIntValue(dwarf::DW_CFA_advance_loc4, 1); + const MCExpr *Length = MakeStartMinusEndExpr(streamer, *BaseLabel, + *ThisSym, 4); + streamer.EmitValue(Length, 4); + BaseLabel = ThisSym; + } + } + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + assert(!Src.isReg() && "Machine move not supported yet."); + + if (Src.getReg() == MachineLocation::VirtualFP) { + streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); + } else { + streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); + streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Src.getReg(), isEH), + 1); + } + + streamer.EmitULEB128IntValue(-Src.getOffset(), 1); + continue; + } + + if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + assert(Dst.isReg() && "Machine move not supported yet."); + streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); + streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Dst.getReg(), isEH)); + continue; + } + + unsigned Reg = asmInfo.getDwarfRegNum(Src.getReg(), isEH); + int Offset = Dst.getOffset() / dataAlignmentFactor; + + if (Offset < 0) { + streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); + streamer.EmitULEB128IntValue(Reg); + streamer.EmitSLEB128IntValue(Offset); + } else if (Reg < 64) { + streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); + streamer.EmitULEB128IntValue(Offset, 1); + } else { + streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); + streamer.EmitULEB128IntValue(Reg, 1); + streamer.EmitULEB128IntValue(Offset, 1); + } + } +} + +static const MCSymbol &EmitCIE(MCStreamer &streamer) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + const MCSection §ion = *asmInfo.getEHFrameSection(); + streamer.SwitchSection(§ion); + MCSymbol *sectionStart = streamer.getContext().CreateTempSymbol(); + MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol(); + + // Length + const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, + *sectionEnd, 4); + streamer.EmitLabel(sectionStart); + streamer.EmitValue(Length, 4); + + // CIE ID + streamer.EmitIntValue(0, 4); + + // Version + streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); + + // Augmentation String + SmallString<8> Augmentation; + Augmentation += "zR"; + streamer.EmitBytes(Augmentation.str(), 0); + streamer.EmitIntValue(0, 1); + + // Code Alignment Factor + streamer.EmitULEB128IntValue(1); + + // Data Alignment Factor + streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); + + // Return Address Register + streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(true)); + + // Augmentation Data Length (optional) + MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol(); + MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol(); + const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer, + *augmentationStart, + *augmentationEnd, 0); + streamer.EmitULEB128Value(augmentationLength); + + // Augmentation Data (optional) + streamer.EmitLabel(augmentationStart); + streamer.EmitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1); + streamer.EmitLabel(augmentationEnd); + + // Initial Instructions + + const std::vector Moves = asmInfo.getInitialFrameState(); + + EmitFrameMoves(streamer, Moves, NULL, true); + + // Padding + streamer.EmitValueToAlignment(asmInfo.getPointerSize()); + + streamer.EmitLabel(sectionEnd); + return *sectionStart; +} + +static void EmitFDE(MCStreamer &streamer, + const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + MCSymbol *fdeStart = streamer.getContext().CreateTempSymbol(); + MCSymbol *fdeEnd = streamer.getContext().CreateTempSymbol(); + + // Length + const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); + streamer.EmitValue(Length, 4); + + streamer.EmitLabel(fdeStart); + // CIE Pointer + const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, + 0); + streamer.EmitValue(offset, 4); + + // PC Begin + streamer.EmitPCRelSymbolValue(frame.Begin, 4); + + // PC Range + const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, + *frame.End, 0); + streamer.EmitValue(Range, 4); + + // Augmentation Data Length + streamer.EmitULEB128IntValue(0); + + // Augmentation Data + // Call Frame Instructions + + // Padding + streamer.EmitValueToAlignment(asmInfo.getPointerSize()); + streamer.EmitLabel(fdeEnd); +} + +void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) { + const MCSymbol &cieStart = EmitCIE(streamer); + for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) + EmitFDE(streamer, cieStart, streamer.getFrameInfo(i)); +} diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 18d8fa39edd..6900b247ce8 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" using namespace llvm; @@ -478,14 +479,8 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { } void MCELFStreamer::Finish() { - // FIXME: duplicated code with the MachO streamer. - // Dump out the dwarf file & directory tables and line tables. - if (getContext().hasDwarfFiles()) { - const MCSection *DwarfLineSection = - getContext().getELFSection(".debug_line", 0, 0, - SectionKind::getDataRelLocal()); - MCDwarfFileTable::Emit(this, DwarfLineSection); - } + if (!FrameInfos.empty()) + MCDwarfFrameEmitter::Emit(*this); for (std::vector::const_iterator i = LocalCommons.begin(), e = LocalCommons.end(); diff --git a/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp index 134554b8006..d9474813837 100644 --- a/lib/MC/MCLoggingStreamer.cpp +++ b/lib/MC/MCLoggingStreamer.cpp @@ -154,9 +154,10 @@ public: return Child->EmitBytes(Data, AddrSpace); } - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace){ + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace){ LogCall("EmitValue"); - return Child->EmitValue(Value, Size, AddrSpace); + return Child->EmitValueImpl(Value, Size, isPCRel, AddrSpace); } virtual void EmitULEB128Value(const MCExpr *Value, diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 47060234b38..df1e7d8e2b5 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" using namespace llvm; @@ -354,15 +355,6 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst) { } void MCMachOStreamer::Finish() { - // Dump out the dwarf file & directory tables and line tables. - if (getContext().hasDwarfFiles()) { - const MCSection *DwarfLineSection = getContext().getMachOSection("__DWARF", - "__debug_line", - MCSectionMachO::S_ATTR_DEBUG, - 0, SectionKind::getDataRelLocal()); - MCDwarfFileTable::Emit(this, DwarfLineSection); - } - // We have to set the fragment atom associations so we can relax properly for // Mach-O. diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index c8f9c636174..b9393ffd2e9 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -68,8 +68,8 @@ namespace { uint64_t Size, unsigned ByteAlignment) {} virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {} - virtual void EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) {} + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) {} virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0) {} virtual void EmitSLEB128Value(const MCExpr *Value, diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 683f2c6adc6..7d3006a712c 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -12,10 +12,12 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" using namespace llvm; MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, @@ -74,8 +76,8 @@ const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { return Value; } -void MCObjectStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { +void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) { assert(AddrSpace == 0 && "Address space must be 0!"); MCDataFragment *DF = getOrCreateDataFragment(); @@ -87,7 +89,7 @@ void MCObjectStreamer::EmitValue(const MCExpr *Value, unsigned Size, } DF->addFixup(MCFixup::Create(DF->getContents().size(), AddValueSymbols(Value), - MCFixup::getKindForSize(Size, false))); + MCFixup::getKindForSize(Size, isPCRel))); DF->getContents().resize(DF->getContents().size() + Size, 0); } @@ -189,7 +191,7 @@ void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label) { if (!LastLabel) { - int PointerSize = getAssembler().getBackend().getPointerSize(); + int PointerSize = getContext().getTargetAsmInfo().getPointerSize(); EmitDwarfSetLineAddr(LineDelta, Label, PointerSize); return; } @@ -215,5 +217,9 @@ void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset, } void MCObjectStreamer::Finish() { + // Dump out the dwarf file & directory tables and line tables. + if (getContext().hasDwarfFiles()) + MCDwarfFileTable::Emit(this); + getAssembler().Finish(); } diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index e003a953ade..6f9692d2274 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -85,9 +85,31 @@ void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size, EmitSymbolValue(ABS, Size, AddrSpace); } + +void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) { + EmitValueImpl(Value, Size, false, AddrSpace); +} + +void MCStreamer::EmitPCRelValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) { + EmitValueImpl(Value, Size, true, AddrSpace); +} + +void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool isPCRel, unsigned AddrSpace) { + EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size, isPCRel, + AddrSpace); +} + void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, unsigned AddrSpace) { - EmitValue(MCSymbolRefExpr::Create(Sym, getContext()), Size, AddrSpace); + EmitSymbolValue(Sym, Size, false, AddrSpace); +} + +void MCStreamer::EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace) { + EmitSymbolValue(Sym, Size, true, AddrSpace); } void MCStreamer::EmitGPRel32Value(const MCExpr *Value) { @@ -116,31 +138,65 @@ void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, Discriminator); } +MCDwarfFrameInfo *MCStreamer::getCurrentFrameInfo() { + if (FrameInfos.empty()) + return NULL; + return &FrameInfos.back(); +} + +void MCStreamer::EnsureValidFrame() { + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + if (!CurFrame || CurFrame->End) + report_fatal_error("No open frame"); +} + bool MCStreamer::EmitCFIStartProc() { + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + if (CurFrame && !CurFrame->End) { + report_fatal_error("Starting a frame before finishing the previous one!"); + return true; + } + MCDwarfFrameInfo Frame = {0, 0, 0, 0}; + Frame.Begin = getContext().CreateTempSymbol(); + EmitLabel(Frame.Begin); + FrameInfos.push_back(Frame); return false; } bool MCStreamer::EmitCFIEndProc() { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + CurFrame->End = getContext().CreateTempSymbol(); + EmitLabel(CurFrame->End); return false; } bool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { + EnsureValidFrame(); return false; } bool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { + EnsureValidFrame(); return false; } bool MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { + EnsureValidFrame(); return false; } bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + CurFrame->Personality = Sym; return false; } bool MCStreamer::EmitCFILsda(const MCSymbol *Sym) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + CurFrame->Lsda = Sym; return false; } diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index c89fe06d99b..6c555a3e9d1 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -1755,7 +1755,7 @@ bool CWriter::doInitialization(Module &M) { TAsm = Match->createAsmInfo(Triple); #endif TAsm = new CBEMCAsmInfo(); - TCtx = new MCContext(*TAsm); + TCtx = new MCContext(*TAsm, NULL); Mang = new Mangler(*TCtx, *TD); // Keep track of which functions are static ctors/dtors so they can have diff --git a/lib/Target/CMakeLists.txt b/lib/Target/CMakeLists.txt index 43ebdac528c..4e62d96e464 100644 --- a/lib/Target/CMakeLists.txt +++ b/lib/Target/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_library(LLVMTarget Mangler.cpp SubtargetFeature.cpp Target.cpp + TargetAsmInfo.cpp TargetAsmLexer.cpp TargetData.cpp TargetELFWriterInfo.cpp diff --git a/lib/Target/PTX/PTXMCAsmStreamer.cpp b/lib/Target/PTX/PTXMCAsmStreamer.cpp index 4e517ad76a2..ec9dc960be7 100644 --- a/lib/Target/PTX/PTXMCAsmStreamer.cpp +++ b/lib/Target/PTX/PTXMCAsmStreamer.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmInfo.h" using namespace llvm; @@ -36,21 +37,19 @@ class PTXMCAsmStreamer : public MCStreamer { SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; - unsigned IsLittleEndian : 1; unsigned IsVerboseAsm : 1; unsigned ShowInst : 1; public: PTXMCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, - bool isLittleEndian, - bool isVerboseAsm, + bool isVerboseAsm, bool useLoc, MCInstPrinter *printer, MCCodeEmitter *emitter, bool showInst) : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit), - IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm), + IsVerboseAsm(isVerboseAsm), ShowInst(showInst) { if (InstPrinter && IsVerboseAsm) InstPrinter->setCommentStream(CommentStream); @@ -58,8 +57,6 @@ public: ~PTXMCAsmStreamer() {} - bool isLittleEndian() const { return IsLittleEndian; } - inline void EmitEOL() { // If we don't have any comments, just emit a \n. if (!IsVerboseAsm) { @@ -147,7 +144,8 @@ public: virtual void EmitBytes(StringRef Data, unsigned AddrSpace); - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace); virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitGPRel32Value(const MCExpr *Value); @@ -359,9 +357,10 @@ void PTXMCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { EmitEOL(); } -void PTXMCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { +void PTXMCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) { assert(CurSection && "Cannot emit contents before setting section!"); + assert(!isPCRel && "Cannot emit pc relative relocations!"); const char *Directive = 0; switch (Size) { default: break; @@ -375,7 +374,7 @@ void PTXMCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, int64_t IntValue; if (!Value->EvaluateAsAbsolute(IntValue)) report_fatal_error("Don't know how to emit this value."); - if (isLittleEndian()) { + if (getContext().getTargetAsmInfo().isLittleEndian()) { EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); } else { @@ -539,10 +538,10 @@ void PTXMCAsmStreamer::Finish() {} namespace llvm { MCStreamer *createPTXAsmStreamer(MCContext &Context, formatted_raw_ostream &OS, - bool isLittleEndian, - bool isVerboseAsm, MCInstPrinter *IP, + bool isVerboseAsm, bool useLoc, + MCInstPrinter *IP, MCCodeEmitter *CE, bool ShowInst) { - return new PTXMCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, + return new PTXMCAsmStreamer(Context, OS, isVerboseAsm, useLoc, IP, CE, ShowInst); } } diff --git a/lib/Target/PTX/PTXTargetMachine.cpp b/lib/Target/PTX/PTXTargetMachine.cpp index f62a5299a11..0e9f5181ed5 100644 --- a/lib/Target/PTX/PTXTargetMachine.cpp +++ b/lib/Target/PTX/PTXTargetMachine.cpp @@ -21,7 +21,7 @@ using namespace llvm; namespace llvm { MCStreamer *createPTXAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool isVerboseAsm, bool useLoc, MCInstPrinter *InstPrint, MCCodeEmitter *CE, bool ShowInst); diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp new file mode 100644 index 00000000000..30b73c46a79 --- /dev/null +++ b/lib/Target/TargetAsmInfo.cpp @@ -0,0 +1,27 @@ +//===-- llvm/Target/TargetAsmInfo.cpp - Target Assembly Info --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +using namespace llvm; + +TargetAsmInfo::TargetAsmInfo(const TargetMachine &TM) { + TLOF = &TM.getTargetLowering()->getObjFileLowering(); + const TargetData &TD = *TM.getTargetData(); + IsLittleEndian = TD.isLittleEndian(); + PointerSize = TD.getPointerSize(); + const TargetFrameInfo &TFI = *TM.getFrameInfo(); + StackDir = TFI.getStackGrowthDirection(); + TRI = TM.getRegisterInfo(); + TFI.getInitialFrameState(InitialFrameState); +} diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp index 5626fd7afd3..f251585f3b1 100644 --- a/lib/Target/X86/X86AsmBackend.cpp +++ b/lib/Target/X86/X86AsmBackend.cpp @@ -279,10 +279,6 @@ public: ELFX86_32AsmBackend(const Target &T, Triple::OSType OSType) : ELFX86AsmBackend(T, OSType) {} - unsigned getPointerSize() const { - return 4; - } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createELFObjectWriter(OS, /*Is64Bit=*/false, OSType, ELF::EM_386, @@ -296,10 +292,6 @@ public: ELFX86_64AsmBackend(const Target &T, Triple::OSType OSType) : ELFX86AsmBackend(T, OSType) {} - unsigned getPointerSize() const { - return 8; - } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createELFObjectWriter(OS, /*Is64Bit=*/true, OSType, ELF::EM_X86_64, @@ -323,13 +315,6 @@ public: return Format; } - unsigned getPointerSize() const { - if (Is64Bit) - return 8; - else - return 4; - } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createWinCOFFObjectWriter(OS, Is64Bit); } @@ -354,10 +339,6 @@ public: DarwinX86_32AsmBackend(const Target &T) : DarwinX86AsmBackend(T) {} - unsigned getPointerSize() const { - return 4; - } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createMachObjectWriter(OS, /*Is64Bit=*/false, object::mach::CTM_i386, @@ -373,10 +354,6 @@ public: HasReliableSymbolDifference = true; } - unsigned getPointerSize() const { - return 8; - } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { return createMachObjectWriter(OS, /*Is64Bit=*/true, object::mach::CTM_x86_64, diff --git a/test/MC/ELF/cfi.s b/test/MC/ELF/cfi.s new file mode 100644 index 00000000000..df62d7de06c --- /dev/null +++ b/test/MC/ELF/cfi.s @@ -0,0 +1,41 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +f: + .cfi_startproc + nop + .cfi_endproc + +// CHECK: # Section 0x00000004 +// CHECK-NEXT: (('sh_name', 0x00000012) # '.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000001) +// CHECK-NEXT: ('sh_flags', 0x00000002) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000048) +// CHECK-NEXT: ('sh_size', 0x00000030) +// CHECK-NEXT: ('sh_link', 0x00000000) +// CHECK-NEXT: ('sh_info', 0x00000000) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000000) +// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 01000000 00000000 00000000') +// CHECK-NEXT: ), + +// CHECK: # Section 0x00000008 +// CHECK-NEXT: (('sh_name', 0x00000036) # '.rela.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000004) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000158) +// CHECK-NEXT: ('sh_size', 0x00000018) +// CHECK-NEXT: ('sh_link', 0x00000006) +// CHECK-NEXT: ('sh_info', 0x00000004) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000018) +// CHECK-NEXT: ('_relocations', [ +// CHECK-NEXT: # Relocation 0x00000000 +// CHECK-NEXT: (('r_offset', 0x00000020) +// CHECK-NEXT: ('r_sym', 0x00000002) +// CHECK-NEXT: ('r_type', 0x00000002) +// CHECK-NEXT: ('r_addend', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) +// CHECK-NEXT: ), diff --git a/test/MC/ELF/empty-dwarf-lines.s b/test/MC/ELF/empty-dwarf-lines.s index 81d98711e9d..0f791ae2aa3 100644 --- a/test/MC/ELF/empty-dwarf-lines.s +++ b/test/MC/ELF/empty-dwarf-lines.s @@ -9,7 +9,7 @@ c: // CHECK: # Section 0x00000004 // CHECK-NEXT: (('sh_name', 0x00000012) # '.debug_line' -// CHECK-NEXT: ('sh_type', 0x00000000) +// CHECK-NEXT: ('sh_type', 0x00000001) // CHECK-NEXT: ('sh_flags', 0x00000000) // CHECK-NEXT: ('sh_addr', 0x00000000) // CHECK-NEXT: ('sh_offset', 0x00000044) diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 46eb3727d66..c59c80a0501 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -24,6 +24,9 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/SubtargetFeature.h" // FIXME. +#include "llvm/Target/TargetAsmInfo.h" // FIXME. +#include "llvm/Target/TargetLowering.h" // FIXME. +#include "llvm/Target/TargetLoweringObjectFile.h" // FIXME. #include "llvm/Target/TargetMachine.h" // FIXME. #include "llvm/Target/TargetSelect.h" #include "llvm/ADT/OwningPtr.h" @@ -298,8 +301,6 @@ static int AssembleInput(const char *ProgName) { llvm::OwningPtr MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); - MCContext Ctx(*MAI); - // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MCPU.size()) { @@ -321,6 +322,9 @@ static int AssembleInput(const char *ProgName) { return 1; } + const TargetAsmInfo *tai = new TargetAsmInfo(*TM); + MCContext Ctx(*MAI, tai); + OwningPtr Out(GetOutputStream()); if (!Out) return 1; @@ -328,15 +332,18 @@ static int AssembleInput(const char *ProgName) { formatted_raw_ostream FOS(Out->os()); OwningPtr Str; + const TargetLoweringObjectFile &TLOF = + TM->getTargetLowering()->getObjFileLowering(); + const_cast(TLOF).Initialize(Ctx, *TM); + if (FileType == OFT_AssemblyFile) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI); MCCodeEmitter *CE = 0; if (ShowEncoding) CE = TheTarget->createCodeEmitter(*TM, Ctx); - Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, - TM->getTargetData()->isLittleEndian(), - /*asmverbose*/true, IP, CE, ShowInst)); + Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true, + /*useLoc*/ true, IP, CE, ShowInst)); } else if (FileType == OFT_Null) { Str.reset(createNullStreamer(Ctx)); } else { diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index f1c5680adda..d49e6a77b30 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -347,7 +347,7 @@ void LTOCodeGenerator::applyScopeRestrictions() { // mark which symbols can not be internalized if (!_mustPreserveSymbols.empty()) { - MCContext Context(*_target->getMCAsmInfo()); + MCContext Context(*_target->getMCAsmInfo(), NULL); Mangler mangler(Context, *_target->getTargetData()); std::vector mustPreserveList; for (Module::iterator f = mergedModule->begin(), diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 2453e2b2c2d..a33b8b473e2 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -428,7 +428,7 @@ void LTOModule::lazyParseSymbols() { _symbolsParsed = true; // Use mangler to add GlobalPrefix to names to match linker names. - MCContext Context(*_target->getMCAsmInfo()); + MCContext Context(*_target->getMCAsmInfo(), NULL); Mangler mangler(Context, *_target->getTargetData()); // add functions