[llvm] b71ef0c - [MC] Support .reloc sym+constant, *, *
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 14 13:46:05 PDT 2020
Author: Fangrui Song
Date: 2020-07-14T13:44:00-07:00
New Revision: b71ef0c50ac6728581e3c82ee90fe400dcc48bd6
URL: https://github.com/llvm/llvm-project/commit/b71ef0c50ac6728581e3c82ee90fe400dcc48bd6
DIFF: https://github.com/llvm/llvm-project/commit/b71ef0c50ac6728581e3c82ee90fe400dcc48bd6.diff
LOG: [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
Added:
llvm/test/MC/ELF/reloc-directive.s
Modified:
llvm/include/llvm/MC/MCObjectStreamer.h
llvm/include/llvm/MC/MCStreamer.h
llvm/lib/MC/MCAsmStreamer.cpp
llvm/lib/MC/MCObjectStreamer.cpp
llvm/lib/MC/MCParser/AsmParser.cpp
llvm/test/MC/Mips/reloc-directive-bad.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h
index f37f2ad76002..c3f3ae5de921 100644
--- a/llvm/include/llvm/MC/MCObjectStreamer.h
+++ b/llvm/include/llvm/MC/MCObjectStreamer.h
@@ -171,9 +171,9 @@ class MCObjectStreamer : public MCStreamer {
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;
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index d7255a22e941..484c62538366 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -1014,13 +1014,12 @@ class MCStreamer {
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() {}
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 0747ab2372ab..6a8572e57922 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -349,9 +349,9 @@ class MCAsmStreamer final : public MCStreamer {
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,9 +2072,10 @@ void MCAsmStreamer::emitBundleUnlock() {
EmitEOL();
}
-bool MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc,
- const MCSubtargetInfo &STI) {
+Optional<std::pair<bool, std::string>>
+MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc,
+ const MCSubtargetInfo &STI) {
OS << "\t.reloc ";
Offset.print(OS, MAI);
OS << ", " << Name;
@@ -2083,7 +2084,7 @@ bool MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
Expr->print(OS, MAI);
}
EmitEOL();
- return false;
+ return None;
}
void MCAsmStreamer::emitAddrsig() {
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 9c564c83b6b5..e39c4a03bc1e 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -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,
- const MCExpr *Expr, SMLoc Loc,
- const MCSubtargetInfo &STI) {
+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(),
- Expr, Kind, Loc));
- return false;
+ // FIXME SRE.getSymbol() may not be relative to DF.
+ DF->getFixups().push_back(
+ MCFixup::create(SRE.getSymbol().getOffset() + OffsetVal.getConstant(),
+ Expr, Kind, Loc));
+ return None;
}
PendingFixups.emplace_back(&SRE.getSymbol(), DF,
- MCFixup::create(-1, Expr, Kind, Loc));
- return false;
+ MCFixup::create(-1, Expr, Kind, Loc));
+ return None;
}
void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 9e92ce09986f..c05f26cbdda5 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -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;
}
diff --git a/llvm/test/MC/ELF/reloc-directive.s b/llvm/test/MC/ELF/reloc-directive.s
new file mode 100644
index 000000000000..59d7ace40d7e
--- /dev/null
+++ b/llvm/test/MC/ELF/reloc-directive.s
@@ -0,0 +1,61 @@
+## Target specific relocation support is tested in MC/$target/*reloc-directive*.s
+# RUN: llvm-mc -triple=x86_64 %s | FileCheck %s --check-prefix=ASM
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s
+
+# ASM: .Ltmp0:
+# ASM-NEXT: .reloc (.Ltmp0+3)-2, R_X86_64_NONE, foo
+# ASM-NEXT: .Ltmp1:
+# ASM-NEXT: .reloc .Ltmp1-1, R_X86_64_NONE, foo
+# ASM-NEXT: .Ltmp2:
+# ASM-NEXT: .reloc 2+.Ltmp2, R_X86_64_NONE, foo
+# ASM-NEXT: .reloc (1+foo)+3, R_X86_64_NONE, data+1
+
+# CHECK: 0x2 R_X86_64_NONE foo 0x0
+# CHECK-NEXT: 0x0 R_X86_64_NONE foo 0x0
+# CHECK-NEXT: 0x3 R_X86_64_NONE foo 0x0
+# CHECK-NEXT: 0x4 R_X86_64_NONE data 0x1
+
+.text
+.globl foo
+foo:
+ ret
+ .reloc .+3-2, R_X86_64_NONE, foo
+ .reloc .-1, R_X86_64_NONE, foo
+ .reloc 2+., R_X86_64_NONE, foo
+ .reloc 1+foo+3, R_X86_64_NONE, data+1
+
+.data
+.globl data
+data:
+ .long 0
+
+# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym=ERR=1 %s 2>&1 | FileCheck %s --check-prefix=ERR
+
+.ifdef ERR
+.text
+.globl a, b
+a: ret
+b: ret
+x: ret
+y: ret
+
+# ERR: {{.*}}.s:[[#@LINE+1]]:10: error: expected comma
+.reloc 0 R_X86_64_NONE, a
+
+# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is negative
+.reloc -1, R_X86_64_NONE, a
+# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not relocatable
+.reloc 2*., R_X86_64_NONE, a
+# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not relocatable
+.reloc a+a, R_X86_64_NONE, a
+## GNU as accepts a-a but rejects b-a.
+# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not representable
+.reloc a-a, R_X86_64_NONE, a
+## TODO GNU as accepts x-x and y-x.
+# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not representable
+.reloc x-x, R_X86_64_NONE, a
+
+# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: directional label undefined
+.reloc 1f, R_X86_64_NONE, a
+.endif
diff --git a/llvm/test/MC/Mips/reloc-directive-bad.s b/llvm/test/MC/Mips/reloc-directive-bad.s
index 929643b914af..bb056b752fb9 100644
--- a/llvm/test/MC/Mips/reloc-directive-bad.s
+++ b/llvm/test/MC/Mips/reloc-directive-bad.s
@@ -2,12 +2,6 @@
# RUN: -target-abi=o32 2>&1 | FileCheck %s
.text
foo:
- .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
More information about the llvm-commits
mailing list