aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-03-12 21:00:49 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-03-12 21:00:49 +0000
commitdf3c8f29691a1e3f9ac4afbf05be52dbc898dae9 (patch)
tree7bb7e05b7318e959bf11cc69d0b4e30473965d14
parenta0e36d55c495b3325805c659ac365b5faea84e34 (diff)
MC: Factor out MCAssembler::EvaluateFixup, and simplify.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98381 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCAssembler.h21
-rw-r--r--lib/MC/MCAssembler.cpp85
2 files changed, 73 insertions, 33 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 4db1c012b0..d614c69742 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -21,6 +21,7 @@
namespace llvm {
class raw_ostream;
+class MCAsmLayout;
class MCAssembler;
class MCContext;
class MCExpr;
@@ -28,6 +29,7 @@ class MCFragment;
class MCSection;
class MCSectionData;
class MCSymbol;
+class MCValue;
class TargetAsmBackend;
/// MCAsmFixup - Represent a fixed size region of bytes inside some fragment
@@ -624,6 +626,25 @@ private:
/// already have been computed.
void LayoutSection(MCSectionData &SD);
+ // 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.
///
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 564111844c..ff930156a0 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -24,6 +24,7 @@
#include "llvm/Support/MachO.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetAsmBackend.h"
// FIXME: Gross.
#include "../Target/X86/X86FixupKinds.h"
@@ -471,19 +472,6 @@ public:
Value2 = B_SD->getAddress();
}
- // The value which goes in the fixup is current value of the expression.
- Fixup.FixedValue = Value - Value2 + Target.getConstant();
- if (IsPCRel)
- Fixup.FixedValue -= Address;
-
- // If this fixup is a vanilla PC relative relocation for a local label, we
- // don't need a relocation.
- //
- // FIXME: Implement proper atom support.
- if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary() &&
- !Target.getSymB())
- return;
-
MachRelocationEntry MRE;
MRE.Word0 = ((Address << 0) |
(Type << 24) |
@@ -514,9 +502,10 @@ public:
// FIXME: Share layout object.
MCAsmLayout Layout(Asm);
+ // Evaluate the fixup; if the value was resolved, no relocation is needed.
MCValue Target;
- if (!Fixup.Value->EvaluateAsRelocatable(Target, &Layout))
- llvm_report_error("expected relocatable expression");
+ if (Asm.EvaluateFixup(Layout, Fixup, &Fragment, Target, Fixup.FixedValue))
+ return;
// If this is a difference or a defined symbol plus an offset, then we need
// a scattered relocation entry.
@@ -567,24 +556,6 @@ public:
Type = RIT_Vanilla;
}
- // The value which goes in the fixup is current value of the expression.
- Fixup.FixedValue = Value + Target.getConstant();
- if (IsPCRel)
- Fixup.FixedValue -= Address;
-
- // If the target evaluates to a constant, we don't need a relocation. This
- // occurs with absolutized expressions which are not resolved to constants
- // until after relaxation.
- if (Target.isAbsolute())
- return;
-
- // If this fixup is a vanilla PC relative relocation for a local label, we
- // don't need a relocation.
- //
- // FIXME: Implement proper atom support.
- if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary())
- return;
-
// struct relocation_info (8 bytes)
MachRelocationEntry MRE;
MRE.Word0 = Address;
@@ -1010,6 +981,54 @@ MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
MCAssembler::~MCAssembler() {
}
+bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, MCAsmFixup &Fixup,
+ MCDataFragment *DF,
+ MCValue &Target, uint64_t &Value) const {
+ if (!Fixup.Value->EvaluateAsRelocatable(Target, &Layout))
+ llvm_report_error("expected relocatable expression");
+
+ // FIXME: How do non-scattered symbols work in ELF? I presume the linker
+ // doesn't support small relocations, but then under what criteria does the
+ // assembler allow symbol differences?
+
+ Value = Target.getConstant();
+
+ // FIXME: This "resolved" check isn't quite right. The assumption is that if
+ // we have a PCrel access to a temporary, then that temporary is in the same
+ // atom, and so the value is resolved. We need explicit atom's to implement
+ // this more precisely.
+ bool IsResolved = true, IsPCRel = isFixupKindPCRel(Fixup.Kind);
+ if (const MCSymbol *Symbol = Target.getSymA()) {
+ if (Symbol->isDefined())
+ Value += getSymbolData(*Symbol).getAddress();
+ else
+ IsResolved = false;
+
+ // With scattered symbols, we assume anything that isn't a PCrel temporary
+ // access can have an arbitrary value.
+ if (getBackend().hasScatteredSymbols() &&
+ (!IsPCRel || !Symbol->isTemporary()))
+ IsResolved = false;
+ }
+ if (const MCSymbol *Symbol = Target.getSymB()) {
+ if (Symbol->isDefined())
+ Value -= getSymbolData(*Symbol).getAddress();
+ else
+ IsResolved = false;
+
+ // With scattered symbols, we assume anything that isn't a PCrel temporary
+ // access can have an arbitrary value.
+ if (getBackend().hasScatteredSymbols() &&
+ (!IsPCRel || !Symbol->isTemporary()))
+ IsResolved = false;
+ }
+
+ if (IsPCRel)
+ Value -= DF->getOffset() + Fixup.Offset;
+
+ return IsResolved;
+}
+
void MCAssembler::LayoutSection(MCSectionData &SD) {
MCAsmLayout Layout(*this);
uint64_t Address = SD.getAddress();