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