1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[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
This commit is contained in:
Fangrui Song 2020-07-14 13:44:00 -07:00
parent f60a7e942d
commit 5044eeb2f2
7 changed files with 111 additions and 54 deletions

View File

@ -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;

View File

@ -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() {}

View File

@ -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,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() {

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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