2017-02-09 06:23:19 +08:00
|
|
|
//===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===//
|
2010-02-22 05:53:53 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-02-22 05:53:53 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/MC/MCAsmBackend.h"
|
2017-02-09 06:23:19 +08:00
|
|
|
#include "llvm/ADT/None.h"
|
2013-07-15 12:27:47 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2017-10-24 14:16:03 +08:00
|
|
|
#include "llvm/MC/MCCodePadder.h"
|
2018-05-22 03:20:29 +08:00
|
|
|
#include "llvm/MC/MCELFObjectWriter.h"
|
2012-03-26 14:58:25 +08:00
|
|
|
#include "llvm/MC/MCFixupKindInfo.h"
|
2018-05-22 03:20:29 +08:00
|
|
|
#include "llvm/MC/MCMachObjectWriter.h"
|
|
|
|
#include "llvm/MC/MCObjectWriter.h"
|
|
|
|
#include "llvm/MC/MCWasmObjectWriter.h"
|
|
|
|
#include "llvm/MC/MCWinCOFFObjectWriter.h"
|
2017-02-09 06:23:19 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
|
2010-02-22 05:53:53 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2018-05-22 01:57:19 +08:00
|
|
|
MCAsmBackend::MCAsmBackend(support::endianness Endian)
|
|
|
|
: CodePadder(new MCCodePadder()), Endian(Endian) {}
|
2010-02-22 05:53:53 +08:00
|
|
|
|
2017-02-09 06:23:19 +08:00
|
|
|
MCAsmBackend::~MCAsmBackend() = default;
|
2018-05-22 03:20:29 +08:00
|
|
|
|
|
|
|
std::unique_ptr<MCObjectWriter>
|
|
|
|
MCAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
|
|
|
|
auto TW = createObjectTargetWriter();
|
|
|
|
switch (TW->getFormat()) {
|
|
|
|
case Triple::ELF:
|
|
|
|
return createELFObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)), OS,
|
|
|
|
Endian == support::little);
|
|
|
|
case Triple::MachO:
|
|
|
|
return createMachObjectWriter(cast<MCMachObjectTargetWriter>(std::move(TW)),
|
|
|
|
OS, Endian == support::little);
|
|
|
|
case Triple::COFF:
|
|
|
|
return createWinCOFFObjectWriter(
|
|
|
|
cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS);
|
|
|
|
case Triple::Wasm:
|
|
|
|
return createWasmObjectWriter(cast<MCWasmObjectTargetWriter>(std::move(TW)),
|
|
|
|
OS);
|
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected object format");
|
|
|
|
}
|
|
|
|
}
|
2018-05-22 03:44:54 +08:00
|
|
|
|
|
|
|
std::unique_ptr<MCObjectWriter>
|
|
|
|
MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
|
|
|
|
raw_pwrite_stream &DwoOS) const {
|
|
|
|
auto TW = createObjectTargetWriter();
|
|
|
|
if (TW->getFormat() != Triple::ELF)
|
|
|
|
report_fatal_error("dwo only supported with ELF");
|
|
|
|
return createELFDwoObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)),
|
|
|
|
OS, DwoOS, Endian == support::little);
|
|
|
|
}
|
2010-12-16 11:20:06 +08:00
|
|
|
|
2016-01-20 07:05:27 +08:00
|
|
|
Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
|
|
|
|
return None;
|
2015-11-12 21:33:00 +08:00
|
|
|
}
|
|
|
|
|
2015-05-31 02:42:22 +08:00
|
|
|
const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
2010-12-16 11:20:06 +08:00
|
|
|
static const MCFixupKindInfo Builtins[] = {
|
2015-05-31 02:42:22 +08:00
|
|
|
{"FK_Data_1", 0, 8, 0},
|
|
|
|
{"FK_Data_2", 0, 16, 0},
|
|
|
|
{"FK_Data_4", 0, 32, 0},
|
|
|
|
{"FK_Data_8", 0, 64, 0},
|
|
|
|
{"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
|
|
|
|
{"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
|
|
|
|
{"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
|
|
|
|
{"FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
|
|
|
|
{"FK_GPRel_1", 0, 8, 0},
|
|
|
|
{"FK_GPRel_2", 0, 16, 0},
|
|
|
|
{"FK_GPRel_4", 0, 32, 0},
|
|
|
|
{"FK_GPRel_8", 0, 64, 0},
|
2016-08-23 00:18:42 +08:00
|
|
|
{"FK_DTPRel_4", 0, 32, 0},
|
|
|
|
{"FK_DTPRel_8", 0, 64, 0},
|
|
|
|
{"FK_TPRel_4", 0, 32, 0},
|
|
|
|
{"FK_TPRel_8", 0, 64, 0},
|
2015-05-31 02:42:22 +08:00
|
|
|
{"FK_SecRel_1", 0, 8, 0},
|
|
|
|
{"FK_SecRel_2", 0, 16, 0},
|
|
|
|
{"FK_SecRel_4", 0, 32, 0},
|
[RISCV] Add symbol diff relocation support for RISC-V
For RISC-V it is desirable to have relaxation happen in the linker once
addresses are known, and as such the size between two instructions/byte
sequences in a section could change.
For most assembler expressions, this is fine, as the absolute address results
in the expression being converted to a fixup, and finally relocations.
However, for expressions such as .quad .L2-.L1, the assembler folds this down
to a constant once fragments are laid out, under the assumption that the
difference can no longer change, although in the case of linker relaxation the
differences can change at link time, so the constant is incorrect. One place
where this commonly appears is in debug information, where the size of a
function expression is in a form similar to the above.
This patch extends the assembler to allow an AsmBackend to declare that it
does not want the assembler to fold down this expression, and instead generate
a pair of relocations that allow the linker to carry out the calculation. In
this case, the expression is not folded, but when it comes to emitting a
fixup, the generic FK_Data_* fixups are converted into a pair, one for the
addition half, one for the subtraction, and this is passed to the relocation
generating methods as usual. I have named these FK_Data_Add_* and
FK_Data_Sub_* to indicate which half these are for.
For RISC-V, which supports this via e.g. the R_RISCV_ADD64, R_RISCV_SUB64 pair
of relocations, these are also set to always emit relocations relative to
local symbols rather than section offsets. This is to deal with the fact that
if relocations were calculated on e.g. .text+8 and .text+4, the result 12
would be stored rather than 4 as both addends are added in the linker.
Differential Revision: https://reviews.llvm.org/D45181
Patch by Simon Cook.
llvm-svn: 333079
2018-05-23 20:36:18 +08:00
|
|
|
{"FK_SecRel_8", 0, 64, 0},
|
|
|
|
{"FK_Data_Add_1", 0, 8, 0},
|
|
|
|
{"FK_Data_Add_2", 0, 16, 0},
|
|
|
|
{"FK_Data_Add_4", 0, 32, 0},
|
|
|
|
{"FK_Data_Add_8", 0, 64, 0},
|
|
|
|
{"FK_Data_Sub_1", 0, 8, 0},
|
|
|
|
{"FK_Data_Sub_2", 0, 16, 0},
|
|
|
|
{"FK_Data_Sub_4", 0, 32, 0},
|
|
|
|
{"FK_Data_Sub_8", 0, 64, 0}};
|
2012-05-11 09:41:30 +08:00
|
|
|
|
2013-07-15 12:27:47 +08:00
|
|
|
assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind");
|
2010-12-16 11:20:06 +08:00
|
|
|
return Builtins[Kind];
|
|
|
|
}
|
2015-05-31 02:42:22 +08:00
|
|
|
|
|
|
|
bool MCAsmBackend::fixupNeedsRelaxationAdvanced(
|
|
|
|
const MCFixup &Fixup, bool Resolved, uint64_t Value,
|
2018-05-18 14:42:21 +08:00
|
|
|
const MCRelaxableFragment *DF, const MCAsmLayout &Layout,
|
|
|
|
const bool WasForced) const {
|
2015-05-31 02:42:22 +08:00
|
|
|
if (!Resolved)
|
|
|
|
return true;
|
|
|
|
return fixupNeedsRelaxation(Fixup, Value, DF, Layout);
|
|
|
|
}
|
2017-10-24 14:16:03 +08:00
|
|
|
|
|
|
|
void MCAsmBackend::handleCodePaddingBasicBlockStart(
|
|
|
|
MCObjectStreamer *OS, const MCCodePaddingContext &Context) {
|
|
|
|
CodePadder->handleBasicBlockStart(OS, Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmBackend::handleCodePaddingBasicBlockEnd(
|
|
|
|
const MCCodePaddingContext &Context) {
|
|
|
|
CodePadder->handleBasicBlockEnd(Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmBackend::handleCodePaddingInstructionBegin(const MCInst &Inst) {
|
|
|
|
CodePadder->handleInstructionBegin(Inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmBackend::handleCodePaddingInstructionEnd(const MCInst &Inst) {
|
|
|
|
CodePadder->handleInstructionEnd(Inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MCAsmBackend::relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout) {
|
|
|
|
return CodePadder->relaxFragment(PF, Layout);
|
2018-05-18 14:42:21 +08:00
|
|
|
}
|