Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp
213764 views
//===-- CodeGenTargetMachineImpl.cpp --------------------------------------===//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/// \file This file implements the CodeGenTargetMachineImpl class.9///10//===----------------------------------------------------------------------===//1112#include "llvm/CodeGen/CodeGenTargetMachineImpl.h"13#include "llvm/CodeGen/AsmPrinter.h"14#include "llvm/CodeGen/BasicTTIImpl.h"15#include "llvm/CodeGen/MachineModuleInfo.h"16#include "llvm/CodeGen/Passes.h"17#include "llvm/CodeGen/TargetPassConfig.h"18#include "llvm/IR/LegacyPassManager.h"19#include "llvm/MC/MCAsmBackend.h"20#include "llvm/MC/MCAsmInfo.h"21#include "llvm/MC/MCCodeEmitter.h"22#include "llvm/MC/MCContext.h"23#include "llvm/MC/MCInstPrinter.h"24#include "llvm/MC/MCInstrInfo.h"25#include "llvm/MC/MCObjectWriter.h"26#include "llvm/MC/MCRegisterInfo.h"27#include "llvm/MC/MCStreamer.h"28#include "llvm/MC/MCSubtargetInfo.h"29#include "llvm/MC/TargetRegistry.h"30#include "llvm/Support/CommandLine.h"31#include "llvm/Support/FormattedStream.h"32#include "llvm/Target/RegisterTargetPassConfigCallback.h"33#include "llvm/Target/TargetMachine.h"34#include "llvm/Target/TargetOptions.h"35using namespace llvm;3637static cl::opt<bool>38EnableTrapUnreachable("trap-unreachable", cl::Hidden,39cl::desc("Enable generating trap for unreachable"));4041static cl::opt<bool> EnableNoTrapAfterNoreturn(42"no-trap-after-noreturn", cl::Hidden,43cl::desc("Do not emit a trap instruction for 'unreachable' IR instructions "44"after noreturn calls, even if --trap-unreachable is set."));4546void CodeGenTargetMachineImpl::initAsmInfo() {47MRI.reset(TheTarget.createMCRegInfo(getTargetTriple().str()));48assert(MRI && "Unable to create reg info");49MII.reset(TheTarget.createMCInstrInfo());50assert(MII && "Unable to create instruction info");51// FIXME: Having an MCSubtargetInfo on the target machine is a hack due52// to some backends having subtarget feature dependent module level53// code generation. This is similar to the hack in the AsmPrinter for54// module level assembly etc.55STI.reset(TheTarget.createMCSubtargetInfo(56getTargetTriple().str(), getTargetCPU(), getTargetFeatureString()));57assert(STI && "Unable to create subtarget info");5859MCAsmInfo *TmpAsmInfo = TheTarget.createMCAsmInfo(60*MRI, getTargetTriple().str(), Options.MCOptions);61// TargetSelect.h moved to a different directory between LLVM 2.9 and 3.0,62// and if the old one gets included then MCAsmInfo will be NULL and63// we'll crash later.64// Provide the user with a useful error message about what's wrong.65assert(TmpAsmInfo && "MCAsmInfo not initialized. "66"Make sure you include the correct TargetSelect.h"67"and that InitializeAllTargetMCs() is being invoked!");6869if (Options.BinutilsVersion.first > 0)70TmpAsmInfo->setBinutilsVersion(Options.BinutilsVersion);7172if (Options.DisableIntegratedAS) {73TmpAsmInfo->setUseIntegratedAssembler(false);74// If there is explict option disable integratedAS, we can't use it for75// inlineasm either.76TmpAsmInfo->setParseInlineAsmUsingAsmParser(false);77}7879TmpAsmInfo->setPreserveAsmComments(Options.MCOptions.PreserveAsmComments);8081TmpAsmInfo->setFullRegisterNames(Options.MCOptions.PPCUseFullRegisterNames);8283assert(TmpAsmInfo->getExceptionHandlingType() ==84getTargetTriple().getDefaultExceptionHandling() &&85"MCAsmInfo and Triple disagree on default exception handling type");8687if (Options.ExceptionModel != ExceptionHandling::None)88TmpAsmInfo->setExceptionsType(Options.ExceptionModel);8990AsmInfo.reset(TmpAsmInfo);91}9293CodeGenTargetMachineImpl::CodeGenTargetMachineImpl(94const Target &T, StringRef DataLayoutString, const Triple &TT,95StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM,96CodeModel::Model CM, CodeGenOptLevel OL)97: TargetMachine(T, DataLayoutString, TT, CPU, FS, Options) {98this->RM = RM;99this->CMModel = CM;100this->OptLevel = OL;101102if (EnableTrapUnreachable)103this->Options.TrapUnreachable = true;104if (EnableNoTrapAfterNoreturn)105this->Options.NoTrapAfterNoreturn = true;106}107108TargetTransformInfo109CodeGenTargetMachineImpl::getTargetTransformInfo(const Function &F) const {110return TargetTransformInfo(std::make_unique<BasicTTIImpl>(this, F));111}112113/// addPassesToX helper drives creation and initialization of TargetPassConfig.114static TargetPassConfig *115addPassesToGenerateCode(CodeGenTargetMachineImpl &TM, PassManagerBase &PM,116bool DisableVerify,117MachineModuleInfoWrapperPass &MMIWP) {118// Targets may override createPassConfig to provide a target-specific119// subclass.120TargetPassConfig *PassConfig = TM.createPassConfig(PM);121// Set PassConfig options provided by TargetMachine.122PassConfig->setDisableVerify(DisableVerify);123PM.add(PassConfig);124PM.add(&MMIWP);125invokeGlobalTargetPassConfigCallbacks(TM, PM, PassConfig);126127if (PassConfig->addISelPasses())128return nullptr;129PassConfig->addMachinePasses();130PassConfig->setInitialized();131return PassConfig;132}133134bool CodeGenTargetMachineImpl::addAsmPrinter(PassManagerBase &PM,135raw_pwrite_stream &Out,136raw_pwrite_stream *DwoOut,137CodeGenFileType FileType,138MCContext &Context) {139Expected<std::unique_ptr<MCStreamer>> MCStreamerOrErr =140createMCStreamer(Out, DwoOut, FileType, Context);141if (!MCStreamerOrErr) {142Context.reportError(SMLoc(), toString(MCStreamerOrErr.takeError()));143return true;144}145146// Create the AsmPrinter, which takes ownership of AsmStreamer if successful.147FunctionPass *Printer =148getTarget().createAsmPrinter(*this, std::move(*MCStreamerOrErr));149if (!Printer)150return true;151152PM.add(Printer);153return false;154}155156Expected<std::unique_ptr<MCStreamer>>157CodeGenTargetMachineImpl::createMCStreamer(raw_pwrite_stream &Out,158raw_pwrite_stream *DwoOut,159CodeGenFileType FileType,160MCContext &Context) {161const MCSubtargetInfo &STI = *getMCSubtargetInfo();162const MCAsmInfo &MAI = *getMCAsmInfo();163const MCRegisterInfo &MRI = *getMCRegisterInfo();164const MCInstrInfo &MII = *getMCInstrInfo();165166std::unique_ptr<MCStreamer> AsmStreamer;167168switch (FileType) {169case CodeGenFileType::AssemblyFile: {170std::unique_ptr<MCInstPrinter> InstPrinter(getTarget().createMCInstPrinter(171getTargetTriple(),172Options.MCOptions.OutputAsmVariant.value_or(MAI.getAssemblerDialect()),173MAI, MII, MRI));174for (StringRef Opt : Options.MCOptions.InstPrinterOptions)175if (!InstPrinter->applyTargetSpecificCLOption(Opt))176return createStringError("invalid InstPrinter option '" + Opt + "'");177178// Create a code emitter if asked to show the encoding.179std::unique_ptr<MCCodeEmitter> MCE;180if (Options.MCOptions.ShowMCEncoding)181MCE.reset(getTarget().createMCCodeEmitter(MII, Context));182183std::unique_ptr<MCAsmBackend> MAB(184getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions));185auto FOut = std::make_unique<formatted_raw_ostream>(Out);186MCStreamer *S = getTarget().createAsmStreamer(187Context, std::move(FOut), std::move(InstPrinter), std::move(MCE),188std::move(MAB));189AsmStreamer.reset(S);190break;191}192case CodeGenFileType::ObjectFile: {193// Create the code emitter for the target if it exists. If not, .o file194// emission fails.195MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(MII, Context);196if (!MCE)197return make_error<StringError>("createMCCodeEmitter failed",198inconvertibleErrorCode());199MCAsmBackend *MAB =200getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions);201if (!MAB)202return make_error<StringError>("createMCAsmBackend failed",203inconvertibleErrorCode());204205Triple T(getTargetTriple());206AsmStreamer.reset(getTarget().createMCObjectStreamer(207T, Context, std::unique_ptr<MCAsmBackend>(MAB),208DwoOut ? MAB->createDwoObjectWriter(Out, *DwoOut)209: MAB->createObjectWriter(Out),210std::unique_ptr<MCCodeEmitter>(MCE), STI));211break;212}213case CodeGenFileType::Null:214// The Null output is intended for use for performance analysis and testing,215// not real users.216AsmStreamer.reset(getTarget().createNullStreamer(Context));217break;218}219220return std::move(AsmStreamer);221}222223bool CodeGenTargetMachineImpl::addPassesToEmitFile(224PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,225CodeGenFileType FileType, bool DisableVerify,226MachineModuleInfoWrapperPass *MMIWP) {227// Add common CodeGen passes.228if (!MMIWP)229MMIWP = new MachineModuleInfoWrapperPass(this);230TargetPassConfig *PassConfig =231addPassesToGenerateCode(*this, PM, DisableVerify, *MMIWP);232if (!PassConfig)233return true;234235if (TargetPassConfig::willCompleteCodeGenPipeline()) {236if (addAsmPrinter(PM, Out, DwoOut, FileType, MMIWP->getMMI().getContext()))237return true;238} else {239// MIR printing is redundant with -filetype=null.240if (FileType != CodeGenFileType::Null)241PM.add(createPrintMIRPass(Out));242}243244PM.add(createFreeMachineFunctionPass());245return false;246}247248/// addPassesToEmitMC - Add passes to the specified pass manager to get249/// machine code emitted with the MCJIT. This method returns true if machine250/// code is not supported. It fills the MCContext Ctx pointer which can be251/// used to build custom MCStreamer.252///253bool CodeGenTargetMachineImpl::addPassesToEmitMC(PassManagerBase &PM,254MCContext *&Ctx,255raw_pwrite_stream &Out,256bool DisableVerify) {257// Add common CodeGen passes.258MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(this);259TargetPassConfig *PassConfig =260addPassesToGenerateCode(*this, PM, DisableVerify, *MMIWP);261if (!PassConfig)262return true;263assert(TargetPassConfig::willCompleteCodeGenPipeline() &&264"Cannot emit MC with limited codegen pipeline");265266Ctx = &MMIWP->getMMI().getContext();267// libunwind is unable to load compact unwind dynamically, so we must generate268// DWARF unwind info for the JIT.269Options.MCOptions.EmitDwarfUnwind = EmitDwarfUnwindType::Always;270271// Create the code emitter for the target if it exists. If not, .o file272// emission fails.273const MCSubtargetInfo &STI = *getMCSubtargetInfo();274const MCRegisterInfo &MRI = *getMCRegisterInfo();275std::unique_ptr<MCCodeEmitter> MCE(276getTarget().createMCCodeEmitter(*getMCInstrInfo(), *Ctx));277if (!MCE)278return true;279MCAsmBackend *MAB =280getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions);281if (!MAB)282return true;283284const Triple &T = getTargetTriple();285std::unique_ptr<MCStreamer> AsmStreamer(getTarget().createMCObjectStreamer(286T, *Ctx, std::unique_ptr<MCAsmBackend>(MAB), MAB->createObjectWriter(Out),287std::move(MCE), STI));288289// Create the AsmPrinter, which takes ownership of AsmStreamer if successful.290FunctionPass *Printer =291getTarget().createAsmPrinter(*this, std::move(AsmStreamer));292if (!Printer)293return true;294295PM.add(Printer);296PM.add(createFreeMachineFunctionPass());297298return false; // success!299}300301302