aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp')
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp170
1 files changed, 169 insertions, 1 deletions
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index bb1f1cc7f49a..b93197e713e5 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -9,6 +9,7 @@
#include "RISCVAsmBackend.h"
#include "RISCVMCExpr.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
@@ -18,7 +19,10 @@
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -30,6 +34,9 @@ Optional<MCFixupKind> RISCVAsmBackend::getFixupKind(StringRef Name) const {
#define ELF_RELOC(X, Y) .Case(#X, Y)
#include "llvm/BinaryFormat/ELFRelocs/RISCV.def"
#undef ELF_RELOC
+ .Case("BFD_RELOC_NONE", ELF::R_RISCV_NONE)
+ .Case("BFD_RELOC_32", ELF::R_RISCV_32)
+ .Case("BFD_RELOC_64", ELF::R_RISCV_64)
.Default(-1u);
if (Type != -1u)
return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
@@ -67,7 +74,26 @@ RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_riscv_relax", 0, 0, 0},
- {"fixup_riscv_align", 0, 0, 0}};
+ {"fixup_riscv_align", 0, 0, 0},
+
+ {"fixup_riscv_set_8", 0, 8, 0},
+ {"fixup_riscv_add_8", 0, 8, 0},
+ {"fixup_riscv_sub_8", 0, 8, 0},
+
+ {"fixup_riscv_set_16", 0, 16, 0},
+ {"fixup_riscv_add_16", 0, 16, 0},
+ {"fixup_riscv_sub_16", 0, 16, 0},
+
+ {"fixup_riscv_set_32", 0, 32, 0},
+ {"fixup_riscv_add_32", 0, 32, 0},
+ {"fixup_riscv_sub_32", 0, 32, 0},
+
+ {"fixup_riscv_add_64", 0, 64, 0},
+ {"fixup_riscv_sub_64", 0, 64, 0},
+
+ {"fixup_riscv_set_6b", 2, 6, 0},
+ {"fixup_riscv_sub_6b", 2, 6, 0},
+ };
static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds,
"Not all fixup kinds added to Infos array");
@@ -176,6 +202,135 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
Inst = std::move(Res);
}
+bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
+ MCAsmLayout &Layout,
+ bool &WasRelaxed) const {
+ MCContext &C = Layout.getAssembler().getContext();
+
+ int64_t LineDelta = DF.getLineDelta();
+ const MCExpr &AddrDelta = DF.getAddrDelta();
+ SmallVectorImpl<char> &Data = DF.getContents();
+ SmallVectorImpl<MCFixup> &Fixups = DF.getFixups();
+ size_t OldSize = Data.size();
+
+ int64_t Value;
+ bool IsAbsolute = AddrDelta.evaluateKnownAbsolute(Value, Layout);
+ assert(IsAbsolute && "CFA with invalid expression");
+ (void)IsAbsolute;
+
+ Data.clear();
+ Fixups.clear();
+ raw_svector_ostream OS(Data);
+
+ // INT64_MAX is a signal that this is actually a DW_LNE_end_sequence.
+ if (LineDelta != INT64_MAX) {
+ OS << uint8_t(dwarf::DW_LNS_advance_line);
+ encodeSLEB128(LineDelta, OS);
+ }
+
+ unsigned Offset;
+ std::pair<unsigned, unsigned> Fixup;
+
+ // According to the DWARF specification, the `DW_LNS_fixed_advance_pc` opcode
+ // takes a single unsigned half (unencoded) operand. The maximum encodable
+ // value is therefore 65535. Set a conservative upper bound for relaxation.
+ if (Value > 60000) {
+ unsigned PtrSize = C.getAsmInfo()->getCodePointerSize();
+
+ OS << uint8_t(dwarf::DW_LNS_extended_op);
+ encodeULEB128(PtrSize + 1, OS);
+
+ OS << uint8_t(dwarf::DW_LNE_set_address);
+ Offset = OS.tell();
+ Fixup = PtrSize == 4 ? std::make_pair(RISCV::fixup_riscv_add_32,
+ RISCV::fixup_riscv_sub_32)
+ : std::make_pair(RISCV::fixup_riscv_add_64,
+ RISCV::fixup_riscv_sub_64);
+ OS.write_zeros(PtrSize);
+ } else {
+ OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
+ Offset = OS.tell();
+ Fixup = {RISCV::fixup_riscv_add_16, RISCV::fixup_riscv_sub_16};
+ support::endian::write<uint16_t>(OS, 0, support::little);
+ }
+
+ const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
+ Fixups.push_back(MCFixup::create(
+ Offset, MBE.getLHS(), static_cast<MCFixupKind>(std::get<0>(Fixup))));
+ Fixups.push_back(MCFixup::create(
+ Offset, MBE.getRHS(), static_cast<MCFixupKind>(std::get<1>(Fixup))));
+
+ if (LineDelta == INT64_MAX) {
+ OS << uint8_t(dwarf::DW_LNS_extended_op);
+ OS << uint8_t(1);
+ OS << uint8_t(dwarf::DW_LNE_end_sequence);
+ } else {
+ OS << uint8_t(dwarf::DW_LNS_copy);
+ }
+
+ WasRelaxed = OldSize != Data.size();
+ return true;
+}
+
+bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF,
+ MCAsmLayout &Layout,
+ bool &WasRelaxed) const {
+
+ const MCExpr &AddrDelta = DF.getAddrDelta();
+ SmallVectorImpl<char> &Data = DF.getContents();
+ SmallVectorImpl<MCFixup> &Fixups = DF.getFixups();
+ size_t OldSize = Data.size();
+
+ int64_t Value;
+ bool IsAbsolute = AddrDelta.evaluateKnownAbsolute(Value, Layout);
+ assert(IsAbsolute && "CFA with invalid expression");
+ (void)IsAbsolute;
+
+ Data.clear();
+ Fixups.clear();
+ raw_svector_ostream OS(Data);
+
+ assert(
+ Layout.getAssembler().getContext().getAsmInfo()->getMinInstAlignment() ==
+ 1 &&
+ "expected 1-byte alignment");
+ if (Value == 0) {
+ WasRelaxed = OldSize != Data.size();
+ return true;
+ }
+
+ auto AddFixups = [&Fixups, &AddrDelta](unsigned Offset,
+ std::pair<unsigned, unsigned> Fixup) {
+ const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
+ Fixups.push_back(MCFixup::create(
+ Offset, MBE.getLHS(), static_cast<MCFixupKind>(std::get<0>(Fixup))));
+ Fixups.push_back(MCFixup::create(
+ Offset, MBE.getRHS(), static_cast<MCFixupKind>(std::get<1>(Fixup))));
+ };
+
+ if (isUIntN(6, Value)) {
+ OS << uint8_t(dwarf::DW_CFA_advance_loc);
+ AddFixups(0, {RISCV::fixup_riscv_set_6b, RISCV::fixup_riscv_sub_6b});
+ } else if (isUInt<8>(Value)) {
+ OS << uint8_t(dwarf::DW_CFA_advance_loc1);
+ support::endian::write<uint8_t>(OS, 0, support::little);
+ AddFixups(1, {RISCV::fixup_riscv_set_8, RISCV::fixup_riscv_sub_8});
+ } else if (isUInt<16>(Value)) {
+ OS << uint8_t(dwarf::DW_CFA_advance_loc2);
+ support::endian::write<uint16_t>(OS, 0, support::little);
+ AddFixups(1, {RISCV::fixup_riscv_set_16, RISCV::fixup_riscv_sub_16});
+ } else if (isUInt<32>(Value)) {
+ OS << uint8_t(dwarf::DW_CFA_advance_loc4);
+ support::endian::write<uint32_t>(OS, 0, support::little);
+ AddFixups(1, {RISCV::fixup_riscv_set_32, RISCV::fixup_riscv_sub_32});
+ } else {
+ llvm_unreachable("unsupported CFA encoding");
+ }
+
+ WasRelaxed = OldSize != Data.size();
+ return true;
+}
+
// Given a compressed control flow instruction this function returns
// the expanded instruction.
unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
@@ -224,12 +379,25 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case RISCV::fixup_riscv_tls_got_hi20:
case RISCV::fixup_riscv_tls_gd_hi20:
llvm_unreachable("Relocation should be unconditionally forced\n");
+ case RISCV::fixup_riscv_set_8:
+ case RISCV::fixup_riscv_add_8:
+ case RISCV::fixup_riscv_sub_8:
+ case RISCV::fixup_riscv_set_16:
+ case RISCV::fixup_riscv_add_16:
+ case RISCV::fixup_riscv_sub_16:
+ case RISCV::fixup_riscv_set_32:
+ case RISCV::fixup_riscv_add_32:
+ case RISCV::fixup_riscv_sub_32:
+ case RISCV::fixup_riscv_add_64:
+ case RISCV::fixup_riscv_sub_64:
case FK_Data_1:
case FK_Data_2:
case FK_Data_4:
case FK_Data_8:
case FK_Data_6b:
return Value;
+ case RISCV::fixup_riscv_set_6b:
+ return Value & 0x03;
case RISCV::fixup_riscv_lo12_i:
case RISCV::fixup_riscv_pcrel_lo12_i:
case RISCV::fixup_riscv_tprel_lo12_i: