summaryrefslogtreecommitdiff
path: root/include/llvm/MC/MCAssembler.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/MC/MCAssembler.h')
-rw-r--r--include/llvm/MC/MCAssembler.h100
1 files changed, 98 insertions, 2 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 882929f2eeef..1d8051fdb060 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -10,6 +10,7 @@
#ifndef LLVM_MC_MCASSEMBLER_H
#define LLVM_MC_MCASSEMBLER_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
@@ -20,6 +21,7 @@
namespace llvm {
class raw_ostream;
+class MCAsmLayout;
class MCAssembler;
class MCContext;
class MCExpr;
@@ -27,6 +29,8 @@ class MCFragment;
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
@@ -160,6 +164,13 @@ public:
/// @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; }
@@ -195,7 +206,8 @@ class MCAlignFragment : public MCFragment {
/// 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:
@@ -505,6 +517,11 @@ 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
/// @{
@@ -581,22 +598,61 @@ private:
MCContext &Context;
+ TargetAsmBackend &Backend;
+
raw_ostream &OS;
iplist<MCSectionData> Sections;
iplist<MCSymbolData> Symbols;
+ /// The map of sections to their associated assembler backend data.
+ //
+ // FIXME: Avoid this indirection?
+ DenseMap<const MCSection*, MCSectionData*> SectionMap;
+
+ /// The map of symbols to their associated assembler backend data.
+ //
+ // FIXME: Avoid this indirection?
+ DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap;
+
std::vector<IndirectSymbolData> IndirectSymbols;
unsigned SubsectionsViaSymbols : 1;
private:
+ /// 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();
+
+ // FIXME: Make protected once we factor out object writer classes.
+public:
+ /// 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;
+
public:
/// Construct a new assembler instance.
///
@@ -606,11 +662,13 @@ public:
// 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, raw_ostream &OS);
+ MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, raw_ostream &OS);
~MCAssembler();
MCContext &getContext() const { return Context; }
+ TargetAsmBackend &getBackend() const { return Backend; }
+
/// Finish - Do final processing and write the object to the output stream.
void Finish();
@@ -673,6 +731,44 @@ public:
size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
/// @}
+ /// @name Backend Data Access
+ /// @{
+
+ MCSectionData &getSectionData(const MCSection &Section) const {
+ MCSectionData *Entry = SectionMap.lookup(&Section);
+ assert(Entry && "Missing section data!");
+ return *Entry;
+ }
+
+ MCSectionData &getOrCreateSectionData(const MCSection &Section,
+ bool *Created = 0) {
+ MCSectionData *&Entry = SectionMap[&Section];
+
+ if (Created) *Created = !Entry;
+ if (!Entry)
+ Entry = new MCSectionData(Section, this);
+
+ return *Entry;
+ }
+
+ MCSymbolData &getSymbolData(const MCSymbol &Symbol) const {
+ MCSymbolData *Entry = SymbolMap.lookup(&Symbol);
+ assert(Entry && "Missing symbol data!");
+ return *Entry;
+ }
+
+ MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol,
+ bool *Created = 0) {
+ MCSymbolData *&Entry = SymbolMap[&Symbol];
+
+ if (Created) *Created = !Entry;
+ if (!Entry)
+ Entry = new MCSymbolData(Symbol, 0, 0, this);
+
+ return *Entry;
+ }
+
+ /// @}
void dump();
};