xref: /src/contrib/llvm-project/llvm/lib/CodeGen/LLVMTargetMachine.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583) !
1009b1c42SEd Schouten //===-- LLVMTargetMachine.cpp - Implement the LLVMTargetMachine class -----===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // This file implements the LLVMTargetMachine class.
10009b1c42SEd Schouten //
11009b1c42SEd Schouten //===----------------------------------------------------------------------===//
12009b1c42SEd Schouten 
135ca98fd9SDimitry Andric #include "llvm/Analysis/Passes.h"
1459850d08SRoman Divacky #include "llvm/CodeGen/AsmPrinter.h"
155a5ac124SDimitry Andric #include "llvm/CodeGen/BasicTTIImpl.h"
16c6910277SRoman Divacky #include "llvm/CodeGen/MachineModuleInfo.h"
174a16efa3SDimitry Andric #include "llvm/CodeGen/Passes.h"
1801095a5dSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
195a5ac124SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
20044eb2f6SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
2163faed5bSDimitry Andric #include "llvm/MC/MCAsmInfo.h"
22044eb2f6SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
2363faed5bSDimitry Andric #include "llvm/MC/MCContext.h"
2463faed5bSDimitry Andric #include "llvm/MC/MCInstrInfo.h"
25eb11fae6SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
26145449b1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
2763faed5bSDimitry Andric #include "llvm/MC/MCStreamer.h"
2863faed5bSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
29c0981da4SDimitry Andric #include "llvm/MC/TargetRegistry.h"
30009b1c42SEd Schouten #include "llvm/Support/CommandLine.h"
314a16efa3SDimitry Andric #include "llvm/Support/FormattedStream.h"
327ab83427SDimitry Andric #include "llvm/Target/TargetMachine.h"
334a16efa3SDimitry Andric #include "llvm/Target/TargetOptions.h"
34009b1c42SEd Schouten using namespace llvm;
35009b1c42SEd Schouten 
36145449b1SDimitry Andric static cl::opt<bool>
37145449b1SDimitry Andric     EnableTrapUnreachable("trap-unreachable", cl::Hidden,
38eb11fae6SDimitry Andric                           cl::desc("Enable generating trap for unreachable"));
39eb11fae6SDimitry Andric 
40b1c73532SDimitry Andric static cl::opt<bool> EnableNoTrapAfterNoreturn(
41b1c73532SDimitry Andric     "no-trap-after-noreturn", cl::Hidden,
42b1c73532SDimitry Andric     cl::desc("Do not emit a trap instruction for 'unreachable' IR instructions "
43b1c73532SDimitry Andric              "after noreturn calls, even if --trap-unreachable is set."));
44b1c73532SDimitry Andric 
initAsmInfo()45f8af5cf6SDimitry Andric void LLVMTargetMachine::initAsmInfo() {
46d8e91e46SDimitry Andric   MRI.reset(TheTarget.createMCRegInfo(getTargetTriple().str()));
47b60736ecSDimitry Andric   assert(MRI && "Unable to create reg info");
48d8e91e46SDimitry Andric   MII.reset(TheTarget.createMCInstrInfo());
49b60736ecSDimitry Andric   assert(MII && "Unable to create instruction info");
505a5ac124SDimitry Andric   // FIXME: Having an MCSubtargetInfo on the target machine is a hack due
515a5ac124SDimitry Andric   // to some backends having subtarget feature dependent module level
525a5ac124SDimitry Andric   // code generation. This is similar to the hack in the AsmPrinter for
535a5ac124SDimitry Andric   // module level assembly etc.
54d8e91e46SDimitry Andric   STI.reset(TheTarget.createMCSubtargetInfo(
55d8e91e46SDimitry Andric       getTargetTriple().str(), getTargetCPU(), getTargetFeatureString()));
56b60736ecSDimitry Andric   assert(STI && "Unable to create subtarget info");
575a5ac124SDimitry Andric 
58706b4fc4SDimitry Andric   MCAsmInfo *TmpAsmInfo = TheTarget.createMCAsmInfo(
59706b4fc4SDimitry Andric       *MRI, getTargetTriple().str(), Options.MCOptions);
6030815c53SDimitry Andric   // TargetSelect.h moved to a different directory between LLVM 2.9 and 3.0,
6130815c53SDimitry Andric   // and if the old one gets included then MCAsmInfo will be NULL and
6230815c53SDimitry Andric   // we'll crash later.
6330815c53SDimitry Andric   // Provide the user with a useful error message about what's wrong.
645ca98fd9SDimitry Andric   assert(TmpAsmInfo && "MCAsmInfo not initialized. "
65d4c8b5d2SDimitry Andric          "Make sure you include the correct TargetSelect.h"
66d4c8b5d2SDimitry Andric          "and that InitializeAllTargetMCs() is being invoked!");
675ca98fd9SDimitry Andric 
68b60736ecSDimitry Andric   if (Options.BinutilsVersion.first > 0)
69b60736ecSDimitry Andric     TmpAsmInfo->setBinutilsVersion(Options.BinutilsVersion);
70b60736ecSDimitry Andric 
71344a3780SDimitry Andric   if (Options.DisableIntegratedAS) {
725ca98fd9SDimitry Andric     TmpAsmInfo->setUseIntegratedAssembler(false);
73344a3780SDimitry Andric     // If there is explict option disable integratedAS, we can't use it for
74344a3780SDimitry Andric     // inlineasm either.
75344a3780SDimitry Andric     TmpAsmInfo->setParseInlineAsmUsingAsmParser(false);
76344a3780SDimitry Andric   }
775ca98fd9SDimitry Andric 
7801095a5dSDimitry Andric   TmpAsmInfo->setPreserveAsmComments(Options.MCOptions.PreserveAsmComments);
7901095a5dSDimitry Andric 
80b1c73532SDimitry Andric   TmpAsmInfo->setFullRegisterNames(Options.MCOptions.PPCUseFullRegisterNames);
81b1c73532SDimitry Andric 
8201095a5dSDimitry Andric   if (Options.ExceptionModel != ExceptionHandling::None)
8301095a5dSDimitry Andric     TmpAsmInfo->setExceptionsType(Options.ExceptionModel);
845ca98fd9SDimitry Andric 
85d8e91e46SDimitry Andric   AsmInfo.reset(TmpAsmInfo);
861e7804dbSRoman Divacky }
87009b1c42SEd Schouten 
LLVMTargetMachine(const Target & T,StringRef DataLayoutString,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,Reloc::Model RM,CodeModel::Model CM,CodeGenOptLevel OL)885a5ac124SDimitry Andric LLVMTargetMachine::LLVMTargetMachine(const Target &T,
895a5ac124SDimitry Andric                                      StringRef DataLayoutString,
903a0822f0SDimitry Andric                                      const Triple &TT, StringRef CPU,
9171d5a254SDimitry Andric                                      StringRef FS, const TargetOptions &Options,
92f8af5cf6SDimitry Andric                                      Reloc::Model RM, CodeModel::Model CM,
93b1c73532SDimitry Andric                                      CodeGenOptLevel OL)
943a0822f0SDimitry Andric     : TargetMachine(T, DataLayoutString, TT, CPU, FS, Options) {
9501095a5dSDimitry Andric   this->RM = RM;
9601095a5dSDimitry Andric   this->CMModel = CM;
9701095a5dSDimitry Andric   this->OptLevel = OL;
98eb11fae6SDimitry Andric 
99eb11fae6SDimitry Andric   if (EnableTrapUnreachable)
100eb11fae6SDimitry Andric     this->Options.TrapUnreachable = true;
101b1c73532SDimitry Andric   if (EnableNoTrapAfterNoreturn)
102b1c73532SDimitry Andric     this->Options.NoTrapAfterNoreturn = true;
103f8af5cf6SDimitry Andric }
104f8af5cf6SDimitry Andric 
105c7dac04cSDimitry Andric TargetTransformInfo
getTargetTransformInfo(const Function & F) const106145449b1SDimitry Andric LLVMTargetMachine::getTargetTransformInfo(const Function &F) const {
1075a5ac124SDimitry Andric   return TargetTransformInfo(BasicTTIImpl(this, F));
1084a16efa3SDimitry Andric }
1094a16efa3SDimitry Andric 
11063faed5bSDimitry Andric /// addPassesToX helper drives creation and initialization of TargetPassConfig.
111d8e91e46SDimitry Andric static TargetPassConfig *
addPassesToGenerateCode(LLVMTargetMachine & TM,PassManagerBase & PM,bool DisableVerify,MachineModuleInfoWrapperPass & MMIWP)112d8e91e46SDimitry Andric addPassesToGenerateCode(LLVMTargetMachine &TM, PassManagerBase &PM,
1131d5ae102SDimitry Andric                         bool DisableVerify,
1141d5ae102SDimitry Andric                         MachineModuleInfoWrapperPass &MMIWP) {
1155ca98fd9SDimitry Andric   // Targets may override createPassConfig to provide a target-specific
1165ca98fd9SDimitry Andric   // subclass.
117d8e91e46SDimitry Andric   TargetPassConfig *PassConfig = TM.createPassConfig(PM);
11863faed5bSDimitry Andric   // Set PassConfig options provided by TargetMachine.
11963faed5bSDimitry Andric   PassConfig->setDisableVerify(DisableVerify);
12063faed5bSDimitry Andric   PM.add(PassConfig);
1211d5ae102SDimitry Andric   PM.add(&MMIWP);
12263faed5bSDimitry Andric 
1237ab83427SDimitry Andric   if (PassConfig->addISelPasses())
12401095a5dSDimitry Andric     return nullptr;
12563faed5bSDimitry Andric   PassConfig->addMachinePasses();
12663faed5bSDimitry Andric   PassConfig->setInitialized();
127d8e91e46SDimitry Andric   return PassConfig;
12863faed5bSDimitry Andric }
12963faed5bSDimitry Andric 
addAsmPrinter(PassManagerBase & PM,raw_pwrite_stream & Out,raw_pwrite_stream * DwoOut,CodeGenFileType FileType,MCContext & Context)1307ab83427SDimitry Andric bool LLVMTargetMachine::addAsmPrinter(PassManagerBase &PM,
131eb11fae6SDimitry Andric                                       raw_pwrite_stream &Out,
132eb11fae6SDimitry Andric                                       raw_pwrite_stream *DwoOut,
133eb11fae6SDimitry Andric                                       CodeGenFileType FileType,
1347ab83427SDimitry Andric                                       MCContext &Context) {
135b60736ecSDimitry Andric   Expected<std::unique_ptr<MCStreamer>> MCStreamerOrErr =
136b60736ecSDimitry Andric       createMCStreamer(Out, DwoOut, FileType, Context);
137b60736ecSDimitry Andric   if (auto Err = MCStreamerOrErr.takeError())
138b60736ecSDimitry Andric     return true;
139b60736ecSDimitry Andric 
140b60736ecSDimitry Andric   // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
141b60736ecSDimitry Andric   FunctionPass *Printer =
142b60736ecSDimitry Andric       getTarget().createAsmPrinter(*this, std::move(*MCStreamerOrErr));
143b60736ecSDimitry Andric   if (!Printer)
144b60736ecSDimitry Andric     return true;
145b60736ecSDimitry Andric 
146b60736ecSDimitry Andric   PM.add(Printer);
147b60736ecSDimitry Andric   return false;
148b60736ecSDimitry Andric }
149b60736ecSDimitry Andric 
createMCStreamer(raw_pwrite_stream & Out,raw_pwrite_stream * DwoOut,CodeGenFileType FileType,MCContext & Context)150b60736ecSDimitry Andric Expected<std::unique_ptr<MCStreamer>> LLVMTargetMachine::createMCStreamer(
151b60736ecSDimitry Andric     raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
152b60736ecSDimitry Andric     MCContext &Context) {
1535a5ac124SDimitry Andric   const MCSubtargetInfo &STI = *getMCSubtargetInfo();
15467c32a98SDimitry Andric   const MCAsmInfo &MAI = *getMCAsmInfo();
1555a5ac124SDimitry Andric   const MCRegisterInfo &MRI = *getMCRegisterInfo();
1565a5ac124SDimitry Andric   const MCInstrInfo &MII = *getMCInstrInfo();
1575a5ac124SDimitry Andric 
1585ca98fd9SDimitry Andric   std::unique_ptr<MCStreamer> AsmStreamer;
1596fe5c7aaSRoman Divacky 
1606fe5c7aaSRoman Divacky   switch (FileType) {
161b1c73532SDimitry Andric   case CodeGenFileType::AssemblyFile: {
1625a5ac124SDimitry Andric     MCInstPrinter *InstPrinter = getTarget().createMCInstPrinter(
1633a0822f0SDimitry Andric         getTargetTriple(), MAI.getAssemblerDialect(), MAI, MII, MRI);
164abdf259dSRoman Divacky 
165abdf259dSRoman Divacky     // Create a code emitter if asked to show the encoding.
166eb11fae6SDimitry Andric     std::unique_ptr<MCCodeEmitter> MCE;
1675ca98fd9SDimitry Andric     if (Options.MCOptions.ShowMCEncoding)
168145449b1SDimitry Andric       MCE.reset(getTarget().createMCCodeEmitter(MII, Context));
169145449b1SDimitry Andric 
170eb11fae6SDimitry Andric     std::unique_ptr<MCAsmBackend> MAB(
171eb11fae6SDimitry Andric         getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions));
1721d5ae102SDimitry Andric     auto FOut = std::make_unique<formatted_raw_ostream>(Out);
1735ca98fd9SDimitry Andric     MCStreamer *S = getTarget().createAsmStreamer(
174ac9a064cSDimitry Andric         Context, std::move(FOut), InstPrinter, std::move(MCE), std::move(MAB));
175cf099d11SDimitry Andric     AsmStreamer.reset(S);
1766fe5c7aaSRoman Divacky     break;
1776fe5c7aaSRoman Divacky   }
178b1c73532SDimitry Andric   case CodeGenFileType::ObjectFile: {
1796fe5c7aaSRoman Divacky     // Create the code emitter for the target if it exists.  If not, .o file
1806fe5c7aaSRoman Divacky     // emission fails.
181145449b1SDimitry Andric     MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(MII, Context);
182b60736ecSDimitry Andric     if (!MCE)
183b60736ecSDimitry Andric       return make_error<StringError>("createMCCodeEmitter failed",
184b60736ecSDimitry Andric                                      inconvertibleErrorCode());
1853a0822f0SDimitry Andric     MCAsmBackend *MAB =
186eb11fae6SDimitry Andric         getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions);
187b60736ecSDimitry Andric     if (!MAB)
188b60736ecSDimitry Andric       return make_error<StringError>("createMCAsmBackend failed",
189b60736ecSDimitry Andric                                      inconvertibleErrorCode());
1906fe5c7aaSRoman Divacky 
1913a0822f0SDimitry Andric     Triple T(getTargetTriple().str());
1925a5ac124SDimitry Andric     AsmStreamer.reset(getTarget().createMCObjectStreamer(
193eb11fae6SDimitry Andric         T, Context, std::unique_ptr<MCAsmBackend>(MAB),
194eb11fae6SDimitry Andric         DwoOut ? MAB->createDwoObjectWriter(Out, *DwoOut)
195eb11fae6SDimitry Andric                : MAB->createObjectWriter(Out),
196ac9a064cSDimitry Andric         std::unique_ptr<MCCodeEmitter>(MCE), STI));
1976fe5c7aaSRoman Divacky     break;
1986fe5c7aaSRoman Divacky   }
199b1c73532SDimitry Andric   case CodeGenFileType::Null:
2006fe5c7aaSRoman Divacky     // The Null output is intended for use for performance analysis and testing,
2016fe5c7aaSRoman Divacky     // not real users.
2027ab83427SDimitry Andric     AsmStreamer.reset(getTarget().createNullStreamer(Context));
2036fe5c7aaSRoman Divacky     break;
2046fe5c7aaSRoman Divacky   }
2056fe5c7aaSRoman Divacky 
206b60736ecSDimitry Andric   return std::move(AsmStreamer);
2077ab83427SDimitry Andric }
2086fe5c7aaSRoman Divacky 
addPassesToEmitFile(PassManagerBase & PM,raw_pwrite_stream & Out,raw_pwrite_stream * DwoOut,CodeGenFileType FileType,bool DisableVerify,MachineModuleInfoWrapperPass * MMIWP)2091d5ae102SDimitry Andric bool LLVMTargetMachine::addPassesToEmitFile(
2101d5ae102SDimitry Andric     PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
2111d5ae102SDimitry Andric     CodeGenFileType FileType, bool DisableVerify,
2121d5ae102SDimitry Andric     MachineModuleInfoWrapperPass *MMIWP) {
2137ab83427SDimitry Andric   // Add common CodeGen passes.
2141d5ae102SDimitry Andric   if (!MMIWP)
2151d5ae102SDimitry Andric     MMIWP = new MachineModuleInfoWrapperPass(this);
216d8e91e46SDimitry Andric   TargetPassConfig *PassConfig =
2171d5ae102SDimitry Andric       addPassesToGenerateCode(*this, PM, DisableVerify, *MMIWP);
218d8e91e46SDimitry Andric   if (!PassConfig)
2197ab83427SDimitry Andric     return true;
2207ab83427SDimitry Andric 
221b60736ecSDimitry Andric   if (TargetPassConfig::willCompleteCodeGenPipeline()) {
222b60736ecSDimitry Andric     if (addAsmPrinter(PM, Out, DwoOut, FileType, MMIWP->getMMI().getContext()))
2237ab83427SDimitry Andric       return true;
224b60736ecSDimitry Andric   } else {
225b60736ecSDimitry Andric     // MIR printing is redundant with -filetype=null.
226b1c73532SDimitry Andric     if (FileType != CodeGenFileType::Null)
227b60736ecSDimitry Andric       PM.add(createPrintMIRPass(Out));
228b60736ecSDimitry Andric   }
2297ab83427SDimitry Andric 
2307ab83427SDimitry Andric   PM.add(createFreeMachineFunctionPass());
23159850d08SRoman Divacky   return false;
23259850d08SRoman Divacky }
23359850d08SRoman Divacky 
234d39c594dSDimitry Andric /// addPassesToEmitMC - Add passes to the specified pass manager to get
235d39c594dSDimitry Andric /// machine code emitted with the MCJIT. This method returns true if machine
236d39c594dSDimitry Andric /// code is not supported. It fills the MCContext Ctx pointer which can be
237d39c594dSDimitry Andric /// used to build custom MCStreamer.
238d39c594dSDimitry Andric ///
addPassesToEmitMC(PassManagerBase & PM,MCContext * & Ctx,raw_pwrite_stream & Out,bool DisableVerify)2395a5ac124SDimitry Andric bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
2405a5ac124SDimitry Andric                                           raw_pwrite_stream &Out,
241d39c594dSDimitry Andric                                           bool DisableVerify) {
242d39c594dSDimitry Andric   // Add common CodeGen passes.
2431d5ae102SDimitry Andric   MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(this);
244d8e91e46SDimitry Andric   TargetPassConfig *PassConfig =
2451d5ae102SDimitry Andric       addPassesToGenerateCode(*this, PM, DisableVerify, *MMIWP);
246d8e91e46SDimitry Andric   if (!PassConfig)
247d39c594dSDimitry Andric     return true;
248d8e91e46SDimitry Andric   assert(TargetPassConfig::willCompleteCodeGenPipeline() &&
249d8e91e46SDimitry Andric          "Cannot emit MC with limited codegen pipeline");
2506b943ff3SDimitry Andric 
2511d5ae102SDimitry Andric   Ctx = &MMIWP->getMMI().getContext();
252145449b1SDimitry Andric   // libunwind is unable to load compact unwind dynamically, so we must generate
253145449b1SDimitry Andric   // DWARF unwind info for the JIT.
254145449b1SDimitry Andric   Options.MCOptions.EmitDwarfUnwind = EmitDwarfUnwindType::Always;
2556b943ff3SDimitry Andric 
2566b943ff3SDimitry Andric   // Create the code emitter for the target if it exists.  If not, .o file
2576b943ff3SDimitry Andric   // emission fails.
258eb11fae6SDimitry Andric   const MCSubtargetInfo &STI = *getMCSubtargetInfo();
2595a5ac124SDimitry Andric   const MCRegisterInfo &MRI = *getMCRegisterInfo();
2607fa27ce4SDimitry Andric   std::unique_ptr<MCCodeEmitter> MCE(
2617fa27ce4SDimitry Andric       getTarget().createMCCodeEmitter(*getMCInstrInfo(), *Ctx));
262ac9a064cSDimitry Andric   MCAsmBackend *MAB =
263ac9a064cSDimitry Andric       getTarget().createMCAsmBackend(STI, MRI, Options.MCOptions);
2645ca98fd9SDimitry Andric   if (!MCE || !MAB)
2656b943ff3SDimitry Andric     return true;
2666b943ff3SDimitry Andric 
2673a0822f0SDimitry Andric   const Triple &T = getTargetTriple();
2685a5ac124SDimitry Andric   std::unique_ptr<MCStreamer> AsmStreamer(getTarget().createMCObjectStreamer(
269ac9a064cSDimitry Andric       T, *Ctx, std::unique_ptr<MCAsmBackend>(MAB), MAB->createObjectWriter(Out),
270ac9a064cSDimitry Andric       std::move(MCE), STI));
2716b943ff3SDimitry Andric 
2726b943ff3SDimitry Andric   // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
2735a5ac124SDimitry Andric   FunctionPass *Printer =
2745a5ac124SDimitry Andric       getTarget().createAsmPrinter(*this, std::move(AsmStreamer));
2755ca98fd9SDimitry Andric   if (!Printer)
2766b943ff3SDimitry Andric     return true;
2776b943ff3SDimitry Andric 
2786b943ff3SDimitry Andric   PM.add(Printer);
279b915e9e0SDimitry Andric   PM.add(createFreeMachineFunctionPass());
2806b943ff3SDimitry Andric 
281d39c594dSDimitry Andric   return false; // success!
282d39c594dSDimitry Andric }
283