To do this:
1. Add PseudoCALLIndirct to match indirect function call.
2. Add PseudoCALL to support parsing and print pseudo `call` in assembly
3. Expand PseudoCALL to the following form with R_RISCV_CALL relocation type
while encoding:
auipc ra, func
jalr ra, ra, 0
If we expand PseudoCALL before emitting assembly, we will see auipc and jalr
pair when compile with -S. It's hard for assembly parser to parsing this
pair and identify it's semantic is function call and then insert R_RISCV_CALL
relocation type. Although we could insert R_RISCV_PCREL_HI20 and
R_RISCV_PCREL_LO12_I relocation types instead of R_RISCV_CALL.
Due to RISCV relocation design, auipc and jalr pair only can relax to jal with
R_RISCV_CALL + R_RISCV_RELAX relocation types.
We expand PseudoCALL as late as encoding(RISCVMCCodeEmitter) instead of before
emitting assembly(RISCVAsmPrinter) because we want to preserve call
pseudoinstruction in assembly code. It's more readable and assembly parser
could identify call assembly and insert R_RISCV_CALL relocation type.
Differential Revision: https://reviews.llvm.org/D45859
llvm-svn: 330826
91 lines
3.0 KiB
C++
91 lines
3.0 KiB
C++
//===-- RISCVELFObjectWriter.cpp - RISCV ELF Writer -----------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MCTargetDesc/RISCVFixupKinds.h"
|
|
#include "MCTargetDesc/RISCVMCTargetDesc.h"
|
|
#include "llvm/MC/MCELFObjectWriter.h"
|
|
#include "llvm/MC/MCFixup.h"
|
|
#include "llvm/MC/MCObjectWriter.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
class RISCVELFObjectWriter : public MCELFObjectTargetWriter {
|
|
public:
|
|
RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit);
|
|
|
|
~RISCVELFObjectWriter() override;
|
|
|
|
// Return true if the given relocation must be with a symbol rather than
|
|
// section plus offset.
|
|
bool needsRelocateWithSymbol(const MCSymbol &Sym,
|
|
unsigned Type) const override {
|
|
// TODO: this is very conservative, update once RISC-V psABI requirements
|
|
// are clarified.
|
|
return true;
|
|
}
|
|
|
|
protected:
|
|
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
|
const MCFixup &Fixup, bool IsPCRel) const override;
|
|
};
|
|
}
|
|
|
|
RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit)
|
|
: MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV,
|
|
/*HasRelocationAddend*/ true) {}
|
|
|
|
RISCVELFObjectWriter::~RISCVELFObjectWriter() {}
|
|
|
|
unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
|
|
const MCValue &Target,
|
|
const MCFixup &Fixup,
|
|
bool IsPCRel) const {
|
|
// Determine the type of the relocation
|
|
switch ((unsigned)Fixup.getKind()) {
|
|
default:
|
|
llvm_unreachable("invalid fixup kind!");
|
|
case FK_Data_4:
|
|
return ELF::R_RISCV_32;
|
|
case FK_Data_8:
|
|
return ELF::R_RISCV_64;
|
|
case RISCV::fixup_riscv_hi20:
|
|
return ELF::R_RISCV_HI20;
|
|
case RISCV::fixup_riscv_lo12_i:
|
|
return ELF::R_RISCV_LO12_I;
|
|
case RISCV::fixup_riscv_lo12_s:
|
|
return ELF::R_RISCV_LO12_S;
|
|
case RISCV::fixup_riscv_pcrel_hi20:
|
|
return ELF::R_RISCV_PCREL_HI20;
|
|
case RISCV::fixup_riscv_pcrel_lo12_i:
|
|
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_jal:
|
|
return ELF::R_RISCV_JAL;
|
|
case RISCV::fixup_riscv_branch:
|
|
return ELF::R_RISCV_BRANCH;
|
|
case RISCV::fixup_riscv_rvc_jump:
|
|
return ELF::R_RISCV_RVC_JUMP;
|
|
case RISCV::fixup_riscv_rvc_branch:
|
|
return ELF::R_RISCV_RVC_BRANCH;
|
|
case RISCV::fixup_riscv_call:
|
|
return ELF::R_RISCV_CALL;
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<MCObjectWriter>
|
|
llvm::createRISCVELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI,
|
|
bool Is64Bit) {
|
|
return createELFObjectWriter(
|
|
llvm::make_unique<RISCVELFObjectWriter>(OSABI, Is64Bit), OS,
|
|
/*IsLittleEndian=*/true);
|
|
}
|