Clang and other frontends generally need the LLVM data layout string in
order to generate LLVM IR modules for LLVM. MLIR clients often need it
as well, since MLIR users often lower to LLVM IR.
Before this change, the LLVM datalayout string was computed in the
LLVM${TGT}CodeGen library in the relevant TargetMachine subclass.
However, none of the logic for computing the data layout string requires
any details of code generation. Clients who want to avoid duplicating
this information were forced to link in LLVMCodeGen and all registered
targets, leading to bloated binaries. This happened in PR #145899,
which measurably increased binary size for some of our users.
By moving this information to the TargetParser library, we
can delete the duplicate datalayout strings in Clang, and retain the
ability to generate IR for unregistered targets.
This is intended to be a very mechanical LLVM-only change, but there is
an immediately obvious follow-up to clang, which will be prepared
separately.
The vast majority of data layouts are computable with two inputs: the
triple and the "ABI name". There is only one exception, NVPTX, which has
a cl::opt to enable short device pointers. I invented a "shortptr" ABI
name to pass this option through the target independent interface.
Everything else fits. Mips is a bit awkward because it uses a special
MipsABIInfo abstraction, which includes members with codegen-like
concepts like ABI physical registers that can't live in TargetParser. I
think the string logic of looking for "n32" "n64" etc is reasonable to
duplicate. We have plenty of other minor duplication to preserve
layering.
---------
Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
Co-authored-by: Sergei Barannikov <barannikov88@gmail.com>
626 lines
25 KiB
C++
626 lines
25 KiB
C++
//===-- MipsAsmBackend.cpp - Mips Asm Backend ----------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the MipsAsmBackend class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
|
|
#include "MCTargetDesc/MipsAsmBackend.h"
|
|
#include "MCTargetDesc/MipsABIInfo.h"
|
|
#include "MCTargetDesc/MipsFixupKinds.h"
|
|
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
#include "llvm/MC/MCAsmBackend.h"
|
|
#include "llvm/MC/MCAssembler.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCELFObjectWriter.h"
|
|
#include "llvm/MC/MCObjectWriter.h"
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
|
#include "llvm/MC/MCTargetOptions.h"
|
|
#include "llvm/MC/MCValue.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/MathExtras.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace llvm;
|
|
|
|
// Prepare value for the target space for it
|
|
static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
|
|
MCContext &Ctx) {
|
|
|
|
unsigned Kind = Fixup.getKind();
|
|
|
|
// Add/subtract and shift
|
|
switch (Kind) {
|
|
default:
|
|
return 0;
|
|
case FK_Data_2:
|
|
case Mips::fixup_Mips_LO16:
|
|
case Mips::fixup_Mips_GPREL16:
|
|
case Mips::fixup_Mips_GPOFF_HI:
|
|
case Mips::fixup_Mips_GPOFF_LO:
|
|
case Mips::fixup_Mips_GOT_PAGE:
|
|
case Mips::fixup_Mips_GOT_OFST:
|
|
case Mips::fixup_Mips_GOT_DISP:
|
|
case Mips::fixup_Mips_GOT_LO16:
|
|
case Mips::fixup_Mips_CALL_LO16:
|
|
case Mips::fixup_MICROMIPS_GPOFF_HI:
|
|
case Mips::fixup_MICROMIPS_GPOFF_LO:
|
|
case Mips::fixup_MICROMIPS_LO16:
|
|
case Mips::fixup_MICROMIPS_GOT_PAGE:
|
|
case Mips::fixup_MICROMIPS_GOT_OFST:
|
|
case Mips::fixup_MICROMIPS_GOT_DISP:
|
|
case Mips::fixup_MIPS_PCLO16:
|
|
Value &= 0xffff;
|
|
break;
|
|
case Mips::fixup_Mips_AnyImm16:
|
|
if (!isInt<16>(Value) && !isUInt<16>(Value))
|
|
Ctx.reportError(Fixup.getLoc(),
|
|
"fixup value out of range [-32768, 65535]");
|
|
break;
|
|
case Mips::fixup_Mips_GPREL32:
|
|
case Mips::fixup_Mips_DTPREL32:
|
|
case Mips::fixup_Mips_DTPREL64:
|
|
case Mips::fixup_Mips_TPREL32:
|
|
case Mips::fixup_Mips_TPREL64:
|
|
case FK_Data_4:
|
|
case FK_Data_8:
|
|
case Mips::fixup_Mips_SUB:
|
|
case Mips::fixup_MICROMIPS_SUB:
|
|
break;
|
|
case Mips::fixup_Mips_PC16:
|
|
// The displacement is then divided by 4 to give us an 18 bit
|
|
// address range. Forcing a signed division because Value can be negative.
|
|
Value = (int64_t)Value / 4;
|
|
// We now check if Value can be encoded as a 16-bit signed immediate.
|
|
if (!isInt<16>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC16 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MIPS_PC19_S2:
|
|
case Mips::fixup_MICROMIPS_PC19_S2:
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t)Value / 4;
|
|
// We now check if Value can be encoded as a 19-bit signed immediate.
|
|
if (!isInt<19>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC19 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_Mips_26:
|
|
// So far we are only using this type for jumps.
|
|
// The displacement is then divided by 4 to give us an 28 bit
|
|
// address range.
|
|
Value >>= 2;
|
|
break;
|
|
case Mips::fixup_Mips_HI16:
|
|
case Mips::fixup_Mips_GOT:
|
|
case Mips::fixup_MICROMIPS_GOT16:
|
|
case Mips::fixup_Mips_GOT_HI16:
|
|
case Mips::fixup_Mips_CALL_HI16:
|
|
case Mips::fixup_MICROMIPS_HI16:
|
|
case Mips::fixup_MIPS_PCHI16:
|
|
// Get the 2nd 16-bits. Also add 1 if bit 15 is 1.
|
|
Value = ((Value + 0x8000) >> 16) & 0xffff;
|
|
break;
|
|
case Mips::fixup_Mips_HIGHER:
|
|
case Mips::fixup_MICROMIPS_HIGHER:
|
|
// Get the 3rd 16-bits.
|
|
Value = ((Value + 0x80008000LL) >> 32) & 0xffff;
|
|
break;
|
|
case Mips::fixup_Mips_HIGHEST:
|
|
case Mips::fixup_MICROMIPS_HIGHEST:
|
|
// Get the 4th 16-bits.
|
|
Value = ((Value + 0x800080008000LL) >> 48) & 0xffff;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_26_S1:
|
|
Value >>= 1;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC7_S1:
|
|
Value -= 4;
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t) Value / 2;
|
|
// We now check if Value can be encoded as a 7-bit signed immediate.
|
|
if (!isInt<7>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC7 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC10_S1:
|
|
Value -= 2;
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t) Value / 2;
|
|
// We now check if Value can be encoded as a 10-bit signed immediate.
|
|
if (!isInt<10>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC10 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC16_S1:
|
|
Value -= 4;
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t)Value / 2;
|
|
// We now check if Value can be encoded as a 16-bit signed immediate.
|
|
if (!isInt<16>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC16 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MIPS_PC18_S3:
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t)Value / 8;
|
|
// We now check if Value can be encoded as a 18-bit signed immediate.
|
|
if (!isInt<18>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC18_S3:
|
|
// Check alignment.
|
|
if ((Value & 7)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup");
|
|
}
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t)Value / 8;
|
|
// We now check if Value can be encoded as a 18-bit signed immediate.
|
|
if (!isInt<18>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MIPS_PC21_S2:
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t) Value / 4;
|
|
// We now check if Value can be encoded as a 21-bit signed immediate.
|
|
if (!isInt<21>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC21 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MIPS_PC26_S2:
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t) Value / 4;
|
|
// We now check if Value can be encoded as a 26-bit signed immediate.
|
|
if (!isInt<26>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC26 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC26_S1:
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t)Value / 2;
|
|
// We now check if Value can be encoded as a 26-bit signed immediate.
|
|
if (!isInt<26>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC26 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC21_S1:
|
|
// Forcing a signed division because Value can be negative.
|
|
Value = (int64_t)Value / 2;
|
|
// We now check if Value can be encoded as a 21-bit signed immediate.
|
|
if (!isInt<21>(Value)) {
|
|
Ctx.reportError(Fixup.getLoc(), "out of range PC21 fixup");
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return Value;
|
|
}
|
|
|
|
std::unique_ptr<MCObjectTargetWriter>
|
|
MipsAsmBackend::createObjectTargetWriter() const {
|
|
return createMipsELFObjectWriter(TheTriple, IsN32);
|
|
}
|
|
|
|
// Little-endian fixup data byte ordering:
|
|
// mips32r2: a | b | x | x
|
|
// microMIPS: x | x | a | b
|
|
|
|
static bool needsMMLEByteOrder(unsigned Kind) {
|
|
return Kind != Mips::fixup_MICROMIPS_PC10_S1 &&
|
|
Kind >= Mips::fixup_MICROMIPS_26_S1 &&
|
|
Kind < Mips::LastTargetFixupKind;
|
|
}
|
|
|
|
// Calculate index for microMIPS specific little endian byte order
|
|
static unsigned calculateMMLEIndex(unsigned i) {
|
|
assert(i <= 3 && "Index out of range!");
|
|
|
|
return (1 - i / 2) * 2 + i % 2;
|
|
}
|
|
|
|
static bool shouldForceRelocation(const MCFixup &Fixup) {
|
|
const unsigned FixupKind = Fixup.getKind();
|
|
switch (FixupKind) {
|
|
default:
|
|
return false;
|
|
// All these relocations require special processing
|
|
// at linking time. Delegate this work to a linker.
|
|
case Mips::fixup_Mips_CALL_HI16:
|
|
case Mips::fixup_Mips_CALL_LO16:
|
|
case Mips::fixup_Mips_CALL16:
|
|
case Mips::fixup_Mips_GOT:
|
|
case Mips::fixup_Mips_GOT_PAGE:
|
|
case Mips::fixup_Mips_GOT_OFST:
|
|
case Mips::fixup_Mips_GOT_DISP:
|
|
case Mips::fixup_Mips_GOT_HI16:
|
|
case Mips::fixup_Mips_GOT_LO16:
|
|
case Mips::fixup_Mips_GOTTPREL:
|
|
case Mips::fixup_Mips_DTPREL_HI:
|
|
case Mips::fixup_Mips_DTPREL_LO:
|
|
case Mips::fixup_Mips_TLSGD:
|
|
case Mips::fixup_Mips_TLSLDM:
|
|
case Mips::fixup_Mips_TPREL_HI:
|
|
case Mips::fixup_Mips_TPREL_LO:
|
|
case Mips::fixup_Mips_JALR:
|
|
case Mips::fixup_MICROMIPS_CALL16:
|
|
case Mips::fixup_MICROMIPS_GOT_DISP:
|
|
case Mips::fixup_MICROMIPS_GOT_PAGE:
|
|
case Mips::fixup_MICROMIPS_GOT_OFST:
|
|
case Mips::fixup_MICROMIPS_GOT16:
|
|
case Mips::fixup_MICROMIPS_GOTTPREL:
|
|
case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16:
|
|
case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
|
|
case Mips::fixup_MICROMIPS_TLS_GD:
|
|
case Mips::fixup_MICROMIPS_TLS_LDM:
|
|
case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
|
|
case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
|
|
case Mips::fixup_MICROMIPS_JALR:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// ApplyFixup - Apply the \p Value for given \p Fixup into the provided
|
|
/// data fragment, at the offset specified by the fixup and following the
|
|
/// fixup kind as appropriate.
|
|
void MipsAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
|
|
const MCValue &Target, uint8_t *Data,
|
|
uint64_t Value, bool IsResolved) {
|
|
if (shouldForceRelocation(Fixup))
|
|
IsResolved = false;
|
|
maybeAddReloc(F, Fixup, Target, Value, IsResolved);
|
|
MCFixupKind Kind = Fixup.getKind();
|
|
MCContext &Ctx = getContext();
|
|
Value = adjustFixupValue(Fixup, Value, Ctx);
|
|
|
|
if (!Value)
|
|
return; // Doesn't change encoding.
|
|
|
|
// Where do we start in the object
|
|
// Number of bytes we need to fixup
|
|
unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
|
|
// Used to point to big endian bytes
|
|
unsigned FullSize;
|
|
|
|
switch ((unsigned)Kind) {
|
|
case FK_Data_2:
|
|
case Mips::fixup_Mips_16:
|
|
case Mips::fixup_MICROMIPS_PC10_S1:
|
|
FullSize = 2;
|
|
break;
|
|
case FK_Data_8:
|
|
case Mips::fixup_Mips_64:
|
|
FullSize = 8;
|
|
break;
|
|
case FK_Data_4:
|
|
default:
|
|
FullSize = 4;
|
|
break;
|
|
}
|
|
|
|
// Grab current value, if any, from bits.
|
|
uint64_t CurVal = 0;
|
|
|
|
bool microMipsLEByteOrder = needsMMLEByteOrder((unsigned) Kind);
|
|
|
|
for (unsigned i = 0; i != NumBytes; ++i) {
|
|
unsigned Idx = Endian == llvm::endianness::little
|
|
? (microMipsLEByteOrder ? calculateMMLEIndex(i) : i)
|
|
: (FullSize - 1 - i);
|
|
CurVal |= (uint64_t)((uint8_t)Data[Idx]) << (i * 8);
|
|
}
|
|
|
|
uint64_t Mask = ((uint64_t)(-1) >>
|
|
(64 - getFixupKindInfo(Kind).TargetSize));
|
|
CurVal |= Value & Mask;
|
|
|
|
// Write out the fixed up bytes back to the code/data bits.
|
|
for (unsigned i = 0; i != NumBytes; ++i) {
|
|
unsigned Idx = Endian == llvm::endianness::little
|
|
? (microMipsLEByteOrder ? calculateMMLEIndex(i) : i)
|
|
: (FullSize - 1 - i);
|
|
Data[Idx] = (uint8_t)((CurVal >> (i * 8)) & 0xff);
|
|
}
|
|
}
|
|
|
|
std::optional<MCFixupKind> MipsAsmBackend::getFixupKind(StringRef Name) const {
|
|
unsigned Type = llvm::StringSwitch<unsigned>(Name)
|
|
.Case("BFD_RELOC_NONE", ELF::R_MIPS_NONE)
|
|
.Case("BFD_RELOC_16", ELF::R_MIPS_16)
|
|
.Case("BFD_RELOC_32", ELF::R_MIPS_32)
|
|
.Case("BFD_RELOC_64", ELF::R_MIPS_64)
|
|
.Default(-1u);
|
|
if (Type != -1u)
|
|
return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
|
|
|
|
return StringSwitch<std::optional<MCFixupKind>>(Name)
|
|
.Case("R_MIPS_NONE", FK_NONE)
|
|
.Case("R_MIPS_32", FK_Data_4)
|
|
.Case("R_MIPS_CALL_HI16", Mips::fixup_Mips_CALL_HI16)
|
|
.Case("R_MIPS_CALL_LO16", Mips::fixup_Mips_CALL_LO16)
|
|
.Case("R_MIPS_CALL16", Mips::fixup_Mips_CALL16)
|
|
.Case("R_MIPS_GOT16", Mips::fixup_Mips_GOT)
|
|
.Case("R_MIPS_GOT_PAGE", Mips::fixup_Mips_GOT_PAGE)
|
|
.Case("R_MIPS_GOT_OFST", Mips::fixup_Mips_GOT_OFST)
|
|
.Case("R_MIPS_GOT_DISP", Mips::fixup_Mips_GOT_DISP)
|
|
.Case("R_MIPS_GOT_HI16", Mips::fixup_Mips_GOT_HI16)
|
|
.Case("R_MIPS_GOT_LO16", Mips::fixup_Mips_GOT_LO16)
|
|
.Case("R_MIPS_TLS_GOTTPREL", Mips::fixup_Mips_GOTTPREL)
|
|
.Case("R_MIPS_TLS_DTPREL_HI16", Mips::fixup_Mips_DTPREL_HI)
|
|
.Case("R_MIPS_TLS_DTPREL_LO16", Mips::fixup_Mips_DTPREL_LO)
|
|
.Case("R_MIPS_TLS_GD", Mips::fixup_Mips_TLSGD)
|
|
.Case("R_MIPS_TLS_LDM", Mips::fixup_Mips_TLSLDM)
|
|
.Case("R_MIPS_TLS_TPREL_HI16", Mips::fixup_Mips_TPREL_HI)
|
|
.Case("R_MIPS_TLS_TPREL_LO16", Mips::fixup_Mips_TPREL_LO)
|
|
.Case("R_MICROMIPS_CALL16", Mips::fixup_MICROMIPS_CALL16)
|
|
.Case("R_MICROMIPS_GOT_DISP", Mips::fixup_MICROMIPS_GOT_DISP)
|
|
.Case("R_MICROMIPS_GOT_PAGE", Mips::fixup_MICROMIPS_GOT_PAGE)
|
|
.Case("R_MICROMIPS_GOT_OFST", Mips::fixup_MICROMIPS_GOT_OFST)
|
|
.Case("R_MICROMIPS_GOT16", Mips::fixup_MICROMIPS_GOT16)
|
|
.Case("R_MICROMIPS_TLS_GOTTPREL", Mips::fixup_MICROMIPS_GOTTPREL)
|
|
.Case("R_MICROMIPS_TLS_DTPREL_HI16",
|
|
Mips::fixup_MICROMIPS_TLS_DTPREL_HI16)
|
|
.Case("R_MICROMIPS_TLS_DTPREL_LO16",
|
|
Mips::fixup_MICROMIPS_TLS_DTPREL_LO16)
|
|
.Case("R_MICROMIPS_TLS_GD", Mips::fixup_MICROMIPS_TLS_GD)
|
|
.Case("R_MICROMIPS_TLS_LDM", Mips::fixup_MICROMIPS_TLS_LDM)
|
|
.Case("R_MICROMIPS_TLS_TPREL_HI16", Mips::fixup_MICROMIPS_TLS_TPREL_HI16)
|
|
.Case("R_MICROMIPS_TLS_TPREL_LO16", Mips::fixup_MICROMIPS_TLS_TPREL_LO16)
|
|
.Case("R_MIPS_JALR", Mips::fixup_Mips_JALR)
|
|
.Case("R_MICROMIPS_JALR", Mips::fixup_MICROMIPS_JALR)
|
|
.Default(MCAsmBackend::getFixupKind(Name));
|
|
}
|
|
|
|
MCFixupKindInfo MipsAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
|
const static MCFixupKindInfo LittleEndianInfos[] = {
|
|
// This table *must* be in same the order of fixup_* kinds in
|
|
// MipsFixupKinds.h.
|
|
//
|
|
// name offset bits flags
|
|
// clang-format off
|
|
{ "fixup_Mips_16", 0, 16, 0 },
|
|
{ "fixup_Mips_32", 0, 32, 0 },
|
|
{ "fixup_Mips_REL32", 0, 32, 0 },
|
|
{ "fixup_Mips_GPREL32", 0, 32, 0 },
|
|
{ "fixup_Mips_DTPREL32", 0, 32, 0 },
|
|
{ "fixup_Mips_DTPREL64", 0, 64, 0 },
|
|
{ "fixup_Mips_TPREL32", 0, 32, 0 },
|
|
{ "fixup_Mips_TPREL64", 0, 64, 0 },
|
|
{ "fixup_Mips_26", 0, 26, 0 },
|
|
{ "fixup_Mips_HI16", 0, 16, 0 },
|
|
{ "fixup_Mips_LO16", 0, 16, 0 },
|
|
{ "fixup_Mips_AnyImm16", 0, 16, 0 },
|
|
{ "fixup_Mips_GPREL16", 0, 16, 0 },
|
|
{ "fixup_Mips_LITERAL", 0, 16, 0 },
|
|
{ "fixup_Mips_GOT", 0, 16, 0 },
|
|
{ "fixup_Mips_PC16", 0, 16, 0 },
|
|
{ "fixup_Mips_CALL16", 0, 16, 0 },
|
|
{ "fixup_Mips_SHIFT5", 6, 5, 0 },
|
|
{ "fixup_Mips_SHIFT6", 6, 5, 0 },
|
|
{ "fixup_Mips_64", 0, 64, 0 },
|
|
{ "fixup_Mips_TLSGD", 0, 16, 0 },
|
|
{ "fixup_Mips_GOTTPREL", 0, 16, 0 },
|
|
{ "fixup_Mips_TPREL_HI", 0, 16, 0 },
|
|
{ "fixup_Mips_TPREL_LO", 0, 16, 0 },
|
|
{ "fixup_Mips_TLSLDM", 0, 16, 0 },
|
|
{ "fixup_Mips_DTPREL_HI", 0, 16, 0 },
|
|
{ "fixup_Mips_DTPREL_LO", 0, 16, 0 },
|
|
{ "fixup_Mips_Branch_PCRel", 0, 16, 0 },
|
|
{ "fixup_Mips_GPOFF_HI", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_GPOFF_HI",0, 16, 0 },
|
|
{ "fixup_Mips_GPOFF_LO", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_GPOFF_LO",0, 16, 0 },
|
|
{ "fixup_Mips_GOT_PAGE", 0, 16, 0 },
|
|
{ "fixup_Mips_GOT_OFST", 0, 16, 0 },
|
|
{ "fixup_Mips_GOT_DISP", 0, 16, 0 },
|
|
{ "fixup_Mips_HIGHER", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_HIGHER", 0, 16, 0 },
|
|
{ "fixup_Mips_HIGHEST", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_HIGHEST", 0, 16, 0 },
|
|
{ "fixup_Mips_GOT_HI16", 0, 16, 0 },
|
|
{ "fixup_Mips_GOT_LO16", 0, 16, 0 },
|
|
{ "fixup_Mips_CALL_HI16", 0, 16, 0 },
|
|
{ "fixup_Mips_CALL_LO16", 0, 16, 0 },
|
|
{ "fixup_Mips_PC18_S3", 0, 18, 0 },
|
|
{ "fixup_MIPS_PC19_S2", 0, 19, 0 },
|
|
{ "fixup_MIPS_PC21_S2", 0, 21, 0 },
|
|
{ "fixup_MIPS_PC26_S2", 0, 26, 0 },
|
|
{ "fixup_MIPS_PCHI16", 0, 16, 0 },
|
|
{ "fixup_MIPS_PCLO16", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_26_S1", 0, 26, 0 },
|
|
{ "fixup_MICROMIPS_HI16", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_LO16", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOT16", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_PC7_S1", 0, 7, 0 },
|
|
{ "fixup_MICROMIPS_PC10_S1", 0, 10, 0 },
|
|
{ "fixup_MICROMIPS_PC16_S1", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_PC26_S1", 0, 26, 0 },
|
|
{ "fixup_MICROMIPS_PC19_S2", 0, 19, 0 },
|
|
{ "fixup_MICROMIPS_PC18_S3", 0, 18, 0 },
|
|
{ "fixup_MICROMIPS_PC21_S1", 0, 21, 0 },
|
|
{ "fixup_MICROMIPS_CALL16", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOT_PAGE", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOT_OFST", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_GD", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_LDM", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_DTPREL_HI16", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_DTPREL_LO16", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOTTPREL", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_TPREL_HI16", 0, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_TPREL_LO16", 0, 16, 0 },
|
|
{ "fixup_Mips_SUB", 0, 64, 0 },
|
|
{ "fixup_MICROMIPS_SUB", 0, 64, 0 },
|
|
{ "fixup_Mips_JALR", 0, 32, 0 },
|
|
{ "fixup_MICROMIPS_JALR", 0, 32, 0 },
|
|
// clang-format on
|
|
};
|
|
static_assert(std::size(LittleEndianInfos) == Mips::NumTargetFixupKinds,
|
|
"Not all MIPS little endian fixup kinds added!");
|
|
|
|
const static MCFixupKindInfo BigEndianInfos[] = {
|
|
// This table *must* be in same the order of fixup_* kinds in
|
|
// MipsFixupKinds.h.
|
|
//
|
|
// name offset bits flags
|
|
// clang-format off
|
|
{ "fixup_Mips_16", 16, 16, 0 },
|
|
{ "fixup_Mips_32", 0, 32, 0 },
|
|
{ "fixup_Mips_REL32", 0, 32, 0 },
|
|
{ "fixup_Mips_GPREL32", 0, 32, 0 },
|
|
{ "fixup_Mips_DTPREL32", 0, 32, 0 },
|
|
{ "fixup_Mips_DTPREL64", 0, 64, 0 },
|
|
{ "fixup_Mips_TPREL32", 0, 32, 0 },
|
|
{ "fixup_Mips_TPREL64", 0, 64, 0 },
|
|
{ "fixup_Mips_26", 6, 26, 0 },
|
|
{ "fixup_Mips_HI16", 16, 16, 0 },
|
|
{ "fixup_Mips_LO16", 16, 16, 0 },
|
|
{ "fixup_Mips_AnyImm16", 16, 16, 0 },
|
|
{ "fixup_Mips_GPREL16", 16, 16, 0 },
|
|
{ "fixup_Mips_LITERAL", 16, 16, 0 },
|
|
{ "fixup_Mips_GOT", 16, 16, 0 },
|
|
{ "fixup_Mips_PC16", 16, 16, 0 },
|
|
{ "fixup_Mips_CALL16", 16, 16, 0 },
|
|
{ "fixup_Mips_SHIFT5", 21, 5, 0 },
|
|
{ "fixup_Mips_SHIFT6", 21, 5, 0 },
|
|
{ "fixup_Mips_64", 0, 64, 0 },
|
|
{ "fixup_Mips_TLSGD", 16, 16, 0 },
|
|
{ "fixup_Mips_GOTTPREL", 16, 16, 0 },
|
|
{ "fixup_Mips_TPREL_HI", 16, 16, 0 },
|
|
{ "fixup_Mips_TPREL_LO", 16, 16, 0 },
|
|
{ "fixup_Mips_TLSLDM", 16, 16, 0 },
|
|
{ "fixup_Mips_DTPREL_HI", 16, 16, 0 },
|
|
{ "fixup_Mips_DTPREL_LO", 16, 16, 0 },
|
|
{ "fixup_Mips_Branch_PCRel",16, 16, 0 },
|
|
{ "fixup_Mips_GPOFF_HI", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_GPOFF_HI", 16, 16, 0 },
|
|
{ "fixup_Mips_GPOFF_LO", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_GPOFF_LO", 16, 16, 0 },
|
|
{ "fixup_Mips_GOT_PAGE", 16, 16, 0 },
|
|
{ "fixup_Mips_GOT_OFST", 16, 16, 0 },
|
|
{ "fixup_Mips_GOT_DISP", 16, 16, 0 },
|
|
{ "fixup_Mips_HIGHER", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_HIGHER", 16, 16, 0 },
|
|
{ "fixup_Mips_HIGHEST", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_HIGHEST",16, 16, 0 },
|
|
{ "fixup_Mips_GOT_HI16", 16, 16, 0 },
|
|
{ "fixup_Mips_GOT_LO16", 16, 16, 0 },
|
|
{ "fixup_Mips_CALL_HI16", 16, 16, 0 },
|
|
{ "fixup_Mips_CALL_LO16", 16, 16, 0 },
|
|
{ "fixup_Mips_PC18_S3", 14, 18, 0 },
|
|
{ "fixup_MIPS_PC19_S2", 13, 19, 0 },
|
|
{ "fixup_MIPS_PC21_S2", 11, 21, 0 },
|
|
{ "fixup_MIPS_PC26_S2", 6, 26, 0 },
|
|
{ "fixup_MIPS_PCHI16", 16, 16, 0 },
|
|
{ "fixup_MIPS_PCLO16", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_26_S1", 6, 26, 0 },
|
|
{ "fixup_MICROMIPS_HI16", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_LO16", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOT16", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_PC7_S1", 9, 7, 0 },
|
|
{ "fixup_MICROMIPS_PC10_S1", 6, 10, 0 },
|
|
{ "fixup_MICROMIPS_PC16_S1",16, 16, 0 },
|
|
{ "fixup_MICROMIPS_PC26_S1", 6, 26, 0 },
|
|
{ "fixup_MICROMIPS_PC19_S2",13, 19, 0 },
|
|
{ "fixup_MICROMIPS_PC18_S3",14, 18, 0 },
|
|
{ "fixup_MICROMIPS_PC21_S1",11, 21, 0 },
|
|
{ "fixup_MICROMIPS_CALL16", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOT_PAGE", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOT_OFST", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_GD", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_LDM", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_DTPREL_HI16", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_DTPREL_LO16", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_GOTTPREL", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_TPREL_HI16", 16, 16, 0 },
|
|
{ "fixup_MICROMIPS_TLS_TPREL_LO16", 16, 16, 0 },
|
|
{ "fixup_Mips_SUB", 0, 64, 0 },
|
|
{ "fixup_MICROMIPS_SUB", 0, 64, 0 },
|
|
{ "fixup_Mips_JALR", 0, 32, 0 },
|
|
{ "fixup_MICROMIPS_JALR", 0, 32, 0 },
|
|
// clang-format on
|
|
};
|
|
static_assert(std::size(BigEndianInfos) == Mips::NumTargetFixupKinds,
|
|
"Not all MIPS big endian fixup kinds added!");
|
|
|
|
if (mc::isRelocation(Kind))
|
|
return {};
|
|
if (Kind < FirstTargetFixupKind)
|
|
return MCAsmBackend::getFixupKindInfo(Kind);
|
|
|
|
assert(unsigned(Kind - FirstTargetFixupKind) < Mips::NumTargetFixupKinds &&
|
|
"Invalid kind!");
|
|
|
|
if (Endian == llvm::endianness::little)
|
|
return LittleEndianInfos[Kind - FirstTargetFixupKind];
|
|
return BigEndianInfos[Kind - FirstTargetFixupKind];
|
|
}
|
|
|
|
/// WriteNopData - Write an (optimal) nop sequence of Count bytes
|
|
/// to the given output. If the target cannot generate such a sequence,
|
|
/// it should return an error.
|
|
///
|
|
/// \return - True on success.
|
|
bool MipsAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
|
|
const MCSubtargetInfo *STI) const {
|
|
// Check for a less than instruction size number of bytes
|
|
// FIXME: 16 bit instructions are not handled yet here.
|
|
// We shouldn't be using a hard coded number for instruction size.
|
|
|
|
// If the count is not 4-byte aligned, we must be writing data into the text
|
|
// section (otherwise we have unaligned instructions, and thus have far
|
|
// bigger problems), so just write zeros instead.
|
|
OS.write_zeros(Count);
|
|
return true;
|
|
}
|
|
|
|
namespace {
|
|
|
|
class WindowsMipsAsmBackend : public MipsAsmBackend {
|
|
public:
|
|
WindowsMipsAsmBackend(const Target &T, const MCRegisterInfo &MRI,
|
|
const MCSubtargetInfo &STI)
|
|
: MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), false) {}
|
|
|
|
std::unique_ptr<MCObjectTargetWriter>
|
|
createObjectTargetWriter() const override {
|
|
return createMipsWinCOFFObjectWriter();
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
MCAsmBackend *llvm::createMipsAsmBackend(const Target &T,
|
|
const MCSubtargetInfo &STI,
|
|
const MCRegisterInfo &MRI,
|
|
const MCTargetOptions &Options) {
|
|
const Triple &TheTriple = STI.getTargetTriple();
|
|
if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
|
|
return new WindowsMipsAsmBackend(T, MRI, STI);
|
|
|
|
MipsABIInfo ABI = MipsABIInfo::computeTargetABI(STI.getTargetTriple(),
|
|
Options.getABIName());
|
|
return new MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(),
|
|
ABI.IsN32());
|
|
}
|