Commit b71ef0c5 authored by Fangrui Song's avatar Fangrui Song
Browse files

[MC] Support .reloc sym+constant, *, *

For `.reloc offset, *, *`, currently offset can be a constant or symbol.
This patch makes it support any expression which can be folded to sym+constant.

Reviewed By: stefanp

Differential Revision: https://reviews.llvm.org/D83751
parent ce6f0303
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -171,9 +171,9 @@ public:
  void emitTPRel64Value(const MCExpr *Value) override;
  void emitGPRel32Value(const MCExpr *Value) override;
  void emitGPRel64Value(const MCExpr *Value) override;
  bool emitRelocDirective(const MCExpr &Offset, StringRef Name,
                          const MCExpr *Expr, SMLoc Loc,
                          const MCSubtargetInfo &STI) override;
  Optional<std::pair<bool, std::string>>
  emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
                     SMLoc Loc, const MCSubtargetInfo &STI) override;
  using MCStreamer::emitFill;
  void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
                SMLoc Loc = SMLoc()) override;
+6 −7
Original line number Diff line number Diff line
@@ -1014,13 +1014,12 @@ public:

  virtual void emitSyntaxDirective();

  /// Emit a .reloc directive.
  /// Returns true if the relocation could not be emitted because Name is not
  /// known.
  virtual bool emitRelocDirective(const MCExpr &Offset, StringRef Name,
                                  const MCExpr *Expr, SMLoc Loc,
                                  const MCSubtargetInfo &STI) {
    return true;
  /// Record a relocation described by the .reloc directive. Return None if
  /// succeeded. Otherwise, return a pair (Name is invalid, error message).
  virtual Optional<std::pair<bool, std::string>>
  emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
                     SMLoc Loc, const MCSubtargetInfo &STI) {
    return None;
  }

  virtual void emitAddrsig() {}
+8 −7
Original line number Diff line number Diff line
@@ -349,9 +349,9 @@ public:
  void emitBundleLock(bool AlignToEnd) override;
  void emitBundleUnlock() override;

  bool emitRelocDirective(const MCExpr &Offset, StringRef Name,
                          const MCExpr *Expr, SMLoc Loc,
                          const MCSubtargetInfo &STI) override;
  Optional<std::pair<bool, std::string>>
  emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
                     SMLoc Loc, const MCSubtargetInfo &STI) override;

  void emitAddrsig() override;
  void emitAddrsigSym(const MCSymbol *Sym) override;
@@ -2072,7 +2072,8 @@ void MCAsmStreamer::emitBundleUnlock() {
  EmitEOL();
}

bool MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
Optional<std::pair<bool, std::string>>
MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
                                  const MCExpr *Expr, SMLoc,
                                  const MCSubtargetInfo &STI) {
  OS << "\t.reloc ";
@@ -2083,7 +2084,7 @@ bool MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
    Expr->print(OS, MAI);
  }
  EmitEOL();
  return false;
  return None;
}

void MCAsmStreamer::emitAddrsig() {
+27 −19
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
using namespace llvm;
@@ -664,12 +665,13 @@ void MCObjectStreamer::emitGPRel64Value(const MCExpr *Value) {
  DF->getContents().resize(DF->getContents().size() + 8, 0);
}

bool MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
Optional<std::pair<bool, std::string>>
MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
                                     const MCExpr *Expr, SMLoc Loc,
                                     const MCSubtargetInfo &STI) {
  Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
  if (!MaybeKind.hasValue())
    return true;
    return std::make_pair(true, std::string("unknown relocation name"));

  MCFixupKind Kind = *MaybeKind;

@@ -680,27 +682,33 @@ bool MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
  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;
  MCValue OffsetVal;
  if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr, nullptr))
    return std::make_pair(false,
                          std::string(".reloc offset is not relocatable"));
  if (OffsetVal.isAbsolute()) {
    if (OffsetVal.getConstant() < 0)
      return std::make_pair(false, std::string(".reloc offset is negative"));
    DF->getFixups().push_back(
        MCFixup::create(OffsetVal.getConstant(), Expr, Kind, Loc));
    return None;
  }
  if (OffsetVal.getSymB())
    return std::make_pair(false,
                          std::string(".reloc offset is not representable"));

  if (Offset.getKind() != llvm::MCExpr::SymbolRef)
    llvm_unreachable(".reloc offset is not absolute nor a label");

  const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Offset);
  const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*OffsetVal.getSymA());
  if (SRE.getSymbol().isDefined()) {
    DF->getFixups().push_back(MCFixup::create(SRE.getSymbol().getOffset(),
    // FIXME SRE.getSymbol() may not be relative to DF.
    DF->getFixups().push_back(
        MCFixup::create(SRE.getSymbol().getOffset() + OffsetVal.getConstant(),
                        Expr, Kind, Loc));
    return false;
    return None;
  }

  PendingFixups.emplace_back(&SRE.getSymbol(), DF,
                             MCFixup::create(-1, Expr, Kind, Loc));
  return false;
  return None;
}

void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+6 −12
Original line number Diff line number Diff line
@@ -3011,20 +3011,12 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
  const MCExpr *Offset;
  const MCExpr *Expr = nullptr;
  int64_t OffsetValue;
  SMLoc OffsetLoc = Lexer.getTok().getLoc();

  if (parseExpression(Offset))
    return true;

  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")))
  if (parseToken(AsmToken::Comma, "expected comma") ||
      check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
    return true;

  SMLoc NameLoc = Lexer.getTok().getLoc();
@@ -3048,8 +3040,10 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {

  const MCTargetAsmParser &MCT = getTargetParser();
  const MCSubtargetInfo &STI = MCT.getSTI();
  if (getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc, STI))
    return Error(NameLoc, "unknown relocation name");
  if (Optional<std::pair<bool, std::string>> Err =
          getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
                                           STI))
    return Error(Err->first ? NameLoc : OffsetLoc, Err->second);

  return false;
}
Loading