1e5dd7070Spatrick //===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick
9e5dd7070Spatrick #include "clang/CodeGen/BackendUtil.h"
10e5dd7070Spatrick #include "clang/Basic/CodeGenOptions.h"
11e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
12e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
13e5dd7070Spatrick #include "clang/Basic/TargetOptions.h"
14e5dd7070Spatrick #include "clang/Frontend/FrontendDiagnostic.h"
15e5dd7070Spatrick #include "clang/Frontend/Utils.h"
16e5dd7070Spatrick #include "clang/Lex/HeaderSearchOptions.h"
17e5dd7070Spatrick #include "llvm/ADT/SmallSet.h"
18e5dd7070Spatrick #include "llvm/ADT/StringExtras.h"
19e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
20e5dd7070Spatrick #include "llvm/ADT/Triple.h"
21a9ac8606Spatrick #include "llvm/Analysis/AliasAnalysis.h"
22*12c85518Srobert #include "llvm/Analysis/GlobalsModRef.h"
23ec727ea7Spatrick #include "llvm/Analysis/StackSafetyAnalysis.h"
24e5dd7070Spatrick #include "llvm/Analysis/TargetLibraryInfo.h"
25e5dd7070Spatrick #include "llvm/Analysis/TargetTransformInfo.h"
26e5dd7070Spatrick #include "llvm/Bitcode/BitcodeReader.h"
27e5dd7070Spatrick #include "llvm/Bitcode/BitcodeWriter.h"
28e5dd7070Spatrick #include "llvm/Bitcode/BitcodeWriterPass.h"
29e5dd7070Spatrick #include "llvm/CodeGen/RegAllocRegistry.h"
30e5dd7070Spatrick #include "llvm/CodeGen/SchedulerRegistry.h"
31e5dd7070Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
32e5dd7070Spatrick #include "llvm/IR/DataLayout.h"
33*12c85518Srobert #include "llvm/IR/DebugInfo.h"
34e5dd7070Spatrick #include "llvm/IR/LegacyPassManager.h"
35e5dd7070Spatrick #include "llvm/IR/Module.h"
36e5dd7070Spatrick #include "llvm/IR/ModuleSummaryIndex.h"
37ec727ea7Spatrick #include "llvm/IR/PassManager.h"
38e5dd7070Spatrick #include "llvm/IR/Verifier.h"
39*12c85518Srobert #include "llvm/IRPrinter/IRPrintingPasses.h"
40e5dd7070Spatrick #include "llvm/LTO/LTOBackend.h"
41e5dd7070Spatrick #include "llvm/MC/MCAsmInfo.h"
42e5dd7070Spatrick #include "llvm/MC/SubtargetFeature.h"
43*12c85518Srobert #include "llvm/MC/TargetRegistry.h"
44*12c85518Srobert #include "llvm/Object/OffloadBinary.h"
45e5dd7070Spatrick #include "llvm/Passes/PassBuilder.h"
46e5dd7070Spatrick #include "llvm/Passes/PassPlugin.h"
47e5dd7070Spatrick #include "llvm/Passes/StandardInstrumentations.h"
48e5dd7070Spatrick #include "llvm/Support/BuryPointer.h"
49e5dd7070Spatrick #include "llvm/Support/CommandLine.h"
50e5dd7070Spatrick #include "llvm/Support/MemoryBuffer.h"
51e5dd7070Spatrick #include "llvm/Support/PrettyStackTrace.h"
52e5dd7070Spatrick #include "llvm/Support/TimeProfiler.h"
53e5dd7070Spatrick #include "llvm/Support/Timer.h"
54ec727ea7Spatrick #include "llvm/Support/ToolOutputFile.h"
55e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
56e5dd7070Spatrick #include "llvm/Target/TargetMachine.h"
57e5dd7070Spatrick #include "llvm/Target/TargetOptions.h"
58ec727ea7Spatrick #include "llvm/Transforms/Coroutines/CoroCleanup.h"
59ec727ea7Spatrick #include "llvm/Transforms/Coroutines/CoroEarly.h"
60ec727ea7Spatrick #include "llvm/Transforms/Coroutines/CoroElide.h"
61ec727ea7Spatrick #include "llvm/Transforms/Coroutines/CoroSplit.h"
62e5dd7070Spatrick #include "llvm/Transforms/IPO.h"
63e5dd7070Spatrick #include "llvm/Transforms/IPO/AlwaysInliner.h"
64ec727ea7Spatrick #include "llvm/Transforms/IPO/LowerTypeTests.h"
65e5dd7070Spatrick #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
66e5dd7070Spatrick #include "llvm/Transforms/InstCombine/InstCombine.h"
67e5dd7070Spatrick #include "llvm/Transforms/Instrumentation.h"
68e5dd7070Spatrick #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
69a9ac8606Spatrick #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
70e5dd7070Spatrick #include "llvm/Transforms/Instrumentation/BoundsChecking.h"
71a9ac8606Spatrick #include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
72e5dd7070Spatrick #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
73e5dd7070Spatrick #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
74e5dd7070Spatrick #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
75*12c85518Srobert #include "llvm/Transforms/Instrumentation/KCFI.h"
76a9ac8606Spatrick #include "llvm/Transforms/Instrumentation/MemProfiler.h"
77e5dd7070Spatrick #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
78*12c85518Srobert #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
79e5dd7070Spatrick #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
80e5dd7070Spatrick #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
81e5dd7070Spatrick #include "llvm/Transforms/ObjCARC.h"
82e5dd7070Spatrick #include "llvm/Transforms/Scalar.h"
83a9ac8606Spatrick #include "llvm/Transforms/Scalar/EarlyCSE.h"
84e5dd7070Spatrick #include "llvm/Transforms/Scalar/GVN.h"
85*12c85518Srobert #include "llvm/Transforms/Scalar/JumpThreading.h"
86a9ac8606Spatrick #include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h"
87e5dd7070Spatrick #include "llvm/Transforms/Utils.h"
88e5dd7070Spatrick #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
89a9ac8606Spatrick #include "llvm/Transforms/Utils/Debugify.h"
90e5dd7070Spatrick #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
91*12c85518Srobert #include "llvm/Transforms/Utils/ModuleUtils.h"
92e5dd7070Spatrick #include "llvm/Transforms/Utils/NameAnonGlobals.h"
93e5dd7070Spatrick #include "llvm/Transforms/Utils/SymbolRewriter.h"
94e5dd7070Spatrick #include <memory>
95*12c85518Srobert #include <optional>
96e5dd7070Spatrick using namespace clang;
97e5dd7070Spatrick using namespace llvm;
98e5dd7070Spatrick
99e5dd7070Spatrick #define HANDLE_EXTENSION(Ext) \
100e5dd7070Spatrick llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
101e5dd7070Spatrick #include "llvm/Support/Extension.def"
102e5dd7070Spatrick
103*12c85518Srobert namespace llvm {
104*12c85518Srobert extern cl::opt<bool> DebugInfoCorrelate;
105*12c85518Srobert
106*12c85518Srobert // Experiment to move sanitizers earlier.
107*12c85518Srobert static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(
108*12c85518Srobert "sanitizer-early-opt-ep", cl::Optional,
109*12c85518Srobert cl::desc("Insert sanitizers on OptimizerEarlyEP."), cl::init(false));
110*12c85518Srobert }
111*12c85518Srobert
112e5dd7070Spatrick namespace {
113e5dd7070Spatrick
114e5dd7070Spatrick // Default filename used for profile generation.
getDefaultProfileGenName()115*12c85518Srobert std::string getDefaultProfileGenName() {
116*12c85518Srobert return DebugInfoCorrelate ? "default_%p.proflite" : "default_%m.profraw";
117*12c85518Srobert }
118e5dd7070Spatrick
119e5dd7070Spatrick class EmitAssemblyHelper {
120e5dd7070Spatrick DiagnosticsEngine &Diags;
121e5dd7070Spatrick const HeaderSearchOptions &HSOpts;
122e5dd7070Spatrick const CodeGenOptions &CodeGenOpts;
123e5dd7070Spatrick const clang::TargetOptions &TargetOpts;
124e5dd7070Spatrick const LangOptions &LangOpts;
125e5dd7070Spatrick Module *TheModule;
126e5dd7070Spatrick
127e5dd7070Spatrick Timer CodeGenerationTime;
128e5dd7070Spatrick
129e5dd7070Spatrick std::unique_ptr<raw_pwrite_stream> OS;
130e5dd7070Spatrick
131*12c85518Srobert Triple TargetTriple;
132*12c85518Srobert
getTargetIRAnalysis() const133e5dd7070Spatrick TargetIRAnalysis getTargetIRAnalysis() const {
134e5dd7070Spatrick if (TM)
135e5dd7070Spatrick return TM->getTargetIRAnalysis();
136e5dd7070Spatrick
137e5dd7070Spatrick return TargetIRAnalysis();
138e5dd7070Spatrick }
139e5dd7070Spatrick
140e5dd7070Spatrick /// Generates the TargetMachine.
141e5dd7070Spatrick /// Leaves TM unchanged if it is unable to create the target machine.
142e5dd7070Spatrick /// Some of our clang tests specify triples which are not built
143e5dd7070Spatrick /// into clang. This is okay because these tests check the generated
144e5dd7070Spatrick /// IR, and they require DataLayout which depends on the triple.
145e5dd7070Spatrick /// In this case, we allow this method to fail and not report an error.
146e5dd7070Spatrick /// When MustCreateTM is used, we print an error if we are unable to load
147e5dd7070Spatrick /// the requested target.
148e5dd7070Spatrick void CreateTargetMachine(bool MustCreateTM);
149e5dd7070Spatrick
150e5dd7070Spatrick /// Add passes necessary to emit assembly or LLVM IR.
151e5dd7070Spatrick ///
152e5dd7070Spatrick /// \return True on success.
153e5dd7070Spatrick bool AddEmitPasses(legacy::PassManager &CodeGenPasses, BackendAction Action,
154e5dd7070Spatrick raw_pwrite_stream &OS, raw_pwrite_stream *DwoOS);
155e5dd7070Spatrick
openOutputFile(StringRef Path)156e5dd7070Spatrick std::unique_ptr<llvm::ToolOutputFile> openOutputFile(StringRef Path) {
157e5dd7070Spatrick std::error_code EC;
158e5dd7070Spatrick auto F = std::make_unique<llvm::ToolOutputFile>(Path, EC,
159e5dd7070Spatrick llvm::sys::fs::OF_None);
160e5dd7070Spatrick if (EC) {
161e5dd7070Spatrick Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
162e5dd7070Spatrick F.reset();
163e5dd7070Spatrick }
164e5dd7070Spatrick return F;
165e5dd7070Spatrick }
166e5dd7070Spatrick
167*12c85518Srobert void
168*12c85518Srobert RunOptimizationPipeline(BackendAction Action,
169*12c85518Srobert std::unique_ptr<raw_pwrite_stream> &OS,
170*12c85518Srobert std::unique_ptr<llvm::ToolOutputFile> &ThinLinkOS);
171*12c85518Srobert void RunCodegenPipeline(BackendAction Action,
172*12c85518Srobert std::unique_ptr<raw_pwrite_stream> &OS,
173*12c85518Srobert std::unique_ptr<llvm::ToolOutputFile> &DwoOS);
174*12c85518Srobert
175*12c85518Srobert /// Check whether we should emit a module summary for regular LTO.
176*12c85518Srobert /// The module summary should be emitted by default for regular LTO
177*12c85518Srobert /// except for ld64 targets.
178*12c85518Srobert ///
179*12c85518Srobert /// \return True if the module summary should be emitted.
shouldEmitRegularLTOSummary() const180*12c85518Srobert bool shouldEmitRegularLTOSummary() const {
181*12c85518Srobert return CodeGenOpts.PrepareForLTO && !CodeGenOpts.DisableLLVMPasses &&
182*12c85518Srobert TargetTriple.getVendor() != llvm::Triple::Apple;
183*12c85518Srobert }
184*12c85518Srobert
185e5dd7070Spatrick public:
EmitAssemblyHelper(DiagnosticsEngine & _Diags,const HeaderSearchOptions & HeaderSearchOpts,const CodeGenOptions & CGOpts,const clang::TargetOptions & TOpts,const LangOptions & LOpts,Module * M)186e5dd7070Spatrick EmitAssemblyHelper(DiagnosticsEngine &_Diags,
187e5dd7070Spatrick const HeaderSearchOptions &HeaderSearchOpts,
188e5dd7070Spatrick const CodeGenOptions &CGOpts,
189e5dd7070Spatrick const clang::TargetOptions &TOpts,
190e5dd7070Spatrick const LangOptions &LOpts, Module *M)
191e5dd7070Spatrick : Diags(_Diags), HSOpts(HeaderSearchOpts), CodeGenOpts(CGOpts),
192e5dd7070Spatrick TargetOpts(TOpts), LangOpts(LOpts), TheModule(M),
193*12c85518Srobert CodeGenerationTime("codegen", "Code Generation Time"),
194*12c85518Srobert TargetTriple(TheModule->getTargetTriple()) {}
195e5dd7070Spatrick
~EmitAssemblyHelper()196e5dd7070Spatrick ~EmitAssemblyHelper() {
197e5dd7070Spatrick if (CodeGenOpts.DisableFree)
198e5dd7070Spatrick BuryPointer(std::move(TM));
199e5dd7070Spatrick }
200e5dd7070Spatrick
201e5dd7070Spatrick std::unique_ptr<TargetMachine> TM;
202e5dd7070Spatrick
203*12c85518Srobert // Emit output using the new pass manager for the optimization pipeline.
204e5dd7070Spatrick void EmitAssembly(BackendAction Action,
205e5dd7070Spatrick std::unique_ptr<raw_pwrite_stream> OS);
206e5dd7070Spatrick };
207e5dd7070Spatrick }
208e5dd7070Spatrick
209e5dd7070Spatrick static SanitizerCoverageOptions
getSancovOptsFromCGOpts(const CodeGenOptions & CGOpts)210e5dd7070Spatrick getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) {
211e5dd7070Spatrick SanitizerCoverageOptions Opts;
212e5dd7070Spatrick Opts.CoverageType =
213e5dd7070Spatrick static_cast<SanitizerCoverageOptions::Type>(CGOpts.SanitizeCoverageType);
214e5dd7070Spatrick Opts.IndirectCalls = CGOpts.SanitizeCoverageIndirectCalls;
215e5dd7070Spatrick Opts.TraceBB = CGOpts.SanitizeCoverageTraceBB;
216e5dd7070Spatrick Opts.TraceCmp = CGOpts.SanitizeCoverageTraceCmp;
217e5dd7070Spatrick Opts.TraceDiv = CGOpts.SanitizeCoverageTraceDiv;
218e5dd7070Spatrick Opts.TraceGep = CGOpts.SanitizeCoverageTraceGep;
219e5dd7070Spatrick Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters;
220e5dd7070Spatrick Opts.TracePC = CGOpts.SanitizeCoverageTracePC;
221e5dd7070Spatrick Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard;
222e5dd7070Spatrick Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune;
223e5dd7070Spatrick Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters;
224ec727ea7Spatrick Opts.InlineBoolFlag = CGOpts.SanitizeCoverageInlineBoolFlag;
225e5dd7070Spatrick Opts.PCTable = CGOpts.SanitizeCoveragePCTable;
226e5dd7070Spatrick Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth;
227*12c85518Srobert Opts.TraceLoads = CGOpts.SanitizeCoverageTraceLoads;
228*12c85518Srobert Opts.TraceStores = CGOpts.SanitizeCoverageTraceStores;
229*12c85518Srobert Opts.CollectControlFlow = CGOpts.SanitizeCoverageControlFlow;
230e5dd7070Spatrick return Opts;
231e5dd7070Spatrick }
232e5dd7070Spatrick
233*12c85518Srobert static SanitizerBinaryMetadataOptions
getSanitizerBinaryMetadataOptions(const CodeGenOptions & CGOpts)234*12c85518Srobert getSanitizerBinaryMetadataOptions(const CodeGenOptions &CGOpts) {
235*12c85518Srobert SanitizerBinaryMetadataOptions Opts;
236*12c85518Srobert Opts.Covered = CGOpts.SanitizeBinaryMetadataCovered;
237*12c85518Srobert Opts.Atomics = CGOpts.SanitizeBinaryMetadataAtomics;
238*12c85518Srobert Opts.UAR = CGOpts.SanitizeBinaryMetadataUAR;
239*12c85518Srobert return Opts;
240e5dd7070Spatrick }
241e5dd7070Spatrick
242e5dd7070Spatrick // Check if ASan should use GC-friendly instrumentation for globals.
243e5dd7070Spatrick // First of all, there is no point if -fdata-sections is off (expect for MachO,
244e5dd7070Spatrick // where this is not a factor). Also, on ELF this feature requires an assembler
245e5dd7070Spatrick // extension that only works with -integrated-as at the moment.
asanUseGlobalsGC(const Triple & T,const CodeGenOptions & CGOpts)246e5dd7070Spatrick static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) {
247e5dd7070Spatrick if (!CGOpts.SanitizeAddressGlobalsDeadStripping)
248e5dd7070Spatrick return false;
249e5dd7070Spatrick switch (T.getObjectFormat()) {
250e5dd7070Spatrick case Triple::MachO:
251e5dd7070Spatrick case Triple::COFF:
252e5dd7070Spatrick return true;
253e5dd7070Spatrick case Triple::ELF:
254*12c85518Srobert return !CGOpts.DisableIntegratedAS;
255a9ac8606Spatrick case Triple::GOFF:
256a9ac8606Spatrick llvm::report_fatal_error("ASan not implemented for GOFF");
257e5dd7070Spatrick case Triple::XCOFF:
258e5dd7070Spatrick llvm::report_fatal_error("ASan not implemented for XCOFF.");
259e5dd7070Spatrick case Triple::Wasm:
260*12c85518Srobert case Triple::DXContainer:
261*12c85518Srobert case Triple::SPIRV:
262e5dd7070Spatrick case Triple::UnknownObjectFormat:
263e5dd7070Spatrick break;
264e5dd7070Spatrick }
265e5dd7070Spatrick return false;
266e5dd7070Spatrick }
267e5dd7070Spatrick
createTLII(llvm::Triple & TargetTriple,const CodeGenOptions & CodeGenOpts)268e5dd7070Spatrick static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
269e5dd7070Spatrick const CodeGenOptions &CodeGenOpts) {
270e5dd7070Spatrick TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
271e5dd7070Spatrick
272e5dd7070Spatrick switch (CodeGenOpts.getVecLib()) {
273e5dd7070Spatrick case CodeGenOptions::Accelerate:
274*12c85518Srobert TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::Accelerate,
275*12c85518Srobert TargetTriple);
276e5dd7070Spatrick break;
277a9ac8606Spatrick case CodeGenOptions::LIBMVEC:
278*12c85518Srobert TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::LIBMVEC_X86,
279*12c85518Srobert TargetTriple);
280a9ac8606Spatrick break;
281e5dd7070Spatrick case CodeGenOptions::MASSV:
282*12c85518Srobert TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::MASSV,
283*12c85518Srobert TargetTriple);
284e5dd7070Spatrick break;
285e5dd7070Spatrick case CodeGenOptions::SVML:
286*12c85518Srobert TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML,
287*12c85518Srobert TargetTriple);
288*12c85518Srobert break;
289*12c85518Srobert case CodeGenOptions::SLEEF:
290*12c85518Srobert TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SLEEFGNUABI,
291*12c85518Srobert TargetTriple);
292e5dd7070Spatrick break;
293a9ac8606Spatrick case CodeGenOptions::Darwin_libsystem_m:
294a9ac8606Spatrick TLII->addVectorizableFunctionsFromVecLib(
295*12c85518Srobert TargetLibraryInfoImpl::DarwinLibSystemM, TargetTriple);
296a9ac8606Spatrick break;
297e5dd7070Spatrick default:
298e5dd7070Spatrick break;
299e5dd7070Spatrick }
300e5dd7070Spatrick return TLII;
301e5dd7070Spatrick }
302e5dd7070Spatrick
303*12c85518Srobert static std::optional<llvm::CodeModel::Model>
getCodeModel(const CodeGenOptions & CodeGenOpts)304e5dd7070Spatrick getCodeModel(const CodeGenOptions &CodeGenOpts) {
305e5dd7070Spatrick unsigned CodeModel = llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel)
306e5dd7070Spatrick .Case("tiny", llvm::CodeModel::Tiny)
307e5dd7070Spatrick .Case("small", llvm::CodeModel::Small)
308e5dd7070Spatrick .Case("kernel", llvm::CodeModel::Kernel)
309e5dd7070Spatrick .Case("medium", llvm::CodeModel::Medium)
310e5dd7070Spatrick .Case("large", llvm::CodeModel::Large)
311e5dd7070Spatrick .Case("default", ~1u)
312e5dd7070Spatrick .Default(~0u);
313e5dd7070Spatrick assert(CodeModel != ~0u && "invalid code model!");
314e5dd7070Spatrick if (CodeModel == ~1u)
315*12c85518Srobert return std::nullopt;
316e5dd7070Spatrick return static_cast<llvm::CodeModel::Model>(CodeModel);
317e5dd7070Spatrick }
318e5dd7070Spatrick
getCodeGenFileType(BackendAction Action)319e5dd7070Spatrick static CodeGenFileType getCodeGenFileType(BackendAction Action) {
320e5dd7070Spatrick if (Action == Backend_EmitObj)
321e5dd7070Spatrick return CGFT_ObjectFile;
322e5dd7070Spatrick else if (Action == Backend_EmitMCNull)
323e5dd7070Spatrick return CGFT_Null;
324e5dd7070Spatrick else {
325e5dd7070Spatrick assert(Action == Backend_EmitAssembly && "Invalid action!");
326e5dd7070Spatrick return CGFT_AssemblyFile;
327e5dd7070Spatrick }
328e5dd7070Spatrick }
329e5dd7070Spatrick
actionRequiresCodeGen(BackendAction Action)330*12c85518Srobert static bool actionRequiresCodeGen(BackendAction Action) {
331*12c85518Srobert return Action != Backend_EmitNothing && Action != Backend_EmitBC &&
332*12c85518Srobert Action != Backend_EmitLL;
333*12c85518Srobert }
334*12c85518Srobert
initTargetOptions(DiagnosticsEngine & Diags,llvm::TargetOptions & Options,const CodeGenOptions & CodeGenOpts,const clang::TargetOptions & TargetOpts,const LangOptions & LangOpts,const HeaderSearchOptions & HSOpts)335a9ac8606Spatrick static bool initTargetOptions(DiagnosticsEngine &Diags,
336ec727ea7Spatrick llvm::TargetOptions &Options,
337e5dd7070Spatrick const CodeGenOptions &CodeGenOpts,
338e5dd7070Spatrick const clang::TargetOptions &TargetOpts,
339e5dd7070Spatrick const LangOptions &LangOpts,
340e5dd7070Spatrick const HeaderSearchOptions &HSOpts) {
341a9ac8606Spatrick switch (LangOpts.getThreadModel()) {
342a9ac8606Spatrick case LangOptions::ThreadModelKind::POSIX:
343a9ac8606Spatrick Options.ThreadModel = llvm::ThreadModel::POSIX;
344a9ac8606Spatrick break;
345a9ac8606Spatrick case LangOptions::ThreadModelKind::Single:
346a9ac8606Spatrick Options.ThreadModel = llvm::ThreadModel::Single;
347a9ac8606Spatrick break;
348a9ac8606Spatrick }
349e5dd7070Spatrick
350e5dd7070Spatrick // Set float ABI type.
351e5dd7070Spatrick assert((CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp" ||
352e5dd7070Spatrick CodeGenOpts.FloatABI == "hard" || CodeGenOpts.FloatABI.empty()) &&
353e5dd7070Spatrick "Invalid Floating Point ABI!");
354e5dd7070Spatrick Options.FloatABIType =
355e5dd7070Spatrick llvm::StringSwitch<llvm::FloatABI::ABIType>(CodeGenOpts.FloatABI)
356e5dd7070Spatrick .Case("soft", llvm::FloatABI::Soft)
357e5dd7070Spatrick .Case("softfp", llvm::FloatABI::Soft)
358e5dd7070Spatrick .Case("hard", llvm::FloatABI::Hard)
359e5dd7070Spatrick .Default(llvm::FloatABI::Default);
360e5dd7070Spatrick
361e5dd7070Spatrick // Set FP fusion mode.
362e5dd7070Spatrick switch (LangOpts.getDefaultFPContractMode()) {
363ec727ea7Spatrick case LangOptions::FPM_Off:
364e5dd7070Spatrick // Preserve any contraction performed by the front-end. (Strict performs
365e5dd7070Spatrick // splitting of the muladd intrinsic in the backend.)
366e5dd7070Spatrick Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
367e5dd7070Spatrick break;
368ec727ea7Spatrick case LangOptions::FPM_On:
369a9ac8606Spatrick case LangOptions::FPM_FastHonorPragmas:
370e5dd7070Spatrick Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
371e5dd7070Spatrick break;
372ec727ea7Spatrick case LangOptions::FPM_Fast:
373e5dd7070Spatrick Options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
374e5dd7070Spatrick break;
375e5dd7070Spatrick }
376e5dd7070Spatrick
377a9ac8606Spatrick Options.BinutilsVersion =
378a9ac8606Spatrick llvm::TargetMachine::parseBinutilsVersion(CodeGenOpts.BinutilsVersion);
379e5dd7070Spatrick Options.UseInitArray = CodeGenOpts.UseInitArray;
380*12c85518Srobert Options.LowerGlobalDtorsViaCxaAtExit =
381*12c85518Srobert CodeGenOpts.RegisterGlobalDtorsWithAtExit;
382e5dd7070Spatrick Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS;
383e5dd7070Spatrick Options.CompressDebugSections = CodeGenOpts.getCompressDebugSections();
384e5dd7070Spatrick Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations;
385e5dd7070Spatrick
386e5dd7070Spatrick // Set EABI version.
387e5dd7070Spatrick Options.EABIVersion = TargetOpts.EABIVersion;
388e5dd7070Spatrick
389a9ac8606Spatrick if (LangOpts.hasSjLjExceptions())
390e5dd7070Spatrick Options.ExceptionModel = llvm::ExceptionHandling::SjLj;
391a9ac8606Spatrick if (LangOpts.hasSEHExceptions())
392e5dd7070Spatrick Options.ExceptionModel = llvm::ExceptionHandling::WinEH;
393a9ac8606Spatrick if (LangOpts.hasDWARFExceptions())
394e5dd7070Spatrick Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI;
395a9ac8606Spatrick if (LangOpts.hasWasmExceptions())
396e5dd7070Spatrick Options.ExceptionModel = llvm::ExceptionHandling::Wasm;
397e5dd7070Spatrick
398ec727ea7Spatrick Options.NoInfsFPMath = LangOpts.NoHonorInfs;
399ec727ea7Spatrick Options.NoNaNsFPMath = LangOpts.NoHonorNaNs;
400e5dd7070Spatrick Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
401*12c85518Srobert Options.UnsafeFPMath = LangOpts.AllowFPReassoc && LangOpts.AllowRecip &&
402*12c85518Srobert LangOpts.NoSignedZero && LangOpts.ApproxFunc &&
403*12c85518Srobert (LangOpts.getDefaultFPContractMode() ==
404*12c85518Srobert LangOptions::FPModeKind::FPM_Fast ||
405*12c85518Srobert LangOpts.getDefaultFPContractMode() ==
406*12c85518Srobert LangOptions::FPModeKind::FPM_FastHonorPragmas);
407*12c85518Srobert Options.ApproxFuncFPMath = LangOpts.ApproxFunc;
408ec727ea7Spatrick
409ec727ea7Spatrick Options.BBSections =
410ec727ea7Spatrick llvm::StringSwitch<llvm::BasicBlockSection>(CodeGenOpts.BBSections)
411ec727ea7Spatrick .Case("all", llvm::BasicBlockSection::All)
412ec727ea7Spatrick .Case("labels", llvm::BasicBlockSection::Labels)
413ec727ea7Spatrick .StartsWith("list=", llvm::BasicBlockSection::List)
414ec727ea7Spatrick .Case("none", llvm::BasicBlockSection::None)
415ec727ea7Spatrick .Default(llvm::BasicBlockSection::None);
416ec727ea7Spatrick
417ec727ea7Spatrick if (Options.BBSections == llvm::BasicBlockSection::List) {
418ec727ea7Spatrick ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
419ec727ea7Spatrick MemoryBuffer::getFile(CodeGenOpts.BBSections.substr(5));
420a9ac8606Spatrick if (!MBOrErr) {
421ec727ea7Spatrick Diags.Report(diag::err_fe_unable_to_load_basic_block_sections_file)
422ec727ea7Spatrick << MBOrErr.getError().message();
423a9ac8606Spatrick return false;
424a9ac8606Spatrick }
425ec727ea7Spatrick Options.BBSectionsFuncListBuf = std::move(*MBOrErr);
426ec727ea7Spatrick }
427ec727ea7Spatrick
428a9ac8606Spatrick Options.EnableMachineFunctionSplitter = CodeGenOpts.SplitMachineFunctions;
429e5dd7070Spatrick Options.FunctionSections = CodeGenOpts.FunctionSections;
430e5dd7070Spatrick Options.DataSections = CodeGenOpts.DataSections;
431a9ac8606Spatrick Options.IgnoreXCOFFVisibility = LangOpts.IgnoreXCOFFVisibility;
432e5dd7070Spatrick Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames;
433ec727ea7Spatrick Options.UniqueBasicBlockSectionNames =
434ec727ea7Spatrick CodeGenOpts.UniqueBasicBlockSectionNames;
435e5dd7070Spatrick Options.TLSSize = CodeGenOpts.TLSSize;
436e5dd7070Spatrick Options.EmulatedTLS = CodeGenOpts.EmulatedTLS;
437*12c85518Srobert Options.ExplicitEmulatedTLS = true;
438e5dd7070Spatrick Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
439e5dd7070Spatrick Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
440a9ac8606Spatrick Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;
441e5dd7070Spatrick Options.EmitAddrsig = CodeGenOpts.Addrsig;
442e5dd7070Spatrick Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
443ec727ea7Spatrick Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;
444a9ac8606Spatrick Options.EnableAIXExtendedAltivecABI = CodeGenOpts.EnableAIXExtendedAltivecABI;
445ec727ea7Spatrick Options.XRayOmitFunctionIndex = CodeGenOpts.XRayOmitFunctionIndex;
446*12c85518Srobert Options.LoopAlignment = CodeGenOpts.LoopAlignment;
447*12c85518Srobert Options.DebugStrictDwarf = CodeGenOpts.DebugStrictDwarf;
448*12c85518Srobert Options.ObjectFilenameForDebug = CodeGenOpts.ObjectFilenameForDebug;
449*12c85518Srobert Options.Hotpatch = CodeGenOpts.HotPatch;
450*12c85518Srobert Options.JMCInstrument = CodeGenOpts.JMCInstrument;
451*12c85518Srobert
452*12c85518Srobert switch (CodeGenOpts.getSwiftAsyncFramePointer()) {
453*12c85518Srobert case CodeGenOptions::SwiftAsyncFramePointerKind::Auto:
454*12c85518Srobert Options.SwiftAsyncFramePointer =
455*12c85518Srobert SwiftAsyncFramePointerMode::DeploymentBased;
456*12c85518Srobert break;
457*12c85518Srobert
458*12c85518Srobert case CodeGenOptions::SwiftAsyncFramePointerKind::Always:
459*12c85518Srobert Options.SwiftAsyncFramePointer = SwiftAsyncFramePointerMode::Always;
460*12c85518Srobert break;
461*12c85518Srobert
462*12c85518Srobert case CodeGenOptions::SwiftAsyncFramePointerKind::Never:
463*12c85518Srobert Options.SwiftAsyncFramePointer = SwiftAsyncFramePointerMode::Never;
464*12c85518Srobert break;
465*12c85518Srobert }
466e5dd7070Spatrick
467e5dd7070Spatrick Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
468*12c85518Srobert Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind();
469e5dd7070Spatrick Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;
470e5dd7070Spatrick Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;
471*12c85518Srobert Options.MCOptions.MCUseDwarfDirectory =
472*12c85518Srobert CodeGenOpts.NoDwarfDirectoryAsm
473*12c85518Srobert ? llvm::MCTargetOptions::DisableDwarfDirectory
474*12c85518Srobert : llvm::MCTargetOptions::EnableDwarfDirectory;
475e5dd7070Spatrick Options.MCOptions.MCNoExecStack = CodeGenOpts.NoExecStack;
476e5dd7070Spatrick Options.MCOptions.MCIncrementalLinkerCompatible =
477e5dd7070Spatrick CodeGenOpts.IncrementalLinkerCompatible;
478e5dd7070Spatrick Options.MCOptions.MCFatalWarnings = CodeGenOpts.FatalWarnings;
479e5dd7070Spatrick Options.MCOptions.MCNoWarn = CodeGenOpts.NoWarn;
480e5dd7070Spatrick Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose;
481a9ac8606Spatrick Options.MCOptions.Dwarf64 = CodeGenOpts.Dwarf64;
482e5dd7070Spatrick Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments;
483e5dd7070Spatrick Options.MCOptions.ABIName = TargetOpts.ABI;
484e5dd7070Spatrick for (const auto &Entry : HSOpts.UserEntries)
485e5dd7070Spatrick if (!Entry.IsFramework &&
486e5dd7070Spatrick (Entry.Group == frontend::IncludeDirGroup::Quoted ||
487e5dd7070Spatrick Entry.Group == frontend::IncludeDirGroup::Angled ||
488e5dd7070Spatrick Entry.Group == frontend::IncludeDirGroup::System))
489e5dd7070Spatrick Options.MCOptions.IASSearchPaths.push_back(
490e5dd7070Spatrick Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path);
491ec727ea7Spatrick Options.MCOptions.Argv0 = CodeGenOpts.Argv0;
492ec727ea7Spatrick Options.MCOptions.CommandLineArgs = CodeGenOpts.CommandLineArgs;
493*12c85518Srobert Options.MCOptions.AsSecureLogFile = CodeGenOpts.AsSecureLogFile;
494*12c85518Srobert Options.MisExpect = CodeGenOpts.MisExpect;
495a9ac8606Spatrick
496a9ac8606Spatrick return true;
497e5dd7070Spatrick }
498a9ac8606Spatrick
499*12c85518Srobert static std::optional<GCOVOptions>
getGCOVOptions(const CodeGenOptions & CodeGenOpts,const LangOptions & LangOpts)500*12c85518Srobert getGCOVOptions(const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts) {
501e5dd7070Spatrick if (!CodeGenOpts.EmitGcovArcs && !CodeGenOpts.EmitGcovNotes)
502*12c85518Srobert return std::nullopt;
503e5dd7070Spatrick // Not using 'GCOVOptions::getDefault' allows us to avoid exiting if
504e5dd7070Spatrick // LLVM's -default-gcov-version flag is set to something invalid.
505e5dd7070Spatrick GCOVOptions Options;
506e5dd7070Spatrick Options.EmitNotes = CodeGenOpts.EmitGcovNotes;
507e5dd7070Spatrick Options.EmitData = CodeGenOpts.EmitGcovArcs;
508e5dd7070Spatrick llvm::copy(CodeGenOpts.CoverageVersion, std::begin(Options.Version));
509e5dd7070Spatrick Options.NoRedZone = CodeGenOpts.DisableRedZone;
510e5dd7070Spatrick Options.Filter = CodeGenOpts.ProfileFilterFiles;
511e5dd7070Spatrick Options.Exclude = CodeGenOpts.ProfileExcludeFiles;
512a9ac8606Spatrick Options.Atomic = CodeGenOpts.AtomicProfileUpdate;
513e5dd7070Spatrick return Options;
514e5dd7070Spatrick }
515e5dd7070Spatrick
516*12c85518Srobert static std::optional<InstrProfOptions>
getInstrProfOptions(const CodeGenOptions & CodeGenOpts,const LangOptions & LangOpts)517e5dd7070Spatrick getInstrProfOptions(const CodeGenOptions &CodeGenOpts,
518e5dd7070Spatrick const LangOptions &LangOpts) {
519e5dd7070Spatrick if (!CodeGenOpts.hasProfileClangInstr())
520*12c85518Srobert return std::nullopt;
521e5dd7070Spatrick InstrProfOptions Options;
522e5dd7070Spatrick Options.NoRedZone = CodeGenOpts.DisableRedZone;
523e5dd7070Spatrick Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput;
524a9ac8606Spatrick Options.Atomic = CodeGenOpts.AtomicProfileUpdate;
525e5dd7070Spatrick return Options;
526e5dd7070Spatrick }
527e5dd7070Spatrick
setCommandLineOpts(const CodeGenOptions & CodeGenOpts)528e5dd7070Spatrick static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) {
529e5dd7070Spatrick SmallVector<const char *, 16> BackendArgs;
530e5dd7070Spatrick BackendArgs.push_back("clang"); // Fake program name.
531e5dd7070Spatrick if (!CodeGenOpts.DebugPass.empty()) {
532e5dd7070Spatrick BackendArgs.push_back("-debug-pass");
533e5dd7070Spatrick BackendArgs.push_back(CodeGenOpts.DebugPass.c_str());
534e5dd7070Spatrick }
535e5dd7070Spatrick if (!CodeGenOpts.LimitFloatPrecision.empty()) {
536e5dd7070Spatrick BackendArgs.push_back("-limit-float-precision");
537e5dd7070Spatrick BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
538e5dd7070Spatrick }
539a9ac8606Spatrick // Check for the default "clang" invocation that won't set any cl::opt values.
540a9ac8606Spatrick // Skip trying to parse the command line invocation to avoid the issues
541a9ac8606Spatrick // described below.
542a9ac8606Spatrick if (BackendArgs.size() == 1)
543a9ac8606Spatrick return;
544e5dd7070Spatrick BackendArgs.push_back(nullptr);
545a9ac8606Spatrick // FIXME: The command line parser below is not thread-safe and shares a global
546a9ac8606Spatrick // state, so this call might crash or overwrite the options of another Clang
547a9ac8606Spatrick // instance in the same process.
548e5dd7070Spatrick llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
549e5dd7070Spatrick BackendArgs.data());
550e5dd7070Spatrick }
551e5dd7070Spatrick
CreateTargetMachine(bool MustCreateTM)552e5dd7070Spatrick void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
553e5dd7070Spatrick // Create the TargetMachine for generating code.
554e5dd7070Spatrick std::string Error;
555e5dd7070Spatrick std::string Triple = TheModule->getTargetTriple();
556e5dd7070Spatrick const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
557e5dd7070Spatrick if (!TheTarget) {
558e5dd7070Spatrick if (MustCreateTM)
559e5dd7070Spatrick Diags.Report(diag::err_fe_unable_to_create_target) << Error;
560e5dd7070Spatrick return;
561e5dd7070Spatrick }
562e5dd7070Spatrick
563*12c85518Srobert std::optional<llvm::CodeModel::Model> CM = getCodeModel(CodeGenOpts);
564e5dd7070Spatrick std::string FeaturesStr =
565e5dd7070Spatrick llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ",");
566e5dd7070Spatrick llvm::Reloc::Model RM = CodeGenOpts.RelocationModel;
567*12c85518Srobert std::optional<CodeGenOpt::Level> OptLevelOrNone =
568*12c85518Srobert CodeGenOpt::getLevel(CodeGenOpts.OptimizationLevel);
569*12c85518Srobert assert(OptLevelOrNone && "Invalid optimization level!");
570*12c85518Srobert CodeGenOpt::Level OptLevel = *OptLevelOrNone;
571e5dd7070Spatrick
572e5dd7070Spatrick llvm::TargetOptions Options;
573a9ac8606Spatrick if (!initTargetOptions(Diags, Options, CodeGenOpts, TargetOpts, LangOpts,
574a9ac8606Spatrick HSOpts))
575a9ac8606Spatrick return;
576e5dd7070Spatrick TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr,
577e5dd7070Spatrick Options, RM, CM, OptLevel));
578e5dd7070Spatrick }
579e5dd7070Spatrick
AddEmitPasses(legacy::PassManager & CodeGenPasses,BackendAction Action,raw_pwrite_stream & OS,raw_pwrite_stream * DwoOS)580e5dd7070Spatrick bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,
581e5dd7070Spatrick BackendAction Action,
582e5dd7070Spatrick raw_pwrite_stream &OS,
583e5dd7070Spatrick raw_pwrite_stream *DwoOS) {
584e5dd7070Spatrick // Add LibraryInfo.
585e5dd7070Spatrick std::unique_ptr<TargetLibraryInfoImpl> TLII(
586e5dd7070Spatrick createTLII(TargetTriple, CodeGenOpts));
587e5dd7070Spatrick CodeGenPasses.add(new TargetLibraryInfoWrapperPass(*TLII));
588e5dd7070Spatrick
589e5dd7070Spatrick // Normal mode, emit a .s or .o file by running the code generator. Note,
590e5dd7070Spatrick // this also adds codegenerator level optimization passes.
591e5dd7070Spatrick CodeGenFileType CGFT = getCodeGenFileType(Action);
592e5dd7070Spatrick
593e5dd7070Spatrick // Add ObjC ARC final-cleanup optimizations. This is done as part of the
594e5dd7070Spatrick // "codegen" passes so that it isn't run multiple times when there is
595e5dd7070Spatrick // inlining happening.
596e5dd7070Spatrick if (CodeGenOpts.OptimizationLevel > 0)
597e5dd7070Spatrick CodeGenPasses.add(createObjCARCContractPass());
598e5dd7070Spatrick
599e5dd7070Spatrick if (TM->addPassesToEmitFile(CodeGenPasses, OS, DwoOS, CGFT,
600e5dd7070Spatrick /*DisableVerify=*/!CodeGenOpts.VerifyModule)) {
601e5dd7070Spatrick Diags.Report(diag::err_fe_unable_to_interface_with_target);
602e5dd7070Spatrick return false;
603e5dd7070Spatrick }
604e5dd7070Spatrick
605e5dd7070Spatrick return true;
606e5dd7070Spatrick }
607e5dd7070Spatrick
mapToLevel(const CodeGenOptions & Opts)608*12c85518Srobert static OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
609e5dd7070Spatrick switch (Opts.OptimizationLevel) {
610e5dd7070Spatrick default:
611e5dd7070Spatrick llvm_unreachable("Invalid optimization level!");
612e5dd7070Spatrick
613a9ac8606Spatrick case 0:
614*12c85518Srobert return OptimizationLevel::O0;
615a9ac8606Spatrick
616e5dd7070Spatrick case 1:
617*12c85518Srobert return OptimizationLevel::O1;
618e5dd7070Spatrick
619e5dd7070Spatrick case 2:
620e5dd7070Spatrick switch (Opts.OptimizeSize) {
621e5dd7070Spatrick default:
622e5dd7070Spatrick llvm_unreachable("Invalid optimization level for size!");
623e5dd7070Spatrick
624e5dd7070Spatrick case 0:
625*12c85518Srobert return OptimizationLevel::O2;
626e5dd7070Spatrick
627e5dd7070Spatrick case 1:
628*12c85518Srobert return OptimizationLevel::Os;
629e5dd7070Spatrick
630e5dd7070Spatrick case 2:
631*12c85518Srobert return OptimizationLevel::Oz;
632e5dd7070Spatrick }
633e5dd7070Spatrick
634e5dd7070Spatrick case 3:
635*12c85518Srobert return OptimizationLevel::O3;
636e5dd7070Spatrick }
637e5dd7070Spatrick }
638e5dd7070Spatrick
addKCFIPass(const Triple & TargetTriple,const LangOptions & LangOpts,PassBuilder & PB)639*12c85518Srobert static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,
640*12c85518Srobert PassBuilder &PB) {
641*12c85518Srobert // If the back-end supports KCFI operand bundle lowering, skip KCFIPass.
642*12c85518Srobert if (TargetTriple.getArch() == llvm::Triple::x86_64 ||
643*12c85518Srobert TargetTriple.isAArch64(64))
644*12c85518Srobert return;
645*12c85518Srobert
646*12c85518Srobert // Ensure we lower KCFI operand bundles with -O0.
647*12c85518Srobert PB.registerOptimizerLastEPCallback(
648*12c85518Srobert [&](ModulePassManager &MPM, OptimizationLevel Level) {
649*12c85518Srobert if (Level == OptimizationLevel::O0 &&
650*12c85518Srobert LangOpts.Sanitize.has(SanitizerKind::KCFI))
651*12c85518Srobert MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass()));
652*12c85518Srobert });
653*12c85518Srobert
654*12c85518Srobert // When optimizations are requested, run KCIFPass after InstCombine to
655*12c85518Srobert // avoid unnecessary checks.
656*12c85518Srobert PB.registerPeepholeEPCallback(
657*12c85518Srobert [&](FunctionPassManager &FPM, OptimizationLevel Level) {
658*12c85518Srobert if (Level != OptimizationLevel::O0 &&
659*12c85518Srobert LangOpts.Sanitize.has(SanitizerKind::KCFI))
660*12c85518Srobert FPM.addPass(KCFIPass());
661*12c85518Srobert });
662*12c85518Srobert }
663*12c85518Srobert
addSanitizers(const Triple & TargetTriple,const CodeGenOptions & CodeGenOpts,const LangOptions & LangOpts,PassBuilder & PB)664a9ac8606Spatrick static void addSanitizers(const Triple &TargetTriple,
665a9ac8606Spatrick const CodeGenOptions &CodeGenOpts,
666a9ac8606Spatrick const LangOptions &LangOpts, PassBuilder &PB) {
667*12c85518Srobert auto SanitizersCallback = [&](ModulePassManager &MPM,
668*12c85518Srobert OptimizationLevel Level) {
669a9ac8606Spatrick if (CodeGenOpts.hasSanitizeCoverage()) {
670ec727ea7Spatrick auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
671*12c85518Srobert MPM.addPass(SanitizerCoveragePass(
672ec727ea7Spatrick SancovOpts, CodeGenOpts.SanitizeCoverageAllowlistFiles,
673a9ac8606Spatrick CodeGenOpts.SanitizeCoverageIgnorelistFiles));
674ec727ea7Spatrick }
675ec727ea7Spatrick
676*12c85518Srobert if (CodeGenOpts.hasSanitizeBinaryMetadata()) {
677*12c85518Srobert MPM.addPass(SanitizerBinaryMetadataPass(
678*12c85518Srobert getSanitizerBinaryMetadataOptions(CodeGenOpts)));
679*12c85518Srobert }
680*12c85518Srobert
681a9ac8606Spatrick auto MSanPass = [&](SanitizerMask Mask, bool CompileKernel) {
682a9ac8606Spatrick if (LangOpts.Sanitize.has(Mask)) {
683ec727ea7Spatrick int TrackOrigins = CodeGenOpts.SanitizeMemoryTrackOrigins;
684a9ac8606Spatrick bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
685e5dd7070Spatrick
686*12c85518Srobert MemorySanitizerOptions options(TrackOrigins, Recover, CompileKernel,
687*12c85518Srobert CodeGenOpts.SanitizeMemoryParamRetval);
688*12c85518Srobert MPM.addPass(MemorySanitizerPass(options));
689*12c85518Srobert if (Level != OptimizationLevel::O0) {
690*12c85518Srobert // MemorySanitizer inserts complex instrumentation that mostly follows
691*12c85518Srobert // the logic of the original code, but operates on "shadow" values. It
692*12c85518Srobert // can benefit from re-running some general purpose optimization
693*12c85518Srobert // passes.
694*12c85518Srobert MPM.addPass(RequireAnalysisPass<GlobalsAA, Module>());
695a9ac8606Spatrick FunctionPassManager FPM;
696*12c85518Srobert FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */));
697*12c85518Srobert FPM.addPass(InstCombinePass());
698*12c85518Srobert FPM.addPass(JumpThreadingPass());
699*12c85518Srobert FPM.addPass(GVNPass());
700*12c85518Srobert FPM.addPass(InstCombinePass());
701a9ac8606Spatrick MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
702a9ac8606Spatrick }
703*12c85518Srobert }
704a9ac8606Spatrick };
705a9ac8606Spatrick MSanPass(SanitizerKind::Memory, false);
706a9ac8606Spatrick MSanPass(SanitizerKind::KernelMemory, true);
707e5dd7070Spatrick
708e5dd7070Spatrick if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
709*12c85518Srobert MPM.addPass(ModuleThreadSanitizerPass());
710e5dd7070Spatrick MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
711e5dd7070Spatrick }
712a9ac8606Spatrick
713a9ac8606Spatrick auto ASanPass = [&](SanitizerMask Mask, bool CompileKernel) {
714a9ac8606Spatrick if (LangOpts.Sanitize.has(Mask)) {
715*12c85518Srobert bool UseGlobalGC = asanUseGlobalsGC(TargetTriple, CodeGenOpts);
716a9ac8606Spatrick bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator;
717a9ac8606Spatrick llvm::AsanDtorKind DestructorKind =
718a9ac8606Spatrick CodeGenOpts.getSanitizeAddressDtor();
719*12c85518Srobert AddressSanitizerOptions Opts;
720*12c85518Srobert Opts.CompileKernel = CompileKernel;
721*12c85518Srobert Opts.Recover = CodeGenOpts.SanitizeRecover.has(Mask);
722*12c85518Srobert Opts.UseAfterScope = CodeGenOpts.SanitizeAddressUseAfterScope;
723*12c85518Srobert Opts.UseAfterReturn = CodeGenOpts.getSanitizeAddressUseAfterReturn();
724*12c85518Srobert MPM.addPass(AddressSanitizerPass(Opts, UseGlobalGC, UseOdrIndicator,
725a9ac8606Spatrick DestructorKind));
726a9ac8606Spatrick }
727a9ac8606Spatrick };
728a9ac8606Spatrick ASanPass(SanitizerKind::Address, false);
729a9ac8606Spatrick ASanPass(SanitizerKind::KernelAddress, true);
730a9ac8606Spatrick
731a9ac8606Spatrick auto HWASanPass = [&](SanitizerMask Mask, bool CompileKernel) {
732a9ac8606Spatrick if (LangOpts.Sanitize.has(Mask)) {
733a9ac8606Spatrick bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
734a9ac8606Spatrick MPM.addPass(HWAddressSanitizerPass(
735*12c85518Srobert {CompileKernel, Recover,
736*12c85518Srobert /*DisableOptimization=*/CodeGenOpts.OptimizationLevel == 0}));
737a9ac8606Spatrick }
738a9ac8606Spatrick };
739a9ac8606Spatrick HWASanPass(SanitizerKind::HWAddress, false);
740a9ac8606Spatrick HWASanPass(SanitizerKind::KernelHWAddress, true);
741a9ac8606Spatrick
742a9ac8606Spatrick if (LangOpts.Sanitize.has(SanitizerKind::DataFlow)) {
743a9ac8606Spatrick MPM.addPass(DataFlowSanitizerPass(LangOpts.NoSanitizeFiles));
744a9ac8606Spatrick }
745*12c85518Srobert };
746*12c85518Srobert if (ClSanitizeOnOptimizerEarlyEP) {
747*12c85518Srobert PB.registerOptimizerEarlyEPCallback(
748*12c85518Srobert [SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level) {
749*12c85518Srobert ModulePassManager NewMPM;
750*12c85518Srobert SanitizersCallback(NewMPM, Level);
751*12c85518Srobert if (!NewMPM.isEmpty()) {
752*12c85518Srobert // Sanitizers can abandon<GlobalsAA>.
753*12c85518Srobert NewMPM.addPass(RequireAnalysisPass<GlobalsAA, Module>());
754*12c85518Srobert MPM.addPass(std::move(NewMPM));
755*12c85518Srobert }
756a9ac8606Spatrick });
757*12c85518Srobert } else {
758*12c85518Srobert // LastEP does not need GlobalsAA.
759*12c85518Srobert PB.registerOptimizerLastEPCallback(SanitizersCallback);
760*12c85518Srobert }
761e5dd7070Spatrick }
762e5dd7070Spatrick
RunOptimizationPipeline(BackendAction Action,std::unique_ptr<raw_pwrite_stream> & OS,std::unique_ptr<llvm::ToolOutputFile> & ThinLinkOS)763*12c85518Srobert void EmitAssemblyHelper::RunOptimizationPipeline(
764*12c85518Srobert BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,
765*12c85518Srobert std::unique_ptr<llvm::ToolOutputFile> &ThinLinkOS) {
766*12c85518Srobert std::optional<PGOOptions> PGOOpt;
767e5dd7070Spatrick
768e5dd7070Spatrick if (CodeGenOpts.hasProfileIRInstr())
769e5dd7070Spatrick // -fprofile-generate.
770e5dd7070Spatrick PGOOpt = PGOOptions(CodeGenOpts.InstrProfileOutput.empty()
771*12c85518Srobert ? getDefaultProfileGenName()
772e5dd7070Spatrick : CodeGenOpts.InstrProfileOutput,
773e5dd7070Spatrick "", "", PGOOptions::IRInstr, PGOOptions::NoCSAction,
774e5dd7070Spatrick CodeGenOpts.DebugInfoForProfiling);
775e5dd7070Spatrick else if (CodeGenOpts.hasProfileIRUse()) {
776e5dd7070Spatrick // -fprofile-use.
777e5dd7070Spatrick auto CSAction = CodeGenOpts.hasProfileCSIRUse() ? PGOOptions::CSIRUse
778e5dd7070Spatrick : PGOOptions::NoCSAction;
779e5dd7070Spatrick PGOOpt = PGOOptions(CodeGenOpts.ProfileInstrumentUsePath, "",
780e5dd7070Spatrick CodeGenOpts.ProfileRemappingFile, PGOOptions::IRUse,
781e5dd7070Spatrick CSAction, CodeGenOpts.DebugInfoForProfiling);
782e5dd7070Spatrick } else if (!CodeGenOpts.SampleProfileFile.empty())
783e5dd7070Spatrick // -fprofile-sample-use
784a9ac8606Spatrick PGOOpt = PGOOptions(
785a9ac8606Spatrick CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile,
786a9ac8606Spatrick PGOOptions::SampleUse, PGOOptions::NoCSAction,
787a9ac8606Spatrick CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling);
788a9ac8606Spatrick else if (CodeGenOpts.PseudoProbeForProfiling)
789a9ac8606Spatrick // -fpseudo-probe-for-profiling
790e5dd7070Spatrick PGOOpt =
791a9ac8606Spatrick PGOOptions("", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction,
792a9ac8606Spatrick CodeGenOpts.DebugInfoForProfiling, true);
793e5dd7070Spatrick else if (CodeGenOpts.DebugInfoForProfiling)
794e5dd7070Spatrick // -fdebug-info-for-profiling
795e5dd7070Spatrick PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
796e5dd7070Spatrick PGOOptions::NoCSAction, true);
797e5dd7070Spatrick
798e5dd7070Spatrick // Check to see if we want to generate a CS profile.
799e5dd7070Spatrick if (CodeGenOpts.hasProfileCSIRInstr()) {
800e5dd7070Spatrick assert(!CodeGenOpts.hasProfileCSIRUse() &&
801e5dd7070Spatrick "Cannot have both CSProfileUse pass and CSProfileGen pass at "
802e5dd7070Spatrick "the same time");
803*12c85518Srobert if (PGOOpt) {
804e5dd7070Spatrick assert(PGOOpt->Action != PGOOptions::IRInstr &&
805e5dd7070Spatrick PGOOpt->Action != PGOOptions::SampleUse &&
806e5dd7070Spatrick "Cannot run CSProfileGen pass with ProfileGen or SampleUse "
807e5dd7070Spatrick " pass");
808e5dd7070Spatrick PGOOpt->CSProfileGenFile = CodeGenOpts.InstrProfileOutput.empty()
809*12c85518Srobert ? getDefaultProfileGenName()
810e5dd7070Spatrick : CodeGenOpts.InstrProfileOutput;
811e5dd7070Spatrick PGOOpt->CSAction = PGOOptions::CSIRInstr;
812e5dd7070Spatrick } else
813e5dd7070Spatrick PGOOpt = PGOOptions("",
814e5dd7070Spatrick CodeGenOpts.InstrProfileOutput.empty()
815*12c85518Srobert ? getDefaultProfileGenName()
816e5dd7070Spatrick : CodeGenOpts.InstrProfileOutput,
817e5dd7070Spatrick "", PGOOptions::NoAction, PGOOptions::CSIRInstr,
818e5dd7070Spatrick CodeGenOpts.DebugInfoForProfiling);
819e5dd7070Spatrick }
820*12c85518Srobert if (TM)
821*12c85518Srobert TM->setPGOOption(PGOOpt);
822e5dd7070Spatrick
823e5dd7070Spatrick PipelineTuningOptions PTO;
824e5dd7070Spatrick PTO.LoopUnrolling = CodeGenOpts.UnrollLoops;
825e5dd7070Spatrick // For historical reasons, loop interleaving is set to mirror setting for loop
826e5dd7070Spatrick // unrolling.
827e5dd7070Spatrick PTO.LoopInterleaving = CodeGenOpts.UnrollLoops;
828e5dd7070Spatrick PTO.LoopVectorization = CodeGenOpts.VectorizeLoop;
829e5dd7070Spatrick PTO.SLPVectorization = CodeGenOpts.VectorizeSLP;
830a9ac8606Spatrick PTO.MergeFunctions = CodeGenOpts.MergeFunctions;
831ec727ea7Spatrick // Only enable CGProfilePass when using integrated assembler, since
832ec727ea7Spatrick // non-integrated assemblers don't recognize .cgprofile section.
833ec727ea7Spatrick PTO.CallGraphProfile = !CodeGenOpts.DisableIntegratedAS;
834e5dd7070Spatrick
835a9ac8606Spatrick LoopAnalysisManager LAM;
836a9ac8606Spatrick FunctionAnalysisManager FAM;
837a9ac8606Spatrick CGSCCAnalysisManager CGAM;
838a9ac8606Spatrick ModuleAnalysisManager MAM;
839a9ac8606Spatrick
840a9ac8606Spatrick bool DebugPassStructure = CodeGenOpts.DebugPass == "Structure";
841e5dd7070Spatrick PassInstrumentationCallbacks PIC;
842a9ac8606Spatrick PrintPassOptions PrintPassOpts;
843a9ac8606Spatrick PrintPassOpts.Indent = DebugPassStructure;
844a9ac8606Spatrick PrintPassOpts.SkipAnalyses = DebugPassStructure;
845*12c85518Srobert StandardInstrumentations SI(
846*12c85518Srobert TheModule->getContext(),
847*12c85518Srobert (CodeGenOpts.DebugPassManager || DebugPassStructure),
848a9ac8606Spatrick /*VerifyEach*/ false, PrintPassOpts);
849a9ac8606Spatrick SI.registerCallbacks(PIC, &FAM);
850e5dd7070Spatrick PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC);
851e5dd7070Spatrick
852*12c85518Srobert if (CodeGenOpts.EnableAssignmentTracking) {
853*12c85518Srobert PB.registerPipelineStartEPCallback(
854*12c85518Srobert [&](ModulePassManager &MPM, OptimizationLevel Level) {
855*12c85518Srobert MPM.addPass(AssignmentTrackingPass());
856*12c85518Srobert });
857*12c85518Srobert }
858*12c85518Srobert
859*12c85518Srobert // Enable verify-debuginfo-preserve-each for new PM.
860*12c85518Srobert DebugifyEachInstrumentation Debugify;
861*12c85518Srobert DebugInfoPerPass DebugInfoBeforePass;
862*12c85518Srobert if (CodeGenOpts.EnableDIPreservationVerify) {
863*12c85518Srobert Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
864*12c85518Srobert Debugify.setDebugInfoBeforePass(DebugInfoBeforePass);
865*12c85518Srobert
866*12c85518Srobert if (!CodeGenOpts.DIBugsReportFilePath.empty())
867*12c85518Srobert Debugify.setOrigDIVerifyBugsReportFilePath(
868*12c85518Srobert CodeGenOpts.DIBugsReportFilePath);
869*12c85518Srobert Debugify.registerCallbacks(PIC);
870*12c85518Srobert }
871e5dd7070Spatrick // Attempt to load pass plugins and register their callbacks with PB.
872e5dd7070Spatrick for (auto &PluginFN : CodeGenOpts.PassPlugins) {
873e5dd7070Spatrick auto PassPlugin = PassPlugin::Load(PluginFN);
874e5dd7070Spatrick if (PassPlugin) {
875e5dd7070Spatrick PassPlugin->registerPassBuilderCallbacks(PB);
876e5dd7070Spatrick } else {
877e5dd7070Spatrick Diags.Report(diag::err_fe_unable_to_load_plugin)
878e5dd7070Spatrick << PluginFN << toString(PassPlugin.takeError());
879e5dd7070Spatrick }
880e5dd7070Spatrick }
881e5dd7070Spatrick #define HANDLE_EXTENSION(Ext) \
882e5dd7070Spatrick get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
883e5dd7070Spatrick #include "llvm/Support/Extension.def"
884e5dd7070Spatrick
885e5dd7070Spatrick // Register the target library analysis directly and give it a customized
886e5dd7070Spatrick // preset TLI.
887e5dd7070Spatrick std::unique_ptr<TargetLibraryInfoImpl> TLII(
888e5dd7070Spatrick createTLII(TargetTriple, CodeGenOpts));
889e5dd7070Spatrick FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
890e5dd7070Spatrick
891e5dd7070Spatrick // Register all the basic analyses with the managers.
892e5dd7070Spatrick PB.registerModuleAnalyses(MAM);
893e5dd7070Spatrick PB.registerCGSCCAnalyses(CGAM);
894e5dd7070Spatrick PB.registerFunctionAnalyses(FAM);
895e5dd7070Spatrick PB.registerLoopAnalyses(LAM);
896e5dd7070Spatrick PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
897e5dd7070Spatrick
898a9ac8606Spatrick ModulePassManager MPM;
899e5dd7070Spatrick
900e5dd7070Spatrick if (!CodeGenOpts.DisableLLVMPasses) {
901e5dd7070Spatrick // Map our optimization levels into one of the distinct levels used to
902e5dd7070Spatrick // configure the pipeline.
903*12c85518Srobert OptimizationLevel Level = mapToLevel(CodeGenOpts);
904e5dd7070Spatrick
905a9ac8606Spatrick bool IsThinLTO = CodeGenOpts.PrepareForThinLTO;
906a9ac8606Spatrick bool IsLTO = CodeGenOpts.PrepareForLTO;
907a9ac8606Spatrick
908a9ac8606Spatrick if (LangOpts.ObjCAutoRefCount) {
909a9ac8606Spatrick PB.registerPipelineStartEPCallback(
910*12c85518Srobert [](ModulePassManager &MPM, OptimizationLevel Level) {
911*12c85518Srobert if (Level != OptimizationLevel::O0)
912a9ac8606Spatrick MPM.addPass(
913a9ac8606Spatrick createModuleToFunctionPassAdaptor(ObjCARCExpandPass()));
914a9ac8606Spatrick });
915a9ac8606Spatrick PB.registerPipelineEarlySimplificationEPCallback(
916*12c85518Srobert [](ModulePassManager &MPM, OptimizationLevel Level) {
917*12c85518Srobert if (Level != OptimizationLevel::O0)
918a9ac8606Spatrick MPM.addPass(ObjCARCAPElimPass());
919a9ac8606Spatrick });
920a9ac8606Spatrick PB.registerScalarOptimizerLateEPCallback(
921*12c85518Srobert [](FunctionPassManager &FPM, OptimizationLevel Level) {
922*12c85518Srobert if (Level != OptimizationLevel::O0)
923a9ac8606Spatrick FPM.addPass(ObjCARCOptPass());
924a9ac8606Spatrick });
925a9ac8606Spatrick }
926a9ac8606Spatrick
927ec727ea7Spatrick // If we reached here with a non-empty index file name, then the index
928ec727ea7Spatrick // file was empty and we are not performing ThinLTO backend compilation
929a9ac8606Spatrick // (used in testing in a distributed build environment).
930a9ac8606Spatrick bool IsThinLTOPostLink = !CodeGenOpts.ThinLTOIndexFile.empty();
931a9ac8606Spatrick // If so drop any the type test assume sequences inserted for whole program
932a9ac8606Spatrick // vtables so that codegen doesn't complain.
933a9ac8606Spatrick if (IsThinLTOPostLink)
934a9ac8606Spatrick PB.registerPipelineStartEPCallback(
935*12c85518Srobert [](ModulePassManager &MPM, OptimizationLevel Level) {
936ec727ea7Spatrick MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr,
937ec727ea7Spatrick /*ImportSummary=*/nullptr,
938ec727ea7Spatrick /*DropTypeTests=*/true));
939ec727ea7Spatrick });
940ec727ea7Spatrick
941a9ac8606Spatrick if (CodeGenOpts.InstrumentFunctions ||
942a9ac8606Spatrick CodeGenOpts.InstrumentFunctionEntryBare ||
943a9ac8606Spatrick CodeGenOpts.InstrumentFunctionsAfterInlining ||
944a9ac8606Spatrick CodeGenOpts.InstrumentForProfiling) {
945a9ac8606Spatrick PB.registerPipelineStartEPCallback(
946*12c85518Srobert [](ModulePassManager &MPM, OptimizationLevel Level) {
947e5dd7070Spatrick MPM.addPass(createModuleToFunctionPassAdaptor(
948e5dd7070Spatrick EntryExitInstrumenterPass(/*PostInlining=*/false)));
949e5dd7070Spatrick });
950a9ac8606Spatrick PB.registerOptimizerLastEPCallback(
951*12c85518Srobert [](ModulePassManager &MPM, OptimizationLevel Level) {
952a9ac8606Spatrick MPM.addPass(createModuleToFunctionPassAdaptor(
953a9ac8606Spatrick EntryExitInstrumenterPass(/*PostInlining=*/true)));
954a9ac8606Spatrick });
955a9ac8606Spatrick }
956e5dd7070Spatrick
957a9ac8606Spatrick // Register callbacks to schedule sanitizer passes at the appropriate part
958a9ac8606Spatrick // of the pipeline.
959e5dd7070Spatrick if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
960e5dd7070Spatrick PB.registerScalarOptimizerLateEPCallback(
961*12c85518Srobert [](FunctionPassManager &FPM, OptimizationLevel Level) {
962e5dd7070Spatrick FPM.addPass(BoundsCheckingPass());
963e5dd7070Spatrick });
964ec727ea7Spatrick
965a9ac8606Spatrick // Don't add sanitizers if we are here from ThinLTO PostLink. That already
966a9ac8606Spatrick // done on PreLink stage.
967*12c85518Srobert if (!IsThinLTOPostLink) {
968a9ac8606Spatrick addSanitizers(TargetTriple, CodeGenOpts, LangOpts, PB);
969*12c85518Srobert addKCFIPass(TargetTriple, LangOpts, PB);
970*12c85518Srobert }
971ec727ea7Spatrick
972*12c85518Srobert if (std::optional<GCOVOptions> Options =
973*12c85518Srobert getGCOVOptions(CodeGenOpts, LangOpts))
974a9ac8606Spatrick PB.registerPipelineStartEPCallback(
975*12c85518Srobert [Options](ModulePassManager &MPM, OptimizationLevel Level) {
976e5dd7070Spatrick MPM.addPass(GCOVProfilerPass(*Options));
977e5dd7070Spatrick });
978*12c85518Srobert if (std::optional<InstrProfOptions> Options =
979e5dd7070Spatrick getInstrProfOptions(CodeGenOpts, LangOpts))
980a9ac8606Spatrick PB.registerPipelineStartEPCallback(
981*12c85518Srobert [Options](ModulePassManager &MPM, OptimizationLevel Level) {
982e5dd7070Spatrick MPM.addPass(InstrProfiling(*Options, false));
983e5dd7070Spatrick });
984e5dd7070Spatrick
985e5dd7070Spatrick if (CodeGenOpts.OptimizationLevel == 0) {
986a9ac8606Spatrick MPM = PB.buildO0DefaultPipeline(Level, IsLTO || IsThinLTO);
987a9ac8606Spatrick } else if (IsThinLTO) {
988a9ac8606Spatrick MPM = PB.buildThinLTOPreLinkDefaultPipeline(Level);
989a9ac8606Spatrick } else if (IsLTO) {
990a9ac8606Spatrick MPM = PB.buildLTOPreLinkDefaultPipeline(Level);
991a9ac8606Spatrick } else {
992a9ac8606Spatrick MPM = PB.buildPerModuleDefaultPipeline(Level);
993a9ac8606Spatrick }
994a9ac8606Spatrick
995a9ac8606Spatrick if (!CodeGenOpts.MemoryProfileOutput.empty()) {
996a9ac8606Spatrick MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
997a9ac8606Spatrick MPM.addPass(ModuleMemProfilerPass());
998e5dd7070Spatrick }
999e5dd7070Spatrick }
1000e5dd7070Spatrick
1001*12c85518Srobert // Add a verifier pass if requested. We don't have to do this if the action
1002*12c85518Srobert // requires code generation because there will already be a verifier pass in
1003*12c85518Srobert // the code-generation pipeline.
1004*12c85518Srobert if (!actionRequiresCodeGen(Action) && CodeGenOpts.VerifyModule)
1005*12c85518Srobert MPM.addPass(VerifierPass());
1006e5dd7070Spatrick
1007*12c85518Srobert if (Action == Backend_EmitBC || Action == Backend_EmitLL) {
1008e5dd7070Spatrick if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) {
1009*12c85518Srobert if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
1010*12c85518Srobert TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
1011*12c85518Srobert CodeGenOpts.EnableSplitLTOUnit);
1012*12c85518Srobert if (Action == Backend_EmitBC) {
1013e5dd7070Spatrick if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
1014e5dd7070Spatrick ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
1015e5dd7070Spatrick if (!ThinLinkOS)
1016e5dd7070Spatrick return;
1017e5dd7070Spatrick }
1018e5dd7070Spatrick MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os()
1019e5dd7070Spatrick : nullptr));
1020e5dd7070Spatrick } else {
1021*12c85518Srobert MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
1022*12c85518Srobert /*EmitLTOSummary=*/true));
1023*12c85518Srobert }
1024*12c85518Srobert
1025*12c85518Srobert } else {
1026e5dd7070Spatrick // Emit a module summary by default for Regular LTO except for ld64
1027e5dd7070Spatrick // targets
1028*12c85518Srobert bool EmitLTOSummary = shouldEmitRegularLTOSummary();
1029e5dd7070Spatrick if (EmitLTOSummary) {
1030e5dd7070Spatrick if (!TheModule->getModuleFlag("ThinLTO"))
1031e5dd7070Spatrick TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
1032*12c85518Srobert if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
1033e5dd7070Spatrick TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
1034e5dd7070Spatrick uint32_t(1));
1035e5dd7070Spatrick }
1036*12c85518Srobert if (Action == Backend_EmitBC)
1037*12c85518Srobert MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
1038*12c85518Srobert EmitLTOSummary));
1039*12c85518Srobert else
1040*12c85518Srobert MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
1041*12c85518Srobert EmitLTOSummary));
1042e5dd7070Spatrick }
1043*12c85518Srobert }
1044e5dd7070Spatrick
1045*12c85518Srobert // Now that we have all of the passes ready, run them.
1046*12c85518Srobert {
1047*12c85518Srobert PrettyStackTraceString CrashInfo("Optimizer");
1048*12c85518Srobert llvm::TimeTraceScope TimeScope("Optimizer");
1049*12c85518Srobert MPM.run(*TheModule, MAM);
1050*12c85518Srobert }
1051*12c85518Srobert }
1052e5dd7070Spatrick
RunCodegenPipeline(BackendAction Action,std::unique_ptr<raw_pwrite_stream> & OS,std::unique_ptr<llvm::ToolOutputFile> & DwoOS)1053*12c85518Srobert void EmitAssemblyHelper::RunCodegenPipeline(
1054*12c85518Srobert BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,
1055*12c85518Srobert std::unique_ptr<llvm::ToolOutputFile> &DwoOS) {
1056*12c85518Srobert // We still use the legacy PM to run the codegen pipeline since the new PM
1057*12c85518Srobert // does not work with the codegen pipeline.
1058*12c85518Srobert // FIXME: make the new PM work with the codegen pipeline.
1059*12c85518Srobert legacy::PassManager CodeGenPasses;
1060*12c85518Srobert
1061*12c85518Srobert // Append any output we need to the pass manager.
1062*12c85518Srobert switch (Action) {
1063e5dd7070Spatrick case Backend_EmitAssembly:
1064e5dd7070Spatrick case Backend_EmitMCNull:
1065e5dd7070Spatrick case Backend_EmitObj:
1066e5dd7070Spatrick CodeGenPasses.add(
1067e5dd7070Spatrick createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
1068e5dd7070Spatrick if (!CodeGenOpts.SplitDwarfOutput.empty()) {
1069e5dd7070Spatrick DwoOS = openOutputFile(CodeGenOpts.SplitDwarfOutput);
1070e5dd7070Spatrick if (!DwoOS)
1071e5dd7070Spatrick return;
1072e5dd7070Spatrick }
1073e5dd7070Spatrick if (!AddEmitPasses(CodeGenPasses, Action, *OS,
1074e5dd7070Spatrick DwoOS ? &DwoOS->os() : nullptr))
1075e5dd7070Spatrick // FIXME: Should we handle this error differently?
1076e5dd7070Spatrick return;
1077e5dd7070Spatrick break;
1078*12c85518Srobert default:
1079*12c85518Srobert return;
1080e5dd7070Spatrick }
1081e5dd7070Spatrick
1082*12c85518Srobert {
1083*12c85518Srobert PrettyStackTraceString CrashInfo("Code generation");
1084*12c85518Srobert llvm::TimeTraceScope TimeScope("CodeGenPasses");
1085*12c85518Srobert CodeGenPasses.run(*TheModule);
1086*12c85518Srobert }
1087*12c85518Srobert }
1088*12c85518Srobert
EmitAssembly(BackendAction Action,std::unique_ptr<raw_pwrite_stream> OS)1089*12c85518Srobert void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
1090*12c85518Srobert std::unique_ptr<raw_pwrite_stream> OS) {
1091*12c85518Srobert TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : nullptr);
1092*12c85518Srobert setCommandLineOpts(CodeGenOpts);
1093*12c85518Srobert
1094*12c85518Srobert bool RequiresCodeGen = actionRequiresCodeGen(Action);
1095*12c85518Srobert CreateTargetMachine(RequiresCodeGen);
1096*12c85518Srobert
1097*12c85518Srobert if (RequiresCodeGen && !TM)
1098*12c85518Srobert return;
1099*12c85518Srobert if (TM)
1100*12c85518Srobert TheModule->setDataLayout(TM->createDataLayout());
1101*12c85518Srobert
1102e5dd7070Spatrick // Before executing passes, print the final values of the LLVM options.
1103e5dd7070Spatrick cl::PrintOptionValues();
1104e5dd7070Spatrick
1105*12c85518Srobert std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS;
1106*12c85518Srobert RunOptimizationPipeline(Action, OS, ThinLinkOS);
1107*12c85518Srobert RunCodegenPipeline(Action, OS, DwoOS);
1108e5dd7070Spatrick
1109e5dd7070Spatrick if (ThinLinkOS)
1110e5dd7070Spatrick ThinLinkOS->keep();
1111e5dd7070Spatrick if (DwoOS)
1112e5dd7070Spatrick DwoOS->keep();
1113e5dd7070Spatrick }
1114e5dd7070Spatrick
runThinLTOBackend(DiagnosticsEngine & Diags,ModuleSummaryIndex * CombinedIndex,Module * M,const HeaderSearchOptions & HeaderOpts,const CodeGenOptions & CGOpts,const clang::TargetOptions & TOpts,const LangOptions & LOpts,std::unique_ptr<raw_pwrite_stream> OS,std::string SampleProfile,std::string ProfileRemapping,BackendAction Action)1115ec727ea7Spatrick static void runThinLTOBackend(
1116ec727ea7Spatrick DiagnosticsEngine &Diags, ModuleSummaryIndex *CombinedIndex, Module *M,
1117ec727ea7Spatrick const HeaderSearchOptions &HeaderOpts, const CodeGenOptions &CGOpts,
1118ec727ea7Spatrick const clang::TargetOptions &TOpts, const LangOptions &LOpts,
1119ec727ea7Spatrick std::unique_ptr<raw_pwrite_stream> OS, std::string SampleProfile,
1120ec727ea7Spatrick std::string ProfileRemapping, BackendAction Action) {
1121e5dd7070Spatrick StringMap<DenseMap<GlobalValue::GUID, GlobalValueSummary *>>
1122e5dd7070Spatrick ModuleToDefinedGVSummaries;
1123e5dd7070Spatrick CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
1124e5dd7070Spatrick
1125e5dd7070Spatrick setCommandLineOpts(CGOpts);
1126e5dd7070Spatrick
1127e5dd7070Spatrick // We can simply import the values mentioned in the combined index, since
1128e5dd7070Spatrick // we should only invoke this using the individual indexes written out
1129e5dd7070Spatrick // via a WriteIndexesThinBackend.
1130e5dd7070Spatrick FunctionImporter::ImportMapTy ImportList;
1131a9ac8606Spatrick if (!lto::initImportList(*M, *CombinedIndex, ImportList))
1132e5dd7070Spatrick return;
1133e5dd7070Spatrick
1134*12c85518Srobert auto AddStream = [&](size_t Task, const Twine &ModuleName) {
1135*12c85518Srobert return std::make_unique<CachedFileStream>(std::move(OS),
1136*12c85518Srobert CGOpts.ObjectFilenameForDebug);
1137e5dd7070Spatrick };
1138e5dd7070Spatrick lto::Config Conf;
1139e5dd7070Spatrick if (CGOpts.SaveTempsFilePrefix != "") {
1140e5dd7070Spatrick if (Error E = Conf.addSaveTemps(CGOpts.SaveTempsFilePrefix + ".",
1141e5dd7070Spatrick /* UseInputModulePath */ false)) {
1142e5dd7070Spatrick handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
1143e5dd7070Spatrick errs() << "Error setting up ThinLTO save-temps: " << EIB.message()
1144e5dd7070Spatrick << '\n';
1145e5dd7070Spatrick });
1146e5dd7070Spatrick }
1147e5dd7070Spatrick }
1148e5dd7070Spatrick Conf.CPU = TOpts.CPU;
1149e5dd7070Spatrick Conf.CodeModel = getCodeModel(CGOpts);
1150e5dd7070Spatrick Conf.MAttrs = TOpts.Features;
1151e5dd7070Spatrick Conf.RelocModel = CGOpts.RelocationModel;
1152*12c85518Srobert std::optional<CodeGenOpt::Level> OptLevelOrNone =
1153*12c85518Srobert CodeGenOpt::getLevel(CGOpts.OptimizationLevel);
1154*12c85518Srobert assert(OptLevelOrNone && "Invalid optimization level!");
1155*12c85518Srobert Conf.CGOptLevel = *OptLevelOrNone;
1156e5dd7070Spatrick Conf.OptLevel = CGOpts.OptimizationLevel;
1157ec727ea7Spatrick initTargetOptions(Diags, Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts);
1158e5dd7070Spatrick Conf.SampleProfile = std::move(SampleProfile);
1159e5dd7070Spatrick Conf.PTO.LoopUnrolling = CGOpts.UnrollLoops;
1160e5dd7070Spatrick // For historical reasons, loop interleaving is set to mirror setting for loop
1161e5dd7070Spatrick // unrolling.
1162e5dd7070Spatrick Conf.PTO.LoopInterleaving = CGOpts.UnrollLoops;
1163e5dd7070Spatrick Conf.PTO.LoopVectorization = CGOpts.VectorizeLoop;
1164e5dd7070Spatrick Conf.PTO.SLPVectorization = CGOpts.VectorizeSLP;
1165ec727ea7Spatrick // Only enable CGProfilePass when using integrated assembler, since
1166ec727ea7Spatrick // non-integrated assemblers don't recognize .cgprofile section.
1167ec727ea7Spatrick Conf.PTO.CallGraphProfile = !CGOpts.DisableIntegratedAS;
1168e5dd7070Spatrick
1169e5dd7070Spatrick // Context sensitive profile.
1170e5dd7070Spatrick if (CGOpts.hasProfileCSIRInstr()) {
1171e5dd7070Spatrick Conf.RunCSIRInstr = true;
1172e5dd7070Spatrick Conf.CSIRProfile = std::move(CGOpts.InstrProfileOutput);
1173e5dd7070Spatrick } else if (CGOpts.hasProfileCSIRUse()) {
1174e5dd7070Spatrick Conf.RunCSIRInstr = false;
1175e5dd7070Spatrick Conf.CSIRProfile = std::move(CGOpts.ProfileInstrumentUsePath);
1176e5dd7070Spatrick }
1177e5dd7070Spatrick
1178e5dd7070Spatrick Conf.ProfileRemapping = std::move(ProfileRemapping);
1179e5dd7070Spatrick Conf.DebugPassManager = CGOpts.DebugPassManager;
1180e5dd7070Spatrick Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness;
1181e5dd7070Spatrick Conf.RemarksFilename = CGOpts.OptRecordFile;
1182e5dd7070Spatrick Conf.RemarksPasses = CGOpts.OptRecordPasses;
1183e5dd7070Spatrick Conf.RemarksFormat = CGOpts.OptRecordFormat;
1184e5dd7070Spatrick Conf.SplitDwarfFile = CGOpts.SplitDwarfFile;
1185e5dd7070Spatrick Conf.SplitDwarfOutput = CGOpts.SplitDwarfOutput;
1186e5dd7070Spatrick switch (Action) {
1187e5dd7070Spatrick case Backend_EmitNothing:
1188e5dd7070Spatrick Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) {
1189e5dd7070Spatrick return false;
1190e5dd7070Spatrick };
1191e5dd7070Spatrick break;
1192e5dd7070Spatrick case Backend_EmitLL:
1193e5dd7070Spatrick Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) {
1194e5dd7070Spatrick M->print(*OS, nullptr, CGOpts.EmitLLVMUseLists);
1195e5dd7070Spatrick return false;
1196e5dd7070Spatrick };
1197e5dd7070Spatrick break;
1198e5dd7070Spatrick case Backend_EmitBC:
1199e5dd7070Spatrick Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) {
1200e5dd7070Spatrick WriteBitcodeToFile(*M, *OS, CGOpts.EmitLLVMUseLists);
1201e5dd7070Spatrick return false;
1202e5dd7070Spatrick };
1203e5dd7070Spatrick break;
1204e5dd7070Spatrick default:
1205e5dd7070Spatrick Conf.CGFileType = getCodeGenFileType(Action);
1206e5dd7070Spatrick break;
1207e5dd7070Spatrick }
1208a9ac8606Spatrick if (Error E =
1209a9ac8606Spatrick thinBackend(Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
1210a9ac8606Spatrick ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
1211a9ac8606Spatrick /* ModuleMap */ nullptr, CGOpts.CmdArgs)) {
1212e5dd7070Spatrick handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
1213e5dd7070Spatrick errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';
1214e5dd7070Spatrick });
1215e5dd7070Spatrick }
1216e5dd7070Spatrick }
1217e5dd7070Spatrick
EmitBackendOutput(DiagnosticsEngine & Diags,const HeaderSearchOptions & HeaderOpts,const CodeGenOptions & CGOpts,const clang::TargetOptions & TOpts,const LangOptions & LOpts,StringRef TDesc,Module * M,BackendAction Action,std::unique_ptr<raw_pwrite_stream> OS)1218e5dd7070Spatrick void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
1219e5dd7070Spatrick const HeaderSearchOptions &HeaderOpts,
1220e5dd7070Spatrick const CodeGenOptions &CGOpts,
1221e5dd7070Spatrick const clang::TargetOptions &TOpts,
1222e5dd7070Spatrick const LangOptions &LOpts,
1223a9ac8606Spatrick StringRef TDesc, Module *M,
1224e5dd7070Spatrick BackendAction Action,
1225e5dd7070Spatrick std::unique_ptr<raw_pwrite_stream> OS) {
1226e5dd7070Spatrick
1227e5dd7070Spatrick llvm::TimeTraceScope TimeScope("Backend");
1228e5dd7070Spatrick
1229e5dd7070Spatrick std::unique_ptr<llvm::Module> EmptyModule;
1230e5dd7070Spatrick if (!CGOpts.ThinLTOIndexFile.empty()) {
1231e5dd7070Spatrick // If we are performing a ThinLTO importing compile, load the function index
1232e5dd7070Spatrick // into memory and pass it into runThinLTOBackend, which will run the
1233e5dd7070Spatrick // function importer and invoke LTO passes.
1234*12c85518Srobert std::unique_ptr<ModuleSummaryIndex> CombinedIndex;
1235*12c85518Srobert if (Error E = llvm::getModuleSummaryIndexForFile(
1236*12c85518Srobert CGOpts.ThinLTOIndexFile,
1237*12c85518Srobert /*IgnoreEmptyThinLTOIndexFile*/ true)
1238*12c85518Srobert .moveInto(CombinedIndex)) {
1239*12c85518Srobert logAllUnhandledErrors(std::move(E), errs(),
1240e5dd7070Spatrick "Error loading index file '" +
1241e5dd7070Spatrick CGOpts.ThinLTOIndexFile + "': ");
1242e5dd7070Spatrick return;
1243e5dd7070Spatrick }
1244*12c85518Srobert
1245e5dd7070Spatrick // A null CombinedIndex means we should skip ThinLTO compilation
1246e5dd7070Spatrick // (LLVM will optionally ignore empty index files, returning null instead
1247e5dd7070Spatrick // of an error).
1248e5dd7070Spatrick if (CombinedIndex) {
1249e5dd7070Spatrick if (!CombinedIndex->skipModuleByDistributedBackend()) {
1250ec727ea7Spatrick runThinLTOBackend(Diags, CombinedIndex.get(), M, HeaderOpts, CGOpts,
1251ec727ea7Spatrick TOpts, LOpts, std::move(OS), CGOpts.SampleProfileFile,
1252e5dd7070Spatrick CGOpts.ProfileRemappingFile, Action);
1253e5dd7070Spatrick return;
1254e5dd7070Spatrick }
1255e5dd7070Spatrick // Distributed indexing detected that nothing from the module is needed
1256e5dd7070Spatrick // for the final linking. So we can skip the compilation. We sill need to
1257e5dd7070Spatrick // output an empty object file to make sure that a linker does not fail
1258e5dd7070Spatrick // trying to read it. Also for some features, like CFI, we must skip
1259e5dd7070Spatrick // the compilation as CombinedIndex does not contain all required
1260e5dd7070Spatrick // information.
1261e5dd7070Spatrick EmptyModule = std::make_unique<llvm::Module>("empty", M->getContext());
1262e5dd7070Spatrick EmptyModule->setTargetTriple(M->getTargetTriple());
1263e5dd7070Spatrick M = EmptyModule.get();
1264e5dd7070Spatrick }
1265e5dd7070Spatrick }
1266e5dd7070Spatrick
1267e5dd7070Spatrick EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M);
1268e5dd7070Spatrick AsmHelper.EmitAssembly(Action, std::move(OS));
1269e5dd7070Spatrick
1270e5dd7070Spatrick // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's
1271e5dd7070Spatrick // DataLayout.
1272e5dd7070Spatrick if (AsmHelper.TM) {
1273e5dd7070Spatrick std::string DLDesc = M->getDataLayout().getStringRepresentation();
1274a9ac8606Spatrick if (DLDesc != TDesc) {
1275e5dd7070Spatrick unsigned DiagID = Diags.getCustomDiagID(
1276e5dd7070Spatrick DiagnosticsEngine::Error, "backend data layout '%0' does not match "
1277e5dd7070Spatrick "expected target description '%1'");
1278a9ac8606Spatrick Diags.Report(DiagID) << DLDesc << TDesc;
1279e5dd7070Spatrick }
1280e5dd7070Spatrick }
1281e5dd7070Spatrick }
1282e5dd7070Spatrick
1283e5dd7070Spatrick // With -fembed-bitcode, save a copy of the llvm IR as data in the
1284e5dd7070Spatrick // __LLVM,__bitcode section.
EmbedBitcode(llvm::Module * M,const CodeGenOptions & CGOpts,llvm::MemoryBufferRef Buf)1285e5dd7070Spatrick void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
1286e5dd7070Spatrick llvm::MemoryBufferRef Buf) {
1287e5dd7070Spatrick if (CGOpts.getEmbedBitcode() == CodeGenOptions::Embed_Off)
1288e5dd7070Spatrick return;
1289*12c85518Srobert llvm::embedBitcodeInModule(
1290e5dd7070Spatrick *M, Buf, CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Marker,
1291e5dd7070Spatrick CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Bitcode,
1292a9ac8606Spatrick CGOpts.CmdArgs);
1293e5dd7070Spatrick }
1294*12c85518Srobert
EmbedObject(llvm::Module * M,const CodeGenOptions & CGOpts,DiagnosticsEngine & Diags)1295*12c85518Srobert void clang::EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts,
1296*12c85518Srobert DiagnosticsEngine &Diags) {
1297*12c85518Srobert if (CGOpts.OffloadObjects.empty())
1298*12c85518Srobert return;
1299*12c85518Srobert
1300*12c85518Srobert for (StringRef OffloadObject : CGOpts.OffloadObjects) {
1301*12c85518Srobert llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ObjectOrErr =
1302*12c85518Srobert llvm::MemoryBuffer::getFileOrSTDIN(OffloadObject);
1303*12c85518Srobert if (std::error_code EC = ObjectOrErr.getError()) {
1304*12c85518Srobert auto DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
1305*12c85518Srobert "could not open '%0' for embedding");
1306*12c85518Srobert Diags.Report(DiagID) << OffloadObject;
1307*12c85518Srobert return;
1308*12c85518Srobert }
1309*12c85518Srobert
1310*12c85518Srobert llvm::embedBufferInModule(*M, **ObjectOrErr, ".llvm.offloading",
1311*12c85518Srobert Align(object::OffloadBinary::getAlignment()));
1312*12c85518Srobert }
1313*12c85518Srobert }
1314