X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCAsmStreamer.cpp;h=a171ba120be64e5625017d3ddfbeb0cc4e7677ca;hb=a75ce9f5d2236d93c117e861e60e6f3f748c9555;hp=5dd115d58c611272cda71c4780ca3d99e979ae4c;hpb=ce79299f78bb04e76e1860ab119b85d69f3a19c7;p=oota-llvm.git diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 5dd115d58c6..a171ba120be 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -12,6 +12,7 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSectionMachO.h" @@ -23,6 +24,10 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include using namespace llvm; namespace { @@ -32,29 +37,33 @@ class MCAsmStreamer : public MCStreamer { const MCAsmInfo &MAI; OwningPtr InstPrinter; OwningPtr Emitter; + OwningPtr AsmBackend; SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; - 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, MCInstPrinter *printer, - MCCodeEmitter *emitter, bool showInst) + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *printer, MCCodeEmitter *emitter, + TargetAsmBackend *asmbackend, + bool showInst) : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), - InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit), - IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm), - ShowInst(showInst) { + InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend), + CommentStream(CommentToEmit), 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) { @@ -115,6 +124,9 @@ public: virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); @@ -141,9 +153,10 @@ public: virtual void EmitBytes(StringRef Data, unsigned AddrSpace); - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); - - virtual void EmitIntValue(uint64_t 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); virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); @@ -166,7 +179,18 @@ public: unsigned char Value = 0); virtual void EmitFileDirective(StringRef Filename); - virtual void EmitDwarfFileDirective(unsigned FileNo, StringRef Filename); + virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Filename); + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator); + + virtual bool EmitCFIStartProc(); + virtual bool EmitCFIEndProc(); + virtual bool EmitCFIDefCfaOffset(int64_t Offset); + virtual bool EmitCFIDefCfaRegister(int64_t Register); + virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); + virtual bool EmitCFIPersonality(const MCSymbol *Sym); + virtual bool EmitCFILsda(const MCSymbol *Sym); virtual void EmitInstruction(const MCInst &Inst); @@ -255,6 +279,7 @@ void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; case MCAF_Code16: OS << "\t.code\t16"; break; + case MCAF_Code32: OS << "\t.code\t32"; break; } EmitEOL(); } @@ -281,6 +306,13 @@ void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { EmitEOL(); } +void MCAsmStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) { + EmitDwarfSetLineAddr(LineDelta, Label, + getContext().getTargetAsmInfo().getPointerSize()); +} + void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { switch (Attribute) { @@ -291,6 +323,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype + case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object assert(MAI.hasDotTypeDotSizeDirective() && "Symbol Attr not supported"); OS << "\t.type\t" << *Symbol << ',' << ((MAI.getCommentString()[0] != '@') ? '@' : '%'); @@ -302,6 +335,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_ELF_TypeTLS: OS << "tls_object"; break; case MCSA_ELF_TypeCommon: OS << "common"; break; case MCSA_ELF_TypeNoType: OS << "no_type"; break; + case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; } EmitEOL(); return; @@ -314,6 +348,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; case MCSA_Local: OS << "\t.local\t"; break; case MCSA_NoDeadStrip: OS << "\t.no_dead_strip\t"; break; + case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; case MCSA_PrivateExtern: OS << "\t.private_extern\t"; break; case MCSA_Protected: OS << "\t.protected\t"; break; case MCSA_Reference: OS << "\t.reference\t"; break; @@ -475,11 +510,15 @@ void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { EmitEOL(); } -/// EmitIntValue - Special case of EmitValue that avoids the client having -/// to pass in a MCExpr for constant integers. void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace) { + EmitValue(MCConstantExpr::Create(Value, getContext()), Size, 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; @@ -490,45 +529,41 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, Directive = MAI.getData64bitsDirective(AddrSpace); // If the target doesn't support 64-bit data, emit as two 32-bit halves. if (Directive) break; - if (isLittleEndian()) { - EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace); - EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace); + int64_t IntValue; + if (!Value->EvaluateAsAbsolute(IntValue)) + report_fatal_error("Don't know how to emit this value."); + if (getContext().getTargetAsmInfo().isLittleEndian()) { + EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); + EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); } else { - EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace); - EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace); + EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); + EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); } return; } - assert(Directive && "Invalid size for machine code value!"); - OS << Directive << truncateToSize(Value, Size); - EmitEOL(); -} - -void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { - assert(CurSection && "Cannot emit contents before setting section!"); - const char *Directive = 0; - switch (Size) { - default: break; - case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; - case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; - case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; - case 8: Directive = MAI.getData64bitsDirective(AddrSpace); break; - } - assert(Directive && "Invalid size for machine code value!"); OS << Directive << *Value; EmitEOL(); } void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) { + int64_t IntValue; + if (Value->EvaluateAsAbsolute(IntValue)) { + EmitULEB128IntValue(IntValue, AddrSpace); + return; + } assert(MAI.hasLEB128() && "Cannot print a .uleb"); OS << ".uleb128 " << *Value; EmitEOL(); } void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace) { + int64_t IntValue; + if (Value->EvaluateAsAbsolute(IntValue)) { + EmitSLEB128IntValue(IntValue, AddrSpace); + return; + } assert(MAI.hasLEB128() && "Cannot print a .sleb"); OS << ".sleb128 " << *Value; EmitEOL(); @@ -630,12 +665,119 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) { EmitEOL(); } -void MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ - OS << "\t.file\t" << FileNo << ' '; - PrintQuotedString(Filename, OS); +bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ + if (UseLoc) { + OS << "\t.file\t" << FileNo << ' '; + PrintQuotedString(Filename, OS); + EmitEOL(); + } + return this->MCStreamer::EmitDwarfFileDirective(FileNo, Filename); +} + +void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, + unsigned Discriminator) { + this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, + Isa, Discriminator); + if (!UseLoc) + return; + + OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; + if (Flags & DWARF2_FLAG_BASIC_BLOCK) + OS << " basic_block"; + if (Flags & DWARF2_FLAG_PROLOGUE_END) + OS << " prologue_end"; + if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) + OS << " epilogue_begin"; + + unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); + if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { + OS << " is_stmt "; + + if (Flags & DWARF2_FLAG_IS_STMT) + OS << "1"; + else + OS << "0"; + } + + if (Isa) + OS << "isa " << Isa; + if (Discriminator) + OS << "discriminator " << Discriminator; EmitEOL(); } +bool MCAsmStreamer::EmitCFIStartProc() { + if (this->MCStreamer::EmitCFIStartProc()) + return true; + + OS << ".cfi_startproc"; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIEndProc() { + if (this->MCStreamer::EmitCFIEndProc()) + return true; + + OS << ".cfi_endproc"; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { + if (this->MCStreamer::EmitCFIDefCfaOffset(Offset)) + return true; + + OS << ".cfi_def_cfa_offset " << Offset; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { + if (this->MCStreamer::EmitCFIDefCfaRegister(Register)) + return true; + + OS << ".cfi_def_cfa_register " << Register; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { + if (this->MCStreamer::EmitCFIOffset(Register, Offset)) + return true; + + OS << ".cfi_offset " << Register << ", " << Offset; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym) { + if (this->MCStreamer::EmitCFIPersonality(Sym)) + return true; + + OS << ".cfi_personality 0, " << *Sym; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym) { + if (this->MCStreamer::EmitCFILsda(Sym)) + return true; + + OS << ".cfi_lsda 0, " << *Sym; + EmitEOL(); + + return false; +} + void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { raw_ostream &OS = GetCommentOS(); SmallString<256> Code; @@ -654,7 +796,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { MCFixup &F = Fixups[i]; - const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); + const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); for (unsigned j = 0; j != Info.TargetSize; ++j) { unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); @@ -689,7 +831,14 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { OS << "0b"; for (unsigned j = 8; j--;) { unsigned Bit = (Code[i] >> j) & 1; - if (uint8_t MapEntry = FixupMap[i * 8 + j]) { + + unsigned FixupBit; + if (getContext().getTargetAsmInfo().isLittleEndian()) + FixupBit = i * 8 + j; + else + FixupBit = i * 8 + (7-j); + + if (uint8_t MapEntry = FixupMap[FixupBit]) { assert(Bit == 0 && "Encoder wrote into fixed up bit!"); OS << char('A' + MapEntry - 1); } else @@ -701,7 +850,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { MCFixup &F = Fixups[i]; - const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); + const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; } @@ -710,6 +859,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { assert(CurSection && "Cannot emit contents before setting section!"); + if (!UseLoc) + MCLineEntry::Make(this, getCurrentSection()); + // Show the encoding in a comment if we have a code emitter. if (Emitter) AddEncodingComment(Inst); @@ -739,13 +891,16 @@ void MCAsmStreamer::EmitRawText(StringRef String) { } void MCAsmStreamer::Finish() { + // Dump out the dwarf file & directory tables and line tables. + if (getContext().hasDwarfFiles() && !UseLoc) + MCDwarfFileTable::Emit(this); } MCStreamer *llvm::createAsmStreamer(MCContext &Context, formatted_raw_ostream &OS, - bool isLittleEndian, - bool isVerboseAsm, MCInstPrinter *IP, - MCCodeEmitter *CE, bool ShowInst) { - return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, - IP, CE, ShowInst); + bool isVerboseAsm, bool useLoc, + MCInstPrinter *IP, MCCodeEmitter *CE, + TargetAsmBackend *TAB, bool ShowInst) { + return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc, + IP, CE, TAB, ShowInst); }