8000 Add support for pc-relative addressing on 64-bit RISC-V by Disasm · Pull Request #16 · rust-lang/llvm-project · GitHub
[go: up one dir, main page]

Skip to content

Add support for pc-relative addressing on 64-bit RISC-V #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[RISCV] Support assembling %got_pcrel_hi operator
Differential Revision: https://reviews.llvm.org/D55279
Patch by James Clarke.

llvm-svn: 354110
  • Loading branch information
asb authored and Disasm committed Jun 30, 2019
commit 8f7bc42ad5b9174f295dacf0fcd6ca44ee7d1b83
10 changes: 6 additions & 4 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,10 +505,12 @@ struct RISCVOperand : public MCParsedAsmOperand {
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
if (!IsConstantImm) {
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
return IsValid && VK == RISCVMCExpr::VK_RISCV_PCREL_HI;
return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
VK == RISCVMCExpr::VK_RISCV_GOT_HI);
} else {
return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
VK == RISCVMCExpr::VK_RISCV_GOT_HI);
}
}

Expand Down Expand Up @@ -861,8 +863,8 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidUImm20AUIPC:
return generateImmOutOfRangeError(
Operands, ErrorInfo, 0, (1 << 20) - 1,
"operand must be a symbol with %pcrel_hi() modifier or an integer in "
"the range");
"operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier "
"or an integer in the range");
case Match_InvalidSImm21Lsb0JAL:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
switch ((unsigned)Fixup.getKind()) {
default:
break;
case RISCV::fixup_riscv_got_hi20:
return true;
case RISCV::fixup_riscv_pcrel_lo12_i:
case RISCV::fixup_riscv_pcrel_lo12_s:
// For pcrel_lo12, force a relocation if the target of the corresponding
Expand All @@ -48,6 +50,9 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
default:
llvm_unreachable("Unexpected fixup kind for pcrel_lo12");
break;
case RISCV::fixup_riscv_got_hi20:
ShouldForce = true;
break;
case RISCV::fixup_riscv_pcrel_hi20:
ShouldForce = T->getValue()->findAssociatedFragment() !=
Fixup.getValue()->findAssociatedFragment();
Expand Down Expand Up @@ -173,6 +178,8 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
switch (Kind) {
default:
llvm_unreachable("Unknown fixup kind!");
case RISCV::fixup_riscv_got_hi20:
llvm_unreachable("Relocation should be unconditionally forced\n");
case FK_Data_1:
case FK_Data_2:
case FK_Data_4:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class RISCVAsmBackend : public MCAsmBackend {
{ "fixup_riscv_pcrel_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel },
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_RISCV_PCREL_LO12_I;
case RISCV::fixup_riscv_pcrel_lo12_s:
return ELF::R_RISCV_PCREL_LO12_S;
case RISCV::fixup_riscv_got_hi20:
return ELF::R_RISCV_GOT_HI20;
case RISCV::fixup_riscv_jal:
return ELF::R_RISCV_JAL;
case RISCV::fixup_riscv_branch:
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ enum Fixups {
// fixup_riscv_pcrel_lo12_s - 12-bit fixup corresponding to pcrel_lo(foo) for
// the S-type store instructions
fixup_riscv_pcrel_lo12_s,
// fixup_riscv_got_hi20 - 20-bit fixup corresponding to got_pcrel_hi(foo) for
// instructions like auipc
fixup_riscv_got_hi20,
// fixup_riscv_jal - 20-bit fixup for symbol references in the jal
// instruction
fixup_riscv_jal,
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
case RISCVMCExpr::VK_RISCV_PCREL_HI:
FixupKind = RISCV::fixup_riscv_pcrel_hi20;
break;
case RISCVMCExpr::VK_RISCV_GOT_HI:
FixupKind = RISCV::fixup_riscv_got_hi20;
break;
case RISCVMCExpr::VK_RISCV_CALL:
FixupKind = RISCV::fixup_riscv_call;
break;
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const MCFixup *RISCVMCExpr::getPCRelHiFixup() const {
switch ((unsigned)F.getKind()) {
default:
continue;
case RISCV::fixup_riscv_got_hi20:
case RISCV::fixup_riscv_pcrel_hi20:
return &F;
}
Expand Down Expand Up @@ -137,6 +138,7 @@ bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
case VK_RISCV_HI:
case VK_RISCV_PCREL_LO:
case VK_RISCV_PCREL_HI:
case VK_RISCV_GOT_HI:
return false;
}
}
Expand All @@ -154,6 +156,7 @@ RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
.Case("hi", VK_RISCV_HI)
.Case("pcrel_lo", VK_RISCV_PCREL_LO)
.Case("pcrel_hi", VK_RISCV_PCREL_HI)
.Case("got_pcrel_hi", VK_RISCV_GOT_HI)
.Default(VK_RISCV_Invalid);
}

Expand All @@ -169,14 +172,16 @@ StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
return "pcrel_lo";
case VK_RISCV_PCREL_HI:
return "pcrel_hi";
case VK_RISCV_GOT_HI:
return "got_pcrel_hi";
}
}

bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
MCValue Value;

if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
Kind == VK_RISCV_CALL)
Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_CALL)
return false;

if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class RISCVMCExpr : public MCTargetExpr {
VK_RISCV_HI,
VK_RISCV_PCREL_LO,
VK_RISCV_PCREL_HI,
VK_RISCV_GOT_HI,
VK_RISCV_CALL,
VK_RISCV_Invalid
};
Expand All @@ -53,11 +54,11 @@ class RISCVMCExpr : public MCTargetExpr {

const MCExpr *getSubExpr() const { return Expr; }

/// Get the MCExpr of the VK_RISCV_PCREL_HI Fixup that the
/// VK_RISCV_PCREL_LO points to.
/// Get the corresponding PC-relative HI fixup that a VK_RISCV_PCREL_LO
/// points to.
///
/// \returns nullptr if this isn't a VK_RISCV_PCREL_LO pointing to a
/// VK_RISCV_PCREL_HI.
/// known PC-relative HI fixup.
const MCFixup *getPCRelHiFixup() const;

void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
Expand Down
34 changes: 34 additions & 0 deletions llvm/test/MC/RISCV/relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,40 @@ sb t1, %pcrel_lo(.L0)(a2)
# INSTR: sb t1, %pcrel_lo(.L0)(a2)
# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L0), kind: fixup_riscv_pcrel_lo12_s

.L1:
auipc t1, %got_pcrel_hi(foo)
# RELOC: R_RISCV_GOT_HI20 F438 foo 0x0
# INSTR: auipc t1, %got_pcrel_hi(foo)
# FIXUP: fixup A - offset: 0, value: %got_pcrel_hi(foo), kind: fixup_riscv_got_hi20

addi t1, t1, %pcrel_lo(.L1)
# RELOC: R_RISCV_PCREL_LO12_I .L1 0x0
# INSTR: addi t1, t1, %pcrel_lo(.L1)
# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L1), kind: fixup_riscv_pcrel_lo12_i

sb t1, %pcrel_lo(.L1)(a2)
# RELOC: R_RISCV_PCREL_LO12_S .L1 0x0
# INSTR: sb t1, %pcrel_lo(.L1)(a2)
# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L1), kind: fixup_riscv_pcrel_lo12_s

# Check that GOT relocations aren't evaluated to a constant when the symbol is
# in the same object file.
.L2:
auipc t1, %got_pcrel_hi(.L1)
# RELOC: R_RISCV_GOT_HI20 .L1 0x0
# INSTR: auipc t1, %got_pcrel_hi(.L1)
# FIXUP: fixup A - offset: 0, value: %got_pcrel_hi(.L1), kind: fixup_riscv_got_hi20

addi t1, t1, %pcrel_lo(.L2)
# RELOC: R_RISCV_PCREL_LO12_I .L2 0x0
# INSTR: addi t1, t1, %pcrel_lo(.L2)
# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L2), kind: fixup_riscv_pcrel_lo12_i

sb t1, %pcrel_lo(.L2)(a2)
# RELOC: R_RISCV_PCREL_LO12_S .L2 0x0
# INSTR: sb t1, %pcrel_lo(.L2)(a2)
# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L2), kind: fixup_riscv_pcrel_lo12_s

jal zero, foo
# RELOC: R_RISCV_JAL
# INSTR: jal zero, foo
Expand Down
12 changes: 6 additions & 6 deletions llvm/test/MC/RISCV/rv32i-invalid.s
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ bgeu t0, t1, -13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of
## uimm20
lui a0, -1 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]

## simm21_lsb0
jal gp, -1048578 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
Expand Down Expand Up @@ -105,7 +105,7 @@ bgeu t0, t1, %pcrel_lo(d) # CHECK: :[[@LINE]]:14: error: immediate must be a mul

## uimm20
lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]

## simm21_lsb0
jal gp, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
Expand All @@ -125,10 +125,10 @@ lui a0, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi
lui a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
lui a0, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]

auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]

# Unrecognized operand modifier
addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier
Expand Down
0