diff options
author | Eli Friedman <efriedma@quicinc.com> | 2019-03-12 18:14:16 +0000 |
---|---|---|
committer | Eli Friedman <efriedma@quicinc.com> | 2019-03-12 18:14:16 +0000 |
commit | 74b6aae4e8f47bfe150bb2d943474b4529403a37 (patch) | |
tree | 83ca31077cd4a9520a8244291558f34d5bd07415 | |
parent | b6bfcfc847afed9580e9cf8c8e3ada647a876a6f (diff) | |
download | bcm5719-llvm-74b6aae4e8f47bfe150bb2d943474b4529403a37.tar.gz bcm5719-llvm-74b6aae4e8f47bfe150bb2d943474b4529403a37.zip |
[RISCV][MC] Find matching pcrel_hi fixup in more cases.
If a symbol points to the end of a fragment, instead of searching for
fixups in that fragment, search in the next fragment.
Fixes spurious assembler error with subtarget change next to "la"
pseudo-instruction, or expanded equivalent.
Alternate proposal to fix the problem discussed in
https://reviews.llvm.org/D58759.
Testcase by Ana Pazos.
Differential Revision: https://reviews.llvm.org/D58943
llvm-svn: 355946
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp | 16 | ||||
-rw-r--r-- | llvm/test/MC/RISCV/option-mix.s | 51 |
2 files changed, 63 insertions, 4 deletions
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp index 98938d25834..c0ca634969b 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -49,14 +49,22 @@ const MCFixup *RISCVMCExpr::getPCRelHiFixup() const { if (!AUIPCSRE) return nullptr; - const auto *DF = - dyn_cast_or_null<MCDataFragment>(AUIPCSRE->findAssociatedFragment()); + const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol(); + const auto *DF = dyn_cast_or_null<MCDataFragment>(AUIPCSymbol->getFragment()); + if (!DF) return nullptr; - const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol(); + uint64_t Offset = AUIPCSymbol->getOffset(); + if (DF->getContents().size() == Offset) { + DF = dyn_cast_or_null<MCDataFragment>(DF->getNextNode()); + if (!DF) + return nullptr; + Offset = 0; + } + for (const MCFixup &F : DF->getFixups()) { - if (F.getOffset() != AUIPCSymbol->getOffset()) + if (F.getOffset() != Offset) continue; switch ((unsigned)F.getKind()) { diff --git a/llvm/test/MC/RISCV/option-mix.s b/llvm/test/MC/RISCV/option-mix.s new file mode 100644 index 00000000000..eccbfe0ce57 --- /dev/null +++ b/llvm/test/MC/RISCV/option-mix.s @@ -0,0 +1,51 @@ +# RUN: llvm-mc %s -triple=riscv32 | FileCheck -check-prefix=ASM %s +# RUN: llvm-mc %s -triple=riscv64 | FileCheck -check-prefix=ASM %s +# RUN: llvm-mc -filetype=obj -triple riscv32 < %s \ +# RUN: | llvm-objdump -d -riscv-no-aliases - | FileCheck -check-prefix=DISASM %s +# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \ +# RUN: | llvm-objdump -d -riscv-no-aliases - | FileCheck -check-prefix=DISASM %s + +# Checks change of options does not cause error: could not find corresponding %pcrel_hi +# when assembling pseudoinstruction and its extended form. + +.option push +.option norelax + la a0, a_symbol +.option pop + la a1, another_symbol + +# ASM: .Lpcrel_hi0: +# ASM: auipc a0, %pcrel_hi(a_symbol) +# ASM: addi a0, a0, %pcrel_lo(.Lpcrel_hi0) +# ASM: .Lpcrel_hi1: +# ASM: auipc a1, %pcrel_hi(another_symbol) +# ASM: addi a1, a1, %pcrel_lo(.Lpcrel_hi1) + +# DISASM: .Lpcrel_hi0: +# DISASM: auipc a0, 0 +# DISASM: addi a0, a0, 0 +# DISASM:.Lpcrel_hi1: +# DISASM: auipc a1, 0 +# DISASM: addi a1, a1, 0 + +.option push +.option norelax +1:auipc a0, %pcrel_hi(a_symbol) + addi a0, a0, %pcrel_lo(1b) +.option pop +2:auipc a1, %pcrel_hi(another_symbol) + addi a1, a1, %pcrel_lo(2b) + +# ASM: .Ltmp0: +# ASM: auipc a0, %pcrel_hi(a_symbol) +# ASM: addi a0, a0, %pcrel_lo(.Ltmp0) +# ASM: .Ltmp1: +# ASM: auipc a1, %pcrel_hi(another_symbol) +# ASM: addi a1, a1, %pcrel_lo(.Ltmp1) + +# DISASM: .Ltmp0: +# DISASM: auipc a0, 0 +# DISASM: addi a0, a0, 0 +# DISASM: .Ltmp1: +# DISASM: auipc a1, 0 +# DISASM: addi a1, a1, 0 |