#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
+#include <algorithm>
#include <vector> // FIXME: Shouldn't be needed.
namespace llvm {
class MCObjectWriter;
class MCSection;
class MCSectionData;
+class MCSubtargetInfo;
class MCSymbol;
class MCSymbolData;
class MCValue;
enum FragmentType {
FT_Align,
FT_Data,
+ FT_Compressed,
+ FT_CompactEncodedInst,
FT_Fill,
FT_Relaxable,
FT_Org,
MCSectionData *Parent;
/// Atom - The atom this fragment is in, as represented by it's defining
- /// symbol. Atom's are only used by backends which set
- /// \see MCAsmBackend::hasReliableSymbolDifference().
+ /// symbol.
MCSymbolData *Atom;
/// @name Assembler Backend Data
/// \brief Should this fragment be placed at the end of an aligned bundle?
virtual bool alignToBundleEnd() const { return false; }
+ virtual void setAlignToBundleEnd(bool V) { }
/// \brief Get the padding size that must be inserted before this fragment.
/// Used for bundling. By default, no padding is inserted.
void dump();
};
+/// Interface implemented by fragments that contain encoded instructions and/or
+/// data.
+///
class MCEncodedFragment : public MCFragment {
virtual void anchor();
}
virtual ~MCEncodedFragment();
- typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator;
- typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator;
-
virtual SmallVectorImpl<char> &getContents() = 0;
virtual const SmallVectorImpl<char> &getContents() const = 0;
+ uint8_t getBundlePadding() const override {
+ return BundlePadding;
+ }
+
+ void setBundlePadding(uint8_t N) override {
+ BundlePadding = N;
+ }
+
+ static bool classof(const MCFragment *F) {
+ MCFragment::FragmentType Kind = F->getKind();
+ switch (Kind) {
+ default:
+ return false;
+ case MCFragment::FT_Relaxable:
+ case MCFragment::FT_CompactEncodedInst:
+ case MCFragment::FT_Compressed:
+ case MCFragment::FT_Data:
+ return true;
+ }
+ }
+};
+
+/// Interface implemented by fragments that contain encoded instructions and/or
+/// data and also have fixups registered.
+///
+class MCEncodedFragmentWithFixups : public MCEncodedFragment {
+ void anchor() override;
+
+public:
+ MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
+ MCSectionData *SD = 0)
+ : MCEncodedFragment(FType, SD)
+ {
+ }
+
+ virtual ~MCEncodedFragmentWithFixups();
+
+ typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator;
+ typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator;
+
virtual SmallVectorImpl<MCFixup> &getFixups() = 0;
virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0;
virtual fixup_iterator fixup_end() = 0;
virtual const_fixup_iterator fixup_end() const = 0;
- virtual uint8_t getBundlePadding() const {
- return BundlePadding;
- }
-
- virtual void setBundlePadding(uint8_t N) {
- BundlePadding = N;
- }
-
static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind();
- return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data;
+ return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
+ Kind == MCFragment::FT_Compressed;
}
};
/// Fragment for data and encoded instructions.
///
-class MCDataFragment : public MCEncodedFragment {
- virtual void anchor();
+class MCDataFragment : public MCEncodedFragmentWithFixups {
+ void anchor() override;
/// \brief Does this fragment contain encoded instructions anywhere in it?
bool HasInstructions;
/// Fixups - The list of fixups in this fragment.
SmallVector<MCFixup, 4> Fixups;
+protected:
+ MCDataFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0)
+ : MCEncodedFragmentWithFixups(FType, SD), HasInstructions(false),
+ AlignToBundleEnd(false) {}
+
public:
MCDataFragment(MCSectionData *SD = 0)
- : MCEncodedFragment(FT_Data, SD),
+ : MCEncodedFragmentWithFixups(FT_Data, SD),
HasInstructions(false), AlignToBundleEnd(false)
{
}
- virtual SmallVectorImpl<char> &getContents() { return Contents; }
- virtual const SmallVectorImpl<char> &getContents() const { return Contents; }
+ SmallVectorImpl<char> &getContents() override { return Contents; }
+ const SmallVectorImpl<char> &getContents() const override {
+ return Contents;
+ }
- SmallVectorImpl<MCFixup> &getFixups() {
+ SmallVectorImpl<MCFixup> &getFixups() override {
return Fixups;
}
- const SmallVectorImpl<MCFixup> &getFixups() const {
+ const SmallVectorImpl<MCFixup> &getFixups() const override {
return Fixups;
}
- virtual bool hasInstructions() const { return HasInstructions; }
+ bool hasInstructions() const override { return HasInstructions; }
virtual void setHasInstructions(bool V) { HasInstructions = V; }
- virtual bool alignToBundleEnd() const { return AlignToBundleEnd; }
- virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
+ bool alignToBundleEnd() const override { return AlignToBundleEnd; }
+ void setAlignToBundleEnd(bool V) override { AlignToBundleEnd = V; }
+
+ fixup_iterator fixup_begin() override { return Fixups.begin(); }
+ const_fixup_iterator fixup_begin() const override { return Fixups.begin(); }
+
+ fixup_iterator fixup_end() override {return Fixups.end();}
+ const_fixup_iterator fixup_end() const override {return Fixups.end();}
+
+ static bool classof(const MCFragment *F) {
+ return F->getKind() == MCFragment::FT_Data ||
+ F->getKind() == MCFragment::FT_Compressed;
+ }
+};
+
+class MCCompressedFragment: public MCDataFragment {
+ mutable SmallVector<char, 32> CompressedContents;
+public:
+ MCCompressedFragment(MCSectionData *SD = nullptr)
+ : MCDataFragment(FT_Compressed, SD) {}
+ const SmallVectorImpl<char> &getCompressedContents() const;
+ using MCDataFragment::getContents;
+ SmallVectorImpl<char> &getContents() override;
+};
- fixup_iterator fixup_begin() { return Fixups.begin(); }
- const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
+/// This is a compact (memory-size-wise) fragment for holding an encoded
+/// instruction (non-relaxable) that has no fixups registered. When applicable,
+/// it can be used instead of MCDataFragment and lead to lower memory
+/// consumption.
+///
+class MCCompactEncodedInstFragment : public MCEncodedFragment {
+ void anchor() override;
- fixup_iterator fixup_end() {return Fixups.end();}
- const_fixup_iterator fixup_end() const {return Fixups.end();}
+ /// \brief Should this fragment be aligned to the end of a bundle?
+ bool AlignToBundleEnd;
+
+ SmallVector<char, 4> Contents;
+public:
+ MCCompactEncodedInstFragment(MCSectionData *SD = 0)
+ : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false)
+ {
+ }
+
+ bool hasInstructions() const override {
+ return true;
+ }
+
+ SmallVectorImpl<char> &getContents() override { return Contents; }
+ const SmallVectorImpl<char> &getContents() const override { return Contents; }
+
+ bool alignToBundleEnd() const override { return AlignToBundleEnd; }
+ void setAlignToBundleEnd(bool V) override { AlignToBundleEnd = V; }
static bool classof(const MCFragment *F) {
- return F->getKind() == MCFragment::FT_Data;
+ return F->getKind() == MCFragment::FT_CompactEncodedInst;
}
};
/// A relaxable fragment holds on to its MCInst, since it may need to be
/// relaxed during the assembler layout and relaxation stage.
///
-class MCRelaxableFragment : public MCEncodedFragment {
- virtual void anchor();
+class MCRelaxableFragment : public MCEncodedFragmentWithFixups {
+ void anchor() override;
/// Inst - The instruction this is a fragment for.
MCInst Inst;
+ /// STI - The MCSubtargetInfo in effect when the instruction was encoded.
+ /// Keep a copy instead of a reference to make sure that updates to STI
+ /// in the assembler are not seen here.
+ const MCSubtargetInfo STI;
+
/// Contents - Binary data for the currently encoded instruction.
SmallVector<char, 8> Contents;
SmallVector<MCFixup, 1> Fixups;
public:
- MCRelaxableFragment(const MCInst &_Inst, MCSectionData *SD = 0)
- : MCEncodedFragment(FT_Relaxable, SD), Inst(_Inst) {
+ MCRelaxableFragment(const MCInst &_Inst,
+ const MCSubtargetInfo &_STI,
+ MCSectionData *SD = 0)
+ : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst), STI(_STI) {
}
- virtual SmallVectorImpl<char> &getContents() { return Contents; }
- virtual const SmallVectorImpl<char> &getContents() const { return Contents; }
+ SmallVectorImpl<char> &getContents() override { return Contents; }
+ const SmallVectorImpl<char> &getContents() const override { return Contents; }
const MCInst &getInst() const { return Inst; }
void setInst(const MCInst& Value) { Inst = Value; }
- SmallVectorImpl<MCFixup> &getFixups() {
+ const MCSubtargetInfo &getSubtargetInfo() { return STI; }
+
+ SmallVectorImpl<MCFixup> &getFixups() override {
return Fixups;
}
- const SmallVectorImpl<MCFixup> &getFixups() const {
+ const SmallVectorImpl<MCFixup> &getFixups() const override {
return Fixups;
}
- virtual bool hasInstructions() const { return true; }
+ bool hasInstructions() const override { return true; }
- fixup_iterator fixup_begin() { return Fixups.begin(); }
- const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
+ fixup_iterator fixup_begin() override { return Fixups.begin(); }
+ const_fixup_iterator fixup_begin() const override { return Fixups.begin(); }
- fixup_iterator fixup_end() {return Fixups.end();}
- const_fixup_iterator fixup_end() const {return Fixups.end();}
+ fixup_iterator fixup_end() override {return Fixups.end();}
+ const_fixup_iterator fixup_end() const override {return Fixups.end();}
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Relaxable;
SmallString<8> Contents;
public:
- MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD)
+ MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD = 0)
: MCFragment(FT_LEB, SD),
Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); }
public:
MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta,
- MCSectionData *SD)
+ MCSectionData *SD = 0)
: MCFragment(FT_Dwarf, SD),
LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); }
SmallString<8> Contents;
public:
- MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD)
+ MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD = 0)
: MCFragment(FT_DwarfFrame, SD),
AddrDelta(&_AddrDelta) { Contents.push_back(0); }
/// it.
unsigned HasInstructions : 1;
+ /// Mapping from subsection number to insertion point for subsection numbers
+ /// below that number.
+ SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
+
/// @}
public:
bool empty() const { return Fragments.empty(); }
+ iterator getSubsectionInsertionPoint(unsigned Subsection);
+
bool isBundleLocked() const {
return BundleLockState != NotBundleLocked;
}
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;
const_data_region_iterator;
typedef std::vector<DataRegionData>::iterator data_region_iterator;
+ /// MachO specific deployment target version info.
+ // A Major version of 0 indicates that no version information was supplied
+ // and so the corresponding load command should not be emitted.
+ typedef struct {
+ MCVersionMinType Kind;
+ unsigned Major;
+ unsigned Minor;
+ unsigned Update;
+ } VersionMinInfoType;
private:
MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION;
void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION;
std::vector<IndirectSymbolData> IndirectSymbols;
std::vector<DataRegionData> DataRegions;
+
+ /// 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.
//
unsigned NoExecStack : 1;
unsigned SubsectionsViaSymbols : 1;
+ /// ELF specific e_header flags
+ // It would be good if there were an MCELFAssembler class to hold this.
+ // ELF header flags are used both by the integrated and standalone assemblers.
+ // Access to the flags is necessary in cases where assembler directives affect
+ // which flags to be set.
+ unsigned ELFHeaderEFlags;
+
+ VersionMinInfoType VersionMinInfo;
private:
/// Evaluate a fixup to a relocatable expression and the value which should be
/// placed into the fixup.
/// finishLayout - Finalize a layout, including fragment lowering.
void finishLayout(MCAsmLayout &Layout);
- uint64_t handleFixup(const MCAsmLayout &Layout,
- MCFragment &F, const MCFixup &Fixup);
+ std::pair<uint64_t, bool> handleFixup(const MCAsmLayout &Layout,
+ MCFragment &F, const MCFixup &Fixup);
public:
/// Compute the effective fragment size assuming it is laid out at the given
/// Flag a function symbol as the target of a .thumb_func directive.
void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); }
+ /// ELF e_header flags
+ unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;}
+ void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;}
+
+ /// MachO deployment target version information.
+ const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; }
+ void setVersionMinInfo(MCVersionMinType Kind, unsigned Major, unsigned Minor,
+ unsigned Update) {
+ VersionMinInfo.Kind = Kind;
+ VersionMinInfo.Major = Major;
+ VersionMinInfo.Minor = Minor;
+ VersionMinInfo.Update = Update;
+ }
+
public:
/// Construct a new assembler instance.
///
size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
+ /// @}
+ /// @name Linker Option List Access
+ /// @{
+
+ std::vector<std::vector<std::string> > &getLinkerOptions() {
+ return LinkerOptions;
+ }
+
/// @}
/// @name Data Region List Access
/// @{
return *Entry;
}
+ bool hasSymbolData(const MCSymbol &Symbol) const {
+ return SymbolMap.lookup(&Symbol) != 0;
+ }
+
MCSymbolData &getSymbolData(const MCSymbol &Symbol) const {
MCSymbolData *Entry = SymbolMap.lookup(&Symbol);
assert(Entry && "Missing symbol data!");
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();