brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.9 KiB · 59d865f Raw
310 lines · cpp
1//===-- M68kSubtarget.cpp - M68k Subtarget Information ----------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements the M68k specific subclass of TargetSubtargetInfo.11///12//===----------------------------------------------------------------------===//13 14#include "M68kSubtarget.h"15#include "GISel/M68kCallLowering.h"16#include "GISel/M68kLegalizerInfo.h"17#include "GISel/M68kRegisterBankInfo.h"18#include "M68k.h"19#include "M68kMachineFunction.h"20#include "M68kRegisterInfo.h"21#include "M68kSelectionDAGInfo.h"22#include "M68kTargetMachine.h"23#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"29 30using namespace llvm;31 32#define DEBUG_TYPE "m68k-subtarget"33 34#define GET_SUBTARGETINFO_TARGET_DESC35#define GET_SUBTARGETINFO_CTOR36#include "M68kGenSubtargetInfo.inc"37 38extern bool FixGlobalBaseReg;39 40/// Select the M68k CPU for the given triple and cpu name.41static StringRef selectM68kCPU(Triple TT, StringRef CPU) {42  if (CPU.empty() || CPU == "generic") {43    CPU = "M68000";44  }45  return CPU;46}47 48void M68kSubtarget::anchor() {}49 50M68kSubtarget::M68kSubtarget(const Triple &TT, StringRef CPU, StringRef FS,51                             const M68kTargetMachine &TM)52    : M68kGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), TM(TM),53      InstrInfo(initializeSubtargetDependencies(CPU, TT, FS, TM)),54      FrameLowering(*this, this->getStackAlignment()), TLInfo(TM, *this),55      TargetTriple(TT) {56  TSInfo = std::make_unique<M68kSelectionDAGInfo>();57 58  CallLoweringInfo.reset(new M68kCallLowering(*getTargetLowering()));59  Legalizer.reset(new M68kLegalizerInfo(*this));60 61  auto *RBI = new M68kRegisterBankInfo(*getRegisterInfo());62  RegBankInfo.reset(RBI);63  InstSelector.reset(createM68kInstructionSelector(TM, *this, *RBI));64}65 66M68kSubtarget::~M68kSubtarget() = default;67 68const SelectionDAGTargetInfo *M68kSubtarget::getSelectionDAGInfo() const {69  return TSInfo.get();70}71 72const CallLowering *M68kSubtarget::getCallLowering() const {73  return CallLoweringInfo.get();74}75 76InstructionSelector *M68kSubtarget::getInstructionSelector() const {77  return InstSelector.get();78}79 80const LegalizerInfo *M68kSubtarget::getLegalizerInfo() const {81  return Legalizer.get();82}83 84const RegisterBankInfo *M68kSubtarget::getRegBankInfo() const {85  return RegBankInfo.get();86}87 88bool M68kSubtarget::isPositionIndependent() const {89  return TM.isPositionIndependent();90}91 92bool M68kSubtarget::isLegalToCallImmediateAddr() const { return true; }93 94M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(95    StringRef CPU, Triple TT, StringRef FS, const M68kTargetMachine &TM) {96  std::string CPUName = selectM68kCPU(TT, CPU).str();97 98  // Parse features string.99  ParseSubtargetFeatures(CPUName, CPUName, FS);100 101  // Initialize scheduling itinerary for the specified CPU.102  InstrItins = getInstrItineraryForCPU(CPUName);103 104  stackAlignment = 8;105 106  return *this;107}108 109//===----------------------------------------------------------------------===//110// Code Model111//112// Key assumptions:113//  - Whenever possible we use pc-rel encoding since it is smaller(16 bit) than114//    absolute(32 bit).115//  - GOT is reachable within 16 bit offset for both Small and Medium models.116//  - Code section is reachable within 16 bit offset for both models.117//118//  ---------------------+-------------------------+--------------------------119//                       |          Small          |          Medium120//                       +-------------------------+------------+-------------121//                       |   Static   |    PIC     |   Static   |    PIC122//  ---------------------+------------+------------+------------+-------------123//                branch |   pc-rel   |   pc-rel   |   pc-rel   |   pc-rel124//  ---------------------+------------+------------+------------+-------------125//           call global |  absolute  |    @PLT    |  absolute  |    @PLT126//  ---------------------+------------+------------+------------+-------------127//         call internal |   pc-rel   |   pc-rel   |   pc-rel   |   pc-rel128//  ---------------------+------------+------------+------------+-------------129//            data local |   pc-rel   |   pc-rel   |  ~pc-rel   |  ^pc-rel130//  ---------------------+------------+------------+------------+-------------131//       data local big* |   pc-rel   |   pc-rel   |  absolute  |  @GOTOFF132//  ---------------------+------------+------------+------------+-------------133//           data global |   pc-rel   |  @GOTPCREL |  ~pc-rel   |  @GOTPCREL134//  ---------------------+------------+------------+------------+-------------135//      data global big* |   pc-rel   |  @GOTPCREL |  absolute  |  @GOTPCREL136//  ---------------------+------------+------------+------------+-------------137//                       |          Large          |138//                       +-------------------------+139//                       |   Static   |    PIC     |140//  ---------------------+------------+------------+141//                branch |  absolute  |   pc-rel   |142//  ---------------------+------------+------------+143//           call global |  absolute  |    @PLT    |144//  ---------------------+------------+------------+145//         call internal |  absolute  |   pc-rel   |146//  ---------------------+------------+------------+147//            data local |  absolute  |  @GOTOFF   |148//  ---------------------+------------+------------+149//       data local big* |  absolute  |  @GOTOFF   |150//  ---------------------+------------+------------+151//           data global |  absolute  |  @GOTOFF   |152//  ---------------------+------------+------------+153//      data global big* |  absolute  |  @GOTOFF   |154//  ---------------------+------------+------------+155//156// * Big data potentially cannot be reached within 16 bit offset and requires157//   special handling for old(x00 and x10) CPUs. Normally these symbols go into158//   separate .ldata section which mapped after normal .data and .text, but I159//   don't really know how this must be done for M68k atm... will try to dig160//   this info out from GCC. For now CPUs prior to M68020 will use static ref161//   for Static Model and @GOT based references for PIC.162//163// ~ These are absolute for older CPUs for now.164// ^ These are @GOTOFF for older CPUs for now.165//===----------------------------------------------------------------------===//166 167/// Classify a blockaddress reference for the current subtarget according to how168/// we should reference it in a non-pcrel context.169unsigned char M68kSubtarget::classifyBlockAddressReference() const {170  switch (TM.getCodeModel()) {171  default:172    llvm_unreachable("Unsupported code model");173  case CodeModel::Small:174  case CodeModel::Kernel:175  case CodeModel::Medium: {176    return M68kII::MO_PC_RELATIVE_ADDRESS;177  }178  case CodeModel::Large: {179    if (isPositionIndependent()) {180      return M68kII::MO_PC_RELATIVE_ADDRESS;181    } else {182      return M68kII::MO_ABSOLUTE_ADDRESS;183    }184  }185  }186}187 188unsigned char189M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {190  switch (TM.getCodeModel()) {191  default:192    llvm_unreachable("Unsupported code model");193  case CodeModel::Small:194  case CodeModel::Kernel: {195    return M68kII::MO_PC_RELATIVE_ADDRESS;196  }197  case CodeModel::Medium: {198    if (isPositionIndependent()) {199      // On M68020 and better we can fit big any data offset into dips field.200      if (atLeastM68020()) {201        return M68kII::MO_PC_RELATIVE_ADDRESS;202      }203      // Otherwise we could check the data size and make sure it will fit into204      // 16 bit offset. For now we will be conservative and go with @GOTOFF205      return M68kII::MO_GOTOFF;206    } else {207      if (atLeastM68020()) {208        return M68kII::MO_PC_RELATIVE_ADDRESS;209      }210      return M68kII::MO_ABSOLUTE_ADDRESS;211    }212  }213  case CodeModel::Large: {214    if (isPositionIndependent()) {215      return M68kII::MO_GOTOFF;216    } else {217      return M68kII::MO_ABSOLUTE_ADDRESS;218    }219  }220  }221}222 223unsigned char M68kSubtarget::classifyExternalReference(const Module &M) const {224  if (TM.shouldAssumeDSOLocal(nullptr))225    return classifyLocalReference(nullptr);226 227  if (isPositionIndependent())228    return M68kII::MO_GOTPCREL;229 230  return M68kII::MO_GOT;231}232 233unsigned char234M68kSubtarget::classifyGlobalReference(const GlobalValue *GV) const {235  return classifyGlobalReference(GV, *GV->getParent());236}237 238unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,239                                                     const Module &M) const {240  if (TM.shouldAssumeDSOLocal(GV))241    return classifyLocalReference(GV);242 243  switch (TM.getCodeModel()) {244  default:245    llvm_unreachable("Unsupported code model");246  case CodeModel::Small:247  case CodeModel::Kernel: {248    if (isPositionIndependent())249      return M68kII::MO_GOTPCREL;250    return M68kII::MO_PC_RELATIVE_ADDRESS;251  }252  case CodeModel::Medium: {253    if (isPositionIndependent())254      return M68kII::MO_GOTPCREL;255 256    if (atLeastM68020())257      return M68kII::MO_PC_RELATIVE_ADDRESS;258 259    return M68kII::MO_ABSOLUTE_ADDRESS;260  }261  case CodeModel::Large: {262    if (isPositionIndependent())263      return M68kII::MO_GOTOFF;264 265    return M68kII::MO_ABSOLUTE_ADDRESS;266  }267  }268}269 270unsigned M68kSubtarget::getJumpTableEncoding() const {271  if (isPositionIndependent()) {272    // The only time we want to use GOTOFF(used when with EK_Custom32) is when273    // the potential delta between the jump target and table base can be larger274    // than displacement field, which is True for older CPUs(16 bit disp)275    // in Medium model(can have large data way beyond 16 bit).276    if ((TM.getCodeModel() == CodeModel::Medium && !atLeastM68020()) ||277        TM.getCodeModel() == CodeModel::Large)278      return MachineJumpTableInfo::EK_Custom32;279 280    return MachineJumpTableInfo::EK_LabelDifference32;281  }282 283  // In non-pic modes, just use the address of a block.284  return MachineJumpTableInfo::EK_BlockAddress;285}286 287unsigned char288M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {289  return classifyGlobalFunctionReference(GV, *GV->getParent());290}291 292unsigned char293M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,294                                               const Module &M) const {295  // local always use pc-rel referencing296  if (TM.shouldAssumeDSOLocal(GV))297    return M68kII::MO_NO_FLAG;298 299  // If the function is marked as non-lazy, generate an indirect call300  // which loads from the GOT directly. This avoids run-time overhead301  // at the cost of eager binding.302  auto *F = dyn_cast_or_null<Function>(GV);303  if (F && F->hasFnAttribute(Attribute::NonLazyBind)) {304    return M68kII::MO_GOTPCREL;305  }306 307  // Ensure that we don't emit PLT relocations when in non-pic modes.308  return isPositionIndependent() ? M68kII::MO_PLT : M68kII::MO_ABSOLUTE_ADDRESS;309}310