mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-27 02:31:09 +00:00
The operand flag word for ISD::INLINEASM nodes now contains a 15-bit memory constraint ID when the operand kind is Kind_Mem. This constraint ID is a numeric equivalent to the constraint code string and is converted with a target specific hook in TargetLowering. This patch maps all memory constraints to InlineAsm::Constraint_m so there is no functional change at this point. It just proves that using these previously unused bits in the encoding of the flag word doesn't break anything. The next patch will make each target preserve the current mapping of everything to Constraint_m for itself while changing the target independent implementation of the hook to return Constraint_Unknown appropriately. Each target will then be adapted in separate patches to use appropriate Constraint_* values. PR22883 was caused the matching operands copying the whole of the operand flags for the matched operand. This included the constraint id which needed to be replaced with the operand number. This has been fixed with a conversion function. Following on from this, matching operands also used the operand number as the constraint id. This has been fixed by looking up the matched operand and taking it from there. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232165 91177308-0d34-0410-b5e6-96231b3b80d8
276 lines
8.3 KiB
C++
276 lines
8.3 KiB
C++
//===-- MipsELFObjectWriter.cpp - Mips 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/MipsBaseInfo.h"
|
|
#include "MCTargetDesc/MipsFixupKinds.h"
|
|
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
|
#include "llvm/MC/MCAssembler.h"
|
|
#include "llvm/MC/MCELF.h"
|
|
#include "llvm/MC/MCELFObjectWriter.h"
|
|
#include "llvm/MC/MCExpr.h"
|
|
#include "llvm/MC/MCSection.h"
|
|
#include "llvm/MC/MCValue.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include <list>
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
class MipsELFObjectWriter : public MCELFObjectTargetWriter {
|
|
public:
|
|
MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
|
|
bool _isN64, bool IsLittleEndian);
|
|
|
|
virtual ~MipsELFObjectWriter();
|
|
|
|
unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
|
|
bool IsPCRel) const override;
|
|
bool needsRelocateWithSymbol(const MCSymbolData &SD,
|
|
unsigned Type) const override;
|
|
};
|
|
}
|
|
|
|
MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
|
|
bool _isN64, bool IsLittleEndian)
|
|
: MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS,
|
|
/*HasRelocationAddend*/ (_isN64) ? true : false,
|
|
/*IsN64*/ _isN64) {}
|
|
|
|
MipsELFObjectWriter::~MipsELFObjectWriter() {}
|
|
|
|
unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
|
|
const MCFixup &Fixup,
|
|
bool IsPCRel) const {
|
|
// determine the type of the relocation
|
|
unsigned Type = (unsigned)ELF::R_MIPS_NONE;
|
|
unsigned Kind = (unsigned)Fixup.getKind();
|
|
|
|
switch (Kind) {
|
|
default:
|
|
llvm_unreachable("invalid fixup kind!");
|
|
case Mips::fixup_Mips_32:
|
|
case FK_Data_4:
|
|
Type = ELF::R_MIPS_32;
|
|
break;
|
|
case Mips::fixup_Mips_64:
|
|
case FK_Data_8:
|
|
Type = ELF::R_MIPS_64;
|
|
break;
|
|
case FK_GPRel_4:
|
|
if (isN64()) {
|
|
Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type);
|
|
Type = setRType2((unsigned)ELF::R_MIPS_64, Type);
|
|
Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type);
|
|
}
|
|
else
|
|
Type = ELF::R_MIPS_GPREL32;
|
|
break;
|
|
case Mips::fixup_Mips_GPREL16:
|
|
Type = ELF::R_MIPS_GPREL16;
|
|
break;
|
|
case Mips::fixup_Mips_26:
|
|
Type = ELF::R_MIPS_26;
|
|
break;
|
|
case Mips::fixup_Mips_CALL16:
|
|
Type = ELF::R_MIPS_CALL16;
|
|
break;
|
|
case Mips::fixup_Mips_GOT_Global:
|
|
case Mips::fixup_Mips_GOT_Local:
|
|
Type = ELF::R_MIPS_GOT16;
|
|
break;
|
|
case Mips::fixup_Mips_HI16:
|
|
Type = ELF::R_MIPS_HI16;
|
|
break;
|
|
case Mips::fixup_Mips_LO16:
|
|
Type = ELF::R_MIPS_LO16;
|
|
break;
|
|
case Mips::fixup_Mips_TLSGD:
|
|
Type = ELF::R_MIPS_TLS_GD;
|
|
break;
|
|
case Mips::fixup_Mips_GOTTPREL:
|
|
Type = ELF::R_MIPS_TLS_GOTTPREL;
|
|
break;
|
|
case Mips::fixup_Mips_TPREL_HI:
|
|
Type = ELF::R_MIPS_TLS_TPREL_HI16;
|
|
break;
|
|
case Mips::fixup_Mips_TPREL_LO:
|
|
Type = ELF::R_MIPS_TLS_TPREL_LO16;
|
|
break;
|
|
case Mips::fixup_Mips_TLSLDM:
|
|
Type = ELF::R_MIPS_TLS_LDM;
|
|
break;
|
|
case Mips::fixup_Mips_DTPREL_HI:
|
|
Type = ELF::R_MIPS_TLS_DTPREL_HI16;
|
|
break;
|
|
case Mips::fixup_Mips_DTPREL_LO:
|
|
Type = ELF::R_MIPS_TLS_DTPREL_LO16;
|
|
break;
|
|
case Mips::fixup_Mips_Branch_PCRel:
|
|
case Mips::fixup_Mips_PC16:
|
|
Type = ELF::R_MIPS_PC16;
|
|
break;
|
|
case Mips::fixup_Mips_GOT_PAGE:
|
|
Type = ELF::R_MIPS_GOT_PAGE;
|
|
break;
|
|
case Mips::fixup_Mips_GOT_OFST:
|
|
Type = ELF::R_MIPS_GOT_OFST;
|
|
break;
|
|
case Mips::fixup_Mips_GOT_DISP:
|
|
Type = ELF::R_MIPS_GOT_DISP;
|
|
break;
|
|
case Mips::fixup_Mips_GPOFF_HI:
|
|
Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
|
|
Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
|
|
Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type);
|
|
break;
|
|
case Mips::fixup_Mips_GPOFF_LO:
|
|
Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
|
|
Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
|
|
Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type);
|
|
break;
|
|
case Mips::fixup_Mips_HIGHER:
|
|
Type = ELF::R_MIPS_HIGHER;
|
|
break;
|
|
case Mips::fixup_Mips_HIGHEST:
|
|
Type = ELF::R_MIPS_HIGHEST;
|
|
break;
|
|
case Mips::fixup_Mips_GOT_HI16:
|
|
Type = ELF::R_MIPS_GOT_HI16;
|
|
break;
|
|
case Mips::fixup_Mips_GOT_LO16:
|
|
Type = ELF::R_MIPS_GOT_LO16;
|
|
break;
|
|
case Mips::fixup_Mips_CALL_HI16:
|
|
Type = ELF::R_MIPS_CALL_HI16;
|
|
break;
|
|
case Mips::fixup_Mips_CALL_LO16:
|
|
Type = ELF::R_MIPS_CALL_LO16;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_26_S1:
|
|
Type = ELF::R_MICROMIPS_26_S1;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_HI16:
|
|
Type = ELF::R_MICROMIPS_HI16;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_LO16:
|
|
Type = ELF::R_MICROMIPS_LO16;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_GOT16:
|
|
Type = ELF::R_MICROMIPS_GOT16;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC7_S1:
|
|
Type = ELF::R_MICROMIPS_PC7_S1;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC10_S1:
|
|
Type = ELF::R_MICROMIPS_PC10_S1;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_PC16_S1:
|
|
Type = ELF::R_MICROMIPS_PC16_S1;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_CALL16:
|
|
Type = ELF::R_MICROMIPS_CALL16;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_GOT_DISP:
|
|
Type = ELF::R_MICROMIPS_GOT_DISP;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_GOT_PAGE:
|
|
Type = ELF::R_MICROMIPS_GOT_PAGE;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_GOT_OFST:
|
|
Type = ELF::R_MICROMIPS_GOT_OFST;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_TLS_GD:
|
|
Type = ELF::R_MICROMIPS_TLS_GD;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_TLS_LDM:
|
|
Type = ELF::R_MICROMIPS_TLS_LDM;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16:
|
|
Type = ELF::R_MICROMIPS_TLS_DTPREL_HI16;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
|
|
Type = ELF::R_MICROMIPS_TLS_DTPREL_LO16;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
|
|
Type = ELF::R_MICROMIPS_TLS_TPREL_HI16;
|
|
break;
|
|
case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
|
|
Type = ELF::R_MICROMIPS_TLS_TPREL_LO16;
|
|
break;
|
|
case Mips::fixup_MIPS_PC19_S2:
|
|
Type = ELF::R_MIPS_PC19_S2;
|
|
break;
|
|
case Mips::fixup_MIPS_PC18_S3:
|
|
Type = ELF::R_MIPS_PC18_S3;
|
|
break;
|
|
case Mips::fixup_MIPS_PC21_S2:
|
|
Type = ELF::R_MIPS_PC21_S2;
|
|
break;
|
|
case Mips::fixup_MIPS_PC26_S2:
|
|
Type = ELF::R_MIPS_PC26_S2;
|
|
break;
|
|
case Mips::fixup_MIPS_PCHI16:
|
|
Type = ELF::R_MIPS_PCHI16;
|
|
break;
|
|
case Mips::fixup_MIPS_PCLO16:
|
|
Type = ELF::R_MIPS_PCLO16;
|
|
break;
|
|
}
|
|
return Type;
|
|
}
|
|
|
|
bool
|
|
MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD,
|
|
unsigned Type) const {
|
|
// FIXME: This is extremely conservative. This really needs to use a
|
|
// whitelist with a clear explanation for why each realocation needs to
|
|
// point to the symbol, not to the section.
|
|
switch (Type) {
|
|
default:
|
|
return true;
|
|
|
|
case ELF::R_MIPS_GOT16:
|
|
case ELF::R_MIPS16_GOT16:
|
|
case ELF::R_MICROMIPS_GOT16:
|
|
llvm_unreachable("Should have been handled already");
|
|
|
|
// These relocations might be paired with another relocation. The pairing is
|
|
// done by the static linker by matching the symbol. Since we only see one
|
|
// relocation at a time, we have to force them to relocate with a symbol to
|
|
// avoid ending up with a pair where one points to a section and another
|
|
// points to a symbol.
|
|
case ELF::R_MIPS_HI16:
|
|
case ELF::R_MIPS16_HI16:
|
|
case ELF::R_MICROMIPS_HI16:
|
|
case ELF::R_MIPS_LO16:
|
|
case ELF::R_MIPS16_LO16:
|
|
case ELF::R_MICROMIPS_LO16:
|
|
return true;
|
|
|
|
case ELF::R_MIPS_32:
|
|
if (MCELF::getOther(SD) & (ELF::STO_MIPS_MICROMIPS >> 2))
|
|
return true;
|
|
// falltrough
|
|
case ELF::R_MIPS_26:
|
|
case ELF::R_MIPS_64:
|
|
case ELF::R_MIPS_GPREL16:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS,
|
|
uint8_t OSABI,
|
|
bool IsLittleEndian,
|
|
bool Is64Bit) {
|
|
MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI,
|
|
(Is64Bit) ? true : false,
|
|
IsLittleEndian);
|
|
return createELFObjectWriter(MOTW, OS, IsLittleEndian);
|
|
}
|