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