namespace llvm {
class raw_ostream;
+class MCAsmLayout;
class MCAssembler;
class MCContext;
+class MCCodeEmitter;
class MCExpr;
class MCFragment;
+class MCObjectWriter;
class MCSection;
class MCSectionData;
class MCSymbol;
+class MCValue;
class TargetAsmBackend;
/// MCAsmFixup - Represent a fixed size region of bytes inside some fragment
/// which needs to be rewritten. This region will either be rewritten by the
/// assembler or cause a relocation entry to be generated.
-struct MCAsmFixup {
+class MCAsmFixup {
/// Offset - The offset inside the fragment which needs to be rewritten.
uint64_t Offset;
/// Kind - The fixup kind.
MCFixupKind Kind;
- /// FixedValue - The value to replace the fix up by.
- //
- // FIXME: This should not be here.
- uint64_t FixedValue;
-
public:
MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, MCFixupKind _Kind)
- : Offset(_Offset), Value(&_Value), Kind(_Kind), FixedValue(0) {}
+ : Offset(_Offset), Value(&_Value), Kind(_Kind) {}
};
class MCFragment : public ilist_node<MCFragment> {
/// @name Fixup Access
/// @{
+ void addFixup(MCAsmFixup Fixup) {
+ // Enforce invariant that fixups are in offset order.
+ assert((Fixups.empty() || Fixup.Offset > Fixups.back().Offset) &&
+ "Fixups must be added in order!");
+ Fixups.push_back(Fixup);
+ }
+
std::vector<MCAsmFixup> &getFixups() { return Fixups; }
const std::vector<MCAsmFixup> &getFixups() const { return Fixups; }
/// cannot be satisfied in this width then this fragment is ignored.
unsigned MaxBytesToEmit;
- /// EmitNops - true when aligning code and optimal nops to be used for filling
+ /// EmitNops - true when aligning code and optimal nops to be used for
+ /// filling.
bool EmitNops;
public:
uint64_t getOffset() const { return Offset; }
void setOffset(uint64_t Value) { Offset = Value; }
+ uint64_t getAddress() const {
+ assert(getFragment() && "Invalid getAddress() on undefined symbol!");
+ return getFragment()->getAddress() + getOffset();
+ }
+
/// @}
/// @name Symbol Attributes
/// @{
typedef SymbolDataListType::const_iterator const_symbol_iterator;
typedef SymbolDataListType::iterator symbol_iterator;
+ typedef std::vector<IndirectSymbolData>::const_iterator
+ const_indirect_symbol_iterator;
typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
private:
TargetAsmBackend &Backend;
+ MCCodeEmitter &Emitter;
+
raw_ostream &OS;
iplist<MCSectionData> Sections;
unsigned SubsectionsViaSymbols : 1;
private:
+ /// Evaluate a fixup to a relocatable expression and the value which should be
+ /// placed into the fixup.
+ ///
+ /// \param Layout The layout to use for evaluation.
+ /// \param Fixup The fixup to evaluate.
+ /// \param DF The fragment the fixup is inside.
+ /// \param Target [out] On return, the relocatable expression the fixup
+ /// evaluates to.
+ /// \param Value [out] On return, the value of the fixup as currently layed
+ /// out.
+ /// \return Whether the fixup value was fully resolved. This is true if the
+ /// \arg Value result is fixed, otherwise the value may change due to
+ /// relocation.
+ bool EvaluateFixup(const MCAsmLayout &Layout,
+ MCAsmFixup &Fixup, MCDataFragment *DF,
+ MCValue &Target, uint64_t &Value) const;
+
+ /// Check whether a fixup can be satisfied, or whether it needs to be relaxed
+ /// (increased in size, in order to hold its value correctly).
+ bool FixupNeedsRelaxation(MCAsmFixup &Fixup, MCDataFragment *DF);
+
/// LayoutSection - Assign offsets and sizes to the fragments in the section
/// \arg SD, and update the section size. The section file offset should
/// already have been computed.
void LayoutSection(MCSectionData &SD);
+ /// LayoutOnce - Perform one layout iteration and return true if any offsets
+ /// were adjusted.
+ bool LayoutOnce();
+
+public:
+ /// Find the symbol which defines the atom containing given address, inside
+ /// the given section, or null if there is no such symbol.
+ //
+ // FIXME: Eliminate this, it is very slow.
+ const MCSymbolData *getAtomForAddress(const MCSectionData *Section,
+ uint64_t Address) const;
+
+ /// Find the symbol which defines the atom containing the given symbol, or
+ /// null if there is no such symbol.
+ //
+ // FIXME: Eliminate this, it is very slow.
+ const MCSymbolData *getAtom(const MCSymbolData *Symbol) const;
+
+ /// Check whether a particular symbol is visible to the linker and is required
+ /// in the symbol table, or whether it can be discarded by the assembler. This
+ /// also effects whether the assembler treats the label as potentially
+ /// defining a separate atom.
+ bool isSymbolLinkerVisible(const MCSymbolData *SD) const;
+
+ /// Emit the section contents using the given object writer.
+ //
+ // FIXME: Should MCAssembler always have a reference to the object writer?
+ void WriteSectionData(const MCSectionData *Section, MCObjectWriter *OW) const;
+
public:
/// Construct a new assembler instance.
///
// concrete and require clients to pass in a target like object. The other
// option is to make this abstract, and have targets provide concrete
// implementations as we do with AsmParser.
- MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, raw_ostream &OS);
+ MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
+ MCCodeEmitter &_Emitter, raw_ostream &OS);
~MCAssembler();
MCContext &getContext() const { return Context; }
+ TargetAsmBackend &getBackend() const { return Backend; }
+
+ MCCodeEmitter &getEmitter() const { return Emitter; }
+
/// Finish - Do final processing and write the object to the output stream.
void Finish();
indirect_symbol_iterator indirect_symbol_begin() {
return IndirectSymbols.begin();
}
+ const_indirect_symbol_iterator indirect_symbol_begin() const {
+ return IndirectSymbols.begin();
+ }
indirect_symbol_iterator indirect_symbol_end() {
return IndirectSymbols.end();
}
+ const_indirect_symbol_iterator indirect_symbol_end() const {
+ return IndirectSymbols.end();
+ }
size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
/// @name Backend Data Access
/// @{
- MCSectionData &getSectionData(const MCSection &Section) {
- MCSectionData *&Entry = SectionMap[&Section];
+ MCSectionData &getSectionData(const MCSection &Section) const {
+ MCSectionData *Entry = SectionMap.lookup(&Section);
assert(Entry && "Missing section data!");
return *Entry;
}
return *Entry;
}
- MCSymbolData &getSymbolData(const MCSymbol &Symbol) {
- MCSymbolData *&Entry = SymbolMap[&Symbol];
+ MCSymbolData &getSymbolData(const MCSymbol &Symbol) const {
+ MCSymbolData *Entry = SymbolMap.lookup(&Symbol);
assert(Entry && "Missing symbol data!");
return *Entry;
}