mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
47606c47b1
In https://reviews.llvm.org/rG2193347e72fa , a cpp file is accidentally included instead of its header file counterpart. This patch fixes this error.
260 lines
9.2 KiB
C++
260 lines
9.2 KiB
C++
//===-- M68kSubtarget.cpp - M68k Subtarget Information ------*- C++ -*-===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file implements the M68k specific subclass of TargetSubtargetInfo.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "M68kSubtarget.h"
|
|
#include "GlSel/M68kCallLowering.h"
|
|
#include "GlSel/M68kLegalizerInfo.h"
|
|
#include "GlSel/M68kRegisterBankInfo.h"
|
|
|
|
#include "M68k.h"
|
|
#include "M68kMachineFunction.h"
|
|
#include "M68kRegisterInfo.h"
|
|
#include "M68kTargetMachine.h"
|
|
|
|
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
|
#include "llvm/IR/Attributes.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "m68k-subtarget"
|
|
|
|
#define GET_SUBTARGETINFO_TARGET_DESC
|
|
#define GET_SUBTARGETINFO_CTOR
|
|
#include "M68kGenSubtargetInfo.inc"
|
|
|
|
extern bool FixGlobalBaseReg;
|
|
|
|
/// Select the M68k CPU for the given triple and cpu name.
|
|
static StringRef selectM68kCPU(Triple TT, StringRef CPU) {
|
|
if (CPU.empty() || CPU == "generic") {
|
|
CPU = "M68000";
|
|
}
|
|
return CPU;
|
|
}
|
|
|
|
void M68kSubtarget::anchor() {}
|
|
|
|
M68kSubtarget::M68kSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
|
const M68kTargetMachine &TM)
|
|
: M68kGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
|
|
UserReservedRegister(M68k::NUM_TARGET_REGS), TM(TM), TSInfo(),
|
|
InstrInfo(initializeSubtargetDependencies(CPU, TT, FS, TM)),
|
|
FrameLowering(*this, this->getStackAlignment()), TLInfo(TM, *this),
|
|
TargetTriple(TT) {
|
|
CallLoweringInfo.reset(new M68kCallLowering(*getTargetLowering()));
|
|
Legalizer.reset(new M68kLegalizerInfo(*this));
|
|
|
|
auto *RBI = new M68kRegisterBankInfo(*getRegisterInfo());
|
|
RegBankInfo.reset(RBI);
|
|
InstSelector.reset(createM68kInstructionSelector(TM, *this, *RBI));
|
|
}
|
|
|
|
const CallLowering *M68kSubtarget::getCallLowering() const {
|
|
return CallLoweringInfo.get();
|
|
}
|
|
|
|
InstructionSelector *M68kSubtarget::getInstructionSelector() const {
|
|
return InstSelector.get();
|
|
}
|
|
|
|
const LegalizerInfo *M68kSubtarget::getLegalizerInfo() const {
|
|
return Legalizer.get();
|
|
}
|
|
|
|
const RegisterBankInfo *M68kSubtarget::getRegBankInfo() const {
|
|
return RegBankInfo.get();
|
|
}
|
|
|
|
bool M68kSubtarget::isPositionIndependent() const {
|
|
return TM.isPositionIndependent();
|
|
}
|
|
|
|
bool M68kSubtarget::isLegalToCallImmediateAddr() const { return true; }
|
|
|
|
bool M68kSubtarget::abiUsesSoftFloat() const { return true; }
|
|
|
|
M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
|
|
StringRef CPU, Triple TT, StringRef FS, const M68kTargetMachine &TM) {
|
|
std::string CPUName = selectM68kCPU(TT, CPU).str();
|
|
|
|
// Parse features string.
|
|
ParseSubtargetFeatures(CPUName, CPUName, FS);
|
|
|
|
// Initialize scheduling itinerary for the specified CPU.
|
|
InstrItins = getInstrItineraryForCPU(CPUName);
|
|
|
|
stackAlignment = 8;
|
|
|
|
return *this;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Code Model
|
|
//
|
|
// Key assumptions:
|
|
// - Whenever possible we use pc-rel encoding since it is smaller(16 bit) than
|
|
// absolute(32 bit).
|
|
// - GOT is reachable within 16 bit offset for both Small and Medium models.
|
|
// - Code section is reachable within 16 bit offset for both models.
|
|
//
|
|
// ---------------------+-------------------------+--------------------------
|
|
// | Small | Medium
|
|
// +-------------------------+------------+-------------
|
|
// | Static | PIC | Static | PIC
|
|
// ---------------------+------------+------------+------------+-------------
|
|
// branch | pc-rel | pc-rel | pc-rel | pc-rel
|
|
// ---------------------+------------+------------+------------+-------------
|
|
// call global | @PLT | @PLT | @PLT | @PLT
|
|
// ---------------------+------------+------------+------------+-------------
|
|
// call internal | pc-rel | pc-rel | pc-rel | pc-rel
|
|
// ---------------------+------------+------------+------------+-------------
|
|
// data local | pc-rel | pc-rel | ~pc-rel | ^pc-rel
|
|
// ---------------------+------------+------------+------------+-------------
|
|
// data local big* | pc-rel | pc-rel | absolute | @GOTOFF
|
|
// ---------------------+------------+------------+------------+-------------
|
|
// data global | pc-rel | @GOTPCREL | ~pc-rel | @GOTPCREL
|
|
// ---------------------+------------+------------+------------+-------------
|
|
// data global big* | pc-rel | @GOTPCREL | absolute | @GOTPCREL
|
|
// ---------------------+------------+------------+------------+-------------
|
|
//
|
|
// * Big data potentially cannot be reached within 16 bit offset and requires
|
|
// special handling for old(x00 and x10) CPUs. Normally these symbols go into
|
|
// separate .ldata section which mapped after normal .data and .text, but I
|
|
// don't really know how this must be done for M68k atm... will try to dig
|
|
// this info out from GCC. For now CPUs prior to M68020 will use static ref
|
|
// for Static Model and @GOT based references for PIC.
|
|
//
|
|
// ~ These are absolute for older CPUs for now.
|
|
// ^ These are @GOTOFF for older CPUs for now.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Classify a blockaddress reference for the current subtarget according to how
|
|
/// we should reference it in a non-pcrel context.
|
|
unsigned char M68kSubtarget::classifyBlockAddressReference() const {
|
|
// Unless we start to support Large Code Model branching is always pc-rel
|
|
return M68kII::MO_PC_RELATIVE_ADDRESS;
|
|
}
|
|
|
|
unsigned char
|
|
M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {
|
|
switch (TM.getCodeModel()) {
|
|
default:
|
|
llvm_unreachable("Unsupported code model");
|
|
case CodeModel::Small:
|
|
case CodeModel::Kernel: {
|
|
return M68kII::MO_PC_RELATIVE_ADDRESS;
|
|
}
|
|
case CodeModel::Medium: {
|
|
if (isPositionIndependent()) {
|
|
// On M68020 and better we can fit big any data offset into dips field.
|
|
if (atLeastM68020()) {
|
|
return M68kII::MO_PC_RELATIVE_ADDRESS;
|
|
}
|
|
// Otherwise we could check the data size and make sure it will fit into
|
|
// 16 bit offset. For now we will be conservative and go with @GOTOFF
|
|
return M68kII::MO_GOTOFF;
|
|
} else {
|
|
if (atLeastM68020()) {
|
|
return M68kII::MO_PC_RELATIVE_ADDRESS;
|
|
}
|
|
return M68kII::MO_ABSOLUTE_ADDRESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned char M68kSubtarget::classifyExternalReference(const Module &M) const {
|
|
if (TM.shouldAssumeDSOLocal(M, nullptr))
|
|
return classifyLocalReference(nullptr);
|
|
|
|
if (isPositionIndependent())
|
|
return M68kII::MO_GOTPCREL;
|
|
|
|
return M68kII::MO_GOT;
|
|
}
|
|
|
|
unsigned char
|
|
M68kSubtarget::classifyGlobalReference(const GlobalValue *GV) const {
|
|
return classifyGlobalReference(GV, *GV->getParent());
|
|
}
|
|
|
|
unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,
|
|
const Module &M) const {
|
|
if (TM.shouldAssumeDSOLocal(M, GV))
|
|
return classifyLocalReference(GV);
|
|
|
|
switch (TM.getCodeModel()) {
|
|
default:
|
|
llvm_unreachable("Unsupported code model");
|
|
case CodeModel::Small:
|
|
case CodeModel::Kernel: {
|
|
if (isPositionIndependent())
|
|
return M68kII::MO_GOTPCREL;
|
|
return M68kII::MO_PC_RELATIVE_ADDRESS;
|
|
}
|
|
case CodeModel::Medium: {
|
|
if (isPositionIndependent())
|
|
return M68kII::MO_GOTPCREL;
|
|
|
|
if (atLeastM68020())
|
|
return M68kII::MO_PC_RELATIVE_ADDRESS;
|
|
|
|
return M68kII::MO_ABSOLUTE_ADDRESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned M68kSubtarget::getJumpTableEncoding() const {
|
|
if (isPositionIndependent()) {
|
|
// The only time we want to use GOTOFF(used when with EK_Custom32) is when
|
|
// the potential delta between the jump target and table base can be larger
|
|
// than displacement field, which is True for older CPUs(16 bit disp)
|
|
// in Medium model(can have large data way beyond 16 bit).
|
|
if (TM.getCodeModel() == CodeModel::Medium && !atLeastM68020())
|
|
return MachineJumpTableInfo::EK_Custom32;
|
|
|
|
return MachineJumpTableInfo::EK_LabelDifference32;
|
|
}
|
|
|
|
// In non-pic modes, just use the address of a block.
|
|
return MachineJumpTableInfo::EK_BlockAddress;
|
|
}
|
|
|
|
unsigned char
|
|
M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
|
|
return classifyGlobalFunctionReference(GV, *GV->getParent());
|
|
}
|
|
|
|
unsigned char
|
|
M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
|
|
const Module &M) const {
|
|
// local always use pc-rel referencing
|
|
if (TM.shouldAssumeDSOLocal(M, GV))
|
|
return M68kII::MO_NO_FLAG;
|
|
|
|
// If the function is marked as non-lazy, generate an indirect call
|
|
// which loads from the GOT directly. This avoids run-time overhead
|
|
// at the cost of eager binding.
|
|
auto *F = dyn_cast_or_null<Function>(GV);
|
|
if (F && F->hasFnAttribute(Attribute::NonLazyBind)) {
|
|
return M68kII::MO_GOTPCREL;
|
|
}
|
|
|
|
// otherwise linker will figure this out
|
|
return M68kII::MO_PLT;
|
|
}
|