[llvm] r347397 - [MC] Support labels as offsets in .reloc directive

Vladimir Stefanovic via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 21 08:28:39 PST 2018


Author: vstefanovic
Date: Wed Nov 21 08:28:39 2018
New Revision: 347397

URL: http://llvm.org/viewvc/llvm-project?rev=347397&view=rev
Log:
[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

Added:
    llvm/trunk/test/MC/Mips/reloc-directive-bad-obj.s
    llvm/trunk/test/MC/Mips/reloc-directive-label-offset.s
Removed:
    llvm/trunk/test/MC/Mips/reloc-directive-negative.s
Modified:
    llvm/trunk/include/llvm/MC/MCObjectStreamer.h
    llvm/trunk/lib/MC/MCObjectStreamer.cpp
    llvm/trunk/lib/MC/MCParser/AsmParser.cpp
    llvm/trunk/test/MC/Mips/reloc-directive-bad.s

Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=347397&r1=347396&r2=347397&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Wed Nov 21 08:28:39 2018
@@ -39,12 +39,21 @@ class MCObjectStreamer : public MCStream
   bool EmitEHFrame;
   bool EmitDebugFrame;
   SmallVector<MCSymbol *, 2> PendingLabels;
+  struct PendingMCFixup {
+    const MCSymbol *Sym;
+    MCFixup Fixup;
+    MCDataFragment *DF;
+    PendingMCFixup(const MCSymbol *McSym, MCDataFragment *F, MCFixup McFixup)
+        : Sym(McSym), Fixup(McFixup), DF(F) {}
+  };
+  SmallVector<PendingMCFixup, 2> PendingFixups;
 
   virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0;
   void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
   void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
   MCSymbol *EmitCFILabel() override;
   void EmitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI);
+  void resolvePendingFixups();
 
 protected:
   MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,

Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=347397&r1=347396&r2=347397&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Wed Nov 21 08:28:39 2018
@@ -59,6 +59,27 @@ void MCObjectStreamer::flushPendingLabel
   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(
 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::EmitRelocDirectiv
   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();
 }

Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=347397&r1=347396&r2=347397&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Wed Nov 21 08:28:39 2018
@@ -2938,20 +2938,20 @@ bool AsmParser::parseDirectiveAscii(Stri
 bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
   const MCExpr *Offset;
   const MCExpr *Expr = nullptr;
-
-  SMLoc OffsetLoc = Lexer.getTok().getLoc();
   int64_t OffsetValue;
-  // We can only deal with constant expressions at the moment.
+  SMLoc OffsetLoc = Lexer.getTok().getLoc();
 
   if (parseExpression(Offset))
     return true;
 
-  if (check(!Offset->evaluateAsAbsolute(OffsetValue,
-                                        getStreamer().getAssemblerPtr()),
-            OffsetLoc, "expression is not a constant value") ||
-      check(OffsetValue < 0, OffsetLoc, "expression is negative") ||
-      parseToken(AsmToken::Comma, "expected comma") ||
-      check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
+  if ((Offset->evaluateAsAbsolute(OffsetValue,
+                                  getStreamer().getAssemblerPtr()) &&
+       check(OffsetValue < 0, OffsetLoc, "expression is negative")) ||
+      (check(Offset->getKind() != llvm::MCExpr::Constant &&
+             Offset->getKind() != llvm::MCExpr::SymbolRef,
+             OffsetLoc, "expected non-negative number or a label")) ||
+      (parseToken(AsmToken::Comma, "expected comma") ||
+       check(getTok().isNot(AsmToken::Identifier), "expected relocation name")))
     return true;
 
   SMLoc NameLoc = Lexer.getTok().getLoc();

Added: llvm/trunk/test/MC/Mips/reloc-directive-bad-obj.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/reloc-directive-bad-obj.s?rev=347397&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/reloc-directive-bad-obj.s (added)
+++ llvm/trunk/test/MC/Mips/reloc-directive-bad-obj.s Wed Nov 21 08:28:39 2018
@@ -0,0 +1,9 @@
+# RUN: not llvm-mc -triple mips-unknown-linux %s -show-encoding \
+# RUN:     -target-abi=o32 -filetype=obj 2>&1 | FileCheck %s
+	.text
+	nop
+	.reloc foo, R_MIPS_32, .text  # CHECK: :[[@LINE]]:2: error: unresolved relocation offset
+	nop
+	nop
+	.reloc bar, R_MIPS_32, .text  # CHECK: :[[@LINE]]:2: error: unresolved relocation offset
+	nop

Modified: llvm/trunk/test/MC/Mips/reloc-directive-bad.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/reloc-directive-bad.s?rev=347397&r1=347396&r2=347397&view=diff
==============================================================================
--- llvm/trunk/test/MC/Mips/reloc-directive-bad.s (original)
+++ llvm/trunk/test/MC/Mips/reloc-directive-bad.s Wed Nov 21 08:28:39 2018
@@ -1,6 +1,13 @@
-# RUN: not llvm-mc -triple mips-unknown-linux < %s -show-encoding -target-abi=o32 \
-# RUN:     2>&1 | FileCheck %s
+# RUN: not llvm-mc -triple mips-unknown-linux < %s -show-encoding \
+# RUN:     -target-abi=o32 2>&1 | FileCheck %s
 	.text
 foo:
-	.reloc 0, R_MIPS_32, .text+.text # CHECK: :[[@LINE]]:23: error: expression must be relocatable
+	.reloc foo+4, R_MIPS_32, .text    # CHECK: :[[@LINE]]:9: error: expected non-negative number or a label
+	.reloc foo+foo, R_MIPS_32, .text  # CHECK: :[[@LINE]]:9: error: expected non-negative number or a label
+	.reloc 0, R_MIPS_32, .text+.text  # CHECK: :[[@LINE]]:23: error: expression must be relocatable
+	.reloc 0 R_MIPS_32, .text         # CHECK: :[[@LINE]]:11: error: expected comma
+	.reloc 0, 0, R_MIPS_32, .text     # CHECK: :[[@LINE]]:12: error: expected relocation name
+	.reloc -1, R_MIPS_32, .text       # CHECK: :[[@LINE]]:9: error: expression is negative
+	.reloc 1b, R_MIPS_32, .text       # CHECK: :[[@LINE]]:9: error: directional label undefined
+	.reloc 1f, R_MIPS_32, .text       # CHECK: :[[@LINE]]:9: error: directional label undefined
 	nop

Added: llvm/trunk/test/MC/Mips/reloc-directive-label-offset.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/reloc-directive-label-offset.s?rev=347397&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/reloc-directive-label-offset.s (added)
+++ llvm/trunk/test/MC/Mips/reloc-directive-label-offset.s Wed Nov 21 08:28:39 2018
@@ -0,0 +1,74 @@
+# RUN: llvm-mc -triple mips-unknown-linux %s -show-encoding -target-abi=o32 \
+# RUN:     | FileCheck --check-prefixes=ASM,ASM-32 %s
+# RUN: llvm-mc -triple mips64-unknown-linux %s -show-encoding -target-abi=n32 \
+# RUN:     | FileCheck --check-prefixes=ASM,ASM-64 %s
+# RUN: llvm-mc -triple mips64-unknown-linux %s -show-encoding -target-abi=n64 \
+# RUN:     | FileCheck --check-prefixes=ASM,ASM-64 %s
+# RUN: llvm-mc -triple mips-unknown-linux %s -show-encoding -target-abi=o32 \
+# RUN:     -filetype=obj | llvm-readobj -r | FileCheck -check-prefix=OBJ-O32 %s
+# RUN: llvm-mc -triple mips64-unknown-linux %s -show-encoding -target-abi=n32 \
+# RUN:     -filetype=obj | llvm-readobj -r | FileCheck -check-prefix=OBJ-N32 %s
+# RUN: llvm-mc -triple mips64-unknown-linux %s -show-encoding -target-abi=n64 \
+# RUN:     -filetype=obj | llvm-readobj -r | FileCheck -check-prefix=OBJ-N64 %s
+
+  .text
+foo: # ASM-LABEL: foo:
+  nop
+1:
+  nop
+  .reloc 1b, R_MIPS_NONE, foo       # ASM-32: .reloc ($tmp0), R_MIPS_NONE, foo
+                                    # ASM-64: .reloc .Ltmp0, R_MIPS_NONE, foo
+  nop
+  .reloc 1f, R_MIPS_32, foo         # ASM-32: .reloc ($tmp1), R_MIPS_32, foo
+                                    # ASM-64: .reloc .Ltmp1, R_MIPS_32, foo
+1:
+  nop
+  .reloc 1f, R_MIPS_CALL16, foo     # ASM-32: .reloc ($tmp2), R_MIPS_CALL16, foo
+                                    # ASM-64: .reloc .Ltmp2, R_MIPS_CALL16, foo
+1:
+  nop
+  .reloc 2f, R_MIPS_GOT_DISP, foo   # ASM-32: .reloc ($tmp3), R_MIPS_GOT_DISP, foo
+                                    # ASM-64: .reloc .Ltmp3, R_MIPS_GOT_DISP, foo
+  nop
+
+  .reloc 3f, R_MIPS_GOT_PAGE, foo   # ASM-32: .reloc ($tmp4), R_MIPS_GOT_PAGE, foo
+                                    # ASM-64: .reloc .Ltmp4, R_MIPS_GOT_PAGE, foo
+  nop
+bar:
+2:
+  nop
+3:
+  nop
+  .reloc bar, R_MIPS_GOT_OFST, foo  # ASM: .reloc bar, R_MIPS_GOT_OFST, foo
+  nop
+  .reloc foo, R_MIPS_32, foo        # ASM: .reloc foo, R_MIPS_32, foo
+  nop
+1:
+  nop
+
+# OBJ-O32-LABEL: Relocations [
+# OBJ-O32:           0x0 R_MIPS_32 .text 0x0
+# OBJ-O32-NEXT:      0x4 R_MIPS_NONE .text 0x0
+# OBJ-O32-NEXT:      0xC R_MIPS_32 .text 0x0
+# OBJ-O32-NEXT:      0x10 R_MIPS_CALL16 foo 0x0
+# OBJ-O32-NEXT:      0x1C R_MIPS_GOT_DISP foo 0x0
+# OBJ-O32-NEXT:      0x1C R_MIPS_GOT_OFST .text 0x0
+# OBJ-O32-NEXT:      0x20 R_MIPS_GOT_PAGE .text 0x0
+
+# OBJ-N32-LABEL: Relocations [
+# OBJ-N32:           0x4 R_MIPS_NONE .text 0x0
+# OBJ-N32-NEXT:      0x1C R_MIPS_GOT_OFST .text 0x0
+# OBJ-N32-NEXT:      0x0 R_MIPS_32 .text 0x0
+# OBJ-N32-NEXT:      0xC R_MIPS_32 .text 0x0
+# OBJ-N32-NEXT:      0x10 R_MIPS_CALL16 foo 0x0
+# OBJ-N32-NEXT:      0x1C R_MIPS_GOT_DISP foo 0x0
+# OBJ-N32-NEXT:      0x20 R_MIPS_GOT_PAGE .text 0x0
+
+# OBJ-N64-LABEL: Relocations [
+# OBJ-N64:           0x4 R_MIPS_NONE/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT:      0x1C R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT:      0x0 R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT:      0xC R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT:      0x10 R_MIPS_CALL16/R_MIPS_NONE/R_MIPS_NONE foo 0x0
+# OBJ-N64-NEXT:      0x1C R_MIPS_GOT_DISP/R_MIPS_NONE/R_MIPS_NONE foo 0x0
+# OBJ-N64-NEXT:      0x20 R_MIPS_GOT_PAGE/R_MIPS_NONE/R_MIPS_NONE .text 0x0

Removed: llvm/trunk/test/MC/Mips/reloc-directive-negative.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/reloc-directive-negative.s?rev=347396&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/reloc-directive-negative.s (original)
+++ llvm/trunk/test/MC/Mips/reloc-directive-negative.s (removed)
@@ -1,6 +0,0 @@
-# RUN: not llvm-mc -triple mips-unknown-linux < %s -show-encoding -target-abi=o32 \
-# RUN:     2>&1 | FileCheck %s
-	.text
-foo:
-	.reloc -1, R_MIPS_32, .text # CHECK: :[[@LINE]]:9: error: expression is negative
-	nop




More information about the llvm-commits mailing list