summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/MCObjectStreamer.cpp
diff options
context:
space:
mode:
authorVladimir Stefanovic <vladimir.stefanovic@rt-rk.com>2018-11-21 16:28:39 +0000
committerVladimir Stefanovic <vladimir.stefanovic@rt-rk.com>2018-11-21 16:28:39 +0000
commit1d2714be13e05d0a134f5936345332ad504e7378 (patch)
treee7b7dbaaf2c83b35159919cf05738b23d0af385d /llvm/lib/MC/MCObjectStreamer.cpp
parent2359864be2192dfa9d6e6384f5df310b4eae1363 (diff)
downloadbcm5719-llvm-1d2714be13e05d0a134f5936345332ad504e7378.tar.gz
bcm5719-llvm-1d2714be13e05d0a134f5936345332ad504e7378.zip
[MC] Support labels as offsets in .reloc directive
Currently, expressions like .reloc 1f, R_MIPS_JALR, foo 1: nop are not allowed, ie. an offset in .reloc can only be absolute value. This patch adds support for labels as offsets. If offset is a forward declared label, MCObjectStreamer keeps the fixup locally and adds it to the fixups vector after the label (and its offset) is defined. label+number is not supported yet. Differential revision: https://reviews.llvm.org/D53990 llvm-svn: 347397
Diffstat (limited to 'llvm/lib/MC/MCObjectStreamer.cpp')
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp57
1 files changed, 46 insertions, 11 deletions
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 8c88db009bd..248c5a1fe35 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -59,6 +59,27 @@ void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
PendingLabels.clear();
}
+// When fixup's offset is a forward declared label, e.g.:
+//
+// .reloc 1f, R_MIPS_JALR, foo
+// 1: nop
+//
+// postpone adding it to Fixups vector until the label is defined and its offset
+// is known.
+void MCObjectStreamer::resolvePendingFixups() {
+ for (PendingMCFixup &PendingFixup : PendingFixups) {
+ if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
+ getContext().reportError(PendingFixup.Fixup.getLoc(),
+ "unresolved relocation offset");
+ continue;
+ }
+ flushPendingLabels(PendingFixup.DF, PendingFixup.DF->getContents().size());
+ PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset());
+ PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup);
+ }
+ PendingFixups.clear();
+}
+
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
static Optional<uint64_t>
@@ -603,16 +624,6 @@ void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
const MCExpr *Expr, SMLoc Loc,
const MCSubtargetInfo &STI) {
- int64_t OffsetValue;
- if (!Offset.evaluateAsAbsolute(OffsetValue))
- llvm_unreachable("Offset is not absolute");
-
- if (OffsetValue < 0)
- llvm_unreachable("Offset is negative");
-
- MCDataFragment *DF = getOrCreateDataFragment(&STI);
- flushPendingLabels(DF, DF->getContents().size());
-
Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
if (!MaybeKind.hasValue())
return true;
@@ -622,7 +633,30 @@ bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
if (Expr == nullptr)
Expr =
MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
- DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
+
+ MCDataFragment *DF = getOrCreateDataFragment(&STI);
+ flushPendingLabels(DF, DF->getContents().size());
+
+ int64_t OffsetValue;
+ if (Offset.evaluateAsAbsolute(OffsetValue)) {
+ if (OffsetValue < 0)
+ llvm_unreachable(".reloc offset is negative");
+ DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
+ return false;
+ }
+
+ if (Offset.getKind() != llvm::MCExpr::SymbolRef)
+ llvm_unreachable(".reloc offset is not absolute nor a label");
+
+ const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Offset);
+ if (SRE.getSymbol().isDefined()) {
+ DF->getFixups().push_back(MCFixup::create(SRE.getSymbol().getOffset(),
+ Expr, Kind, Loc));
+ return false;
+ }
+
+ PendingFixups.emplace_back(&SRE.getSymbol(), DF,
+ MCFixup::create(-1, Expr, Kind, Loc));
return false;
}
@@ -689,5 +723,6 @@ void MCObjectStreamer::FinishImpl() {
MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
flushPendingLabels();
+ resolvePendingFixups();
getAssembler().Finish();
}
OpenPOWER on IntegriCloud