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:
parent
f60a7e942d
commit
5044eeb2f2
@ -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;
|
||||
|
@ -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() {}
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
61
test/MC/ELF/reloc-directive.s
Normal file
61
test/MC/ELF/reloc-directive.s
Normal 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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user