brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.7 KiB · 5d7e2b5 Raw
301 lines · cpp
1//===-- CodeGenTargetMachineImpl.cpp --------------------------------------===//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/// \file This file implements the CodeGenTargetMachineImpl class.10///11//===----------------------------------------------------------------------===//12 13#include "llvm/CodeGen/CodeGenTargetMachineImpl.h"14#include "llvm/CodeGen/AsmPrinter.h"15#include "llvm/CodeGen/BasicTTIImpl.h"16#include "llvm/CodeGen/MachineModuleInfo.h"17#include "llvm/CodeGen/Passes.h"18#include "llvm/CodeGen/TargetPassConfig.h"19#include "llvm/IR/LegacyPassManager.h"20#include "llvm/MC/MCAsmBackend.h"21#include "llvm/MC/MCAsmInfo.h"22#include "llvm/MC/MCCodeEmitter.h"23#include "llvm/MC/MCContext.h"24#include "llvm/MC/MCInstPrinter.h"25#include "llvm/MC/MCInstrInfo.h"26#include "llvm/MC/MCObjectWriter.h"27#include "llvm/MC/MCRegisterInfo.h"28#include "llvm/MC/MCStreamer.h"29#include "llvm/MC/MCSubtargetInfo.h"30#include "llvm/MC/TargetRegistry.h"31#include "llvm/Support/CommandLine.h"32#include "llvm/Support/FormattedStream.h"33#include "llvm/Target/RegisterTargetPassConfigCallback.h"34#include "llvm/Target/TargetMachine.h"35#include "llvm/Target/TargetOptions.h"36using namespace llvm;37 38static cl::opt<bool>39    EnableTrapUnreachable("trap-unreachable", cl::Hidden,40                          cl::desc("Enable generating trap for unreachable"));41 42static cl::opt<bool> EnableNoTrapAfterNoreturn(43    "no-trap-after-noreturn", cl::Hidden,44    cl::desc("Do not emit a trap instruction for 'unreachable' IR instructions "45             "after noreturn calls, even if --trap-unreachable is set."));46 47void CodeGenTargetMachineImpl::initAsmInfo() {48  MRI.reset(TheTarget.createMCRegInfo(getTargetTriple()));49  assert(MRI && "Unable to create reg info");50  MII.reset(TheTarget.createMCInstrInfo());51  assert(MII && "Unable to create instruction info");52  // FIXME: Having an MCSubtargetInfo on the target machine is a hack due53  // to some backends having subtarget feature dependent module level54  // code generation. This is similar to the hack in the AsmPrinter for55  // module level assembly etc.56  STI.reset(TheTarget.createMCSubtargetInfo(getTargetTriple(), getTargetCPU(),57                                            getTargetFeatureString()));58  assert(STI && "Unable to create subtarget info");59 60  MCAsmInfo *TmpAsmInfo =61      TheTarget.createMCAsmInfo(*MRI, getTargetTriple(), Options.MCOptions);62  // TargetSelect.h moved to a different directory between LLVM 2.9 and 3.0,63  // and if the old one gets included then MCAsmInfo will be NULL and64  // we'll crash later.65  // Provide the user with a useful error message about what's wrong.66  assert(TmpAsmInfo && "MCAsmInfo not initialized. "67                       "Make sure you include the correct TargetSelect.h"68                       "and that InitializeAllTargetMCs() is being invoked!");69 70  if (Options.BinutilsVersion.first > 0)71    TmpAsmInfo->setBinutilsVersion(Options.BinutilsVersion);72 73  if (Options.DisableIntegratedAS) {74    TmpAsmInfo->setUseIntegratedAssembler(false);75    // If there is explict option disable integratedAS, we can't use it for76    // inlineasm either.77    TmpAsmInfo->setParseInlineAsmUsingAsmParser(false);78  }79 80  TmpAsmInfo->setPreserveAsmComments(Options.MCOptions.PreserveAsmComments);81 82  TmpAsmInfo->setFullRegisterNames(Options.MCOptions.PPCUseFullRegisterNames);83 84  assert(TmpAsmInfo->getExceptionHandlingType() ==85             getTargetTriple().getDefaultExceptionHandling() &&86         "MCAsmInfo and Triple disagree on default exception handling type");87 88  if (Options.ExceptionModel != ExceptionHandling::None)89    TmpAsmInfo->setExceptionsType(Options.ExceptionModel);90 91  AsmInfo.reset(TmpAsmInfo);92}93 94CodeGenTargetMachineImpl::CodeGenTargetMachineImpl(95    const Target &T, StringRef DataLayoutString, const Triple &TT,96    StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM,97    CodeModel::Model CM, CodeGenOptLevel OL)98    : TargetMachine(T, DataLayoutString, TT, CPU, FS, Options) {99  this->RM = RM;100  this->CMModel = CM;101  this->OptLevel = OL;102 103  if (EnableTrapUnreachable)104    this->Options.TrapUnreachable = true;105  if (EnableNoTrapAfterNoreturn)106    this->Options.NoTrapAfterNoreturn = true;107}108 109TargetTransformInfo110CodeGenTargetMachineImpl::getTargetTransformInfo(const Function &F) const {111  return TargetTransformInfo(std::make_unique<BasicTTIImpl>(this, F));112}113 114/// addPassesToX helper drives creation and initialization of TargetPassConfig.115static TargetPassConfig *116addPassesToGenerateCode(CodeGenTargetMachineImpl &TM, PassManagerBase &PM,117                        bool DisableVerify,118                        MachineModuleInfoWrapperPass &MMIWP) {119  // Targets may override createPassConfig to provide a target-specific120  // subclass.121  TargetPassConfig *PassConfig = TM.createPassConfig(PM);122  // Set PassConfig options provided by TargetMachine.123  PassConfig->setDisableVerify(DisableVerify);124  PM.add(PassConfig);125  PM.add(&MMIWP);126  invokeGlobalTargetPassConfigCallbacks(TM, PM, PassConfig);127 128  if (PassConfig->addISelPasses())129    return nullptr;130  PassConfig->addMachinePasses();131  PassConfig->setInitialized();132  return PassConfig;133}134 135bool CodeGenTargetMachineImpl::addAsmPrinter(PassManagerBase &PM,136                                             raw_pwrite_stream &Out,137                                             raw_pwrite_stream *DwoOut,138                                             CodeGenFileType FileType,139                                             MCContext &Context) {140  Expected<std::unique_ptr<MCStreamer>> MCStreamerOrErr =141      createMCStreamer(Out, DwoOut, FileType, Context);142  if (!MCStreamerOrErr) {143    Context.reportError(SMLoc(), toString(MCStreamerOrErr.takeError()));144    return true;145  }146 147  // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.148  FunctionPass *Printer =149      getTarget().createAsmPrinter(*this, std::move(*MCStreamerOrErr));150  if (!Printer)151    return true;152 153  PM.add(Printer);154  return false;155}156 157Expected<std::unique_ptr<MCStreamer>>158CodeGenTargetMachineImpl::createMCStreamer(raw_pwrite_stream &Out,159                                           raw_pwrite_stream *DwoOut,160                                           CodeGenFileType FileType,161                                           MCContext &Context) {162  const MCSubtargetInfo &STI = *getMCSubtargetInfo();163  const MCAsmInfo &MAI = *getMCAsmInfo();164  const MCRegisterInfo &MRI = *getMCRegisterInfo();165  const MCInstrInfo &MII = *getMCInstrInfo();166 167  std::unique_ptr<MCStreamer> AsmStreamer;168 169  switch (FileType) {170  case CodeGenFileType::AssemblyFile: {171    std::unique_ptr<MCInstPrinter> InstPrinter(getTarget().createMCInstPrinter(172        getTargetTriple(),173        Options.MCOptions.OutputAsmVariant.value_or(MAI.getAssemblerDialect()),174        MAI, MII, MRI));175    for (StringRef Opt : Options.MCOptions.InstPrinterOptions)176      if (!InstPrinter->applyTargetSpecificCLOption(Opt))177        return createStringError("invalid InstPrinter option '" + Opt + "'");178 179    // Create a code emitter if asked to show the encoding.180    std::unique_ptr<MCCodeEmitter> MCE;181    if (Options.MCOptions.ShowMCEncoding)182      MCE.reset(getTarget().createMCCodeEmitter(MII, Context));183 184    std::unique_ptr<MCAsmBackend> MAB(185        getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions));186    auto FOut = std::make_unique<formatted_raw_ostream>(Out);187    MCStreamer *S = getTarget().createAsmStreamer(188        Context, std::move(FOut), std::move(InstPrinter), std::move(MCE),189        std::move(MAB));190    AsmStreamer.reset(S);191    break;192  }193  case CodeGenFileType::ObjectFile: {194    // Create the code emitter for the target if it exists.  If not, .o file195    // emission fails.196    MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(MII, Context);197    if (!MCE)198      return make_error<StringError>("createMCCodeEmitter failed",199                                     inconvertibleErrorCode());200    MCAsmBackend *MAB =201        getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions);202    if (!MAB)203      return make_error<StringError>("createMCAsmBackend failed",204                                     inconvertibleErrorCode());205 206    Triple T(getTargetTriple());207    AsmStreamer.reset(getTarget().createMCObjectStreamer(208        T, Context, std::unique_ptr<MCAsmBackend>(MAB),209        DwoOut ? MAB->createDwoObjectWriter(Out, *DwoOut)210               : MAB->createObjectWriter(Out),211        std::unique_ptr<MCCodeEmitter>(MCE), STI));212    break;213  }214  case CodeGenFileType::Null:215    // The Null output is intended for use for performance analysis and testing,216    // not real users.217    AsmStreamer.reset(getTarget().createNullStreamer(Context));218    break;219  }220 221  return std::move(AsmStreamer);222}223 224bool CodeGenTargetMachineImpl::addPassesToEmitFile(225    PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,226    CodeGenFileType FileType, bool DisableVerify,227    MachineModuleInfoWrapperPass *MMIWP) {228  // Add common CodeGen passes.229  if (!MMIWP)230    MMIWP = new MachineModuleInfoWrapperPass(this);231  TargetPassConfig *PassConfig =232      addPassesToGenerateCode(*this, PM, DisableVerify, *MMIWP);233  if (!PassConfig)234    return true;235 236  if (TargetPassConfig::willCompleteCodeGenPipeline()) {237    if (addAsmPrinter(PM, Out, DwoOut, FileType, MMIWP->getMMI().getContext()))238      return true;239  } else {240    // MIR printing is redundant with -filetype=null.241    if (FileType != CodeGenFileType::Null)242      PM.add(createPrintMIRPass(Out));243  }244 245  PM.add(createFreeMachineFunctionPass());246  return false;247}248 249/// addPassesToEmitMC - Add passes to the specified pass manager to get250/// machine code emitted with the MCJIT. This method returns true if machine251/// code is not supported. It fills the MCContext Ctx pointer which can be252/// used to build custom MCStreamer.253///254bool CodeGenTargetMachineImpl::addPassesToEmitMC(PassManagerBase &PM,255                                                 MCContext *&Ctx,256                                                 raw_pwrite_stream &Out,257                                                 bool DisableVerify) {258  // Add common CodeGen passes.259  MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(this);260  TargetPassConfig *PassConfig =261      addPassesToGenerateCode(*this, PM, DisableVerify, *MMIWP);262  if (!PassConfig)263    return true;264  assert(TargetPassConfig::willCompleteCodeGenPipeline() &&265         "Cannot emit MC with limited codegen pipeline");266 267  Ctx = &MMIWP->getMMI().getContext();268  // libunwind is unable to load compact unwind dynamically, so we must generate269  // DWARF unwind info for the JIT.270  Options.MCOptions.EmitDwarfUnwind = EmitDwarfUnwindType::Always;271 272  // Create the code emitter for the target if it exists.  If not, .o file273  // emission fails.274  const MCSubtargetInfo &STI = *getMCSubtargetInfo();275  const MCRegisterInfo &MRI = *getMCRegisterInfo();276  std::unique_ptr<MCCodeEmitter> MCE(277      getTarget().createMCCodeEmitter(*getMCInstrInfo(), *Ctx));278  if (!MCE)279    return true;280  MCAsmBackend *MAB =281      getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions);282  if (!MAB)283    return true;284 285  const Triple &T = getTargetTriple();286  std::unique_ptr<MCStreamer> AsmStreamer(getTarget().createMCObjectStreamer(287      T, *Ctx, std::unique_ptr<MCAsmBackend>(MAB), MAB->createObjectWriter(Out),288      std::move(MCE), STI));289 290  // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.291  FunctionPass *Printer =292      getTarget().createAsmPrinter(*this, std::move(AsmStreamer));293  if (!Printer)294    return true;295 296  PM.add(Printer);297  PM.add(createFreeMachineFunctionPass());298 299  return false; // success!300}301