Path: blob/main/contrib/llvm-project/llvm/lib/Target/M68k/M68kSubtarget.cpp
35266 views
//===-- M68kSubtarget.cpp - M68k Subtarget Information ----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file implements the M68k specific subclass of TargetSubtargetInfo.10///11//===----------------------------------------------------------------------===//1213#include "M68kSubtarget.h"14#include "GISel/M68kCallLowering.h"15#include "GISel/M68kLegalizerInfo.h"16#include "GISel/M68kRegisterBankInfo.h"1718#include "M68k.h"19#include "M68kMachineFunction.h"20#include "M68kRegisterInfo.h"21#include "M68kTargetMachine.h"2223#include "llvm/CodeGen/MachineJumpTableInfo.h"24#include "llvm/IR/Attributes.h"25#include "llvm/IR/Function.h"26#include "llvm/MC/TargetRegistry.h"27#include "llvm/Support/CommandLine.h"28#include "llvm/Support/ErrorHandling.h"2930using namespace llvm;3132#define DEBUG_TYPE "m68k-subtarget"3334#define GET_SUBTARGETINFO_TARGET_DESC35#define GET_SUBTARGETINFO_CTOR36#include "M68kGenSubtargetInfo.inc"3738extern bool FixGlobalBaseReg;3940/// Select the M68k CPU for the given triple and cpu name.41static StringRef selectM68kCPU(Triple TT, StringRef CPU) {42if (CPU.empty() || CPU == "generic") {43CPU = "M68000";44}45return CPU;46}4748void M68kSubtarget::anchor() {}4950M68kSubtarget::M68kSubtarget(const Triple &TT, StringRef CPU, StringRef FS,51const M68kTargetMachine &TM)52: M68kGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), TM(TM), TSInfo(),53InstrInfo(initializeSubtargetDependencies(CPU, TT, FS, TM)),54FrameLowering(*this, this->getStackAlignment()), TLInfo(TM, *this),55TargetTriple(TT) {56CallLoweringInfo.reset(new M68kCallLowering(*getTargetLowering()));57Legalizer.reset(new M68kLegalizerInfo(*this));5859auto *RBI = new M68kRegisterBankInfo(*getRegisterInfo());60RegBankInfo.reset(RBI);61InstSelector.reset(createM68kInstructionSelector(TM, *this, *RBI));62}6364const CallLowering *M68kSubtarget::getCallLowering() const {65return CallLoweringInfo.get();66}6768InstructionSelector *M68kSubtarget::getInstructionSelector() const {69return InstSelector.get();70}7172const LegalizerInfo *M68kSubtarget::getLegalizerInfo() const {73return Legalizer.get();74}7576const RegisterBankInfo *M68kSubtarget::getRegBankInfo() const {77return RegBankInfo.get();78}7980bool M68kSubtarget::isPositionIndependent() const {81return TM.isPositionIndependent();82}8384bool M68kSubtarget::isLegalToCallImmediateAddr() const { return true; }8586M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(87StringRef CPU, Triple TT, StringRef FS, const M68kTargetMachine &TM) {88std::string CPUName = selectM68kCPU(TT, CPU).str();8990// Parse features string.91ParseSubtargetFeatures(CPUName, CPUName, FS);9293// Initialize scheduling itinerary for the specified CPU.94InstrItins = getInstrItineraryForCPU(CPUName);9596stackAlignment = 8;9798return *this;99}100101//===----------------------------------------------------------------------===//102// Code Model103//104// Key assumptions:105// - Whenever possible we use pc-rel encoding since it is smaller(16 bit) than106// absolute(32 bit).107// - GOT is reachable within 16 bit offset for both Small and Medium models.108// - Code section is reachable within 16 bit offset for both models.109//110// ---------------------+-------------------------+--------------------------111// | Small | Medium112// +-------------------------+------------+-------------113// | Static | PIC | Static | PIC114// ---------------------+------------+------------+------------+-------------115// branch | pc-rel | pc-rel | pc-rel | pc-rel116// ---------------------+------------+------------+------------+-------------117// call global | @PLT | @PLT | @PLT | @PLT118// ---------------------+------------+------------+------------+-------------119// call internal | pc-rel | pc-rel | pc-rel | pc-rel120// ---------------------+------------+------------+------------+-------------121// data local | pc-rel | pc-rel | ~pc-rel | ^pc-rel122// ---------------------+------------+------------+------------+-------------123// data local big* | pc-rel | pc-rel | absolute | @GOTOFF124// ---------------------+------------+------------+------------+-------------125// data global | pc-rel | @GOTPCREL | ~pc-rel | @GOTPCREL126// ---------------------+------------+------------+------------+-------------127// data global big* | pc-rel | @GOTPCREL | absolute | @GOTPCREL128// ---------------------+------------+------------+------------+-------------129//130// * Big data potentially cannot be reached within 16 bit offset and requires131// special handling for old(x00 and x10) CPUs. Normally these symbols go into132// separate .ldata section which mapped after normal .data and .text, but I133// don't really know how this must be done for M68k atm... will try to dig134// this info out from GCC. For now CPUs prior to M68020 will use static ref135// for Static Model and @GOT based references for PIC.136//137// ~ These are absolute for older CPUs for now.138// ^ These are @GOTOFF for older CPUs for now.139//===----------------------------------------------------------------------===//140141/// Classify a blockaddress reference for the current subtarget according to how142/// we should reference it in a non-pcrel context.143unsigned char M68kSubtarget::classifyBlockAddressReference() const {144// Unless we start to support Large Code Model branching is always pc-rel145return M68kII::MO_PC_RELATIVE_ADDRESS;146}147148unsigned char149M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {150switch (TM.getCodeModel()) {151default:152llvm_unreachable("Unsupported code model");153case CodeModel::Small:154case CodeModel::Kernel: {155return M68kII::MO_PC_RELATIVE_ADDRESS;156}157case CodeModel::Medium: {158if (isPositionIndependent()) {159// On M68020 and better we can fit big any data offset into dips field.160if (atLeastM68020()) {161return M68kII::MO_PC_RELATIVE_ADDRESS;162}163// Otherwise we could check the data size and make sure it will fit into164// 16 bit offset. For now we will be conservative and go with @GOTOFF165return M68kII::MO_GOTOFF;166} else {167if (atLeastM68020()) {168return M68kII::MO_PC_RELATIVE_ADDRESS;169}170return M68kII::MO_ABSOLUTE_ADDRESS;171}172}173}174}175176unsigned char M68kSubtarget::classifyExternalReference(const Module &M) const {177if (TM.shouldAssumeDSOLocal(nullptr))178return classifyLocalReference(nullptr);179180if (isPositionIndependent())181return M68kII::MO_GOTPCREL;182183return M68kII::MO_GOT;184}185186unsigned char187M68kSubtarget::classifyGlobalReference(const GlobalValue *GV) const {188return classifyGlobalReference(GV, *GV->getParent());189}190191unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,192const Module &M) const {193if (TM.shouldAssumeDSOLocal(GV))194return classifyLocalReference(GV);195196switch (TM.getCodeModel()) {197default:198llvm_unreachable("Unsupported code model");199case CodeModel::Small:200case CodeModel::Kernel: {201if (isPositionIndependent())202return M68kII::MO_GOTPCREL;203return M68kII::MO_PC_RELATIVE_ADDRESS;204}205case CodeModel::Medium: {206if (isPositionIndependent())207return M68kII::MO_GOTPCREL;208209if (atLeastM68020())210return M68kII::MO_PC_RELATIVE_ADDRESS;211212return M68kII::MO_ABSOLUTE_ADDRESS;213}214}215}216217unsigned M68kSubtarget::getJumpTableEncoding() const {218if (isPositionIndependent()) {219// The only time we want to use GOTOFF(used when with EK_Custom32) is when220// the potential delta between the jump target and table base can be larger221// than displacement field, which is True for older CPUs(16 bit disp)222// in Medium model(can have large data way beyond 16 bit).223if (TM.getCodeModel() == CodeModel::Medium && !atLeastM68020())224return MachineJumpTableInfo::EK_Custom32;225226return MachineJumpTableInfo::EK_LabelDifference32;227}228229// In non-pic modes, just use the address of a block.230return MachineJumpTableInfo::EK_BlockAddress;231}232233unsigned char234M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {235return classifyGlobalFunctionReference(GV, *GV->getParent());236}237238unsigned char239M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,240const Module &M) const {241// local always use pc-rel referencing242if (TM.shouldAssumeDSOLocal(GV))243return M68kII::MO_NO_FLAG;244245// If the function is marked as non-lazy, generate an indirect call246// which loads from the GOT directly. This avoids run-time overhead247// at the cost of eager binding.248auto *F = dyn_cast_or_null<Function>(GV);249if (F && F->hasFnAttribute(Attribute::NonLazyBind)) {250return M68kII::MO_GOTPCREL;251}252253// Ensure that we don't emit PLT relocations when in non-pic modes.254return isPositionIndependent() ? M68kII::MO_PLT : M68kII::MO_ABSOLUTE_ADDRESS;255}256257258