diff options
Diffstat (limited to 'include/llvm/MC')
41 files changed, 2492 insertions, 1385 deletions
diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 9a6b703408088..f946f41981c8a 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -10,7 +10,9 @@ #ifndef LLVM_MC_MCASMBACKEND_H #define LLVM_MC_MCASMBACKEND_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCFixup.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -32,6 +34,7 @@ class raw_ostream; class MCAsmBackend { MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION; void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION; + protected: // Can only create subclasses. MCAsmBackend(); @@ -42,7 +45,7 @@ public: virtual ~MCAsmBackend(); /// lifetime management - virtual void reset() { } + virtual void reset() {} /// createObjectWriter - Create a new MCObjectWriter instance for use by the /// assembler backend to emit the final object file. @@ -50,7 +53,7 @@ public: /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable /// non-standard ELFObjectWriters. - virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { llvm_unreachable("createELFObjectTargetWriter is not supported by asm " "backend"); } @@ -71,9 +74,7 @@ public: /// hasDataInCodeSupport - Check whether this target implements data-in-code /// markers. If not, data region directives will be ignored. - bool hasDataInCodeSupport() const { - return HasDataInCodeSupport; - } + bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } /// doesSectionRequireSymbols - Check whether the given section requires that /// all symbols (even temporaries) have symbol table entries. @@ -128,8 +129,7 @@ public: /// fixupNeedsRelaxation - Target specific predicate for whether a given /// fixup requires the associated instruction to be relaxed. - virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, - uint64_t Value, + virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; @@ -160,6 +160,12 @@ public: /// handleAssemblerFlag - Handle any target-specific assembler flags. /// By default, do nothing. virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} + + /// \brief Generate the compact unwind encoding for the CFI instructions. + virtual uint32_t + generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const { + return 0; + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index d020de3004f2e..7a99394621475 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -17,6 +17,7 @@ #define LLVM_MC_MCASMINFO_H #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MachineLocation.h" #include <cassert> #include <vector> @@ -88,9 +89,13 @@ namespace llvm { /// which is needed to compute the size of an inline asm. unsigned MaxInstLength; // Defaults to 4. - /// PCSymbol - The symbol used to represent the current PC. Used in PC - /// relative expressions. - const char *PCSymbol; // Defaults to "$". + /// MinInstAlignment - Every possible instruction length is a multiple of + /// this value. Factored out in .debug_frame and .debug_line. + unsigned MinInstAlignment; // Defaults to 1. + + /// DollarIsPC - The '$' token, when not referencing an identifier or + /// constant, refers to the current PC. + bool DollarIsPC; // Defaults to false. /// SeparatorString - This string, if specified, is used to separate /// instructions from each other when on the same line. @@ -139,21 +144,9 @@ namespace llvm { /// AssemblerDialect - Which dialect of an assembler variant to use. unsigned AssemblerDialect; // Defaults to 0 - /// AllowQuotesInName - This is true if the assembler allows for complex - /// symbol names to be surrounded in quotes. This defaults to false. - bool AllowQuotesInName; - - /// AllowNameToStartWithDigit - This is true if the assembler allows symbol - /// names to start with a digit (e.g., "0x0021"). This defaults to false. - bool AllowNameToStartWithDigit; - - /// AllowPeriodsInName - This is true if the assembler allows periods in - /// symbol names. This defaults to true. - bool AllowPeriodsInName; - - /// AllowUTF8 - This is true if the assembler accepts UTF-8 input. - // FIXME: Make this a more general encoding setting? - bool AllowUTF8; + /// \brief This is true if the assembler allows @ characters in symbol + /// names. Defaults to false. + bool AllowAtInName; /// UseDataRegionDirectives - This is true if data region markers should /// be printed as ".data_region/.end_data_region" directives. If false, @@ -195,13 +188,6 @@ namespace llvm { /// on Mips or .gprel32 on Alpha. const char *GPRel32Directive; // Defaults to NULL. - /// getDataASDirective - Return the directive that should be used to emit - /// data of the specified size to the specified numeric address space. - virtual const char *getDataASDirective(unsigned Size, unsigned AS) const { - assert(AS != 0 && "Don't know the directives for default addr space"); - return 0; - } - /// SunStyleELFSectionSwitchSyntax - This is true if this target uses "Sun /// Style" syntax for section switching ("#alloc,#write" etc) instead of the /// normal ELF syntax (,"a,w") in .section directives. @@ -242,11 +228,6 @@ namespace llvm { /// const char *GlobalDirective; // Defaults to NULL. - /// ExternDirective - This is the directive used to declare external - /// globals. - /// - const char *ExternDirective; // Defaults to NULL. - /// HasSetDirective - True if the assembler supports the .set directive. bool HasSetDirective; // Defaults to true. @@ -273,14 +254,14 @@ namespace llvm { /// .file directive, this is true for ELF targets. bool HasSingleParameterDotFile; // Defaults to true. + /// hasIdentDirective - True if the target has a .ident directive, this is + /// true for ELF targets. + bool HasIdentDirective; // Defaults to false. + /// HasNoDeadStrip - True if this target supports the MachO .no_dead_strip /// directive. bool HasNoDeadStrip; // Defaults to false. - /// HasSymbolResolver - True if this target supports the MachO - /// .symbol_resolver directive. - bool HasSymbolResolver; // Defaults to false. - /// WeakRefDirective - This directive, if non-null, is used to declare a /// global as being a weak undefined symbol. const char *WeakRefDirective; // Defaults to NULL. @@ -318,10 +299,6 @@ namespace llvm { /// SupportsExceptionHandling - True if target supports exception handling. ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None - /// DwarfUsesInlineInfoSection - True if DwarfDebugInlineSection is used to - /// encode inline subroutine information. - bool DwarfUsesInlineInfoSection; // Defaults to false. - /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally /// uses relocations for references to other .debug_* sections. bool DwarfUsesRelocationsAcrossSections; @@ -332,15 +309,15 @@ namespace llvm { //===--- Prologue State ----------------------------------------------===// - std::vector<MachineMove> InitialFrameState; + std::vector<MCCFIInstruction> InitialFrameState; public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); // FIXME: move these methods to DwarfPrinter when the JIT stops using them. - static unsigned getSLEB128Size(int Value); - static unsigned getULEB128Size(unsigned Value); + static unsigned getSLEB128Size(int64_t Value); + static unsigned getULEB128Size(uint64_t Value); /// getPointerSize - Get the pointer size in bytes. unsigned getPointerSize() const { @@ -367,17 +344,17 @@ namespace llvm { // Data directive accessors. // - const char *getData8bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data8bitsDirective : getDataASDirective(8, AS); + const char *getData8bitsDirective() const { + return Data8bitsDirective; } - const char *getData16bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data16bitsDirective : getDataASDirective(16, AS); + const char *getData16bitsDirective() const { + return Data16bitsDirective; } - const char *getData32bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data32bitsDirective : getDataASDirective(32, AS); + const char *getData32bitsDirective() const { + return Data32bitsDirective; } - const char *getData64bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data64bitsDirective : getDataASDirective(64, AS); + const char *getData64bitsDirective() const { + return Data64bitsDirective; } const char *getGPRel64Directive() const { return GPRel64Directive; } const char *getGPRel32Directive() const { return GPRel32Directive; } @@ -428,8 +405,11 @@ namespace llvm { unsigned getMaxInstLength() const { return MaxInstLength; } - const char *getPCSymbol() const { - return PCSymbol; + unsigned getMinInstAlignment() const { + return MinInstAlignment; + } + bool getDollarIsPC() const { + return DollarIsPC; } const char *getSeparatorString() const { return SeparatorString; @@ -475,17 +455,8 @@ namespace llvm { unsigned getAssemblerDialect() const { return AssemblerDialect; } - bool doesAllowQuotesInName() const { - return AllowQuotesInName; - } - bool doesAllowNameToStartWithDigit() const { - return AllowNameToStartWithDigit; - } - bool doesAllowPeriodsInName() const { - return AllowPeriodsInName; - } - bool doesAllowUTF8() const { - return AllowUTF8; + bool doesAllowAtInName() const { + return AllowAtInName; } bool doesSupportDataRegionDirectives() const { return UseDataRegionDirectives; @@ -511,9 +482,6 @@ namespace llvm { const char *getGlobalDirective() const { return GlobalDirective; } - const char *getExternDirective() const { - return ExternDirective; - } bool hasSetDirective() const { return HasSetDirective; } bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; @@ -526,8 +494,8 @@ namespace llvm { } bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } - bool hasSymbolResolver() const { return HasSymbolResolver; } const char *getWeakRefDirective() const { return WeakRefDirective; } const char *getWeakDefDirective() const { return WeakDefDirective; } const char *getLinkOnceDirective() const { return LinkOnceDirective; } @@ -557,9 +525,6 @@ namespace llvm { ExceptionsType == ExceptionHandling::ARM || ExceptionsType == ExceptionHandling::Win64); } - bool doesDwarfUseInlineInfoSection() const { - return DwarfUsesInlineInfoSection; - } bool doesDwarfUseRelocationsAcrossSections() const { return DwarfUsesRelocationsAcrossSections; } @@ -567,11 +532,11 @@ namespace llvm { return DwarfRegNumForCFI; } - void addInitialFrameState(MCSymbol *label, const MachineLocation &D, - const MachineLocation &S) { - InitialFrameState.push_back(MachineMove(label, D, S)); + void addInitialFrameState(const MCCFIInstruction &Inst) { + InitialFrameState.push_back(Inst); } - const std::vector<MachineMove> &getInitialFrameState() const { + + const std::vector<MCCFIInstruction> &getInitialFrameState() const { return InitialFrameState; } }; diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h new file mode 100644 index 0000000000000..27fea84e7a6da --- /dev/null +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -0,0 +1,23 @@ +//===-- llvm/MC/MCAsmInfoELF.h - ELF Asm info -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFOELF_H +#define LLVM_MC_MCASMINFOELF_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { +class MCAsmInfoELF : public MCAsmInfo { + virtual void anchor(); +protected: + MCAsmInfoELF(); +}; +} + +#endif diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 38a70f0adf016..8735a55ce044e 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -19,6 +19,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" +#include <algorithm> #include <vector> // FIXME: Shouldn't be needed. namespace llvm { @@ -816,6 +817,9 @@ public: typedef SymbolDataListType::const_iterator const_symbol_iterator; typedef SymbolDataListType::iterator symbol_iterator; + typedef std::vector<std::string> FileNameVectorType; + typedef FileNameVectorType::const_iterator const_file_name_iterator; + typedef std::vector<IndirectSymbolData>::const_iterator const_indirect_symbol_iterator; typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; @@ -859,6 +863,9 @@ private: /// The list of linker options to propagate into the object file. std::vector<std::vector<std::string> > LinkerOptions; + /// List of declared file names + FileNameVectorType FileNames; + /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -1152,6 +1159,20 @@ public: return *Entry; } + const_file_name_iterator file_names_begin() const { + return FileNames.begin(); + } + + const_file_name_iterator file_names_end() const { + return FileNames.end(); + } + + void addFileName(StringRef FileName) { + if (std::find(file_names_begin(), file_names_end(), FileName) == + file_names_end()) + FileNames.push_back(FileName); + } + /// @} void dump(); diff --git a/include/llvm/MC/MCAtom.h b/include/llvm/MC/MCAtom.h index ae5bf0bc20693..eab32d691fa84 100644 --- a/include/llvm/MC/MCAtom.h +++ b/include/llvm/MC/MCAtom.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCAtom.h - MCAtom class ---------------------*- C++ -*-===// +//===-- llvm/MC/MCAtom.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,13 +9,14 @@ // // This file contains the declaration of the MCAtom class, which is used to // represent a contiguous region in a decoded object that is uniformly data or -// instructions; +// instructions. // //===----------------------------------------------------------------------===// #ifndef LLVM_MC_MCATOM_H #define LLVM_MC_MCATOM_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/DataTypes.h" #include <vector> @@ -24,45 +25,175 @@ namespace llvm { class MCModule; -/// MCData - An entry in a data MCAtom. -// NOTE: This may change to a more complex type in the future. -typedef uint8_t MCData; +class MCAtom; +class MCTextAtom; +class MCDataAtom; -/// MCAtom - Represents a contiguous range of either instructions (a TextAtom) +/// \brief Represents a contiguous range of either instructions (a TextAtom) /// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. class MCAtom { - friend class MCModule; - typedef enum { TextAtom, DataAtom } AtomType; - - AtomType Type; + virtual void anchor(); +public: + virtual ~MCAtom() {} + + enum AtomKind { TextAtom, DataAtom }; + AtomKind getKind() const { return Kind; } + + /// \brief Get the start address of the atom. + uint64_t getBeginAddr() const { return Begin; } + /// \brief Get the end address, i.e. the last one inside the atom. + uint64_t getEndAddr() const { return End; } + + /// \name Atom modification methods: + /// When modifying a TextAtom, keep instruction boundaries in mind. + /// For instance, split must me given the start address of an instruction. + /// @{ + + /// \brief Splits the atom in two at a given address. + /// \param SplitPt Address at which to start a new atom, splitting this one. + /// \returns The newly created atom starting at \p SplitPt. + virtual MCAtom *split(uint64_t SplitPt) = 0; + + /// \brief Truncates an atom, discarding everything after \p TruncPt. + /// \param TruncPt Last byte address to be contained in this atom. + virtual void truncate(uint64_t TruncPt) = 0; + /// @} + + /// \name Naming: + /// + /// This is mostly for display purposes, and may contain anything that hints + /// at what the atom contains: section or symbol name, BB start address, .. + /// @{ + StringRef getName() const { return Name; } + void setName(StringRef NewName) { Name = NewName.str(); } + /// @} + +protected: + const AtomKind Kind; + std::string Name; MCModule *Parent; uint64_t Begin, End; - std::vector<std::pair<uint64_t, MCInst> > Text; - std::vector<MCData> Data; + friend class MCModule; + MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E) + : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { } + + /// \name Atom remapping helpers + /// @{ + + /// \brief Remap the atom, using the given range, updating Begin/End. + /// One or both of the bounds can remain the same, but overlapping with other + /// atoms in the module is still forbidden. + void remap(uint64_t NewBegin, uint64_t NewEnd); + + /// \brief Remap the atom to prepare for a truncation at TruncPt. + /// Equivalent to: + /// \code + /// // Bound checks + /// remap(Begin, TruncPt); + /// \endcode + void remapForTruncate(uint64_t TruncPt); + + /// \brief Remap the atom to prepare for a split at SplitPt. + /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}. + /// The current atom is truncated to \p LEnd. + void remapForSplit(uint64_t SplitPt, + uint64_t &LBegin, uint64_t &LEnd, + uint64_t &RBegin, uint64_t &REnd); + /// @} +}; - // Private constructor - only callable by MCModule - MCAtom(AtomType T, MCModule *P, uint64_t B, uint64_t E) - : Type(T), Parent(P), Begin(B), End(E) { } +/// \name Text atom +/// @{ +/// \brief An entry in an MCTextAtom: a disassembled instruction. +/// NOTE: Both the Address and Size field are actually redundant when taken in +/// the context of the text atom, and may better be exposed in an iterator +/// instead of stored in the atom, which would replace this class. +class MCDecodedInst { public: - bool isTextAtom() const { return Type == TextAtom; } - bool isDataAtom() const { return Type == DataAtom; } + MCInst Inst; + uint64_t Address; + uint64_t Size; + MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size) + : Inst(Inst), Address(Address), Size(Size) {} +}; + +/// \brief An atom consisting of disassembled instructions. +class MCTextAtom : public MCAtom { +private: + typedef std::vector<MCDecodedInst> InstListTy; + InstListTy Insts; - void addInst(const MCInst &I, uint64_t Address, unsigned Size); + /// \brief The address of the next appended instruction, i.e., the + /// address immediately after the last instruction in the atom. + uint64_t NextInstAddress; +public: + /// Append an instruction, expanding the atom if necessary. + void addInst(const MCInst &Inst, uint64_t Size); + + /// \name Instruction list access + /// @{ + typedef InstListTy::const_iterator const_iterator; + const_iterator begin() const { return Insts.begin(); } + const_iterator end() const { return Insts.end(); } + + const MCDecodedInst &back() const { return Insts.back(); } + const MCDecodedInst &at(size_t n) const { return Insts.at(n); } + size_t size() const { return Insts.size(); } + /// @} + + /// \name Atom type specific split/truncate logic. + /// @{ + MCTextAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; + void truncate(uint64_t TruncPt) LLVM_OVERRIDE; + /// @} + + // Class hierarchy. + static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; } +private: + friend class MCModule; + // Private constructor - only callable by MCModule + MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End) + : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {} +}; +/// @} + +/// \name Data atom +/// @{ + +/// \brief An entry in an MCDataAtom. +// NOTE: This may change to a more complex type in the future. +typedef uint8_t MCData; + +/// \brief An atom consising of a sequence of bytes. +class MCDataAtom : public MCAtom { + std::vector<MCData> Data; + +public: + /// Append a data entry, expanding the atom if necessary. void addData(const MCData &D); - /// split - Splits the atom in two at a given address, which must align with - /// and instruction boundary if this is a TextAtom. Returns the newly created - /// atom representing the high part of the split. - MCAtom *split(uint64_t SplitPt); + /// Get a reference to the data in this atom. + ArrayRef<MCData> getData() const { return Data; } + + /// \name Atom type specific split/truncate logic. + /// @{ + MCDataAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; + void truncate(uint64_t TruncPt) LLVM_OVERRIDE; + /// @} - /// truncate - Truncates an atom so that TruncPt is the last byte address - /// contained in the atom. - void truncate(uint64_t TruncPt); + // Class hierarchy. + static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; } +private: + friend class MCModule; + // Private constructor - only callable by MCModule + MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) + : MCAtom(DataAtom, P, Begin, End) { + Data.reserve(End + 1 - Begin); + } }; } #endif - diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h index d1765e1240a47..84ce934d822ee 100644 --- a/include/llvm/MC/MCCodeGenInfo.h +++ b/include/llvm/MC/MCCodeGenInfo.h @@ -42,6 +42,9 @@ namespace llvm { CodeModel::Model getCodeModel() const { return CMModel; } CodeGenOpt::Level getOptLevel() const { return OptLevel; } + + // Allow overriding OptLevel on a per-function basis. + void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } }; } // namespace llvm diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 0db3dee2ff050..c8b66261bfea7 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCCONTEXT_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCDwarf.h" @@ -37,6 +38,7 @@ namespace llvm { class Twine; class MCSectionMachO; class MCSectionELF; + class MCSectionCOFF; /// MCContext - Context object for machine code objects. This class owns all /// of the sections that it creates. @@ -51,10 +53,10 @@ namespace llvm { const SourceMgr *SrcMgr; /// The MCAsmInfo for this target. - const MCAsmInfo &MAI; + const MCAsmInfo *MAI; /// The MCRegisterInfo for this target. - const MCRegisterInfo &MRI; + const MCRegisterInfo *MRI; /// The MCObjectFileInfo for this target. const MCObjectFileInfo *MOFI; @@ -97,7 +99,7 @@ namespace llvm { bool SecureLogUsed; /// The compilation directory to use for DW_AT_comp_dir. - std::string CompilationDir; + SmallString<128> CompilationDir; /// The main file name if passed in explicitly. std::string MainFileName; @@ -163,16 +165,16 @@ namespace llvm { MCSymbol *CreateSymbol(StringRef Name); public: - explicit MCContext(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, + explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI, const MCObjectFileInfo *MOFI, const SourceMgr *Mgr = 0, bool DoAutoReset = true); ~MCContext(); const SourceMgr *getSourceManager() const { return SrcMgr; } - const MCAsmInfo &getAsmInfo() const { return MAI; } + const MCAsmInfo *getAsmInfo() const { return MAI; } - const MCRegisterInfo &getRegisterInfo() const { return MRI; } + const MCRegisterInfo *getRegisterInfo() const { return MRI; } const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } @@ -254,14 +256,18 @@ namespace llvm { const MCSectionELF *CreateELFGroupSection(); - const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, - int Selection, SectionKind Kind); + const MCSectionCOFF *getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind, + StringRef COMDATSymName, + int Selection, + const MCSectionCOFF *Assoc = 0); - const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, - SectionKind Kind) { - return getCOFFSection (Section, Characteristics, 0, Kind); - } + const MCSectionCOFF *getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind); + const MCSectionCOFF *getCOFFSection(StringRef Section); /// @} @@ -272,7 +278,7 @@ namespace llvm { /// This can be overridden by clients which want to control the reported /// compilation directory and have it be something other than the current /// working directory. - const std::string &getCompilationDir() const { return CompilationDir; } + StringRef getCompilationDir() const { return CompilationDir; } /// \brief Set the compilation directory for DW_AT_comp_dir /// Override the default (CWD) compilation directory. @@ -406,7 +412,7 @@ namespace llvm { void Deallocate(void *Ptr) { } - // Unrecoverable error has occured. Display the best diagnostic we can + // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg); diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index 36fbcb02d9f6f..83f26ef3edb9e 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -10,6 +10,9 @@ #define LLVM_MC_MCDISASSEMBLER_H #include "llvm-c/Disassembler.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCSymbolizer.h" +#include "llvm/MC/MCRelocationInfo.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -55,7 +58,8 @@ public: /// Constructor - Performs initial setup for the disassembler. MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), SymbolLookUp(0), DisInfo(0), Ctx(0), - STI(STI), CommentStream(0) {} + STI(STI), Symbolizer(0), + CommentStream(0) {} virtual ~MCDisassembler(); @@ -81,7 +85,6 @@ public: uint64_t address, raw_ostream &vStream, raw_ostream &cStream) const = 0; - private: // // Hooks for symbolic disassembly via the public 'C' interface. @@ -95,20 +98,32 @@ private: // The assembly context for creating symbols and MCExprs in place of // immediate operands when there is symbolic information. MCContext *Ctx; + protected: // Subtarget information, for instruction decoding predicates if required. const MCSubtargetInfo &STI; + OwningPtr<MCSymbolizer> Symbolizer; public: - void setupForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo, - LLVMSymbolLookupCallback symbolLookUp, - void *disInfo, - MCContext *ctx) { - GetOpInfo = getOpInfo; - SymbolLookUp = symbolLookUp; - DisInfo = disInfo; - Ctx = ctx; - } + // Helpers around MCSymbolizer + bool tryAddingSymbolicOperand(MCInst &Inst, + int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize) const; + + void tryAddingPcLoadReferenceComment(int64_t Value, uint64_t Address) const; + + /// Set \p Symzer as the current symbolizer. + /// This takes ownership of \p Symzer, and deletes the previously set one. + void setSymbolizer(OwningPtr<MCSymbolizer> &Symzer); + + /// Sets up an external symbolizer that uses the C API callbacks. + void setupForSymbolicDisassembly(LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, + void *DisInfo, + MCContext *Ctx, + OwningPtr<MCRelocationInfo> &RelInfo); + LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; } LLVMSymbolLookupCallback getLLVMSymbolLookupCallback() const { return SymbolLookUp; @@ -116,6 +131,8 @@ public: void *getDisInfoBlock() const { return DisInfo; } MCContext *getMCContext() const { return Ctx; } + const MCSubtargetInfo& getSubtargetInfo() const { return STI; } + // Marked mutable because we cache it inside the disassembler, rather than // having to pass it around as an argument through all the autogenerated code. mutable raw_ostream *CommentStream; diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 1a392e8755ee3..65b920bf232e7 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -23,403 +23,445 @@ #include <vector> namespace llvm { - class MCContext; - class MCObjectWriter; - class MCSection; - class MCStreamer; - class MCSymbol; - class SourceMgr; - class SMLoc; - - /// MCDwarfFile - Instances of this class represent the name of the dwarf - /// .file directive and its associated dwarf file number in the MC file, - /// and MCDwarfFile's are created and unique'd by the MCContext class where - /// the file number for each is its index into the vector of DwarfFiles (note - /// index 0 is not used and not a valid dwarf file number). - class MCDwarfFile { - // Name - the base name of the file without its directory path. - // The StringRef references memory allocated in the MCContext. - StringRef Name; - - // DirIndex - the index into the list of directory names for this file name. - unsigned DirIndex; - - private: // MCContext creates and uniques these. - friend class MCContext; - MCDwarfFile(StringRef name, unsigned dirIndex) +class MCAsmBackend; +class MCContext; +class MCSection; +class MCStreamer; +class MCSymbol; +class SourceMgr; +class SMLoc; + +/// MCDwarfFile - Instances of this class represent the name of the dwarf +/// .file directive and its associated dwarf file number in the MC file, +/// and MCDwarfFile's are created and unique'd by the MCContext class where +/// the file number for each is its index into the vector of DwarfFiles (note +/// index 0 is not used and not a valid dwarf file number). +class MCDwarfFile { + // Name - the base name of the file without its directory path. + // The StringRef references memory allocated in the MCContext. + StringRef Name; + + // DirIndex - the index into the list of directory names for this file name. + unsigned DirIndex; + +private: // MCContext creates and uniques these. + friend class MCContext; + MCDwarfFile(StringRef name, unsigned dirIndex) : Name(name), DirIndex(dirIndex) {} - MCDwarfFile(const MCDwarfFile&) LLVM_DELETED_FUNCTION; - void operator=(const MCDwarfFile&) LLVM_DELETED_FUNCTION; - public: - /// getName - Get the base name of this MCDwarfFile. - StringRef getName() const { return Name; } - - /// getDirIndex - Get the dirIndex of this MCDwarfFile. - unsigned getDirIndex() const { return DirIndex; } - - - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS) const; - - /// dump - Print the value to stderr. - void dump() const; - }; - - inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){ - DwarfFile.print(OS); - return OS; - } - - /// MCDwarfLoc - Instances of this class represent the information from a - /// dwarf .loc directive. - class MCDwarfLoc { - // FileNum - the file number. - unsigned FileNum; - // Line - the line number. - unsigned Line; - // Column - the column position. - unsigned Column; - // Flags (see #define's below) - unsigned Flags; - // Isa - unsigned Isa; - // Discriminator - unsigned Discriminator; + MCDwarfFile(const MCDwarfFile &) LLVM_DELETED_FUNCTION; + void operator=(const MCDwarfFile &) LLVM_DELETED_FUNCTION; + +public: + /// getName - Get the base name of this MCDwarfFile. + StringRef getName() const { return Name; } + + /// getDirIndex - Get the dirIndex of this MCDwarfFile. + unsigned getDirIndex() const { return DirIndex; } + + /// print - Print the value to the stream \p OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile) { + DwarfFile.print(OS); + return OS; +} + +/// MCDwarfLoc - Instances of this class represent the information from a +/// dwarf .loc directive. +class MCDwarfLoc { + // FileNum - the file number. + unsigned FileNum; + // Line - the line number. + unsigned Line; + // Column - the column position. + unsigned Column; + // Flags (see #define's below) + unsigned Flags; + // Isa + unsigned Isa; + // Discriminator + unsigned Discriminator; // Flag that indicates the initial value of the is_stmt_start flag. -#define DWARF2_LINE_DEFAULT_IS_STMT 1 +#define DWARF2_LINE_DEFAULT_IS_STMT 1 -#define DWARF2_FLAG_IS_STMT (1 << 0) -#define DWARF2_FLAG_BASIC_BLOCK (1 << 1) -#define DWARF2_FLAG_PROLOGUE_END (1 << 2) +#define DWARF2_FLAG_IS_STMT (1 << 0) +#define DWARF2_FLAG_BASIC_BLOCK (1 << 1) +#define DWARF2_FLAG_PROLOGUE_END (1 << 2) #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) - private: // MCContext manages these - friend class MCContext; - friend class MCLineEntry; - MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, - unsigned isa, unsigned discriminator) +private: // MCContext manages these + friend class MCContext; + friend class MCLineEntry; + MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, + unsigned isa, unsigned discriminator) : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), Discriminator(discriminator) {} - // Allow the default copy constructor and assignment operator to be used - // for an MCDwarfLoc object. + // Allow the default copy constructor and assignment operator to be used + // for an MCDwarfLoc object. - public: - /// getFileNum - Get the FileNum of this MCDwarfLoc. - unsigned getFileNum() const { return FileNum; } +public: + /// getFileNum - Get the FileNum of this MCDwarfLoc. + unsigned getFileNum() const { return FileNum; } - /// getLine - Get the Line of this MCDwarfLoc. - unsigned getLine() const { return Line; } + /// getLine - Get the Line of this MCDwarfLoc. + unsigned getLine() const { return Line; } - /// getColumn - Get the Column of this MCDwarfLoc. - unsigned getColumn() const { return Column; } + /// getColumn - Get the Column of this MCDwarfLoc. + unsigned getColumn() const { return Column; } - /// getFlags - Get the Flags of this MCDwarfLoc. - unsigned getFlags() const { return Flags; } + /// getFlags - Get the Flags of this MCDwarfLoc. + unsigned getFlags() const { return Flags; } - /// getIsa - Get the Isa of this MCDwarfLoc. - unsigned getIsa() const { return Isa; } + /// getIsa - Get the Isa of this MCDwarfLoc. + unsigned getIsa() const { return Isa; } - /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. - unsigned getDiscriminator() const { return Discriminator; } + /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. + unsigned getDiscriminator() const { return Discriminator; } - /// setFileNum - Set the FileNum of this MCDwarfLoc. - void setFileNum(unsigned fileNum) { FileNum = fileNum; } + /// setFileNum - Set the FileNum of this MCDwarfLoc. + void setFileNum(unsigned fileNum) { FileNum = fileNum; } - /// setLine - Set the Line of this MCDwarfLoc. - void setLine(unsigned line) { Line = line; } + /// setLine - Set the Line of this MCDwarfLoc. + void setLine(unsigned line) { Line = line; } - /// setColumn - Set the Column of this MCDwarfLoc. - void setColumn(unsigned column) { Column = column; } + /// setColumn - Set the Column of this MCDwarfLoc. + void setColumn(unsigned column) { Column = column; } - /// setFlags - Set the Flags of this MCDwarfLoc. - void setFlags(unsigned flags) { Flags = flags; } + /// setFlags - Set the Flags of this MCDwarfLoc. + void setFlags(unsigned flags) { Flags = flags; } - /// setIsa - Set the Isa of this MCDwarfLoc. - void setIsa(unsigned isa) { Isa = isa; } + /// setIsa - Set the Isa of this MCDwarfLoc. + void setIsa(unsigned isa) { Isa = isa; } - /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. - void setDiscriminator(unsigned discriminator) { - Discriminator = discriminator; - } - }; + /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. + void setDiscriminator(unsigned discriminator) { + Discriminator = discriminator; + } +}; + +/// MCLineEntry - Instances of this class represent the line information for +/// the dwarf line table entries. Which is created after a machine +/// instruction is assembled and uses an address from a temporary label +/// created at the current address in the current section and the info from +/// the last .loc directive seen as stored in the context. +class MCLineEntry : public MCDwarfLoc { + MCSymbol *Label; + +private: + // Allow the default copy constructor and assignment operator to be used + // for an MCLineEntry object. + +public: + // Constructor to create an MCLineEntry given a symbol and the dwarf loc. + MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) + : MCDwarfLoc(loc), Label(label) {} + + MCSymbol *getLabel() const { return Label; } + + // This is called when an instruction is assembled into the specified + // section and if there is information from the last .loc directive that + // has yet to have a line entry made for it is made. + static void Make(MCStreamer *MCOS, const MCSection *Section); +}; + +/// MCLineSection - Instances of this class represent the line information +/// for a section where machine instructions have been assembled after seeing +/// .loc directives. This is the information used to build the dwarf line +/// table for a section. +class MCLineSection { + +private: + MCLineSection(const MCLineSection &) LLVM_DELETED_FUNCTION; + void operator=(const MCLineSection &) LLVM_DELETED_FUNCTION; + +public: + // Constructor to create an MCLineSection with an empty MCLineEntries + // vector. + MCLineSection() {} + + // addLineEntry - adds an entry to this MCLineSection's line entries + void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { + MCLineDivisions[CUID].push_back(LineEntry); + } - /// MCLineEntry - Instances of this class represent the line information for - /// the dwarf line table entries. Which is created after a machine - /// instruction is assembled and uses an address from a temporary label - /// created at the current address in the current section and the info from - /// the last .loc directive seen as stored in the context. - class MCLineEntry : public MCDwarfLoc { - MCSymbol *Label; - - private: - // Allow the default copy constructor and assignment operator to be used - // for an MCLineEntry object. - - public: - // Constructor to create an MCLineEntry given a symbol and the dwarf loc. - MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), - Label(label) {} - - MCSymbol *getLabel() const { return Label; } - - // This is called when an instruction is assembled into the specified - // section and if there is information from the last .loc directive that - // has yet to have a line entry made for it is made. - static void Make(MCStreamer *MCOS, const MCSection *Section); - }; + typedef std::vector<MCLineEntry> MCLineEntryCollection; + typedef MCLineEntryCollection::iterator iterator; + typedef MCLineEntryCollection::const_iterator const_iterator; + typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap; + +private: + // A collection of MCLineEntry for each Compile Unit ID. + MCLineDivisionMap MCLineDivisions; - /// MCLineSection - Instances of this class represent the line information - /// for a section where machine instructions have been assembled after seeing - /// .loc directives. This is the information used to build the dwarf line - /// table for a section. - class MCLineSection { - - private: - MCLineSection(const MCLineSection&) LLVM_DELETED_FUNCTION; - void operator=(const MCLineSection&) LLVM_DELETED_FUNCTION; - - public: - // Constructor to create an MCLineSection with an empty MCLineEntries - // vector. - MCLineSection() {} - - // addLineEntry - adds an entry to this MCLineSection's line entries - void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { - MCLineDivisions[CUID].push_back(LineEntry); - } - - typedef std::vector<MCLineEntry> MCLineEntryCollection; - typedef MCLineEntryCollection::iterator iterator; - typedef MCLineEntryCollection::const_iterator const_iterator; - typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap; - - private: - // A collection of MCLineEntry for each Compile Unit ID. - MCLineDivisionMap MCLineDivisions; - - public: - // Returns whether MCLineSection contains entries for a given Compile - // Unit ID. - bool containEntriesForID(unsigned CUID) const { - return MCLineDivisions.count(CUID); - } - // Returns the collection of MCLineEntry for a given Compile Unit ID. - const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { - MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); - assert(CIter != MCLineDivisions.end()); - return CIter->second; - } +public: + // Returns whether MCLineSection contains entries for a given Compile + // Unit ID. + bool containEntriesForID(unsigned CUID) const { + return MCLineDivisions.count(CUID); + } + // Returns the collection of MCLineEntry for a given Compile Unit ID. + const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { + MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); + assert(CIter != MCLineDivisions.end()); + return CIter->second; + } +}; + +class MCDwarfFileTable { +public: + // + // This emits the Dwarf file and the line tables for all Compile Units. + // + static const MCSymbol *Emit(MCStreamer *MCOS); + // + // This emits the Dwarf file and the line tables for a given Compile Unit. + // + static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); +}; + +class MCDwarfLineAddr { +public: + /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. + static void Encode(MCContext &Context, int64_t LineDelta, uint64_t AddrDelta, + raw_ostream &OS); + + /// Utility function to emit the encoding to a streamer. + static void Emit(MCStreamer *MCOS, int64_t LineDelta, uint64_t AddrDelta); +}; + +class MCGenDwarfInfo { +public: + // + // When generating dwarf for assembly source files this emits the Dwarf + // sections. + // + static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); +}; + +// When generating dwarf for assembly source files this is the info that is +// needed to be gathered for each symbol that will have a dwarf label. +class MCGenDwarfLabelEntry { +private: + // Name of the symbol without a leading underbar, if any. + StringRef Name; + // The dwarf file number this symbol is in. + unsigned FileNumber; + // The line number this symbol is at. + unsigned LineNumber; + // The low_pc for the dwarf label is taken from this symbol. + MCSymbol *Label; + +public: + MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, + MCSymbol *label) + : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), + Label(label) {} + + StringRef getName() const { return Name; } + unsigned getFileNumber() const { return FileNumber; } + unsigned getLineNumber() const { return LineNumber; } + MCSymbol *getLabel() const { return Label; } + + // This is called when label is created when we are generating dwarf for + // assembly source files. + static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, + SMLoc &Loc); +}; + +class MCCFIInstruction { +public: + enum OpType { + OpSameValue, + OpRememberState, + OpRestoreState, + OpOffset, + OpDefCfaRegister, + OpDefCfaOffset, + OpDefCfa, + OpRelOffset, + OpAdjustCfaOffset, + OpEscape, + OpRestore, + OpUndefined, + OpRegister, + OpWindowSave }; - class MCDwarfFileTable { - public: - // - // This emits the Dwarf file and the line tables for all Compile Units. - // - static const MCSymbol *Emit(MCStreamer *MCOS); - // - // This emits the Dwarf file and the line tables for a given Compile Unit. - // - static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); +private: + OpType Operation; + MCSymbol *Label; + unsigned Register; + union { + int Offset; + unsigned Register2; }; + std::vector<char> Values; - class MCDwarfLineAddr { - public: - /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. - static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) + : Operation(Op), Label(L), Register(R), Offset(O), + Values(V.begin(), V.end()) { + assert(Op != OpRegister); + } - /// Utility function to emit the encoding to a streamer. - static void Emit(MCStreamer *MCOS, - int64_t LineDelta,uint64_t AddrDelta); + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) + : Operation(Op), Label(L), Register(R1), Register2(R2) { + assert(Op == OpRegister); + } - /// Utility function to write the encoding to an object writer. - static void Write(MCObjectWriter *OW, - int64_t LineDelta, uint64_t AddrDelta); - }; +public: + /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from + /// Register and add Offset to it. + static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); + } - class MCGenDwarfInfo { - public: - // - // When generating dwarf for assembly source files this emits the Dwarf - // sections. - // - static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); - }; + /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now + /// on Register will be used instead of the old one. Offset remains the same. + static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); + } - // When generating dwarf for assembly source files this is the info that is - // needed to be gathered for each symbol that will have a dwarf label. - class MCGenDwarfLabelEntry { - private: - // Name of the symbol without a leading underbar, if any. - StringRef Name; - // The dwarf file number this symbol is in. - unsigned FileNumber; - // The line number this symbol is at. - unsigned LineNumber; - // The low_pc for the dwarf label is taken from this symbol. - MCSymbol *Label; - - public: - MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, - unsigned lineNumber, MCSymbol *label) : - Name(name), FileNumber(fileNumber), LineNumber(lineNumber), Label(label){} - - StringRef getName() const { return Name; } - unsigned getFileNumber() const { return FileNumber; } - unsigned getLineNumber() const { return LineNumber; } - MCSymbol *getLabel() const { return Label; } - - // This is called when label is created when we are generating dwarf for - // assembly source files. - static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, - SMLoc &Loc); - }; + /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register + /// remains the same, but offset is new. Note that it is the absolute offset + /// that will be added to a defined register to the compute CFA address. + static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { + return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); + } - class MCCFIInstruction { - public: - enum OpType { OpSameValue, OpRememberState, OpRestoreState, OpOffset, - OpDefCfaRegister, OpDefCfaOffset, OpDefCfa, OpRelOffset, - OpAdjustCfaOffset, OpEscape, OpRestore, OpUndefined, - OpRegister }; - private: - OpType Operation; - MCSymbol *Label; - unsigned Register; - union { - int Offset; - unsigned Register2; - }; - std::vector<char> Values; - - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) : - Operation(Op), Label(L), Register(R), Offset(O), - Values(V.begin(), V.end()) { - assert(Op != OpRegister); - } - - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) : - Operation(Op), Label(L), Register(R1), Register2(R2) { - assert(Op == OpRegister); - } - - public: - static MCCFIInstruction - createOffset(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpOffset, L, Register, Offset, ""); - } - - static MCCFIInstruction - createDefCfaRegister(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); - } - - static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { - return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); - } - - static MCCFIInstruction - createDefCfa(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); - } - - static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpUndefined, L, Register, 0, ""); - } - - static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpRestore, L, Register, 0, ""); - } - - static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpSameValue, L, Register, 0, ""); - } - - static MCCFIInstruction createRestoreState(MCSymbol *L) { - return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); - } - - static MCCFIInstruction createRememberState(MCSymbol *L) { - return MCCFIInstruction(OpRememberState, L, 0, 0, ""); - } - - static MCCFIInstruction - createRelOffset(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); - } - - static MCCFIInstruction - createAdjustCfaOffset(MCSymbol *L, int Adjustment) { - return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); - } - - static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { - return MCCFIInstruction(OpEscape, L, 0, 0, Vals); - } - - static MCCFIInstruction - createRegister(MCSymbol *L, unsigned Register1, unsigned Register2) { - return MCCFIInstruction(OpRegister, L, Register1, Register2); - } - - OpType getOperation() const { return Operation; } - MCSymbol *getLabel() const { return Label; } - - unsigned getRegister() const { - assert(Operation == OpDefCfa || Operation == OpOffset || - Operation == OpRestore || Operation == OpUndefined || - Operation == OpSameValue || Operation == OpDefCfaRegister || - Operation == OpRelOffset || Operation == OpRegister); - return Register; - } - - unsigned getRegister2() const { - assert(Operation == OpRegister); - return Register2; - } - - int getOffset() const { - assert(Operation == OpDefCfa || Operation == OpOffset || - Operation == OpRelOffset || Operation == OpDefCfaOffset || - Operation == OpAdjustCfaOffset); - return Offset; - } - - const StringRef getValues() const { - assert(Operation == OpEscape); - return StringRef(&Values[0], Values.size()); - } - }; + /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but + /// Offset is a relative value that is added/subtracted from the previous + /// offset. + static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { + return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); + } - struct MCDwarfFrameInfo { - MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), - Function(0), Instructions(), PersonalityEncoding(), - LsdaEncoding(0), CompactUnwindEncoding(0), - IsSignalFrame(false) {} - MCSymbol *Begin; - MCSymbol *End; - const MCSymbol *Personality; - const MCSymbol *Lsda; - const MCSymbol *Function; - std::vector<MCCFIInstruction> Instructions; - unsigned PersonalityEncoding; - unsigned LsdaEncoding; - uint32_t CompactUnwindEncoding; - bool IsSignalFrame; - }; + /// \brief .cfi_offset Previous value of Register is saved at offset Offset + /// from CFA. + static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpOffset, L, Register, Offset, ""); + } - class MCDwarfFrameEmitter { - public: - // - // This emits the frame info section. - // - static void Emit(MCStreamer &streamer, bool usingCFI, - bool isEH); - static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); - static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); - }; + /// \brief .cfi_rel_offset Previous value of Register is saved at offset + /// Offset from the current CFA register. This is transformed to .cfi_offset + /// using the known displacement of the CFA register from the CFA. + static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); + } + + /// \brief .cfi_register Previous value of Register1 is saved in + /// register Register2. + static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, + unsigned Register2) { + return MCCFIInstruction(OpRegister, L, Register1, Register2); + } + + /// \brief .cfi_window_save SPARC register window is saved. + static MCCFIInstruction createWindowSave(MCSymbol *L) { + return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); + } + + /// \brief .cfi_restore says that the rule for Register is now the same as it + /// was at the beginning of the function, after all initial instructions added + /// by .cfi_startproc were executed. + static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpRestore, L, Register, 0, ""); + } + + /// \brief .cfi_undefined From now on the previous value of Register can't be + /// restored anymore. + static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpUndefined, L, Register, 0, ""); + } + + /// \brief .cfi_same_value Current value of Register is the same as in the + /// previous frame. I.e., no restoration is needed. + static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpSameValue, L, Register, 0, ""); + } + + /// \brief .cfi_remember_state Save all current rules for all registers. + static MCCFIInstruction createRememberState(MCSymbol *L) { + return MCCFIInstruction(OpRememberState, L, 0, 0, ""); + } + + /// \brief .cfi_restore_state Restore the previously saved state. + static MCCFIInstruction createRestoreState(MCSymbol *L) { + return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); + } + + /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind + /// info. + static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { + return MCCFIInstruction(OpEscape, L, 0, 0, Vals); + } + + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + + unsigned getRegister() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRestore || Operation == OpUndefined || + Operation == OpSameValue || Operation == OpDefCfaRegister || + Operation == OpRelOffset || Operation == OpRegister); + return Register; + } + + unsigned getRegister2() const { + assert(Operation == OpRegister); + return Register2; + } + + int getOffset() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRelOffset || Operation == OpDefCfaOffset || + Operation == OpAdjustCfaOffset); + return Offset; + } + + const StringRef getValues() const { + assert(Operation == OpEscape); + return StringRef(&Values[0], Values.size()); + } +}; + +struct MCDwarfFrameInfo { + MCDwarfFrameInfo() + : Begin(0), End(0), Personality(0), Lsda(0), Function(0), Instructions(), + PersonalityEncoding(), LsdaEncoding(0), CompactUnwindEncoding(0), + IsSignalFrame(false) {} + MCSymbol *Begin; + MCSymbol *End; + const MCSymbol *Personality; + const MCSymbol *Lsda; + const MCSymbol *Function; + std::vector<MCCFIInstruction> Instructions; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + uint32_t CompactUnwindEncoding; + bool IsSignalFrame; +}; + +class MCDwarfFrameEmitter { +public: + // + // This emits the frame info section. + // + static void Emit(MCStreamer &streamer, MCAsmBackend *MAB, + bool usingCFI, bool isEH); + static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); + static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, + raw_ostream &OS); +}; } // end namespace llvm #endif diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 65dd1e8998cc6..92ad1b1a46fec 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -42,18 +42,6 @@ struct ELFRelocationEntry { const MCSymbol *Sym, uint64_t Addend, const MCFixup &Fixup) : r_offset(RelocOffset), Index(Idx), Type(RelType), Symbol(Sym), r_addend(Addend), Fixup(&Fixup) {} - - // Support lexicographic sorting. - bool operator<(const ELFRelocationEntry &RE) const { - if (RE.r_offset != r_offset) - return RE.r_offset < r_offset; - if (Type != RE.Type) - return Type < RE.Type; - if (Index != RE.Index) - return Index < RE.Index; - llvm_unreachable("ELFRelocs might be unstable!"); - return 0; - } }; class MCELFObjectTargetWriter { @@ -94,8 +82,6 @@ public: virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const; - virtual void adjustFixupOffset(const MCFixup &Fixup, - uint64_t &RelocOffset); virtual void sortRelocs(const MCAssembler &Asm, std::vector<ELFRelocationEntry> &Relocs); diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 55c05b0363ddb..4e24dcfacd507 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -28,20 +28,17 @@ class MCSymbolData; class raw_ostream; class MCELFStreamer : public MCObjectStreamer { -protected: - MCELFStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Kind, Context, TAB, OS, Emitter) {} - public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter) - : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter) {} + MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter), + SeenIdent(false) {} - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, MCAssembler *Assembler) - : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter, - Assembler) {} + MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, + MCAssembler *Assembler) + : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter, Assembler), + SeenIdent(false) {} virtual ~MCELFStreamer(); @@ -57,7 +54,7 @@ public: virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); @@ -77,21 +74,17 @@ public: uint64_t Size = 0, unsigned ByteAlignment = 0); virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); virtual void EmitFileDirective(StringRef Filename); - virtual void EmitTCEntry(const MCSymbol &S); + virtual void EmitIdent(StringRef IdentString); virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned); - virtual void FinishImpl(); - /// @} + virtual void Flush(); - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_ELFStreamer || S->getKind() == SK_ARMELFStreamer; - } + virtual void FinishImpl(); private: virtual void EmitInstToFragment(const MCInst &Inst); @@ -103,6 +96,8 @@ private: void fixSymbolsInTLSFixups(const MCExpr *expr); + bool SeenIdent; + struct LocalCommon { MCSymbolData *SD; uint64_t Size; @@ -121,6 +116,11 @@ private: void SetSectionBss(); }; +MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter, + bool RelaxAll, bool NoExecStack, + bool IsThumb); + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h index 2225ea07868f1..d0e1dace99d1a 100644 --- a/include/llvm/MC/MCELFSymbolFlags.h +++ b/include/llvm/MC/MCELFSymbolFlags.h @@ -27,7 +27,7 @@ namespace llvm { ELF_Other_Shift = 10 // Shift value for other flags. }; - enum SymbolFlags { + enum ELFSymbolFlags { ELF_STB_Local = (ELF::STB_LOCAL << ELF_STB_Shift), ELF_STB_Global = (ELF::STB_GLOBAL << ELF_STB_Shift), ELF_STB_Weak = (ELF::STB_WEAK << ELF_STB_Shift), diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index a2c5bd3f76613..5d559744da972 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -171,26 +171,56 @@ public: VK_ARM_TARGET2, VK_ARM_PREL31, - VK_PPC_TOC, // TOC base - VK_PPC_TOC_ENTRY, // TOC entry - VK_PPC_DARWIN_HA16, // ha16(symbol) - VK_PPC_DARWIN_LO16, // lo16(symbol) - VK_PPC_GAS_HA16, // symbol@ha - VK_PPC_GAS_LO16, // symbol@l - VK_PPC_TPREL16_HA, // symbol@tprel@ha - VK_PPC_TPREL16_LO, // symbol@tprel@l - VK_PPC_DTPREL16_HA, // symbol@dtprel@ha - VK_PPC_DTPREL16_LO, // symbol@dtprel@l - VK_PPC_TOC16_HA, // symbol@toc@ha - VK_PPC_TOC16_LO, // symbol@toc@l - VK_PPC_GOT_TPREL16_HA, // symbol@got@tprel@ha - VK_PPC_GOT_TPREL16_LO, // symbol@got@tprel@l + VK_PPC_LO, // symbol@l + VK_PPC_HI, // symbol@h + VK_PPC_HA, // symbol@ha + VK_PPC_HIGHER, // symbol@higher + VK_PPC_HIGHERA, // symbol@highera + VK_PPC_HIGHEST, // symbol@highest + VK_PPC_HIGHESTA, // symbol@highesta + VK_PPC_GOT_LO, // symbol@got@l + VK_PPC_GOT_HI, // symbol@got@h + VK_PPC_GOT_HA, // symbol@got@ha + VK_PPC_TOCBASE, // symbol@tocbase + VK_PPC_TOC, // symbol@toc + VK_PPC_TOC_LO, // symbol@toc@l + VK_PPC_TOC_HI, // symbol@toc@h + VK_PPC_TOC_HA, // symbol@toc@ha + VK_PPC_DTPMOD, // symbol@dtpmod + VK_PPC_TPREL, // symbol@tprel + VK_PPC_TPREL_LO, // symbol@tprel@l + VK_PPC_TPREL_HI, // symbol@tprel@h + VK_PPC_TPREL_HA, // symbol@tprel@ha + VK_PPC_TPREL_HIGHER, // symbol@tprel@higher + VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera + VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest + VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta + VK_PPC_DTPREL, // symbol@dtprel + VK_PPC_DTPREL_LO, // symbol@dtprel@l + VK_PPC_DTPREL_HI, // symbol@dtprel@h + VK_PPC_DTPREL_HA, // symbol@dtprel@ha + VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher + VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera + VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest + VK_PPC_DTPREL_HIGHESTA,// symbol@dtprel@highesta + VK_PPC_GOT_TPREL, // symbol@got@tprel + VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l + VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h + VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha + VK_PPC_GOT_DTPREL, // symbol@got@dtprel + VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l + VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h + VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha VK_PPC_TLS, // symbol@tls - VK_PPC_GOT_TLSGD16_HA, // symbol@got@tlsgd@ha - VK_PPC_GOT_TLSGD16_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD, // symbol@got@tlsgd + VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h + VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha VK_PPC_TLSGD, // symbol@tlsgd - VK_PPC_GOT_TLSLD16_HA, // symbol@got@tlsld@ha - VK_PPC_GOT_TLSLD16_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD, // symbol@got@tlsld + VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h + VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_TLSLD, // symbol@tlsld VK_Mips_GPREL, diff --git a/include/llvm/MC/MCExternalSymbolizer.h b/include/llvm/MC/MCExternalSymbolizer.h new file mode 100644 index 0000000000000..c942adca3b4d0 --- /dev/null +++ b/include/llvm/MC/MCExternalSymbolizer.h @@ -0,0 +1,58 @@ +//===-- llvm/MC/MCExternalSymbolizer.h - ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCExternalSymbolizer class, which +// enables library users to provide callbacks (through the C API) to do the +// symbolization externally. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCEXTERNALSYMBOLIZER_H +#define LLVM_MC_MCEXTERNALSYMBOLIZER_H + +#include "llvm-c/Disassembler.h" +#include "llvm/MC/MCSymbolizer.h" + +namespace llvm { + +/// \brief Symbolize using user-provided, C API, callbacks. +/// +/// See llvm-c/Disassembler.h. +class MCExternalSymbolizer : public MCSymbolizer { + + /// \name Hooks for symbolic disassembly via the public 'C' interface. + /// @{ + /// The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + /// The function to lookup a symbol name. + LLVMSymbolLookupCallback SymbolLookUp; + /// The pointer to the block of symbolic information for above call back. + void *DisInfo; + /// @} + +public: + MCExternalSymbolizer(MCContext &Ctx, + OwningPtr<MCRelocationInfo> &RelInfo, + LLVMOpInfoCallback getOpInfo, + LLVMSymbolLookupCallback symbolLookUp, + void *disInfo) + : MCSymbolizer(Ctx, RelInfo), + GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), DisInfo(disInfo) {} + + bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &CommentStream, + int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize); + void tryAddingPcLoadReferenceComment(raw_ostream &CommentStream, + int64_t Value, uint64_t Address); +}; + +} + +#endif diff --git a/include/llvm/MC/MCFunction.h b/include/llvm/MC/MCFunction.h new file mode 100644 index 0000000000000..22c9192ac4b5a --- /dev/null +++ b/include/llvm/MC/MCFunction.h @@ -0,0 +1,142 @@ +//===-- llvm/MC/MCFunction.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the data structures to hold a CFG reconstructed from +// machine code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFUNCTION_H +#define LLVM_MC_MCFUNCTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCInst.h" +#include <string> +#include <vector> + +namespace llvm { + +class MCFunction; +class MCModule; +class MCTextAtom; + +/// \brief Basic block containing a sequence of disassembled instructions. +/// The basic block is backed by an MCTextAtom, which holds the instructions, +/// and the address range it covers. +/// Create a basic block using MCFunction::createBlock. +class MCBasicBlock { + const MCTextAtom *Insts; + + // MCFunction owns the basic block. + MCFunction *Parent; + friend class MCFunction; + MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent); + + /// \name Predecessors/Successors, to represent the CFG. + /// @{ + typedef std::vector<const MCBasicBlock *> BasicBlockListTy; + BasicBlockListTy Successors; + BasicBlockListTy Predecessors; + /// @} +public: + + /// \brief Get the backing MCTextAtom, containing the instruction sequence. + const MCTextAtom *getInsts() const { return Insts; } + + /// \name Get the owning MCFunction. + /// @{ + const MCFunction *getParent() const { return Parent; } + MCFunction *getParent() { return Parent; } + /// @} + + /// MC CFG access: Predecessors/Successors. + /// @{ + typedef BasicBlockListTy::const_iterator succ_const_iterator; + succ_const_iterator succ_begin() const { return Successors.begin(); } + succ_const_iterator succ_end() const { return Successors.end(); } + + typedef BasicBlockListTy::const_iterator pred_const_iterator; + pred_const_iterator pred_begin() const { return Predecessors.begin(); } + pred_const_iterator pred_end() const { return Predecessors.end(); } + + void addSuccessor(const MCBasicBlock *MCBB); + bool isSuccessor(const MCBasicBlock *MCBB) const; + + void addPredecessor(const MCBasicBlock *MCBB); + bool isPredecessor(const MCBasicBlock *MCBB) const; + + /// \brief Split block, mirrorring NewAtom = Insts->split(..). + /// This moves all successors to \p SplitBB, and + /// adds a fallthrough to it. + /// \p SplitBB The result of splitting Insts, a basic block directly following + /// this basic block. + void splitBasicBlock(MCBasicBlock *SplitBB); + /// @} +}; + +/// \brief Represents a function in machine code, containing MCBasicBlocks. +/// MCFunctions are created by MCModule. +class MCFunction { + MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION; + MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION; + + std::string Name; + MCModule *ParentModule; + typedef std::vector<MCBasicBlock*> BasicBlockListTy; + BasicBlockListTy Blocks; + + // MCModule owns the function. + friend class MCModule; + MCFunction(StringRef Name, MCModule *Parent); + ~MCFunction(); + +public: + /// \brief Create an MCBasicBlock backed by Insts and add it to this function. + /// \param Insts Sequence of straight-line code backing the basic block. + /// \returns The newly created basic block. + MCBasicBlock &createBlock(const MCTextAtom &Insts); + + StringRef getName() const { return Name; } + + /// \name Get the owning MC Module. + /// @{ + const MCModule *getParent() const { return ParentModule; } + MCModule *getParent() { return ParentModule; } + /// @} + + /// \name Access to the function's basic blocks. No ordering is enforced, + /// except that the first block is the entry block. + /// @{ + /// \brief Get the entry point basic block. + const MCBasicBlock *getEntryBlock() const { return front(); } + MCBasicBlock *getEntryBlock() { return front(); } + + bool empty() const { return Blocks.empty(); } + + typedef BasicBlockListTy::const_iterator const_iterator; + typedef BasicBlockListTy:: iterator iterator; + const_iterator begin() const { return Blocks.begin(); } + iterator begin() { return Blocks.begin(); } + const_iterator end() const { return Blocks.end(); } + iterator end() { return Blocks.end(); } + + const MCBasicBlock* front() const { return Blocks.front(); } + MCBasicBlock* front() { return Blocks.front(); } + const MCBasicBlock* back() const { return Blocks.back(); } + MCBasicBlock* back() { return Blocks.back(); } + + /// \brief Find the basic block, if any, that starts at \p StartAddr. + const MCBasicBlock *find(uint64_t StartAddr) const; + MCBasicBlock *find(uint64_t StartAddr); + /// @} +}; + +} + +#endif diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index a18cbd94bbbf1..b4258bef04ce1 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -21,6 +21,13 @@ class MCInstrInfo; class MCRegisterInfo; class StringRef; +namespace HexStyle { + enum Style { + C, ///< 0xff + Asm ///< 0ffh + }; +} + /// MCInstPrinter - This is an instance of a target assembly language printer /// that converts an MCInst to valid target assembly syntax. class MCInstPrinter { @@ -34,7 +41,7 @@ protected: const MCRegisterInfo &MRI; /// The current set of available features. - unsigned AvailableFeatures; + uint64_t AvailableFeatures; /// True if we are printing marked up assembly. bool UseMarkup; @@ -42,13 +49,16 @@ protected: /// True if we are printing immediates as hex. bool PrintImmHex; + /// Which style to use for printing hexadecimal values. + HexStyle::Style PrintHexStyle; + /// Utility function for printing annotations. void printAnnotation(raw_ostream &OS, StringRef Annot); public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) : CommentStream(0), MAI(mai), MII(mii), MRI(mri), AvailableFeatures(0), - UseMarkup(0), PrintImmHex(0) {} + UseMarkup(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); @@ -67,8 +77,8 @@ public: /// printRegName - Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - unsigned getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + uint64_t getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } bool getUseMarkup() const { return UseMarkup; } void setUseMarkup(bool Value) { UseMarkup = Value; } @@ -80,8 +90,16 @@ public: bool getPrintImmHex() const { return PrintImmHex; } void setPrintImmHex(bool Value) { PrintImmHex = Value; } + HexStyle::Style getPrintHexStyleHex() const { return PrintHexStyle; } + void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } + /// Utility function to print immediates in decimal or hex. - format_object1<int64_t> formatImm(const int64_t Value) const; + format_object1<int64_t> formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); } + + /// Utility functions to print decimal/hexadecimal values. + format_object1<int64_t> formatDec(const int64_t Value) const; + format_object1<int64_t> formatHex(const int64_t Value) const; + format_object1<uint64_t> formatHex(const uint64_t Value) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index acad6336aca73..17bfd1582ae59 100644 --- a/include/llvm/MC/MCInstrAnalysis.h +++ b/include/llvm/MC/MCInstrAnalysis.h @@ -52,10 +52,15 @@ public: return Info->get(Inst.getOpcode()).isReturn(); } + virtual bool isTerminator(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isTerminator(); + } + /// evaluateBranch - Given a branch instruction try to get the address the - /// branch targets. Otherwise return -1. - virtual uint64_t - evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size) const; + /// branch targets. Return true on success, and the address in Target. + virtual bool + evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const; }; } diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 9b5415add2413..214b593f4ad6e 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -17,6 +17,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -145,6 +146,10 @@ public: const uint16_t *ImplicitUses; // Registers implicitly read by this instr const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands + uint64_t DeprecatedFeatureMask;// Feature bits that this is deprecated on, if any + // A complex method to determine is a certain is deprecated or not, and return + // the reason for deprecation. + bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &); /// \brief Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. @@ -158,6 +163,20 @@ public: return -1; } + /// \brief Returns true if a certain instruction is deprecated and if so + /// returns the reason in \p Info. + bool getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI, + std::string &Info) const { + if (ComplexDeprecationInfo) + return ComplexDeprecationInfo(MI, STI, Info); + if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) { + // FIXME: it would be nice to include the subtarget feature here. + Info = "deprecated"; + return true; + } + return false; + } + /// \brief Return the opcode number for this descriptor. unsigned getOpcode() const { return Opcode; @@ -268,8 +287,20 @@ public: if (isBranch() || isCall() || isReturn() || isIndirectBranch()) return true; unsigned PC = RI.getProgramCounter(); - if (PC == 0) return false; - return hasDefOfPhysReg(MI, PC, RI); + if (PC == 0) + return false; + if (hasDefOfPhysReg(MI, PC, RI)) + return true; + // A variadic instruction may define PC in the variable operand list. + // There's currently no indication of which entries in a variable + // list are defs and which are uses. While that's the case, this function + // needs to assume they're defs in order to be conservatively correct. + for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) { + if (MI.getOperand(i).isReg() && + RI.isSubRegisterEq(PC, MI.getOperand(i).getReg())) + return true; + } + return false; } /// \brief Return true if this instruction has a predicate operand diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 65d1559ac66a3..c4f9e1c32ab10 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -157,17 +157,12 @@ public: /// class. The latency is the maximum completion time for any stage /// in the itinerary. /// - /// InstrStages override the itinerary's MinLatency property. In fact, if the - /// stage latencies, which may be zero, are less than MinLatency, - /// getStageLatency returns a value less than MinLatency. - /// - /// If no stages exist, MinLatency is used. If MinLatency is invalid (<0), - /// then it defaults to one cycle. + /// If no stages exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple // non-zero default value for all instructions. if (isEmpty()) - return SchedModel->MinLatency < 0 ? 1 : SchedModel->MinLatency; + return 1; // Calculate the maximum completion time for any stage. unsigned Latency = 0, StartCycle = 0; @@ -176,7 +171,6 @@ public: Latency = std::max(Latency, StartCycle + IS->getCycles()); StartCycle += IS->getNextCycles(); } - return Latency; } diff --git a/include/llvm/MC/MCMachOSymbolFlags.h b/include/llvm/MC/MCMachOSymbolFlags.h index 696436dffa6ec..71f01fab20648 100644 --- a/include/llvm/MC/MCMachOSymbolFlags.h +++ b/include/llvm/MC/MCMachOSymbolFlags.h @@ -19,9 +19,9 @@ // the correct relocation information. namespace llvm { - /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest - /// 16 bits of the implementation defined flags. - enum SymbolFlags { // See <mach-o/nlist.h>. + /// MachOSymbolFlags - We store the value for the 'desc' symbol field in the + /// lowest 16 bits of the implementation defined flags. + enum MachOSymbolFlags { // See <mach-o/nlist.h>. SF_DescFlagsMask = 0xFFFF, // Reference type flags. diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 3c9a588d04134..3ba6e651007c5 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -15,8 +15,8 @@ #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" -#include "llvm/Object/MachOFormat.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MachO.h" #include <vector> namespace llvm { @@ -98,7 +98,7 @@ class MachObjectWriter : public MCObjectWriter { /// @{ llvm::DenseMap<const MCSectionData*, - std::vector<object::macho::RelocationEntry> > Relocations; + std::vector<MachO::any_relocation_info> > Relocations; llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase; /// @} @@ -155,9 +155,8 @@ public: bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool isARM() const { - uint32_t CPUType = TargetObjectWriter->getCPUType() & - ~object::mach::CTFM_ArchMask; - return CPUType == object::mach::CTM_ARM; + uint32_t CPUType = TargetObjectWriter->getCPUType() & ~MachO::CPU_ARCH_MASK; + return CPUType == MachO::CPU_TYPE_ARM; } /// @} @@ -213,7 +212,7 @@ public: // these through in many cases. void addRelocation(const MCSectionData *SD, - object::macho::RelocationEntry &MRE) { + MachO::any_relocation_info &MRE) { Relocations[SD].push_back(MRE); } diff --git a/include/llvm/MC/MCModule.h b/include/llvm/MC/MCModule.h index 755fa025fbc7b..63635c7478ce4 100644 --- a/include/llvm/MC/MCModule.h +++ b/include/llvm/MC/MCModule.h @@ -15,44 +15,119 @@ #ifndef LLVM_MC_MCMODULE_H #define LLVM_MC_MCMODULE_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include <vector> namespace llvm { class MCAtom; +class MCBasicBlock; +class MCDataAtom; +class MCFunction; +class MCObjectDisassembler; +class MCTextAtom; -/// MCModule - This class represent a completely disassembled object file or -/// executable. It comprises a list of MCAtom's, and a branch target table. -/// Each atom represents a contiguous range of either instructions or data. +/// \brief A completely disassembled object file or executable. +/// It comprises a list of MCAtom's, each representing a contiguous range of +/// either instructions or data. +/// An MCModule is created using MCObjectDisassembler::buildModule. class MCModule { - /// AtomAllocationTracker - An MCModule owns its component MCAtom's, so it - /// must track them in order to ensure they are properly freed as atoms are - /// merged or otherwise manipulated. - SmallPtrSet<MCAtom*, 8> AtomAllocationTracker; + /// \name Atom tracking + /// @{ - /// OffsetMap - Efficiently maps offset ranges to MCAtom's. - IntervalMap<uint64_t, MCAtom*> OffsetMap; - - /// BranchTargetMap - Maps offsets that are determined to be branches and - /// can be statically resolved to their target offsets. - DenseMap<uint64_t, MCAtom*> BranchTargetMap; + /// \brief Atoms in this module, sorted by begin address. + /// FIXME: This doesn't handle overlapping atoms (which happen when a basic + /// block starts in the middle of an instruction of another basic block.) + typedef std::vector<MCAtom*> AtomListTy; + AtomListTy Atoms; + // For access to map/remap. friend class MCAtom; - /// remap - Update the interval mapping for an MCAtom. + /// \brief Remap \p Atom to the given range, and update its Begin/End fields. + /// \param Atom An atom belonging to this module. + /// An atom should always use this method to update its bounds, because this + /// enables the owning MCModule to keep track of its atoms. void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd); + /// \brief Insert an atom in the module, using its Begin and End addresses. + void map(MCAtom *NewAtom); + /// @} + + /// \name Basic block tracking + /// @{ + typedef std::vector<MCBasicBlock*> BBsByAtomTy; + BBsByAtomTy BBsByAtom; + + // For access to basic block > atom tracking. + friend class MCBasicBlock; + friend class MCTextAtom; + + /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom. + /// This is used to update succs/preds when \p Atom is split. + void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom); + void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA); + /// @} + + /// \name Function tracking + /// @{ + typedef std::vector<MCFunction*> FunctionListTy; + FunctionListTy Functions; + /// @} + + /// The address of the entrypoint function. + uint64_t Entrypoint; + + MCModule (const MCModule &) LLVM_DELETED_FUNCTION; + MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION; + + // MCObjectDisassembler creates MCModules. + friend class MCObjectDisassembler; + public: - MCModule(IntervalMap<uint64_t, MCAtom*>::Allocator &A) : OffsetMap(A) { } + MCModule() : Entrypoint(0) { } + ~MCModule(); + + /// \name Create a new MCAtom covering the specified offset range. + /// @{ + MCTextAtom *createTextAtom(uint64_t Begin, uint64_t End); + MCDataAtom *createDataAtom(uint64_t Begin, uint64_t End); + /// @} + + /// \name Access to the owned atom list, ordered by begin address. + /// @{ + const MCAtom *findAtomContaining(uint64_t Addr) const; + MCAtom *findAtomContaining(uint64_t Addr); + const MCAtom *findFirstAtomAfter(uint64_t Addr) const; + MCAtom *findFirstAtomAfter(uint64_t Addr); + + typedef AtomListTy::const_iterator const_atom_iterator; + typedef AtomListTy:: iterator atom_iterator; + const_atom_iterator atom_begin() const { return Atoms.begin(); } + atom_iterator atom_begin() { return Atoms.begin(); } + const_atom_iterator atom_end() const { return Atoms.end(); } + atom_iterator atom_end() { return Atoms.end(); } + /// @} - /// createAtom - Creates a new MCAtom covering the specified offset range. - MCAtom *createAtom(MCAtom::AtomType Type, uint64_t Begin, uint64_t End); + /// \brief Create a new MCFunction. + MCFunction *createFunction(StringRef Name); + + /// \name Access to the owned function list. + /// @{ + typedef FunctionListTy::const_iterator const_func_iterator; + typedef FunctionListTy:: iterator func_iterator; + const_func_iterator func_begin() const { return Functions.begin(); } + func_iterator func_begin() { return Functions.begin(); } + const_func_iterator func_end() const { return Functions.end(); } + func_iterator func_end() { return Functions.end(); } + /// @} + + /// \brief Get the address of the entrypoint function, or 0 if there is none. + uint64_t getEntrypoint() const { return Entrypoint; } }; } #endif - diff --git a/include/llvm/MC/MCModuleYAML.h b/include/llvm/MC/MCModuleYAML.h new file mode 100644 index 0000000000000..281e3d8dc912b --- /dev/null +++ b/include/llvm/MC/MCModuleYAML.h @@ -0,0 +1,41 @@ +//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file declares classes for handling the YAML representation +/// of MCModule. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMODULEYAML_H +#define LLVM_MC_MCMODULEYAML_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCModule.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class MCInstrInfo; +class MCRegisterInfo; + +/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS. +/// \returns The empty string on success, an error message on failure. +StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +/// \brief Creates a new module and returns it in \p MCM. +/// \returns The empty string on success, an error message on failure. +StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h new file mode 100644 index 0000000000000..0d87d33bab985 --- /dev/null +++ b/include/llvm/MC/MCObjectDisassembler.h @@ -0,0 +1,175 @@ +//===-- llvm/MC/MCObjectDisassembler.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCObjectDisassembler class, which +// can be used to construct an MCModule and an MC CFG from an ObjectFile. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTDISASSEMBLER_H +#define LLVM_MC_MCOBJECTDISASSEMBLER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryObject.h" +#include <vector> + +namespace llvm { + +namespace object { + class ObjectFile; + class MachOObjectFile; +} + +class MCBasicBlock; +class MCDisassembler; +class MCFunction; +class MCInstrAnalysis; +class MCModule; +class MCObjectSymbolizer; + +/// \brief Disassemble an ObjectFile to an MCModule and MCFunctions. +/// This class builds on MCDisassembler to disassemble whole sections, creating +/// MCAtom (MCTextAtom for disassembled sections and MCDataAtom for raw data). +/// It can also be used to create a control flow graph consisting of MCFunctions +/// and MCBasicBlocks. +class MCObjectDisassembler { +public: + MCObjectDisassembler(const object::ObjectFile &Obj, + const MCDisassembler &Dis, + const MCInstrAnalysis &MIA); + virtual ~MCObjectDisassembler() {} + + /// \brief Build an MCModule, creating atoms and optionally functions. + /// \param withCFG Also build a CFG by adding MCFunctions to the Module. + /// If withCFG is false, the MCModule built only contains atoms, representing + /// what was found in the object file. If withCFG is true, MCFunctions are + /// created, containing MCBasicBlocks. All text atoms are split to form basic + /// block atoms, which then each back an MCBasicBlock. + MCModule *buildModule(bool withCFG = false); + + MCModule *buildEmptyModule(); + + typedef std::vector<uint64_t> AddressSetTy; + /// \name Create a new MCFunction. + MCFunction *createFunction(MCModule *Module, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets); + + /// \brief Set the region on which to fallback if disassembly was requested + /// somewhere not accessible in the object file. + /// This is used for dynamic disassembly (see RawMemoryObject). + void setFallbackRegion(OwningPtr<MemoryObject> &Region) { + FallbackRegion.reset(Region.take()); + } + + /// \brief Set the symbolizer to use to get information on external functions. + /// Note that this isn't used to do instruction-level symbolization (that is, + /// plugged into MCDisassembler), but to symbolize function call targets. + void setSymbolizer(MCObjectSymbolizer *ObjectSymbolizer) { + MOS = ObjectSymbolizer; + } + + /// \brief Get the effective address of the entrypoint, or 0 if there is none. + virtual uint64_t getEntrypoint(); + + /// \name Get the addresses of static constructors/destructors in the object. + /// The caller is expected to know how to interpret the addresses; + /// for example, Mach-O init functions expect 5 arguments, not for ELF. + /// The addresses are original object file load addresses, not effective. + /// @{ + virtual ArrayRef<uint64_t> getStaticInitFunctions(); + virtual ArrayRef<uint64_t> getStaticExitFunctions(); + /// @} + + /// \name Translation between effective and objectfile load address. + /// @{ + /// \brief Compute the effective load address, from an objectfile virtual + /// address. This is implemented in a format-specific way, to take into + /// account things like PIE/ASLR when doing dynamic disassembly. + /// For example, on Mach-O this would be done by adding the VM addr slide, + /// on glibc ELF by keeping a map between segment load addresses, filled + /// using dl_iterate_phdr, etc.. + /// In most static situations and in the default impl., this returns \p Addr. + virtual uint64_t getEffectiveLoadAddr(uint64_t Addr); + + /// \brief Compute the original load address, as specified in the objectfile. + /// This is the inverse of getEffectiveLoadAddr. + virtual uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr); + /// @} + +protected: + const object::ObjectFile &Obj; + const MCDisassembler &Dis; + const MCInstrAnalysis &MIA; + MCObjectSymbolizer *MOS; + + /// \brief The fallback memory region, outside the object file. + OwningPtr<MemoryObject> FallbackRegion; + + /// \brief Return a memory region suitable for reading starting at \p Addr. + /// In most cases, this returns a StringRefMemoryObject backed by the + /// containing section. When no section was found, this returns the + /// FallbackRegion, if it is suitable. + /// If it is not, or if there is no fallback region, this returns 0. + MemoryObject *getRegionFor(uint64_t Addr); + +private: + /// \brief Fill \p Module by creating an atom for each section. + /// This could be made much smarter, using information like symbols, but also + /// format-specific features, like mach-o function_start or data_in_code LCs. + void buildSectionAtoms(MCModule *Module); + + /// \brief Enrich \p Module with a CFG consisting of MCFunctions. + /// \param Module An MCModule returned by buildModule, with no CFG. + /// NOTE: Each MCBasicBlock in a MCFunction is backed by a single MCTextAtom. + /// When the CFG is built, contiguous instructions that were previously in a + /// single MCTextAtom will be split in multiple basic block atoms. + void buildCFG(MCModule *Module); + + MCBasicBlock *getBBAt(MCModule *Module, MCFunction *MCFN, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets); +}; + +class MCMachOObjectDisassembler : public MCObjectDisassembler { + const object::MachOObjectFile &MOOF; + + uint64_t VMAddrSlide; + uint64_t HeaderLoadAddress; + + // __DATA;__mod_init_func support. + llvm::StringRef ModInitContents; + // __DATA;__mod_exit_func support. + llvm::StringRef ModExitContents; + +public: + /// \brief Construct a Mach-O specific object disassembler. + /// \param VMAddrSlide The virtual address slide applied by dyld. + /// \param HeaderLoadAddress The load address of the mach_header for this + /// object. + MCMachOObjectDisassembler(const object::MachOObjectFile &MOOF, + const MCDisassembler &Dis, + const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, + uint64_t HeaderLoadAddress); + +protected: + uint64_t getEffectiveLoadAddr(uint64_t Addr) LLVM_OVERRIDE; + uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) LLVM_OVERRIDE; + uint64_t getEntrypoint() LLVM_OVERRIDE; + + ArrayRef<uint64_t> getStaticInitFunctions() LLVM_OVERRIDE; + ArrayRef<uint64_t> getStaticExitFunctions() LLVM_OVERRIDE; +}; + +} + +#endif diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index a5853b602c871..c48dcb021620d 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -125,6 +125,10 @@ protected: const MCSection *DwarfStrOffDWOSection; const MCSection *DwarfAddrSection; + /// Sections for newer gnu pubnames and pubtypes. + const MCSection *DwarfGnuPubNamesSection; + const MCSection *DwarfGnuPubTypesSection; + // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. const MCSection *TLSExtraDataSection; @@ -138,6 +142,8 @@ protected: /// ELF and MachO only. const MCSection *TLSBSSSection; // Defaults to ".tbss". + /// StackMap section. + const MCSection *StackMapSection; /// EHFrameSection - EH frame section. It is initialized on demand so it /// can be overwritten (with uniquing). @@ -223,6 +229,12 @@ public: const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} + const MCSection *getDwarfGnuPubNamesSection() const { + return DwarfGnuPubNamesSection; + } + const MCSection *getDwarfGnuPubTypesSection() const { + return DwarfGnuPubTypesSection; + } const MCSection *getDwarfDebugInlineSection() const { return DwarfDebugInlineSection; } @@ -275,6 +287,8 @@ public: const MCSection *getTLSDataSection() const { return TLSDataSection; } const MCSection *getTLSBSSSection() const { return TLSBSSSection; } + const MCSection *getStackMapSection() const { return StackMapSection; } + /// ELF specific sections. /// const MCSection *getDataRelSection() const { return DataRelSection; } diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 22a283986975d..56675443015eb 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -40,10 +40,11 @@ class MCObjectStreamer : public MCStreamer { virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame); protected: - MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter); - MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, + MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &_OS, + MCCodeEmitter *_Emitter); + MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, MCAssembler *_Assembler); ~MCObjectStreamer(); @@ -78,8 +79,7 @@ public: virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); @@ -94,7 +94,7 @@ public: virtual void EmitBundleAlignMode(unsigned AlignPow2); virtual void EmitBundleLock(bool AlignToEnd); virtual void EmitBundleUnlock(); - virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0); + virtual void EmitBytes(StringRef Data); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -102,6 +102,10 @@ public: virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0); virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value); + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName); virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, @@ -110,15 +114,9 @@ public: const MCSymbol *Label); virtual void EmitGPRel32Value(const MCExpr *Value); virtual void EmitGPRel64Value(const MCExpr *Value); - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace = 0); + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); + virtual void EmitZeros(uint64_t NumBytes); virtual void FinishImpl(); - - /// @} - - static bool classof(const MCStreamer *S) { - return S->getKind() >= SK_ELFStreamer && S->getKind() <= SK_WinCOFFStreamer; - } }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h new file mode 100644 index 0000000000000..64b932ebe4f9c --- /dev/null +++ b/include/llvm/MC/MCObjectSymbolizer.h @@ -0,0 +1,81 @@ +//===-- llvm/MC/MCObjectSymbolizer.h --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCObjectSymbolizer class, an MCSymbolizer that is +// backed by an object::ObjectFile. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTSYMBOLIZER_H +#define LLVM_MC_MCOBJECTSYMBOLIZER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/MC/MCSymbolizer.h" +#include "llvm/Object/ObjectFile.h" +#include <vector> + +namespace llvm { + +class MCExpr; +class MCInst; +class MCRelocationInfo; +class raw_ostream; + +/// \brief An ObjectFile-backed symbolizer. +class MCObjectSymbolizer : public MCSymbolizer { +protected: + const object::ObjectFile *Obj; + + // Map a load address to the first relocation that applies there. As far as I + // know, if there are several relocations at the exact same address, they are + // related and the others can be determined from the first that was found in + // the relocation table. For instance, on x86-64 mach-o, a SUBTRACTOR + // relocation (referencing the minuend symbol) is followed by an UNSIGNED + // relocation (referencing the subtrahend symbol). + const object::RelocationRef *findRelocationAt(uint64_t Addr); + const object::SectionRef *findSectionContaining(uint64_t Addr); + + MCObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, + const object::ObjectFile *Obj); + +public: + /// \name Overridden MCSymbolizer methods: + /// @{ + bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, + int64_t Value, uint64_t Address, + bool IsBranch, uint64_t Offset, + uint64_t InstSize); + + void tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, uint64_t Address); + /// @} + + /// \brief Look for an external function symbol at \p Addr. + /// (References through the ELF PLT, Mach-O stubs, and similar). + /// \returns An MCExpr representing the external symbol, or 0 if not found. + virtual StringRef findExternalFunctionAt(uint64_t Addr); + + /// \brief Create an object symbolizer for \p Obj. + static MCObjectSymbolizer * + createObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, + const object::ObjectFile *Obj); + +private: + typedef DenseMap<uint64_t, object::RelocationRef> AddrToRelocMap; + typedef std::vector<object::SectionRef> SortedSectionList; + SortedSectionList SortedSections; + AddrToRelocMap AddrToReloc; + + void buildSectionList(); + void buildRelocationByAddrMap(); +}; + +} + +#endif diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 0dab31489fbb6..1b3ab577519ba 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -63,6 +63,7 @@ private: AsmToken LexSingleQuote(); AsmToken LexQuote(); AsmToken LexFloatLiteral(); + AsmToken LexHexFloatLiteral(bool NoIntDigits); }; } // end namespace llvm diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index dcc98863333bd..1d15534299949 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -47,7 +47,7 @@ public: } } InlineAsmIdentifierInfo; - virtual ~MCAsmParserSemaCallback(); + virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf, InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) = 0; diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index f5b4dddc5198a..3fa89c109c1c6 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -99,19 +99,15 @@ public: bool isAllocatable() const { return Allocatable; } }; -/// MCRegisterDesc - This record contains all of the information known about -/// a particular register. The Overlaps field contains a pointer to a zero -/// terminated array of registers that this register aliases, starting with -/// itself. This is needed for architectures like X86 which have AL alias AX -/// alias EAX. The SubRegs field is a zero terminated array of registers that -/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of -/// AX. The SuperRegs field is a zero terminated array of registers that are -/// super-registers of the specific register, e.g. RAX, EAX, are super-registers -/// of AX. +/// MCRegisterDesc - This record contains information about a particular +/// register. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers +/// of AX. The SuperRegs field is a zero terminated array of registers that are +/// super-registers of the specific register, e.g. RAX, EAX, are +/// super-registers of AX. /// struct MCRegisterDesc { uint32_t Name; // Printable name for the reg (for debugging) - uint32_t Overlaps; // Overlapping registers, described above uint32_t SubRegs; // Sub-register set, described above uint32_t SuperRegs; // Super-register set, described above @@ -148,6 +144,13 @@ public: bool operator<(DwarfLLVMRegPair RHS) const { return FromReg < RHS.FromReg; } }; + + /// SubRegCoveredBits - Emitted by tablegen: bit range covered by a subreg + /// index, -1 in any being invalid. + struct SubRegCoveredBits { + uint16_t Offset; + uint16_t Size; + }; private: const MCRegisterDesc *Desc; // Pointer to the descriptor array unsigned NumRegs; // Number of entries in the array @@ -161,6 +164,8 @@ private: const char *RegStrings; // Pointer to the string table. const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. + const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered + // bit ranges array. unsigned NumSubRegIndices; // Number of subreg indices. const uint16_t *RegEncodingTable; // Pointer to array of register // encodings. @@ -226,7 +231,6 @@ public: // internal list pointers. friend class MCSubRegIterator; friend class MCSuperRegIterator; - friend class MCRegAliasIterator; friend class MCRegUnitIterator; friend class MCRegUnitRootIterator; @@ -241,6 +245,7 @@ public: const char *Strings, const uint16_t *SubIndices, unsigned NumIndices, + const SubRegCoveredBits *SubIdxRanges, const uint16_t *RET) { Desc = D; NumRegs = NR; @@ -254,6 +259,7 @@ public: NumRegUnits = NRU; SubRegIndices = SubIndices; NumSubRegIndices = NumIndices; + SubRegIdxRanges = SubIdxRanges; RegEncodingTable = RET; } @@ -332,6 +338,16 @@ public: /// otherwise. unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const; + /// \brief Get the size of the bit range covered by a sub-register index. + /// If the index isn't continuous, return the sum of the sizes of its parts. + /// If the index is used to access subregisters of different sizes, return -1. + unsigned getSubRegIdxSize(unsigned Idx) const; + + /// \brief Get the offset of the bit range covered by a sub-register index. + /// If an Offset doesn't make sense (the index isn't continuous, or is used to + /// access sub-registers at different offsets), return -1. + unsigned getSubRegIdxOffset(unsigned Idx) const; + /// \brief Return the human-readable symbolic target-specific name for the /// specified physical register. const char *getName(unsigned RegNo) const { @@ -421,30 +437,26 @@ public: // aliasing registers. Use these iterator classes to traverse the lists. /// MCSubRegIterator enumerates all sub-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. class MCSubRegIterator : public MCRegisterInfo::DiffListIterator { public: - MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { init(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs); - ++*this; + // Initially, the iterator points to Reg itself. + if (!IncludeSelf) + ++*this; } }; /// MCSuperRegIterator enumerates all super-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { public: - MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + MCSuperRegIterator() {} + MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs); - ++*this; - } -}; - -/// MCRegAliasIterator enumerates all registers aliasing Reg. -/// If IncludeSelf is set, Reg itself is included in the list. -class MCRegAliasIterator : public MCRegisterInfo::DiffListIterator { -public: - MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, - bool IncludeSelf) { - init(Reg, MCRI->DiffLists + MCRI->get(Reg).Overlaps); // Initially, the iterator points to Reg itself. if (!IncludeSelf) ++*this; @@ -478,6 +490,7 @@ class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator { public: /// MCRegUnitIterator - Create an iterator that traverses the register units /// in Reg. + MCRegUnitIterator() {} MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) { assert(Reg && "Null register has no regunits"); // Decode the RegUnits MCRegisterDesc field. @@ -502,9 +515,7 @@ public: // super-registers. All registers aliasing Unit can be visited like this: // // for (MCRegUnitRootIterator RI(Unit, MCRI); RI.isValid(); ++RI) { -// unsigned Root = *RI; -// visit(Root); -// for (MCSuperRegIterator SI(Root, MCRI); SI.isValid(); ++SI) +// for (MCSuperRegIterator SI(*RI, MCRI, true); SI.isValid(); ++SI) // visit(*SI); // } @@ -513,6 +524,7 @@ class MCRegUnitRootIterator { uint16_t Reg0; uint16_t Reg1; public: + MCRegUnitRootIterator() : Reg0(0), Reg1(0) {} MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) { assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit"); Reg0 = MCRI->RegUnitRoots[RegUnit][0]; @@ -537,6 +549,68 @@ public: } }; +/// MCRegAliasIterator enumerates all registers aliasing Reg. If IncludeSelf is +/// set, Reg itself is included in the list. This iterator does not guarantee +/// any ordering or that entries are unique. +class MCRegAliasIterator { +private: + unsigned Reg; + const MCRegisterInfo *MCRI; + bool IncludeSelf; + + MCRegUnitIterator RI; + MCRegUnitRootIterator RRI; + MCSuperRegIterator SI; +public: + MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf) + : Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) { + + // Initialize the iterators. + for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) { + for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) { + for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) { + if (!(!IncludeSelf && Reg == *SI)) + return; + } + } + } + } + + bool isValid() const { + return RI.isValid(); + } + + unsigned operator*() const { + assert (SI.isValid() && "Cannot dereference an invalid iterator."); + return *SI; + } + + void advance() { + // Assuming SI is valid. + ++SI; + if (SI.isValid()) return; + + ++RRI; + if (RRI.isValid()) { + SI = MCSuperRegIterator(*RRI, MCRI, true); + return; + } + + ++RI; + if (RI.isValid()) { + RRI = MCRegUnitRootIterator(*RI, MCRI); + SI = MCSuperRegIterator(*RRI, MCRI, true); + } + } + + void operator++() { + assert(isValid() && "Cannot move off the end of the list."); + do advance(); + while (!IncludeSelf && isValid() && *SI == Reg); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCRelocationInfo.h new file mode 100644 index 0000000000000..9dab90099b7d1 --- /dev/null +++ b/include/llvm/MC/MCRelocationInfo.h @@ -0,0 +1,55 @@ +//==-- llvm/MC/MCRelocationInfo.h --------------------------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCRelocationInfo class, which provides methods to +// create MCExprs from relocations, either found in an object::ObjectFile +// (object::RelocationRef), or provided through the C API. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCRELOCATIONINFO_H +#define LLVM_MC_MCRELOCATIONINFO_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + +namespace object { +class RelocationRef; +} +class MCExpr; +class MCContext; + +/// \brief Create MCExprs from relocations found in an object file. +class MCRelocationInfo { + MCRelocationInfo(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; + void operator=(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; + +protected: + MCContext &Ctx; + +public: + MCRelocationInfo(MCContext &Ctx); + virtual ~MCRelocationInfo(); + + /// \brief Create an MCExpr for the relocation \p Rel. + /// \returns If possible, an MCExpr corresponding to Rel, else 0. + virtual const MCExpr *createExprForRelocation(object::RelocationRef Rel); + + /// \brief Create an MCExpr for the target-specific \p VariantKind. + /// The VariantKinds are defined in llvm-c/Disassembler.h. + /// Used by MCExternalSymbolizer. + /// \returns If possible, an MCExpr corresponding to VariantKind, else 0. + virtual const MCExpr *createExprForCAPIVariantKind(const MCExpr *SubExpr, + unsigned VariantKind); +}; + +} + +#endif diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index defa299035433..6881e1d05ac3e 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -30,15 +30,18 @@ struct MCProcResourceDesc { unsigned NumUnits; // Number of resource of this kind unsigned SuperIdx; // Index of the resources kind that contains this kind. - // Buffered resources may be consumed at some indeterminate cycle after - // dispatch (e.g. for instructions that may issue out-of-order). Unbuffered - // resources always consume their resource some fixed number of cycles after - // dispatch (e.g. for instruction interlocking that may stall the pipeline). - bool IsBuffered; + // Number of resources that may be buffered. + // + // Buffered resources (BufferSize > 0 || BufferSize == -1) may be consumed at + // some indeterminate cycle after dispatch (e.g. for instructions that may + // issue out-of-order). Unbuffered resources (BufferSize == 0) always consume + // their resource some fixed number of cycles after dispatch (e.g. for + // instruction interlocking that may stall the pipeline). + int BufferSize; bool operator==(const MCProcResourceDesc &Other) const { return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx - && IsBuffered == Other.IsBuffered; + && BufferSize == Other.BufferSize; } }; @@ -121,7 +124,7 @@ struct MCSchedClassDesc { /// microarchitecture to the scheduler in the form of properties. It also /// optionally refers to scheduler resource tables and itinerary /// tables. Scheduler resource tables model the latency and cost for each -/// instruction type. Itinerary tables are an independant mechanism that +/// instruction type. Itinerary tables are an independent mechanism that /// provides a detailed reservation table describing each cycle of instruction /// execution. Subtargets may define any or all of the above categories of data /// depending on the type of CPU and selected scheduler. @@ -134,28 +137,22 @@ public: unsigned IssueWidth; static const unsigned DefaultIssueWidth = 1; - // MinLatency is the minimum latency between a register write - // followed by a data dependent read. This determines which - // instructions may be scheduled in the same per-cycle group. This - // is distinct from *expected* latency, which determines the likely - // critical path but does not guarantee a pipeline - // hazard. MinLatency can always be overridden by the number of - // InstrStage cycles. + // MicroOpBufferSize is the number of micro-ops that the processor may buffer + // for out-of-order execution. // - // (-1) Standard in-order processor. - // Use InstrItinerary OperandCycles as MinLatency. - // If no OperandCycles exist, then use the cycle of the last InstrStage. + // "0" means operations that are not ready in this cycle are not considered + // for scheduling (they go in the pending queue). Latency is paramount. This + // may be more efficient if many instructions are pending in a schedule. // - // (0) Out-of-order processor, or in-order with bundled dependencies. - // RAW dependencies may be dispatched in the same cycle. - // Optional InstrItinerary OperandCycles provides expected latency. + // "1" means all instructions are considered for scheduling regardless of + // whether they are ready in this cycle. Latency still causes issue stalls, + // but we balance those stalls against other heuristics. // - // (>0) In-order processor with variable latencies. - // Use the greater of this value or the cycle of the last InstrStage. - // Optional InstrItinerary OperandCycles provides expected latency. - // TODO: can't yet specify both min and expected latency per operand. - int MinLatency; - static const int DefaultMinLatency = -1; + // "> 1" means the processor is out-of-order. This is a machine independent + // estimate of highly machine specific characteristics such are the register + // renaming pool and reorder buffer. + unsigned MicroOpBufferSize; + static const unsigned DefaultMicroOpBufferSize = 0; // LoadLatency is the expected latency of load instructions. // @@ -172,21 +169,13 @@ public: unsigned HighLatency; static const unsigned DefaultHighLatency = 10; - // ILPWindow is the number of cycles that the scheduler effectively ignores - // before attempting to hide latency. This should be zero for in-order cpus to - // always hide expected latency. For out-of-order cpus, it may be tweaked as - // desired to roughly approximate instruction buffers. The actual threshold is - // not very important for an OOO processor, as long as it isn't too high. A - // nonzero value helps avoid rescheduling to hide latency when its is fairly - // obviously useless and makes register pressure heuristics more effective. - unsigned ILPWindow; - static const unsigned DefaultILPWindow = 0; - // MispredictPenalty is the typical number of extra cycles the processor // takes to recover from a branch misprediction. unsigned MispredictPenalty; static const unsigned DefaultMispredictPenalty = 10; + bool CompleteModel; + private: unsigned ProcID; const MCProcResourceDesc *ProcResourceTable; @@ -203,11 +192,11 @@ public: // initialized in this default ctor because some clients directly instantiate // MCSchedModel instead of using a generated itinerary. MCSchedModel(): IssueWidth(DefaultIssueWidth), - MinLatency(DefaultMinLatency), + MicroOpBufferSize(DefaultMicroOpBufferSize), LoadLatency(DefaultLoadLatency), HighLatency(DefaultHighLatency), - ILPWindow(DefaultILPWindow), MispredictPenalty(DefaultMispredictPenalty), + CompleteModel(true), ProcID(0), ProcResourceTable(0), SchedClassTable(0), NumProcResourceKinds(0), NumSchedClasses(0), InstrItineraries(0) { @@ -216,20 +205,24 @@ public: } // Table-gen driven ctor. - MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned ilp, - unsigned mp, unsigned pi, const MCProcResourceDesc *pr, + MCSchedModel(unsigned iw, int mbs, unsigned ll, unsigned hl, + unsigned mp, bool cm, unsigned pi, const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, const InstrItinerary *ii): - IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl), - ILPWindow(ilp), MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), - SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc), - InstrItineraries(ii) {} + IssueWidth(iw), MicroOpBufferSize(mbs), LoadLatency(ll), HighLatency(hl), + MispredictPenalty(mp), CompleteModel(cm), ProcID(pi), + ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), + NumSchedClasses(nsc), InstrItineraries(ii) {} unsigned getProcessorID() const { return ProcID; } /// Does this machine model include instruction-level scheduling. bool hasInstrSchedModel() const { return SchedClassTable; } + /// Return true if this machine model data for all instructions with a + /// scheduling class (itinerary class or SchedRW list). + bool isComplete() const { return CompleteModel; } + unsigned getNumProcResourceKinds() const { return NumProcResourceKinds; } diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 50e33a5b040af..45c84ae71eeb6 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -19,28 +19,47 @@ #include "llvm/Support/COFF.h" namespace llvm { +class MCSymbol; /// MCSectionCOFF - This represents a section on Windows class MCSectionCOFF : public MCSection { // The memory for this string is stored in the same MCContext as *this. StringRef SectionName; + // FIXME: The following fields should not be mutable, but are for now so + // the asm parser can honor the .linkonce directive. + /// Characteristics - This is the Characteristics field of a section, - // drawn from the enums below. - unsigned Characteristics; + /// drawn from the enums below. + mutable unsigned Characteristics; + + /// The COMDAT symbol of this section. Only valid if this is a COMDAT + /// section. Two COMDAT sections are merged if they have the same + /// COMDAT symbol. + const MCSymbol *COMDATSymbol; /// Selection - This is the Selection field for the section symbol, if /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 - int Selection; + mutable int Selection; + + /// Assoc - This is name of the associated section, if it is a COMDAT + /// section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 with an + /// associative Selection (IMAGE_COMDAT_SELECT_ASSOCIATIVE). + mutable const MCSectionCOFF *Assoc; private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - int Selection, SectionKind K) - : MCSection(SV_COFF, K), SectionName(Section), - Characteristics(Characteristics), Selection (Selection) { + const MCSymbol *COMDATSymbol, int Selection, + const MCSectionCOFF *Assoc, SectionKind K) + : MCSection(SV_COFF, K), SectionName(Section), + Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), + Selection(Selection), Assoc(Assoc) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); + assert ((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == + (Assoc != 0) && + "associative COMDAT section must have an associated section"); } ~MCSectionCOFF(); @@ -57,7 +76,10 @@ namespace llvm { return SectionName.str() + "_end"; } unsigned getCharacteristics() const { return Characteristics; } - int getSelection () const { return Selection; } + int getSelection() const { return Selection; } + const MCSectionCOFF *getAssocSection() const { return Assoc; } + + void setSelection(int Selection, const MCSectionCOFF *Assoc = 0) const; virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index b68bd8596801a..d7e88ea561247 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -41,7 +41,7 @@ public: /// These are the section type and attributes fields. A MachO section can /// have only one Type, but can have any of the attributes specified. - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // TypeAndAttributes bitmasks. SECTION_TYPE = 0x000000FFU, SECTION_ATTRIBUTES = 0xFFFFFF00U, diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 2cab481c3d8d8..0b1fe6ec01291 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -24,683 +24,716 @@ #include <string> namespace llvm { - class MCAsmBackend; - class MCCodeEmitter; - class MCContext; - class MCExpr; - class MCInst; - class MCInstPrinter; - class MCSection; - class MCSymbol; - class StringRef; - class Twine; - class raw_ostream; - class formatted_raw_ostream; - - typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; - - /// MCStreamer - Streaming machine code generation interface. This interface - /// is intended to provide a programatic interface that is very similar to the - /// level that an assembler .s file provides. It has callbacks to emit bytes, - /// handle directives, etc. The implementation of this interface retains - /// state to know what the current section is etc. - /// - /// There are multiple implementations of this interface: one for writing out - /// a .s file, and implementations that write out .o files of various formats. - /// - class MCStreamer { - public: - enum StreamerKind { - SK_AsmStreamer, - SK_NullStreamer, - SK_RecordStreamer, - - // MCObjectStreamer subclasses. - SK_ELFStreamer, - SK_ARMELFStreamer, - SK_MachOStreamer, - SK_PureStreamer, - SK_MipsELFStreamer, - SK_WinCOFFStreamer - }; - - private: - const StreamerKind Kind; - MCContext &Context; - - MCStreamer(const MCStreamer&) LLVM_DELETED_FUNCTION; - MCStreamer &operator=(const MCStreamer&) LLVM_DELETED_FUNCTION; - - bool EmitEHFrame; - bool EmitDebugFrame; - - std::vector<MCDwarfFrameInfo> FrameInfos; - MCDwarfFrameInfo *getCurrentFrameInfo(); - MCSymbol *EmitCFICommon(); - void EnsureValidFrame(); - - std::vector<MCWin64EHUnwindInfo *> W64UnwindInfos; - MCWin64EHUnwindInfo *CurrentW64UnwindInfo; - void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); - void EnsureValidW64UnwindInfo(); - - MCSymbol* LastSymbol; - - /// SectionStack - This is stack of current and previous section - /// values saved by PushSection. - SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; - - bool AutoInitSections; - - protected: - MCStreamer(StreamerKind Kind, MCContext &Ctx); - - const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, - const MCSymbol *B); - - const MCExpr *ForceExpAbs(const MCExpr* Expr); - - void RecordProcStart(MCDwarfFrameInfo &Frame); - virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); - void RecordProcEnd(MCDwarfFrameInfo &Frame); - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); - void EmitFrames(bool usingCFI); - - MCWin64EHUnwindInfo *getCurrentW64UnwindInfo(){return CurrentW64UnwindInfo;} - void EmitW64Tables(); - - public: - virtual ~MCStreamer(); - - StreamerKind getKind() const { return Kind; } - - /// State management - /// - virtual void reset(); - - MCContext &getContext() const { return Context; } - - unsigned getNumFrameInfos() { - return FrameInfos.size(); - } +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCExpr; +class MCInst; +class MCInstPrinter; +class MCSection; +class MCStreamer; +class MCSymbol; +class StringRef; +class Twine; +class raw_ostream; +class formatted_raw_ostream; + +typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; + +/// Target specific streamer interface. This is used so that targets can +/// implement support for target specific assembly directives. +/// +/// If target foo wants to use this, it should implement 3 classes: +/// * FooTargetStreamer : public MCTargetStreamer +/// * FooTargetAsmSreamer : public FooTargetStreamer +/// * FooTargetELFStreamer : public FooTargetStreamer +/// +/// FooTargetStreamer should have a pure virtual method for each directive. For +/// example, for a ".bar symbol_name" directive, it should have +/// virtual emitBar(const MCSymbol &Symbol) = 0; +/// +/// The FooTargetAsmSreamer and FooTargetELFStreamer classes implement the +/// method. The assembly streamer just prints ".bar symbol_name". The object +/// streamer does whatever is needed to implement .bar in the object file. +/// +/// In the assembly printer and parser the target streamer can be used by +/// calling getTargetStreamer and casting it to FooTargetStreamer: +/// +/// MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); +/// FooTargetStreamer &ATS = static_cast<FooTargetStreamer &>(TS); +/// +/// The base classes FooTargetAsmSreamer and FooTargetELFStreamer should *never* +/// be treated differently. Callers should always talk to a FooTargetStreamer. +class MCTargetStreamer { +protected: + MCStreamer *Streamer; + +public: + virtual ~MCTargetStreamer(); + void setStreamer(MCStreamer *S) { Streamer = S; } +}; + +// FIXME: declared here because it is used from +// lib/CodeGen/AsmPrinter/ARMException.cpp. +class ARMTargetStreamer : public MCTargetStreamer { + virtual void anchor(); +public: + virtual void emitFnStart() = 0; + virtual void emitFnEnd() = 0; + virtual void emitCantUnwind() = 0; + virtual void emitPersonality(const MCSymbol *Personality) = 0; + virtual void emitHandlerData() = 0; + virtual void emitSetFP(unsigned FpReg, unsigned SpReg, + int64_t Offset = 0) = 0; + virtual void emitPad(int64_t Offset) = 0; + virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, + bool isVector) = 0; + + virtual void switchVendor(StringRef Vendor) = 0; + virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0; + virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0; + virtual void emitFPU(unsigned FPU) = 0; + virtual void finishAttributeSection() = 0; +}; + +/// MCStreamer - Streaming machine code generation interface. This interface +/// is intended to provide a programatic interface that is very similar to the +/// level that an assembler .s file provides. It has callbacks to emit bytes, +/// handle directives, etc. The implementation of this interface retains +/// state to know what the current section is etc. +/// +/// There are multiple implementations of this interface: one for writing out +/// a .s file, and implementations that write out .o files of various formats. +/// +class MCStreamer { + MCContext &Context; + OwningPtr<MCTargetStreamer> TargetStreamer; + + MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; + MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; + + bool EmitEHFrame; + bool EmitDebugFrame; + + std::vector<MCDwarfFrameInfo> FrameInfos; + MCDwarfFrameInfo *getCurrentFrameInfo(); + MCSymbol *EmitCFICommon(); + void EnsureValidFrame(); + + std::vector<MCWin64EHUnwindInfo *> W64UnwindInfos; + MCWin64EHUnwindInfo *CurrentW64UnwindInfo; + void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); + void EnsureValidW64UnwindInfo(); + + MCSymbol *LastSymbol; + + // SymbolOrdering - Tracks an index to represent the order + // a symbol was emitted in. Zero means we did not emit that symbol. + DenseMap<const MCSymbol *, unsigned> SymbolOrdering; + + /// SectionStack - This is stack of current and previous section + /// values saved by PushSection. + SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; + + bool AutoInitSections; + +protected: + MCStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer); + + const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, + const MCSymbol *B); + + const MCExpr *ForceExpAbs(const MCExpr *Expr); + + void RecordProcStart(MCDwarfFrameInfo &Frame); + virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); + void RecordProcEnd(MCDwarfFrameInfo &Frame); + virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); + void EmitFrames(MCAsmBackend *MAB, bool usingCFI); + + MCWin64EHUnwindInfo *getCurrentW64UnwindInfo() { + return CurrentW64UnwindInfo; + } + void EmitW64Tables(); + + virtual void EmitRawTextImpl(StringRef String); + +public: + virtual ~MCStreamer(); + + /// State management + /// + virtual void reset(); - const MCDwarfFrameInfo &getFrameInfo(unsigned i) { - return FrameInfos[i]; - } + MCContext &getContext() const { return Context; } - ArrayRef<MCDwarfFrameInfo> getFrameInfos() { - return FrameInfos; - } + MCTargetStreamer &getTargetStreamer() { + assert(TargetStreamer); + return *TargetStreamer; + } - unsigned getNumW64UnwindInfos() { - return W64UnwindInfos.size(); - } + unsigned getNumFrameInfos() { return FrameInfos.size(); } - MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { - return *W64UnwindInfos[i]; - } + const MCDwarfFrameInfo &getFrameInfo(unsigned i) { return FrameInfos[i]; } - /// @name Assembly File Formatting. - /// @{ - - /// isVerboseAsm - Return true if this streamer supports verbose assembly - /// and if it is enabled. - virtual bool isVerboseAsm() const { return false; } - - /// hasRawTextSupport - Return true if this asm streamer supports emitting - /// unformatted text to the .s file with EmitRawText. - virtual bool hasRawTextSupport() const { return false; } - - /// AddComment - Add a comment that can be emitted to the generated .s - /// file if applicable as a QoI issue to make the output of the compiler - /// more readable. This only affects the MCAsmStreamer, and only when - /// verbose assembly output is enabled. - /// - /// If the comment includes embedded \n's, they will each get the comment - /// prefix as appropriate. The added comment should not end with a \n. - virtual void AddComment(const Twine &T) {} - - /// GetCommentOS - Return a raw_ostream that comments can be written to. - /// Unlike AddComment, you are required to terminate comments with \n if you - /// use this method. - virtual raw_ostream &GetCommentOS(); - - /// AddBlankLine - Emit a blank line to a .s file to pretty it up. - virtual void AddBlankLine() {} - - /// @} - - /// @name Symbol & Section Management - /// @{ - - /// getCurrentSection - Return the current section that the streamer is - /// emitting code to. - MCSectionSubPair getCurrentSection() const { - if (!SectionStack.empty()) - return SectionStack.back().first; - return MCSectionSubPair(); - } + ArrayRef<MCDwarfFrameInfo> getFrameInfos() const { return FrameInfos; } - /// getPreviousSection - Return the previous section that the streamer is - /// emitting code to. - MCSectionSubPair getPreviousSection() const { - if (!SectionStack.empty()) - return SectionStack.back().second; - return MCSectionSubPair(); - } + unsigned getNumW64UnwindInfos() { return W64UnwindInfos.size(); } - /// ChangeSection - Update streamer for a new active section. - /// - /// This is called by PopSection and SwitchSection, if the current - /// section changes. - virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; - - /// pushSection - Save the current and previous section on the - /// section stack. - void PushSection() { - SectionStack.push_back(std::make_pair(getCurrentSection(), - getPreviousSection())); - } + MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { + return *W64UnwindInfos[i]; + } - /// popSection - Restore the current and previous section from - /// the section stack. Calls ChangeSection as needed. - /// - /// Returns false if the stack was empty. - bool PopSection() { - if (SectionStack.size() <= 1) - return false; - MCSectionSubPair oldSection = SectionStack.pop_back_val().first; - MCSectionSubPair curSection = SectionStack.back().first; - - if (oldSection != curSection) - ChangeSection(curSection.first, curSection.second); - return true; - } + void generateCompactUnwindEncodings(MCAsmBackend *MAB); - bool SubSection(const MCExpr *Subsection) { - if (SectionStack.empty()) - return false; + /// @name Assembly File Formatting. + /// @{ - SwitchSection(SectionStack.back().first.first, Subsection); - return true; - } + /// isVerboseAsm - Return true if this streamer supports verbose assembly + /// and if it is enabled. + virtual bool isVerboseAsm() const { return false; } - /// SwitchSection - Set the current section where code is being emitted to - /// @p Section. This is required to update CurSection. - /// - /// This corresponds to assembler directives like .section, .text, etc. - void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) { - SectionStack.back().first = MCSectionSubPair(Section, Subsection); - ChangeSection(Section, Subsection); - } - } + /// hasRawTextSupport - Return true if this asm streamer supports emitting + /// unformatted text to the .s file with EmitRawText. + virtual bool hasRawTextSupport() const { return false; } - /// SwitchSectionNoChange - Set the current section where code is being - /// emitted to @p Section. This is required to update CurSection. This - /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section, - const MCExpr *Subsection = 0) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) - SectionStack.back().first = MCSectionSubPair(Section, Subsection); + /// AddComment - Add a comment that can be emitted to the generated .s + /// file if applicable as a QoI issue to make the output of the compiler + /// more readable. This only affects the MCAsmStreamer, and only when + /// verbose assembly output is enabled. + /// + /// If the comment includes embedded \n's, they will each get the comment + /// prefix as appropriate. The added comment should not end with a \n. + virtual void AddComment(const Twine &T) {} + + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS(); + + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. + virtual void AddBlankLine() {} + + /// @} + + /// @name Symbol & Section Management + /// @{ + + /// getCurrentSection - Return the current section that the streamer is + /// emitting code to. + MCSectionSubPair getCurrentSection() const { + if (!SectionStack.empty()) + return SectionStack.back().first; + return MCSectionSubPair(); + } + + /// getPreviousSection - Return the previous section that the streamer is + /// emitting code to. + MCSectionSubPair getPreviousSection() const { + if (!SectionStack.empty()) + return SectionStack.back().second; + return MCSectionSubPair(); + } + + /// GetSymbolOrder - Returns an index to represent the order + /// a symbol was emitted in. (zero if we did not emit that symbol) + unsigned GetSymbolOrder(const MCSymbol *Sym) const { + return SymbolOrdering.lookup(Sym); + } + + /// ChangeSection - Update streamer for a new active section. + /// + /// This is called by PopSection and SwitchSection, if the current + /// section changes. + virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; + + /// pushSection - Save the current and previous section on the + /// section stack. + void PushSection() { + SectionStack.push_back( + std::make_pair(getCurrentSection(), getPreviousSection())); + } + + /// popSection - Restore the current and previous section from + /// the section stack. Calls ChangeSection as needed. + /// + /// Returns false if the stack was empty. + bool PopSection() { + if (SectionStack.size() <= 1) + return false; + MCSectionSubPair oldSection = SectionStack.pop_back_val().first; + MCSectionSubPair curSection = SectionStack.back().first; + + if (oldSection != curSection) + ChangeSection(curSection.first, curSection.second); + return true; + } + + bool SubSection(const MCExpr *Subsection) { + if (SectionStack.empty()) + return false; + + SwitchSection(SectionStack.back().first.first, Subsection); + return true; + } + + /// SwitchSection - Set the current section where code is being emitted to + /// @p Section. This is required to update CurSection. + /// + /// This corresponds to assembler directives like .section, .text, etc. + void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) { + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + ChangeSection(Section, Subsection); } + } + + /// SwitchSectionNoChange - Set the current section where code is being + /// emitted to @p Section. This is required to update CurSection. This + /// version does not call ChangeSection. + void SwitchSectionNoChange(const MCSection *Section, + const MCExpr *Subsection = 0) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + } + + /// Initialize the streamer. + void InitStreamer() { + if (AutoInitSections) + InitSections(); + } + + /// Tell this MCStreamer to call InitSections upon initialization. + void setAutoInitSections(bool AutoInitSections) { + this->AutoInitSections = AutoInitSections; + } + + /// InitSections - Create the default sections and set the initial one. + virtual void InitSections() = 0; + + /// InitToTextSection - Create a text section and switch the streamer to it. + virtual void InitToTextSection() = 0; + + /// AssignSection - Sets the symbol's section. + /// + /// Each emitted symbol will be tracked in the ordering table, + /// so we can sort on them later. + void AssignSection(MCSymbol *Symbol, const MCSection *Section); - /// Initialize the streamer. - void InitStreamer() { - if (AutoInitSections) - InitSections(); - } + /// EmitLabel - Emit a label for @p Symbol into the current section. + /// + /// This corresponds to an assembler statement such as: + /// foo: + /// + /// @param Symbol - The symbol to emit. A given symbol should only be + /// emitted as a label once, and symbols emitted as a label should never be + /// used in an assignment. + virtual void EmitLabel(MCSymbol *Symbol); - /// Tell this MCStreamer to call InitSections upon initialization. - void setAutoInitSections(bool AutoInitSections) { - this->AutoInitSections = AutoInitSections; - } + virtual void EmitDebugLabel(MCSymbol *Symbol); - /// InitSections - Create the default sections and set the initial one. - virtual void InitSections() = 0; - - /// InitToTextSection - Create a text section and switch the streamer to it. - virtual void InitToTextSection() = 0; - - /// EmitLabel - Emit a label for @p Symbol into the current section. - /// - /// This corresponds to an assembler statement such as: - /// foo: - /// - /// @param Symbol - The symbol to emit. A given symbol should only be - /// emitted as a label once, and symbols emitted as a label should never be - /// used in an assignment. - virtual void EmitLabel(MCSymbol *Symbol); - - virtual void EmitDebugLabel(MCSymbol *Symbol); - - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol); - - /// EmitAssemblerFlag - Note in the output the specified @p Flag. - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; - - /// EmitLinkerOptions - Emit the given list @p Options of strings as linker - /// options into the output. - virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {} - - /// EmitDataRegion - Note in the output the specified region @p Kind. - virtual void EmitDataRegion(MCDataRegionType Kind) {} - - /// EmitThumbFunc - Note in the output that the specified @p Func is - /// a Thumb mode function (ARM target only). - virtual void EmitThumbFunc(MCSymbol *Func) = 0; - - /// getOrCreateSymbolData - Get symbol data for given symbol. - virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); - - /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. - /// - /// This corresponds to an assembler statement such as: - /// symbol = value - /// - /// The assignment generates no code, but has the side effect of binding the - /// value in the current context. For the assembly streamer, this prints the - /// binding into the .s file. - /// - /// @param Symbol - The symbol being assigned to. - /// @param Value - The value for the symbol. - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; - - /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. - /// - /// This corresponds to an assembler statement such as: - /// .weakref alias, symbol - /// - /// @param Alias - The alias that is being created. - /// @param Symbol - The symbol being aliased. - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; - - /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. - virtual void EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) = 0; - - /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. - /// - /// @param Symbol - The symbol to have its n_desc field set. - /// @param DescValue - The value to set into the n_desc field. - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; - - /// BeginCOFFSymbolDef - Start emitting COFF symbol definition - /// - /// @param Symbol - The symbol to have its External & Type fields set. - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; - - /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. - /// - /// @param StorageClass - The storage class the symbol should have. - virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; - - /// EmitCOFFSymbolType - Emit the type of the symbol. - /// - /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) - virtual void EmitCOFFSymbolType(int Type) = 0; - - /// EndCOFFSymbolDef - Marks the end of the symbol definition. - virtual void EndCOFFSymbolDef() = 0; - - /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. - /// - /// @param Symbol - Symbol the section relative realocation should point to. - virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - - /// EmitELFSize - Emit an ELF .size directive. - /// - /// This corresponds to an assembler statement such as: - /// .size symbol, expression - /// - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; - - /// EmitCommonSymbol - Emit a common symbol. - /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the symbol if - /// non-zero. This must be a power of 2. - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 0; - - /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. - /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the common symbol in bytes. - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 0; - - /// EmitZerofill - Emit the zerofill section and an optional symbol. - /// - /// @param Section - The zerofill section to create and or to put the symbol - /// @param Symbol - The zerofill symbol to emit, if non-NULL. - /// @param Size - The size of the zerofill symbol. - /// @param ByteAlignment - The alignment of the zerofill symbol if - /// non-zero. This must be a power of 2 on some targets. - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0,unsigned ByteAlignment = 0) = 0; - - /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. - /// - /// @param Section - The thread local common section. - /// @param Symbol - The thread local common symbol to emit. - /// @param Size - The size of the symbol. - /// @param ByteAlignment - The alignment of the thread local common symbol - /// if non-zero. This must be a power of 2 on some targets. - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) = 0; - - /// @} - /// @name Generating Data - /// @{ - - /// EmitBytes - Emit the bytes in \p Data into the output. - /// - /// This is used to implement assembler directives such as .byte, .ascii, - /// etc. - virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0) = 0; - - /// EmitValue - Emit the expression @p Value into the output as a native - /// integer of the given @p Size bytes. - /// - /// This is used to implement assembler directives such as .word, .quad, - /// etc. - /// - /// @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 EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) = 0; - - void EmitValue(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. - virtual void EmitIntValue(uint64_t Value, unsigned Size, - unsigned AddrSpace = 0); - - /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO - /// this is done by producing - /// foo = value - /// .long foo - void EmitAbsValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace = 0); - - virtual void EmitULEB128Value(const MCExpr *Value) = 0; - - virtual void EmitSLEB128Value(const MCExpr *Value) = 0; - - /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. - void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0, - unsigned AddrSpace = 0); - - /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. - void EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace = 0); - - /// EmitSymbolValue - Special case of EmitValue that avoids the client - /// having to pass in a MCExpr for MCSymbols. - void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - unsigned AddrSpace = 0); - - /// EmitGPRel64Value - Emit the expression @p Value into the output as a - /// gprel64 (64-bit GP relative) value. - /// - /// This is used to implement assembler directives such as .gpdword on - /// targets that support them. - virtual void EmitGPRel64Value(const MCExpr *Value); - - /// EmitGPRel32Value - Emit the expression @p Value into the output as a - /// gprel32 (32-bit GP relative) value. - /// - /// This is used to implement assembler directives such as .gprel32 on - /// targets that support them. - virtual void EmitGPRel32Value(const MCExpr *Value); - - /// EmitFill - Emit NumBytes bytes worth of the value specified by - /// FillValue. This implements directives such as '.space'. - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace = 0); - - /// EmitZeros - Emit NumBytes worth of zeros. This is a convenience - /// function that just wraps EmitFill. - void EmitZeros(uint64_t NumBytes, unsigned AddrSpace = 0) { - EmitFill(NumBytes, 0, AddrSpace); - } + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// EmitValueToAlignment - Emit some number of copies of @p Value until - /// the byte alignment @p ByteAlignment is reached. - /// - /// If the number of bytes need to emit for the alignment is not a multiple - /// of @p ValueSize, then the contents of the emitted fill bytes is - /// undefined. - /// - /// This used to implement the .align assembler directive. - /// - /// @param ByteAlignment - The alignment to reach. This must be a power of - /// two on some targets. - /// @param Value - The value to use when filling bytes. - /// @param ValueSize - The size of the integer (in bytes) to emit for - /// @p Value. This must match a native machine width. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If - /// the alignment cannot be reached in this many bytes, no bytes are - /// emitted. - virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0) = 0; - - /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment - /// is reached. - /// - /// This used to align code where the alignment bytes may be executed. This - /// can emit different bytes for different sizes to optimize execution. - /// - /// @param ByteAlignment - The alignment to reach. This must be a power of - /// two on some targets. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If - /// the alignment cannot be reached in this many bytes, no bytes are - /// emitted. - virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0) = 0; - - /// EmitValueToOffset - Emit some number of copies of @p Value until the - /// byte offset @p Offset is reached. - /// - /// This is used to implement assembler directives such as .org. - /// - /// @param Offset - The offset to reach. This may be an expression, but the - /// expression must be associated with the current section. - /// @param Value - The value to use when filling bytes. - /// @return false on success, true if the offset was invalid. - virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0) = 0; - - /// @} - - /// EmitFileDirective - Switch to a new logical file. This is used to - /// implement the '.file "foo.c"' assembler directive. - virtual void EmitFileDirective(StringRef Filename) = 0; - - /// EmitDwarfFileDirective - Associate a filename with a specified logical - /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler - /// directive. - virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, unsigned CUID = 0); - - /// EmitDwarfLocDirective - This implements the DWARF2 - // '.loc fileno lineno ...' assembler directive. - virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, - unsigned Discriminator, - StringRef FileName); - - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) = 0; - - virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label) { - } + /// EmitAssemblerFlag - Note in the output the specified @p Flag. + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; - void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, - int PointerSize); - - virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); - virtual void EmitCFISections(bool EH, bool Debug); - void EmitCFIStartProc(); - void EmitCFIEndProc(); - virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); - virtual void EmitCFIDefCfaOffset(int64_t Offset); - virtual void EmitCFIDefCfaRegister(int64_t Register); - virtual void EmitCFIOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFIRememberState(); - virtual void EmitCFIRestoreState(); - virtual void EmitCFISameValue(int64_t Register); - virtual void EmitCFIRestore(int64_t Register); - virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); - virtual void EmitCFIEscape(StringRef Values); - virtual void EmitCFISignalFrame(); - virtual void EmitCFIUndefined(int64_t Register); - virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); - - virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); - virtual void EmitWin64EHEndProc(); - virtual void EmitWin64EHStartChained(); - virtual void EmitWin64EHEndChained(); - virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except); - virtual void EmitWin64EHHandlerData(); - virtual void EmitWin64EHPushReg(unsigned Register); - virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); - virtual void EmitWin64EHAllocStack(unsigned Size); - virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); - virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); - virtual void EmitWin64EHPushFrame(bool Code); - virtual void EmitWin64EHEndProlog(); - - /// EmitInstruction - Emit the given @p Instruction into the current - /// section. - virtual void EmitInstruction(const MCInst &Inst) = 0; - - /// \brief Set the bundle alignment mode from now on in the section. - /// The argument is the power of 2 to which the alignment is set. The - /// value 0 means turn the bundle alignment off. - virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; - - /// \brief The following instructions are a bundle-locked group. - /// - /// \param AlignToEnd - If true, the bundle-locked group will be aligned to - /// the end of a bundle. - virtual void EmitBundleLock(bool AlignToEnd) = 0; - - /// \brief Ends a bundle-locked group. - virtual void EmitBundleUnlock() = 0; - - /// EmitRawText - If this file is backed by a assembly streamer, this dumps - /// the specified string in the output .s file. This capability is - /// indicated by the hasRawTextSupport() predicate. By default this aborts. - virtual void EmitRawText(StringRef String); - void EmitRawText(const Twine &String); - - /// ARM-related methods. - /// FIXME: Eventually we should have some "target MC streamer" and move - /// these methods there. - virtual void EmitFnStart(); - virtual void EmitFnEnd(); - virtual void EmitCantUnwind(); - virtual void EmitPersonality(const MCSymbol *Personality); - virtual void EmitHandlerData(); - virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); - virtual void EmitPad(int64_t Offset); - virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList, - bool isVector); - - /// PPC-related methods. - /// FIXME: Eventually replace it with some "target MC streamer" and move - /// these methods there. - virtual void EmitTCEntry(const MCSymbol &S); - - /// FinishImpl - Streamer specific finalization. - virtual void FinishImpl() = 0; - /// Finish - Finish emission of machine code. - void Finish(); - }; - - /// createNullStreamer - Create a dummy machine code streamer, which does - /// nothing. This is useful for timing the assembler front end. - MCStreamer *createNullStreamer(MCContext &Ctx); - - /// createAsmStreamer - Create a machine code streamer which will print out - /// assembly for the native target, suitable for compiling with a native - /// assembler. - /// - /// \param InstPrint - If given, the instruction printer to use. If not given - /// the MCInst representation will be printed. This method takes ownership of - /// InstPrint. - /// - /// \param CE - If given, a code emitter to use to show the instruction - /// encoding inline with the assembly. This method takes ownership of \p CE. - /// - /// \param TAB - If given, a target asm backend to use to show the fixup - /// information in conjunction with encoding information. This method takes - /// ownership of \p TAB. - /// - /// \param ShowInst - Whether to show the MCInst representation inline with - /// the assembly. - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, - bool useLoc, - bool useCFI, - bool useDwarfDirectory, - MCInstPrinter *InstPrint = 0, - MCCodeEmitter *CE = 0, - MCAsmBackend *TAB = 0, - bool ShowInst = false); - - /// createMachOStreamer - Create a machine code streamer which will generate - /// Mach-O format object files. - /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); + /// EmitLinkerOptions - Emit the given list @p Options of strings as linker + /// options into the output. + virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {} + + /// EmitDataRegion - Note in the output the specified region @p Kind. + virtual void EmitDataRegion(MCDataRegionType Kind) {} + + /// EmitThumbFunc - Note in the output that the specified @p Func is + /// a Thumb mode function (ARM target only). + virtual void EmitThumbFunc(MCSymbol *Func) = 0; - /// createWinCOFFStreamer - Create a machine code streamer which will - /// generate Microsoft COFF format object files. + /// getOrCreateSymbolData - Get symbol data for given symbol. + virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + + /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// symbol = value + /// + /// The assignment generates no code, but has the side effect of binding the + /// value in the current context. For the assembly streamer, this prints the + /// binding into the .s file. /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createWinCOFFStreamer(MCContext &Ctx, - MCAsmBackend &TAB, - MCCodeEmitter &CE, raw_ostream &OS, - bool RelaxAll = false); + /// @param Symbol - The symbol being assigned to. + /// @param Value - The value for the symbol. + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; - /// createELFStreamer - Create a machine code streamer which will generate - /// ELF format object files. - MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll, bool NoExecStack); + /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// .weakref alias, symbol + /// + /// @param Alias - The alias that is being created. + /// @param Symbol - The symbol being aliased. + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; + + /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) = 0; + + /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. + /// + /// @param Symbol - The symbol to have its n_desc field set. + /// @param DescValue - The value to set into the n_desc field. + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; + + /// BeginCOFFSymbolDef - Start emitting COFF symbol definition + /// + /// @param Symbol - The symbol to have its External & Type fields set. + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; + + /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. + /// + /// @param StorageClass - The storage class the symbol should have. + virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; - /// createPureStreamer - Create a machine code streamer which will generate - /// "pure" MC object files, for use with MC-JIT and testing tools. + /// EmitCOFFSymbolType - Emit the type of the symbol. /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE); + /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + virtual void EmitCOFFSymbolType(int Type) = 0; + + /// EndCOFFSymbolDef - Marks the end of the symbol definition. + virtual void EndCOFFSymbolDef() = 0; + + /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. + /// + /// @param Symbol - Symbol the section relative realocation should point to. + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); + + /// EmitELFSize - Emit an ELF .size directive. + /// + /// This corresponds to an assembler statement such as: + /// .size symbol, expression + /// + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; + + /// EmitCommonSymbol - Emit a common symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + /// @param ByteAlignment - The alignment of the symbol if + /// non-zero. This must be a power of 2. + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 0; + + /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + /// @param ByteAlignment - The alignment of the common symbol in bytes. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 0; + + /// EmitZerofill - Emit the zerofill section and an optional symbol. + /// + /// @param Section - The zerofill section to create and or to put the symbol + /// @param Symbol - The zerofill symbol to emit, if non-NULL. + /// @param Size - The size of the zerofill symbol. + /// @param ByteAlignment - The alignment of the zerofill symbol if + /// non-zero. This must be a power of 2 on some targets. + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + uint64_t Size = 0, unsigned ByteAlignment = 0) = 0; + + /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. + /// + /// @param Section - The thread local common section. + /// @param Symbol - The thread local common symbol to emit. + /// @param Size - The size of the symbol. + /// @param ByteAlignment - The alignment of the thread local common symbol + /// if non-zero. This must be a power of 2 on some targets. + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) = 0; + + /// @} + /// @name Generating Data + /// @{ + + /// EmitBytes - Emit the bytes in \p Data into the output. + /// + /// This is used to implement assembler directives such as .byte, .ascii, + /// etc. + virtual void EmitBytes(StringRef Data) = 0; + + /// EmitValue - Emit the expression @p Value into the output as a native + /// integer of the given @p Size bytes. + /// + /// This is used to implement assembler directives such as .word, .quad, + /// etc. + /// + /// @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 EmitValueImpl(const MCExpr *Value, unsigned Size) = 0; + + void EmitValue(const MCExpr *Value, unsigned Size); + + /// EmitIntValue - Special case of EmitValue that avoids the client having + /// to pass in a MCExpr for constant integers. + virtual void EmitIntValue(uint64_t Value, unsigned Size); + + /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO + /// this is done by producing + /// foo = value + /// .long foo + void EmitAbsValue(const MCExpr *Value, unsigned Size); + + virtual void EmitULEB128Value(const MCExpr *Value) = 0; + + virtual void EmitSLEB128Value(const MCExpr *Value) = 0; + + /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0); + + /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitSLEB128IntValue(int64_t Value); + + /// EmitSymbolValue - Special case of EmitValue that avoids the client + /// having to pass in a MCExpr for MCSymbols. + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size); + + /// EmitGPRel64Value - Emit the expression @p Value into the output as a + /// gprel64 (64-bit GP relative) value. + /// + /// This is used to implement assembler directives such as .gpdword on + /// targets that support them. + virtual void EmitGPRel64Value(const MCExpr *Value); + + /// EmitGPRel32Value - Emit the expression @p Value into the output as a + /// gprel32 (32-bit GP relative) value. + /// + /// This is used to implement assembler directives such as .gprel32 on + /// targets that support them. + virtual void EmitGPRel32Value(const MCExpr *Value); + + /// EmitFill - Emit NumBytes bytes worth of the value specified by + /// FillValue. This implements directives such as '.space'. + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); + + /// \brief Emit NumBytes worth of zeros. + /// This function properly handles data in virtual sections. + virtual void EmitZeros(uint64_t NumBytes); + + /// EmitValueToAlignment - Emit some number of copies of @p Value until + /// the byte alignment @p ByteAlignment is reached. + /// + /// If the number of bytes need to emit for the alignment is not a multiple + /// of @p ValueSize, then the contents of the emitted fill bytes is + /// undefined. + /// + /// This used to implement the .align assembler directive. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param Value - The value to use when filling bytes. + /// @param ValueSize - The size of the integer (in bytes) to emit for + /// @p Value. This must match a native machine width. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment + /// is reached. + /// + /// This used to align code where the alignment bytes may be executed. This + /// can emit different bytes for different sizes to optimize execution. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitValueToOffset - Emit some number of copies of @p Value until the + /// byte offset @p Offset is reached. + /// + /// This is used to implement assembler directives such as .org. + /// + /// @param Offset - The offset to reach. This may be an expression, but the + /// expression must be associated with the current section. + /// @param Value - The value to use when filling bytes. + /// @return false on success, true if the offset was invalid. + virtual bool EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) = 0; + + /// @} + + /// EmitFileDirective - Switch to a new logical file. This is used to + /// implement the '.file "foo.c"' assembler directive. + virtual void EmitFileDirective(StringRef Filename) = 0; + + /// Emit the "identifiers" directive. This implements the + /// '.ident "version foo"' assembler directive. + virtual void EmitIdent(StringRef IdentString) {} + + /// EmitDwarfFileDirective - Associate a filename with a specified logical + /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler + /// directive. + virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, + StringRef Filename, unsigned CUID = 0); + + /// EmitDwarfLocDirective - This implements the DWARF2 + // '.loc fileno lineno ...' assembler directive. + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName); + + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize) = 0; + + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) {} + + void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, + int PointerSize); + + virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); + virtual void EmitCFISections(bool EH, bool Debug); + void EmitCFIStartProc(); + void EmitCFIEndProc(); + virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual void EmitCFIDefCfaOffset(int64_t Offset); + virtual void EmitCFIDefCfaRegister(int64_t Register); + virtual void EmitCFIOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIRememberState(); + virtual void EmitCFIRestoreState(); + virtual void EmitCFISameValue(int64_t Register); + virtual void EmitCFIRestore(int64_t Register); + virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); + virtual void EmitCFIEscape(StringRef Values); + virtual void EmitCFISignalFrame(); + virtual void EmitCFIUndefined(int64_t Register); + virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); + virtual void EmitCFIWindowSave(); + + virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); + virtual void EmitWin64EHEndProc(); + virtual void EmitWin64EHStartChained(); + virtual void EmitWin64EHEndChained(); + virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, + bool Except); + virtual void EmitWin64EHHandlerData(); + virtual void EmitWin64EHPushReg(unsigned Register); + virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); + virtual void EmitWin64EHAllocStack(unsigned Size); + virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); + virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); + virtual void EmitWin64EHPushFrame(bool Code); + virtual void EmitWin64EHEndProlog(); + + /// EmitInstruction - Emit the given @p Instruction into the current + /// section. + virtual void EmitInstruction(const MCInst &Inst) = 0; + + /// \brief Set the bundle alignment mode from now on in the section. + /// The argument is the power of 2 to which the alignment is set. The + /// value 0 means turn the bundle alignment off. + virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; + + /// \brief The following instructions are a bundle-locked group. + /// + /// \param AlignToEnd - If true, the bundle-locked group will be aligned to + /// the end of a bundle. + virtual void EmitBundleLock(bool AlignToEnd) = 0; + + /// \brief Ends a bundle-locked group. + virtual void EmitBundleUnlock() = 0; + + /// EmitRawText - If this file is backed by a assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. By default this aborts. + void EmitRawText(const Twine &String); + + /// Flush - Causes any cached state to be written out. + virtual void Flush() {} + + /// FinishImpl - Streamer specific finalization. + virtual void FinishImpl() = 0; + /// Finish - Finish emission of machine code. + void Finish(); +}; + +/// createNullStreamer - Create a dummy machine code streamer, which does +/// nothing. This is useful for timing the assembler front end. +MCStreamer *createNullStreamer(MCContext &Ctx); + +/// createAsmStreamer - Create a machine code streamer which will print out +/// assembly for the native target, suitable for compiling with a native +/// assembler. +/// +/// \param InstPrint - If given, the instruction printer to use. If not given +/// the MCInst representation will be printed. This method takes ownership of +/// InstPrint. +/// +/// \param CE - If given, a code emitter to use to show the instruction +/// encoding inline with the assembly. This method takes ownership of \p CE. +/// +/// \param TAB - If given, a target asm backend to use to show the fixup +/// information in conjunction with encoding information. This method takes +/// ownership of \p TAB. +/// +/// \param ShowInst - Whether to show the MCInst representation inline with +/// the assembly. +MCStreamer *createAsmStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, + formatted_raw_ostream &OS, bool isVerboseAsm, + bool useLoc, bool useCFI, bool useDwarfDirectory, + MCInstPrinter *InstPrint = 0, + MCCodeEmitter *CE = 0, MCAsmBackend *TAB = 0, + bool ShowInst = false); + +/// createMachOStreamer - Create a machine code streamer which will generate +/// Mach-O format object files. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll = false); + +/// createWinCOFFStreamer - Create a machine code streamer which will +/// generate Microsoft COFF format object files. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createWinCOFFStreamer(MCContext &Ctx, MCAsmBackend &TAB, + MCCodeEmitter &CE, raw_ostream &OS, + bool RelaxAll = false); + +/// createELFStreamer - Create a machine code streamer which will generate +/// ELF format object files. +MCStreamer *createELFStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *CE, bool RelaxAll, + bool NoExecStack); + +/// createPureStreamer - Create a machine code streamer which will generate +/// "pure" MC object files, for use with MC-JIT and testing tools. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE); } // end namespace llvm diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 346fb2df0ffc0..01e8236482f7a 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -72,6 +72,9 @@ public: /// feature string). Recompute feature bits and scheduling model. void InitMCProcessorInfo(StringRef CPU, StringRef FS); + /// InitCPUSchedModel - Recompute scheduling model based on CPU. + void InitCPUSchedModel(StringRef CPU); + /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. uint64_t ToggleFeature(uint64_t FB); diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h new file mode 100644 index 0000000000000..e42a2146dc539 --- /dev/null +++ b/include/llvm/MC/MCSymbolizer.h @@ -0,0 +1,81 @@ +//===-- llvm/MC/MCSymbolizer.h - MCSymbolizer class -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCSymbolizer class, which is used +// to symbolize instructions decoded from an object, that is, transform their +// immediate operands to MCExprs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSYMBOLIZER_H +#define LLVM_MC_MCSYMBOLIZER_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCRelocationInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MCContext; +class MCInst; +class raw_ostream; + +/// \brief Symbolize and annotate disassembled instructions. +/// +/// For now this mimics the old symbolization logic (from both ARM and x86), that +/// relied on user-provided (C API) callbacks to do the actual symbol lookup in +/// the object file. This was moved to MCExternalSymbolizer. +/// A better API would not rely on actually calling the two methods here from +/// inside each disassembler, but would use the instr info to determine what +/// operands are actually symbolizable, and in what way. I don't think this +/// information exists right now. +class MCSymbolizer { + MCSymbolizer(const MCSymbolizer &) LLVM_DELETED_FUNCTION; + void operator=(const MCSymbolizer &) LLVM_DELETED_FUNCTION; + +protected: + MCContext &Ctx; + OwningPtr<MCRelocationInfo> RelInfo; + +public: + /// \brief Construct an MCSymbolizer, taking ownership of \p RelInfo. + MCSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo); + virtual ~MCSymbolizer(); + + /// \brief Try to add a symbolic operand instead of \p Value to the MCInst. + /// + /// Instead of having a difficult to read immediate, a symbolic operand would + /// represent this immediate in a more understandable way, for instance as a + /// symbol or an offset from a symbol. Relocations can also be used to enrich + /// the symbolic expression. + /// @param Inst - The MCInst where to insert the symbolic operand. + /// @param cStream - Stream to print comments and annotations on. + /// @param Value - Operand value, pc-adjusted by the caller if necessary. + /// @param Address - Load address of the instruction. + /// @param IsBranch - Is the instruction a branch? + /// @param Offset - Byte offset of the operand inside the inst. + /// @param InstSize - Size of the instruction in bytes. + /// @return Whether a symbolic operand was added. + virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, + int64_t Value, uint64_t Address, + bool IsBranch, uint64_t Offset, + uint64_t InstSize) = 0; + + /// \brief Try to add a comment on the PC-relative load. + /// For instance, in Mach-O, this is used to add annotations to instructions + /// that use C string literals, as found in __cstring. + virtual void tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, + uint64_t Address) = 0; +}; + +} + +#endif diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 6e878df3cb1e0..d132a732c4163 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -11,6 +11,7 @@ #define LLVM_MC_TARGETPARSER_H #include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCExpr.h" namespace llvm { class MCStreamer; @@ -143,7 +144,7 @@ public: /// mnemonicIsValid - This returns true if this is a valid mnemonic and false /// otherwise. - virtual bool mnemonicIsValid(StringRef Mnemonic) = 0; + virtual bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) = 0; /// MatchAndEmitInstruction - Recognize a series of operands of a parsed /// instruction as an actual MCInst and emit it to the specified MCStreamer. @@ -174,6 +175,14 @@ public: virtual void convertToMapAndConstraints(unsigned Kind, const SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0; + + virtual const MCExpr *applyModifierToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind, + MCContext &Ctx) { + return 0; + } + + virtual void onLabelParsed(MCSymbol *Symbol) { }; }; } // End llvm namespace diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index f13e7d5480267..213481c9090cf 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -17,6 +17,7 @@ namespace llvm { class raw_ostream; class MCWinCOFFObjectTargetWriter { + virtual void anchor(); const unsigned Machine; protected: diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h index 83c8b72ee4a33..b3fbee77021d7 100644 --- a/include/llvm/MC/MachineLocation.h +++ b/include/llvm/MC/MachineLocation.h @@ -10,17 +10,15 @@ // frame. Locations will be one of two forms; a register or an address formed // from a base address plus an offset. Register indirection can be specified by // explicitly passing an offset to the constructor. -// -// The MachineMove class is used to represent abstract move operations in the -// prolog/epilog of a compiled function. A collection of these objects can be -// used by a debug consumer to track the location of values when unwinding stack -// frames. //===----------------------------------------------------------------------===// #ifndef LLVM_MC_MACHINELOCATION_H #define LLVM_MC_MACHINELOCATION_H +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + namespace llvm { class MCSymbol; @@ -30,7 +28,7 @@ private: unsigned Register; // gcc/gdb register number. int Offset; // Displacement if not register. public: - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // The target register number for an abstract frame pointer. The value is // an arbitrary value that doesn't collide with any real target register. VirtualFP = ~0U @@ -49,7 +47,8 @@ public: Offset == Other.Offset; } - // Accessors + // Accessors. + /// \return true iff this is a register-indirect location. bool isIndirect() const { return !IsRegister; } bool isReg() const { return IsRegister; } unsigned getReg() const { return Register; } @@ -74,30 +73,6 @@ public: void dump(); #endif }; - -/// MachineMove - This class represents the save or restore of a callee saved -/// register that exception or debug info needs to know about. -class MachineMove { -private: - /// Label - Symbol for post-instruction address when result of move takes - /// effect. - MCSymbol *Label; - - // Move to & from location. - MachineLocation Destination, Source; -public: - MachineMove() : Label(0) {} - - MachineMove(MCSymbol *label, const MachineLocation &D, - const MachineLocation &S) - : Label(label), Destination(D), Source(S) {} - - // Accessors - MCSymbol *getLabel() const { return Label; } - const MachineLocation &getDestination() const { return Destination; } - const MachineLocation &getSource() const { return Source; } -}; - } // End llvm namespace #endif diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 8862c8b762960..d0735ccd9fa31 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -37,9 +37,9 @@ struct SubtargetFeatureKV { uint64_t Value; // K-V integer value uint64_t Implies; // K-V bit mask - // Compare routine for std binary search - bool operator<(const SubtargetFeatureKV &S) const { - return strcmp(Key, S.Key) < 0; + // Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; } }; @@ -52,9 +52,9 @@ struct SubtargetInfoKV { const char *Key; // K-V key string const void *Value; // K-V pointer value - // Compare routine for std binary search - bool operator<(const SubtargetInfoKV &S) const { - return strcmp(Key, S.Key) < 0; + // Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; } }; @@ -99,8 +99,7 @@ public: // Dump feature info. void dump() const; - /// Retrieve a formatted string of the default features for the specified - /// target triple. + /// Adds the default features for the specified target triple. void getDefaultSubtargetFeatures(const Triple& Triple); }; |