clang 24.0.0git
BackendUtil.cpp
Go to the documentation of this file.
1//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===//
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
10#include "BackendConsumer.h"
11#include "LinkInModulesPass.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/ADT/StringSwitch.h"
21#include "llvm/Analysis/GlobalsModRef.h"
22#include "llvm/Analysis/RuntimeLibcallInfo.h"
23#include "llvm/Analysis/TargetLibraryInfo.h"
24#include "llvm/Analysis/TargetTransformInfo.h"
25#include "llvm/BinaryFormat/ELF.h"
26#include "llvm/Bitcode/BitcodeReader.h"
27#include "llvm/Bitcode/BitcodeWriter.h"
28#include "llvm/Bitcode/BitcodeWriterPass.h"
29#include "llvm/CodeGen/MachineModuleInfo.h"
30#include "llvm/CodeGen/TargetSubtargetInfo.h"
31#include "llvm/Config/llvm-config.h"
32#include "llvm/Frontend/Driver/CodeGenOptions.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/DebugInfo.h"
35#include "llvm/IR/LLVMRemarkStreamer.h"
36#include "llvm/IR/LegacyPassManager.h"
37#include "llvm/IR/Module.h"
38#include "llvm/IR/ModuleSummaryIndex.h"
39#include "llvm/IR/PassManager.h"
40#include "llvm/IR/Verifier.h"
41#include "llvm/IRPrinter/IRPrintingPasses.h"
42#include "llvm/LTO/LTOBackend.h"
43#include "llvm/MC/TargetRegistry.h"
44#include "llvm/Object/OffloadBinary.h"
45#include "llvm/Passes/PassBuilder.h"
46#include "llvm/Passes/StandardInstrumentations.h"
47#include "llvm/Plugins/PassPlugin.h"
48#include "llvm/ProfileData/InstrProfCorrelator.h"
49#include "llvm/Support/BuryPointer.h"
50#include "llvm/Support/CodeGen.h"
51#include "llvm/Support/CommandLine.h"
52#include "llvm/Support/Compiler.h"
53#include "llvm/Support/IOSandbox.h"
54#include "llvm/Support/MemoryBuffer.h"
55#include "llvm/Support/PrettyStackTrace.h"
56#include "llvm/Support/Program.h"
57#include "llvm/Support/TimeProfiler.h"
58#include "llvm/Support/Timer.h"
59#include "llvm/Support/ToolOutputFile.h"
60#include "llvm/Support/VirtualFileSystem.h"
61#include "llvm/Support/raw_ostream.h"
62#include "llvm/Target/TargetMachine.h"
63#include "llvm/Target/TargetOptions.h"
64#include "llvm/TargetParser/SubtargetFeature.h"
65#include "llvm/TargetParser/Triple.h"
66#include "llvm/Transforms/HipStdPar/HipStdPar.h"
67#include "llvm/Transforms/IPO/EmbedBitcodePass.h"
68#include "llvm/Transforms/IPO/InferFunctionAttrs.h"
69#include "llvm/Transforms/IPO/LowerTypeTests.h"
70#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
71#include "llvm/Transforms/InstCombine/InstCombine.h"
72#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
73#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
74#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
75#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
76#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
77#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
78#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
79#include "llvm/Transforms/Instrumentation/KCFI.h"
80#include "llvm/Transforms/Instrumentation/LowerAllowCheckPass.h"
81#include "llvm/Transforms/Instrumentation/MemProfInstrumentation.h"
82#include "llvm/Transforms/Instrumentation/MemProfUse.h"
83#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
84#include "llvm/Transforms/Instrumentation/NumericalStabilitySanitizer.h"
85#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
86#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
87#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
88#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
89#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
90#include "llvm/Transforms/Instrumentation/TypeSanitizer.h"
91#include "llvm/Transforms/ObjCARC.h"
92#include "llvm/Transforms/Scalar/EarlyCSE.h"
93#include "llvm/Transforms/Scalar/GVN.h"
94#include "llvm/Transforms/Scalar/JumpThreading.h"
95#include "llvm/Transforms/Utils/AssignGUID.h"
96#include "llvm/Transforms/Utils/Debugify.h"
97#include "llvm/Transforms/Utils/DynamicDebugging.h"
98#include "llvm/Transforms/Utils/ModuleUtils.h"
99#include <limits>
100#include <memory>
101#include <optional>
102using namespace clang;
103using namespace llvm;
104
105#define HANDLE_EXTENSION(Ext) \
106 llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
107#include "llvm/Support/Extension.def"
108
109namespace llvm {
110// Experiment to move sanitizers earlier.
111static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(
112 "sanitizer-early-opt-ep", cl::Optional,
113 cl::desc("Insert sanitizers on OptimizerEarlyEP."));
114
115// Experiment to mark cold functions as optsize/minsize/optnone.
116// TODO: remove once this is exposed as a proper driver flag.
117static cl::opt<PGOOptions::ColdFuncOpt> ClPGOColdFuncAttr(
118 "pgo-cold-func-opt", cl::init(PGOOptions::ColdFuncOpt::Default), cl::Hidden,
119 cl::desc(
120 "Function attribute to apply to cold functions as determined by PGO"),
121 cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default",
122 "Default (no attribute)"),
123 clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize",
124 "Mark cold functions with optsize."),
125 clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize",
126 "Mark cold functions with minsize."),
127 clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone",
128 "Mark cold functions with optnone.")));
129
130LLVM_ABI extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind>
132} // namespace llvm
133namespace clang {
134extern llvm::cl::opt<bool> ClSanitizeGuardChecks;
135}
136
137// Path and name of file used for profile generation
138static std::string getProfileGenName(const CodeGenOptions &CodeGenOpts) {
139 std::string FileName = CodeGenOpts.InstrProfileOutput.empty()
140 ? llvm::driver::getDefaultProfileGenName()
141 : CodeGenOpts.InstrProfileOutput;
142 if (CodeGenOpts.ContinuousProfileSync)
143 FileName = "%c" + FileName;
144 return FileName;
145}
146
147namespace {
148
149class EmitAssemblyHelper {
150 CompilerInstance &CI;
151 DiagnosticsEngine &Diags;
152 const CodeGenOptions &CodeGenOpts;
153 const clang::TargetOptions &TargetOpts;
154 const LangOptions &LangOpts;
155 llvm::Module *TheModule;
156 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
157
158 std::unique_ptr<raw_pwrite_stream> OS;
159
160 Triple TargetTriple;
161
162 TargetIRAnalysis getTargetIRAnalysis() const {
163 if (TM)
164 return TM->getTargetIRAnalysis();
165
166 return TargetIRAnalysis();
167 }
168
169 /// Generates the TargetMachine.
170 /// Leaves TM unchanged if it is unable to create the target machine.
171 /// Some of our clang tests specify triples which are not built
172 /// into clang. This is okay because these tests check the generated
173 /// IR, and they require DataLayout which depends on the triple.
174 /// In this case, we allow this method to fail and not report an error.
175 /// When MustCreateTM is used, we print an error if we are unable to load
176 /// the requested target.
177 void CreateTargetMachine(bool MustCreateTM);
178
179 std::unique_ptr<llvm::ToolOutputFile> openOutputFile(StringRef Path) {
180 std::error_code EC;
181 auto F = std::make_unique<llvm::ToolOutputFile>(Path, EC,
182 llvm::sys::fs::OF_None);
183 if (EC) {
184 Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
185 F.reset();
186 }
187 return F;
188 }
189
190 void RunOptimizationPipeline(
191 BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,
192 std::unique_ptr<llvm::ToolOutputFile> &ThinLinkOS, BackendConsumer *BC);
193 void RunCodegenPipeline(BackendAction Action,
194 std::unique_ptr<raw_pwrite_stream> &OS,
195 std::unique_ptr<llvm::ToolOutputFile> &DwoOS);
196 void RunCodegenPipelineLegacy(BackendAction Action,
197 std::unique_ptr<raw_pwrite_stream> &OS,
198 std::unique_ptr<llvm::ToolOutputFile> &DwoOS,
199 CodeGenFileType CGFT);
200 void RunCodegenPipelineNewPM(BackendAction Action,
201 std::unique_ptr<raw_pwrite_stream> &OS,
202 std::unique_ptr<llvm::ToolOutputFile> &DwoOS,
203 CodeGenFileType CGFT);
204 void TimeCodegenPasses(llvm::function_ref<void()> RunPasses);
205
206 /// Check whether we should emit a module summary for regular LTO.
207 /// The module summary should be emitted by default for regular LTO
208 /// except for ld64 targets.
209 ///
210 /// \return True if the module summary should be emitted.
211 bool shouldEmitRegularLTOSummary() const {
212 return CodeGenOpts.PrepareForLTO && !CodeGenOpts.DisableLLVMPasses &&
213 TargetTriple.getVendor() != llvm::Triple::Apple;
214 }
215
216 /// Check whether we should emit a flag for UnifiedLTO.
217 /// The UnifiedLTO module flag should be set when UnifiedLTO is enabled for
218 /// ThinLTO or Full LTO with module summaries.
219 bool shouldEmitUnifiedLTOModueFlag() const {
220 return CodeGenOpts.UnifiedLTO &&
221 (CodeGenOpts.PrepareForThinLTO || shouldEmitRegularLTOSummary());
222 }
223
224public:
225 EmitAssemblyHelper(CompilerInstance &CI, CodeGenOptions &CGOpts,
226 llvm::Module *M,
227 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
228 : CI(CI), Diags(CI.getDiagnostics()), CodeGenOpts(CGOpts),
229 TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()),
230 TheModule(M), VFS(std::move(VFS)),
231 TargetTriple(TheModule->getTargetTriple()) {}
232
233 ~EmitAssemblyHelper() {
234 if (CodeGenOpts.DisableFree)
235 BuryPointer(std::move(TM));
236 }
237
238 std::unique_ptr<TargetMachine> TM;
239
240 // Emit output using the new pass manager for the optimization pipeline.
241 void emitAssembly(BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS,
242 BackendConsumer *BC);
243};
244} // namespace
245
246static SanitizerCoverageOptions
248 SanitizerCoverageOptions Opts;
249 Opts.CoverageType =
250 static_cast<SanitizerCoverageOptions::Type>(CGOpts.SanitizeCoverageType);
251 Opts.IndirectCalls = CGOpts.SanitizeCoverageIndirectCalls;
252 Opts.TraceBB = CGOpts.SanitizeCoverageTraceBB;
253 Opts.TraceCmp = CGOpts.SanitizeCoverageTraceCmp;
254 Opts.TraceDiv = CGOpts.SanitizeCoverageTraceDiv;
255 Opts.TraceGep = CGOpts.SanitizeCoverageTraceGep;
256 Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters;
257 Opts.TracePC = CGOpts.SanitizeCoverageTracePC;
258 Opts.TracePCEntryExit = CGOpts.SanitizeCoverageTracePCEntryExit;
259 Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard;
260 Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune;
261 Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters;
262 Opts.InlineBoolFlag = CGOpts.SanitizeCoverageInlineBoolFlag;
263 Opts.PCTable = CGOpts.SanitizeCoveragePCTable;
264 Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth;
265 Opts.StackDepthCallbackMin = CGOpts.SanitizeCoverageStackDepthCallbackMin;
266 Opts.TraceLoads = CGOpts.SanitizeCoverageTraceLoads;
267 Opts.TraceStores = CGOpts.SanitizeCoverageTraceStores;
268 Opts.CollectControlFlow = CGOpts.SanitizeCoverageControlFlow;
269 return Opts;
270}
271
272static SanitizerBinaryMetadataOptions
274 SanitizerBinaryMetadataOptions Opts;
275 Opts.Covered = CGOpts.SanitizeBinaryMetadataCovered;
276 Opts.Atomics = CGOpts.SanitizeBinaryMetadataAtomics;
277 Opts.UAR = CGOpts.SanitizeBinaryMetadataUAR;
278 return Opts;
279}
280
281// Check if ASan should use GC-friendly instrumentation for globals.
282// First of all, there is no point if -fdata-sections is off (expect for MachO,
283// where this is not a factor). Also, on ELF this feature requires an assembler
284// extension that only works with -integrated-as at the moment.
285static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) {
286 if (!CGOpts.SanitizeAddressGlobalsDeadStripping)
287 return false;
288 switch (T.getObjectFormat()) {
289 case Triple::MachO:
290 case Triple::COFF:
291 return true;
292 case Triple::ELF:
293 return !CGOpts.DisableIntegratedAS;
294 case Triple::GOFF:
295 llvm::report_fatal_error("ASan not implemented for GOFF");
296 case Triple::XCOFF:
297 llvm::report_fatal_error("ASan not implemented for XCOFF.");
298 case Triple::Wasm:
299 case Triple::DXContainer:
300 case Triple::SPIRV:
301 case Triple::UnknownObjectFormat:
302 break;
303 }
304 return false;
305}
306
307static std::optional<llvm::CodeModel::Model>
308getCodeModel(const CodeGenOptions &CodeGenOpts) {
309 unsigned CodeModel = llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel)
310 .Case("tiny", llvm::CodeModel::Tiny)
311 .Case("small", llvm::CodeModel::Small)
312 .Case("kernel", llvm::CodeModel::Kernel)
313 .Case("medium", llvm::CodeModel::Medium)
314 .Case("large", llvm::CodeModel::Large)
315 .Cases({"default", ""}, ~1u)
316 .Default(~0u);
317 assert(CodeModel != ~0u && "invalid code model!");
318 if (CodeModel == ~1u)
319 return std::nullopt;
320 return static_cast<llvm::CodeModel::Model>(CodeModel);
321}
322
323static CodeGenFileType getCodeGenFileType(BackendAction Action) {
324 if (Action == Backend_EmitObj)
325 return CodeGenFileType::ObjectFile;
326 else if (Action == Backend_EmitMCNull)
327 return CodeGenFileType::Null;
328 else {
329 assert(Action == Backend_EmitAssembly && "Invalid action!");
330 return CodeGenFileType::AssemblyFile;
331 }
332}
333
335 return Action != Backend_EmitNothing && Action != Backend_EmitBC &&
336 Action != Backend_EmitLL;
337}
338
340 StringRef MainFilename,
341 ArrayRef<StringRef> InputFiles) {
342 if (Args.empty())
343 return std::string{};
344
345 std::string FlatCmdLine;
346 raw_string_ostream OS(FlatCmdLine);
347 bool PrintedOneArg = false;
348 if (!StringRef(Args[0]).contains("-cc1")) {
349 llvm::sys::printArg(OS, "-cc1", /*Quote=*/true);
350 PrintedOneArg = true;
351 }
352 for (unsigned i = 0; i < Args.size(); i++) {
353 StringRef Arg = Args[i];
354 if (Arg.empty())
355 continue;
356 if (Arg == "-main-file-name" || Arg == "-o") {
357 i++; // Skip this argument and next one.
358 continue;
359 }
360 if (Arg.starts_with("-object-file-name"))
361 continue;
362 // Strip the source positional, matching either MainFilename (the
363 // -main-file-name basename) or one of the resolved frontend input paths
364 // (which is what the cc1 positional looks like for an absolute driver
365 // input). Avoid a generic basename match: it would also strip values of
366 // args like `-include <path>` whose trailing component happens to equal
367 // the source basename.
368 if (Arg == MainFilename || llvm::is_contained(InputFiles, Arg))
369 continue;
370 // Skip fmessage-length for reproducibility.
371 if (Arg.starts_with("-fmessage-length"))
372 continue;
373 if (PrintedOneArg)
374 OS << " ";
375 llvm::sys::printArg(OS, Arg, /*Quote=*/true);
376 PrintedOneArg = true;
377 }
378 return FlatCmdLine;
379}
380
382 DiagnosticsEngine &Diags,
383 llvm::TargetOptions &Options) {
384 const auto &CodeGenOpts = CI.getCodeGenOpts();
385 const auto &TargetOpts = CI.getTargetOpts();
386 const auto &LangOpts = CI.getLangOpts();
387 const auto &HSOpts = CI.getHeaderSearchOpts();
388 switch (LangOpts.getThreadModel()) {
390 Options.ThreadModel = llvm::ThreadModel::POSIX;
391 break;
393 Options.ThreadModel = llvm::ThreadModel::Single;
394 break;
395 }
396
397 // Set float ABI type.
398 assert((CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp" ||
399 CodeGenOpts.FloatABI == "hard" || CodeGenOpts.FloatABI.empty()) &&
400 "Invalid Floating Point ABI!");
401 Options.FloatABIType =
402 llvm::StringSwitch<llvm::FloatABI::ABIType>(CodeGenOpts.FloatABI)
403 .Case("soft", llvm::FloatABI::Soft)
404 .Case("softfp", llvm::FloatABI::Soft)
405 .Case("hard", llvm::FloatABI::Hard)
406 .Default(llvm::FloatABI::Default);
407
408 // Set FP fusion mode.
409 switch (LangOpts.getDefaultFPContractMode()) {
411 // Preserve any contraction performed by the front-end. (Strict performs
412 // splitting of the muladd intrinsic in the backend.)
413 Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
414 break;
417 Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
418 break;
420 Options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
421 break;
422 }
423
424 Options.BinutilsVersion =
425 llvm::TargetMachine::parseBinutilsVersion(CodeGenOpts.BinutilsVersion);
426 Options.UseInitArray = CodeGenOpts.UseInitArray;
427 Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS;
428
429 // Set EABI version.
430 Options.EABIVersion = TargetOpts.EABIVersion;
431
432 if (CodeGenOpts.hasSjLjExceptions())
433 Options.ExceptionModel = llvm::ExceptionHandling::SjLj;
434 if (CodeGenOpts.hasSEHExceptions())
435 Options.ExceptionModel = llvm::ExceptionHandling::WinEH;
436 if (CodeGenOpts.hasDWARFExceptions())
437 Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI;
438 if (CodeGenOpts.hasWasmExceptions())
439 Options.ExceptionModel = llvm::ExceptionHandling::Wasm;
440
441 Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
442
443 Options.BBAddrMap = CodeGenOpts.BBAddrMap;
444 Options.BBSections =
445 llvm::StringSwitch<llvm::BasicBlockSection>(CodeGenOpts.BBSections)
446 .Case("all", llvm::BasicBlockSection::All)
447 .StartsWith("list=", llvm::BasicBlockSection::List)
448 .Case("none", llvm::BasicBlockSection::None)
449 .Default(llvm::BasicBlockSection::None);
450
451 if (Options.BBSections == llvm::BasicBlockSection::List) {
452 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
453 CI.getVirtualFileSystem().getBufferForFile(
454 CodeGenOpts.BBSections.substr(5));
455 if (!MBOrErr) {
456 Diags.Report(diag::err_fe_unable_to_load_basic_block_sections_file)
457 << MBOrErr.getError().message();
458 return false;
459 }
460 Options.BBSectionsFuncListBuf = std::move(*MBOrErr);
461 }
462
463 Options.EnableMachineFunctionSplitter = CodeGenOpts.SplitMachineFunctions;
464 Options.EnableStaticDataPartitioning =
465 CodeGenOpts.PartitionStaticDataSections;
466 Options.FunctionSections = CodeGenOpts.FunctionSections;
467 Options.DataSections = CodeGenOpts.DataSections;
468 Options.IgnoreXCOFFVisibility = LangOpts.IgnoreXCOFFVisibility;
469 Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames;
470 Options.UniqueBasicBlockSectionNames =
471 CodeGenOpts.UniqueBasicBlockSectionNames;
472 Options.SeparateNamedSections = CodeGenOpts.SeparateNamedSections;
473 Options.TLSSize = CodeGenOpts.TLSSize;
474 Options.EnableTLSDESC = CodeGenOpts.EnableTLSDESC;
475 Options.EmulatedTLS = CodeGenOpts.EmulatedTLS;
476 Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
477 Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
478 Options.StackUsageFile = CodeGenOpts.StackUsageFile;
479 Options.EmitAddrsig = CodeGenOpts.Addrsig;
480 Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
481 Options.EmitCallGraphSection = CodeGenOpts.CallGraphSection;
482 Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;
483 Options.EnableAIXExtendedAltivecABI = LangOpts.EnableAIXExtendedAltivecABI;
484 Options.XRayFunctionIndex = CodeGenOpts.XRayFunctionIndex;
485 Options.LoopAlignment = CodeGenOpts.LoopAlignment;
486 Options.DebugStrictDwarf = CodeGenOpts.DebugStrictDwarf;
488 Options.Hotpatch = CodeGenOpts.HotPatch;
489 Options.JMCInstrument = CodeGenOpts.JMCInstrument;
490 Options.XCOFFReadOnlyPointers = CodeGenOpts.XCOFFReadOnlyPointers;
491 Options.VecLib =
492 convertDriverVectorLibraryToVectorLibrary(CodeGenOpts.getVecLib());
493
494 switch (CodeGenOpts.getSwiftAsyncFramePointer()) {
496 Options.SwiftAsyncFramePointer =
497 SwiftAsyncFramePointerMode::DeploymentBased;
498 break;
499
501 Options.SwiftAsyncFramePointer = SwiftAsyncFramePointerMode::Always;
502 break;
503
505 Options.SwiftAsyncFramePointer = SwiftAsyncFramePointerMode::Never;
506 break;
507 }
508
509 Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
510 Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind();
511 Options.MCOptions.EmitCompactUnwindNonCanonical =
512 CodeGenOpts.EmitCompactUnwindNonCanonical;
513 Options.MCOptions.EmitSFrameUnwind = CodeGenOpts.EmitSFrameUnwind;
514 Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;
515 Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;
516 Options.MCOptions.MCUseDwarfDirectory =
517 CodeGenOpts.NoDwarfDirectoryAsm
518 ? llvm::MCTargetOptions::DisableDwarfDirectory
519 : llvm::MCTargetOptions::EnableDwarfDirectory;
520 Options.MCOptions.MCNoExecStack = CodeGenOpts.NoExecStack;
521 Options.MCOptions.MCIncrementalLinkerCompatible =
522 CodeGenOpts.IncrementalLinkerCompatible;
523 Options.MCOptions.MCFatalWarnings = CodeGenOpts.FatalWarnings;
524 Options.MCOptions.MCNoWarn = CodeGenOpts.NoWarn;
525 Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose;
526 Options.MCOptions.Dwarf64 = CodeGenOpts.Dwarf64;
527 Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments;
528 Options.MCOptions.Crel = CodeGenOpts.Crel;
529 Options.MCOptions.RelocSectionSym = CodeGenOpts.getRelocSectionSym();
530 Options.MCOptions.ImplicitMapSyms = CodeGenOpts.ImplicitMapSyms;
531 Options.MCOptions.X86RelaxRelocations = CodeGenOpts.X86RelaxRelocations;
532 Options.MCOptions.CompressDebugSections =
533 CodeGenOpts.getCompressDebugSections();
534 if (CodeGenOpts.OutputAsmVariant != 3) // 3 (default): not specified
535 Options.MCOptions.OutputAsmVariant = CodeGenOpts.OutputAsmVariant;
536 Options.MCOptions.ABIName = TargetOpts.ABI;
537 for (const auto &Entry : HSOpts.UserEntries)
538 if (!Entry.IsFramework &&
539 (Entry.Group == frontend::IncludeDirGroup::Quoted ||
540 Entry.Group == frontend::IncludeDirGroup::Angled ||
541 Entry.Group == frontend::IncludeDirGroup::System))
542 Options.MCOptions.IASSearchPaths.push_back(
543 Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path);
544 Options.MCOptions.Argv0 = CodeGenOpts.Argv0 ? CodeGenOpts.Argv0 : "";
545 // Pass the resolved frontend inputs so flattenClangCommandLine can strip
546 // the cc1 source positional even when the driver received an absolute path
547 // (which won't match CodeGenOpts.MainFileName, that's just the basename).
548 SmallVector<StringRef, 1> InputFiles;
549 for (const auto &Input : CI.getFrontendOpts().Inputs)
550 if (Input.isFile())
551 InputFiles.push_back(Input.getFile());
552 Options.MCOptions.CommandlineArgs = flattenClangCommandLine(
553 CodeGenOpts.CommandLineArgs, CodeGenOpts.MainFileName, InputFiles);
554 Options.MCOptions.AsSecureLogFile = CodeGenOpts.AsSecureLogFile;
555 Options.MCOptions.PPCUseFullRegisterNames =
556 CodeGenOpts.PPCUseFullRegisterNames;
557 Options.MisExpect = CodeGenOpts.MisExpect;
558
559 return true;
560}
561
562static std::optional<GCOVOptions>
563getGCOVOptions(const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts) {
564 if (CodeGenOpts.CoverageNotesFile.empty() &&
565 CodeGenOpts.CoverageDataFile.empty())
566 return std::nullopt;
567 // Not using 'GCOVOptions::getDefault' allows us to avoid exiting if
568 // LLVM's -default-gcov-version flag is set to something invalid.
569 GCOVOptions Options;
570 Options.EmitNotes = !CodeGenOpts.CoverageNotesFile.empty();
571 Options.EmitData = !CodeGenOpts.CoverageDataFile.empty();
572 llvm::copy(CodeGenOpts.CoverageVersion, std::begin(Options.Version));
573 Options.NoRedZone = CodeGenOpts.DisableRedZone;
574 Options.Filter = CodeGenOpts.ProfileFilterFiles;
575 Options.Exclude = CodeGenOpts.ProfileExcludeFiles;
576 Options.Atomic = CodeGenOpts.AtomicProfileUpdate;
577 return Options;
578}
579
580static std::optional<InstrProfOptions>
582 const LangOptions &LangOpts) {
583 if (!CodeGenOpts.hasProfileClangInstr())
584 return std::nullopt;
585 InstrProfOptions Options;
586 Options.NoRedZone = CodeGenOpts.DisableRedZone;
587 Options.InstrProfileOutput = CodeGenOpts.ContinuousProfileSync
588 ? ("%c" + CodeGenOpts.InstrProfileOutput)
589 : CodeGenOpts.InstrProfileOutput;
590 Options.Atomic = CodeGenOpts.AtomicProfileUpdate;
591 return Options;
592}
593
594static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts,
595 vfs::FileSystem &VFS) {
597 BackendArgs.push_back("clang"); // Fake program name.
598 if (!CodeGenOpts.DebugPass.empty()) {
599 BackendArgs.push_back("-debug-pass");
600 BackendArgs.push_back(CodeGenOpts.DebugPass.c_str());
601 }
602 if (!CodeGenOpts.LimitFloatPrecision.empty()) {
603 BackendArgs.push_back("-limit-float-precision");
604 BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
605 }
606
607 // Check for the default "clang" invocation that won't set any cl::opt values.
608 // Skip trying to parse the command line invocation to avoid the issues
609 // described below.
610 if (BackendArgs.size() == 1)
611 return;
612 BackendArgs.push_back(nullptr);
613 // FIXME: The command line parser below is not thread-safe and shares a global
614 // state, so this call might crash or overwrite the options of another Clang
615 // instance in the same process.
616 llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, BackendArgs.data(),
617 /*Overview=*/"", /*Errs=*/nullptr,
618 /*VFS=*/&VFS);
619}
620
621void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
622 // Create the TargetMachine for generating code.
623 std::string Error;
624 const llvm::Triple &Triple = TheModule->getTargetTriple();
625 const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
626 if (!TheTarget) {
627 if (MustCreateTM)
628 Diags.Report(diag::err_fe_unable_to_create_target) << Error;
629 return;
630 }
631
632 std::optional<llvm::CodeModel::Model> CM = getCodeModel(CodeGenOpts);
633 std::string FeaturesStr =
634 llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ",");
635 llvm::Reloc::Model RM = CodeGenOpts.RelocationModel;
636 std::optional<CodeGenOptLevel> OptLevelOrNone =
637 CodeGenOpt::getLevel(CodeGenOpts.OptimizationLevel);
638 assert(OptLevelOrNone && "Invalid optimization level!");
639 CodeGenOptLevel OptLevel = *OptLevelOrNone;
640
641 llvm::TargetOptions Options;
642 if (!initTargetOptions(CI, Diags, Options))
643 return;
644 TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr,
645 Options, RM, CM, OptLevel));
646 if (TM)
647 TM->setLargeDataThreshold(CodeGenOpts.LargeDataThreshold);
648}
649
650static OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
651 switch (Opts.OptimizationLevel) {
652 default:
653 llvm_unreachable("Invalid optimization level!");
654
655 case 0:
656 return OptimizationLevel::O0;
657
658 case 1:
659 return OptimizationLevel::O1;
660
661 case 2:
662 return OptimizationLevel::O2;
663
664 case 3:
665 return OptimizationLevel::O3;
666 }
667}
668
669static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,
670 PassBuilder &PB) {
671 // If the back-end supports KCFI operand bundle lowering, skip KCFIPass.
672 if (TargetTriple.getArch() == llvm::Triple::x86_64 ||
673 TargetTriple.isAArch64(64) || TargetTriple.isRISCV() ||
674 TargetTriple.isARM() || TargetTriple.isThumb() ||
675 TargetTriple.getArch() == llvm::Triple::hexagon)
676 return;
677
678 // Ensure we lower KCFI operand bundles with -O0.
679 PB.registerOptimizerLastEPCallback(
680 [&](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase) {
681 if (Level == OptimizationLevel::O0 &&
682 LangOpts.Sanitize.has(SanitizerKind::KCFI))
683 MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass()));
684 });
685
686 // When optimizations are requested, run KCIFPass after InstCombine to
687 // avoid unnecessary checks.
688 PB.registerPeepholeEPCallback(
689 [&](FunctionPassManager &FPM, OptimizationLevel Level) {
690 if (Level != OptimizationLevel::O0 &&
691 LangOpts.Sanitize.has(SanitizerKind::KCFI))
692 FPM.addPass(KCFIPass());
693 });
694}
695
696static void addSanitizers(const Triple &TargetTriple,
697 const CodeGenOptions &CodeGenOpts,
698 const LangOptions &LangOpts, PassBuilder &PB) {
699 auto SanitizersCallback = [&](ModulePassManager &MPM, OptimizationLevel Level,
700 ThinOrFullLTOPhase) {
701 if (CodeGenOpts.hasSanitizeCoverage()) {
702 auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
703 MPM.addPass(
704 SanitizerCoveragePass(SancovOpts, PB.getVirtualFileSystemPtr(),
707 }
708
709 if (CodeGenOpts.hasSanitizeBinaryMetadata()) {
710 MPM.addPass(SanitizerBinaryMetadataPass(
712 PB.getVirtualFileSystemPtr(),
714 }
715
716 auto MSanPass = [&](SanitizerMask Mask, bool CompileKernel) {
717 if (LangOpts.Sanitize.has(Mask)) {
718 int TrackOrigins = CodeGenOpts.SanitizeMemoryTrackOrigins;
719 bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
720
721 MemorySanitizerOptions options(TrackOrigins, Recover, CompileKernel,
722 CodeGenOpts.SanitizeMemoryParamRetval);
723 MPM.addPass(MemorySanitizerPass(options));
724 if (Level != OptimizationLevel::O0) {
725 // MemorySanitizer inserts complex instrumentation that mostly follows
726 // the logic of the original code, but operates on "shadow" values. It
727 // can benefit from re-running some general purpose optimization
728 // passes.
729 MPM.addPass(RequireAnalysisPass<GlobalsAA, llvm::Module>());
730 FunctionPassManager FPM;
731 FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */));
732 FPM.addPass(InstCombinePass());
733 FPM.addPass(JumpThreadingPass());
734 FPM.addPass(GVNPass());
735 FPM.addPass(InstCombinePass());
736 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
737 }
738 }
739 };
740 MSanPass(SanitizerKind::Memory, false);
741 MSanPass(SanitizerKind::KernelMemory, true);
742
743 if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
744 MPM.addPass(ModuleThreadSanitizerPass());
745 MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
746 }
747
748 if (LangOpts.Sanitize.has(SanitizerKind::Type))
749 MPM.addPass(TypeSanitizerPass());
750
751 if (LangOpts.Sanitize.has(SanitizerKind::NumericalStability))
752 MPM.addPass(NumericalStabilitySanitizerPass());
753
754 if (LangOpts.Sanitize.has(SanitizerKind::Realtime))
755 MPM.addPass(RealtimeSanitizerPass());
756
757 auto ASanPass = [&](SanitizerMask Mask, bool CompileKernel) {
758 if (LangOpts.Sanitize.has(Mask)) {
759 bool UseGlobalGC = asanUseGlobalsGC(TargetTriple, CodeGenOpts);
760 bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator;
761 llvm::AsanDtorKind DestructorKind =
762 CodeGenOpts.getSanitizeAddressDtor();
763 AddressSanitizerOptions Opts;
764 Opts.CompileKernel = CompileKernel;
765 Opts.Recover = CodeGenOpts.SanitizeRecover.has(Mask);
766 Opts.UseAfterScope = CodeGenOpts.SanitizeAddressUseAfterScope;
767 Opts.UseAfterReturn = CodeGenOpts.getSanitizeAddressUseAfterReturn();
768 MPM.addPass(AddressSanitizerPass(Opts, UseGlobalGC, UseOdrIndicator,
769 DestructorKind));
770 }
771 };
772 ASanPass(SanitizerKind::Address, false);
773 ASanPass(SanitizerKind::KernelAddress, true);
774
775 auto HWASanPass = [&](SanitizerMask Mask, bool CompileKernel) {
776 if (LangOpts.Sanitize.has(Mask)) {
777 bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
778 MPM.addPass(HWAddressSanitizerPass(
779 {CompileKernel, Recover,
780 /*DisableOptimization=*/CodeGenOpts.OptimizationLevel == 0}));
781 }
782 };
783 HWASanPass(SanitizerKind::HWAddress, false);
784 HWASanPass(SanitizerKind::KernelHWAddress, true);
785
786 if (LangOpts.Sanitize.has(SanitizerKind::DataFlow)) {
787 MPM.addPass(DataFlowSanitizerPass(LangOpts.NoSanitizeFiles,
788 PB.getVirtualFileSystemPtr()));
789 }
790 };
792 PB.registerOptimizerEarlyEPCallback(
793 [SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level,
794 ThinOrFullLTOPhase Phase) {
795 ModulePassManager NewMPM;
796 SanitizersCallback(NewMPM, Level, Phase);
797 if (!NewMPM.isEmpty()) {
798 // Sanitizers can abandon<GlobalsAA>.
799 NewMPM.addPass(RequireAnalysisPass<GlobalsAA, llvm::Module>());
800 MPM.addPass(std::move(NewMPM));
801 }
802 });
803 } else {
804 // LastEP does not need GlobalsAA.
805 PB.registerOptimizerLastEPCallback(SanitizersCallback);
806 }
807}
808
810 const LangOptions &LangOpts, PassBuilder &PB) {
811 // SanitizeSkipHotCutoffs: doubles with range [0, 1]
812 // Opts.cutoffs: unsigned ints with range [0, 1000000]
813 auto ScaledCutoffs = CodeGenOpts.SanitizeSkipHotCutoffs.getAllScaled(1000000);
814 uint64_t AllowRuntimeCheckSkipHotCutoff =
815 CodeGenOpts.AllowRuntimeCheckSkipHotCutoff.value_or(0.0) * 1000000;
816 // Only register the pass if one of the relevant sanitizers is enabled.
817 // This avoids pipeline overhead for builds that do not use these sanitizers.
818 bool LowerAllowSanitize = LangOpts.Sanitize.hasOneOf(
819 SanitizerKind::Address | SanitizerKind::KernelAddress |
820 SanitizerKind::Thread | SanitizerKind::Memory |
821 SanitizerKind::KernelMemory | SanitizerKind::HWAddress |
822 SanitizerKind::KernelHWAddress);
823
824 // TODO: remove IsRequested()
825 if (LowerAllowCheckPass::IsRequested() || ScaledCutoffs.has_value() ||
826 CodeGenOpts.AllowRuntimeCheckSkipHotCutoff.has_value() ||
827 LowerAllowSanitize) {
828 // We want to call it after inline, which is about OptimizerEarlyEPCallback.
829 PB.registerOptimizerEarlyEPCallback(
830 [ScaledCutoffs, AllowRuntimeCheckSkipHotCutoff](
831 ModulePassManager &MPM, OptimizationLevel Level,
832 ThinOrFullLTOPhase Phase) {
833 LowerAllowCheckPass::Options Opts;
834 // TODO: after removing IsRequested(), make this unconditional
835 if (ScaledCutoffs.has_value())
836 Opts.cutoffs = ScaledCutoffs.value();
837 Opts.runtime_check = AllowRuntimeCheckSkipHotCutoff;
838 MPM.addPass(
839 createModuleToFunctionPassAdaptor(LowerAllowCheckPass(Opts)));
840 });
841 }
842}
843
844void EmitAssemblyHelper::RunOptimizationPipeline(
845 BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,
846 std::unique_ptr<llvm::ToolOutputFile> &ThinLinkOS, BackendConsumer *BC) {
847 std::optional<PGOOptions> PGOOpt;
848
849 if (CodeGenOpts.hasProfileIRInstr())
850 // -fprofile-generate.
851 PGOOpt = PGOOptions(getProfileGenName(CodeGenOpts), "", "",
852 CodeGenOpts.MemoryProfileUsePath, PGOOptions::IRInstr,
853 PGOOptions::NoCSAction, ClPGOColdFuncAttr,
854 CodeGenOpts.DebugInfoForProfiling,
855 /*PseudoProbeForProfiling=*/false,
856 CodeGenOpts.AtomicProfileUpdate);
857 else if (CodeGenOpts.hasProfileIRUse()) {
858 // -fprofile-use.
859 auto CSAction = CodeGenOpts.hasProfileCSIRUse() ? PGOOptions::CSIRUse
860 : PGOOptions::NoCSAction;
861 PGOOpt = PGOOptions(CodeGenOpts.ProfileInstrumentUsePath, "",
862 CodeGenOpts.ProfileRemappingFile,
863 CodeGenOpts.MemoryProfileUsePath, PGOOptions::IRUse,
864 CSAction, ClPGOColdFuncAttr,
865 CodeGenOpts.DebugInfoForProfiling);
866 } else if (!CodeGenOpts.SampleProfileFile.empty())
867 // -fprofile-sample-use
868 PGOOpt = PGOOptions(
869 CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile,
870 CodeGenOpts.MemoryProfileUsePath, PGOOptions::SampleUse,
871 PGOOptions::NoCSAction, ClPGOColdFuncAttr,
872 CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling);
873 else if (!CodeGenOpts.MemoryProfileUsePath.empty())
874 // -fmemory-profile-use (without any of the above options)
875 PGOOpt = PGOOptions("", "", "", CodeGenOpts.MemoryProfileUsePath,
876 PGOOptions::NoAction, PGOOptions::NoCSAction,
877 ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling);
878 else if (CodeGenOpts.PseudoProbeForProfiling)
879 // -fpseudo-probe-for-profiling
880 PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", PGOOptions::NoAction,
881 PGOOptions::NoCSAction, ClPGOColdFuncAttr,
882 CodeGenOpts.DebugInfoForProfiling, true);
883 else if (CodeGenOpts.DebugInfoForProfiling)
884 // -fdebug-info-for-profiling
885 PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", PGOOptions::NoAction,
886 PGOOptions::NoCSAction, ClPGOColdFuncAttr, true);
887
888 // Check to see if we want to generate a CS profile.
889 if (CodeGenOpts.hasProfileCSIRInstr()) {
890 assert(!CodeGenOpts.hasProfileCSIRUse() &&
891 "Cannot have both CSProfileUse pass and CSProfileGen pass at "
892 "the same time");
893 if (PGOOpt) {
894 assert(PGOOpt->Action != PGOOptions::IRInstr &&
895 PGOOpt->Action != PGOOptions::SampleUse &&
896 "Cannot run CSProfileGen pass with ProfileGen or SampleUse "
897 " pass");
898 PGOOpt->CSProfileGenFile = getProfileGenName(CodeGenOpts);
899 PGOOpt->CSAction = PGOOptions::CSIRInstr;
900 } else
901 PGOOpt = PGOOptions("", getProfileGenName(CodeGenOpts), "",
902 /*MemoryProfile=*/"", PGOOptions::NoAction,
903 PGOOptions::CSIRInstr, ClPGOColdFuncAttr,
904 CodeGenOpts.DebugInfoForProfiling);
905 }
906 if (TM)
907 TM->setPGOOption(PGOOpt);
908
909 PipelineTuningOptions PTO;
910 PTO.LoopUnrolling = CodeGenOpts.UnrollLoops;
911 PTO.LoopInterchange = CodeGenOpts.InterchangeLoops;
912 PTO.LoopFusion = CodeGenOpts.FuseLoops;
913 // For historical reasons, loop interleaving is set to mirror setting for loop
914 // unrolling.
915 PTO.LoopInterleaving = CodeGenOpts.UnrollLoops;
916 PTO.LoopVectorization = CodeGenOpts.VectorizeLoop;
917 PTO.SLPVectorization = CodeGenOpts.VectorizeSLP;
918 PTO.MergeFunctions = CodeGenOpts.MergeFunctions;
919 // Only enable CGProfilePass when using integrated assembler, since
920 // non-integrated assemblers don't recognize .cgprofile section.
921 PTO.CallGraphProfile = !CodeGenOpts.DisableIntegratedAS;
922 PTO.UnifiedLTO = CodeGenOpts.UnifiedLTO;
923 PTO.DevirtualizeSpeculatively = CodeGenOpts.DevirtualizeSpeculatively;
924
925 LoopAnalysisManager LAM;
926 FunctionAnalysisManager FAM;
927 CGSCCAnalysisManager CGAM;
928 ModuleAnalysisManager MAM;
929
930 bool DebugPassStructure = CodeGenOpts.DebugPass == "Structure";
931 PassInstrumentationCallbacks PIC;
932 PrintPassOptions PrintPassOpts;
933 PrintPassOpts.Indent = DebugPassStructure;
934 PrintPassOpts.SkipAnalyses = DebugPassStructure;
935 StandardInstrumentations SI(
936 TheModule->getContext(),
937 (CodeGenOpts.DebugPassManager || DebugPassStructure),
938 CodeGenOpts.VerifyEach, PrintPassOpts);
939 SI.registerCallbacks(PIC, &MAM);
940 PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC, CI.getVirtualFileSystemPtr());
941
942 // Handle the assignment tracking feature options.
943 switch (CodeGenOpts.getAssignmentTrackingMode()) {
944 case CodeGenOptions::AssignmentTrackingOpts::Forced:
945 PB.registerPipelineStartEPCallback(
946 [&](ModulePassManager &MPM, OptimizationLevel Level) {
947 MPM.addPass(AssignmentTrackingPass());
948 });
949 break;
950 case CodeGenOptions::AssignmentTrackingOpts::Enabled:
951 // Disable assignment tracking in LTO builds for now as the performance
952 // cost is too high. Disable for LLDB tuning due to llvm.org/PR43126.
953 if (!CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.PrepareForLTO &&
954 CodeGenOpts.getDebuggerTuning() != llvm::DebuggerKind::LLDB) {
955 PB.registerPipelineStartEPCallback(
956 [&](ModulePassManager &MPM, OptimizationLevel Level) {
957 // Only use assignment tracking if optimisations are enabled.
958 if (Level != OptimizationLevel::O0)
959 MPM.addPass(AssignmentTrackingPass());
960 });
961 }
962 break;
963 case CodeGenOptions::AssignmentTrackingOpts::Disabled:
964 break;
965 }
966
967 // Enable verify-debuginfo-preserve-each for new PM.
968 DebugifyEachInstrumentation Debugify;
969 DebugInfoPerPass DebugInfoBeforePass;
970 if (CodeGenOpts.EnableDIPreservationVerify) {
971 Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
972 Debugify.setDebugInfoBeforePass(DebugInfoBeforePass);
973
974 if (!CodeGenOpts.DIBugsReportFilePath.empty())
975 Debugify.setOrigDIVerifyBugsReportFilePath(
976 CodeGenOpts.DIBugsReportFilePath);
977 Debugify.registerCallbacks(PIC, MAM);
978
979#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
980 // If we're using debug location coverage tracking, mark all the
981 // instructions coming out of the frontend without a DebugLoc as being
982 // compiler-generated, to prevent both those instructions and new
983 // instructions that inherit their location from being treated as
984 // incorrectly empty locations.
985 for (Function &F : *TheModule) {
986 if (!F.getSubprogram())
987 continue;
988 for (BasicBlock &BB : F)
989 for (Instruction &I : BB)
990 if (!I.getDebugLoc())
991 I.setDebugLoc(DebugLoc::getCompilerGenerated());
992 }
993#endif
994 }
995 // Register plugin callbacks with PB.
996 for (const std::unique_ptr<PassPlugin> &Plugin : CI.getPassPlugins())
997 Plugin->registerPassBuilderCallbacks(PB);
998 for (const auto &PassCallback : CodeGenOpts.PassBuilderCallbacks)
999 PassCallback(PB);
1000#define HANDLE_EXTENSION(Ext) \
1001 get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
1002#include "llvm/Support/Extension.def"
1003
1004 // Register the target library analysis directly and give it a customized
1005 // preset TLI.
1006 std::unique_ptr<TargetLibraryInfoImpl> TLII(
1007 llvm::driver::createTLII(TargetTriple, CodeGenOpts.getVecLib()));
1008 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
1009
1010 // Register all the basic analyses with the managers.
1011 PB.registerModuleAnalyses(MAM);
1012 PB.registerCGSCCAnalyses(CGAM);
1013 PB.registerFunctionAnalyses(FAM);
1014 PB.registerLoopAnalyses(LAM);
1015 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
1016
1017 ModulePassManager MPM;
1018 // Add a verifier pass, before any other passes, to catch CodeGen issues.
1019 if (CodeGenOpts.VerifyModule)
1020 MPM.addPass(VerifierPass());
1021
1022 if (!CodeGenOpts.DisableLLVMPasses) {
1023 // Map our optimization levels into one of the distinct levels used to
1024 // configure the pipeline.
1025 OptimizationLevel Level = mapToLevel(CodeGenOpts);
1026
1027 const bool PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO;
1028 const bool PrepareForLTO = CodeGenOpts.PrepareForLTO;
1029
1030 if (LangOpts.ObjCAutoRefCount) {
1031 PB.registerPipelineStartEPCallback(
1032 [](ModulePassManager &MPM, OptimizationLevel Level) {
1033 if (Level != OptimizationLevel::O0)
1034 MPM.addPass(
1035 createModuleToFunctionPassAdaptor(ObjCARCExpandPass()));
1036 });
1037 PB.registerScalarOptimizerLateEPCallback(
1038 [](FunctionPassManager &FPM, OptimizationLevel Level) {
1039 if (Level != OptimizationLevel::O0)
1040 FPM.addPass(ObjCARCOptPass());
1041 });
1042 }
1043
1044 // If we reached here with a non-empty index file name, then the index
1045 // file was empty and we are not performing ThinLTO backend compilation
1046 // (used in testing in a distributed build environment).
1047 bool IsThinLTOPostLink = !CodeGenOpts.ThinLTOIndexFile.empty();
1048 // If so drop any the type test assume sequences inserted for whole program
1049 // vtables so that codegen doesn't complain.
1050 if (IsThinLTOPostLink)
1051 PB.registerPipelineStartEPCallback(
1052 [](ModulePassManager &MPM, OptimizationLevel Level) {
1053 MPM.addPass(DropTypeTestsPass());
1054 });
1055
1056 // Register callbacks to schedule sanitizer passes at the appropriate part
1057 // of the pipeline.
1058 if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
1059 PB.registerScalarOptimizerLateEPCallback([this](FunctionPassManager &FPM,
1060 OptimizationLevel Level) {
1061 BoundsCheckingPass::Options Options;
1062 if (CodeGenOpts.SanitizeSkipHotCutoffs[SanitizerKind::SO_LocalBounds] ||
1064 static_assert(SanitizerKind::SO_LocalBounds <=
1065 std::numeric_limits<
1066 decltype(Options.GuardKind)::value_type>::max(),
1067 "Update type of llvm.allow.ubsan.check to represent "
1068 "SanitizerKind::SO_LocalBounds.");
1069 Options.GuardKind = SanitizerKind::SO_LocalBounds;
1070 }
1071 Options.Merge =
1072 CodeGenOpts.SanitizeMergeHandlers.has(SanitizerKind::LocalBounds);
1073 if (!CodeGenOpts.SanitizeTrap.has(SanitizerKind::LocalBounds)) {
1074 Options.Rt = {
1075 /*MinRuntime=*/static_cast<bool>(
1076 CodeGenOpts.SanitizeMinimalRuntime),
1077 /*MayReturn=*/
1078 CodeGenOpts.SanitizeRecover.has(SanitizerKind::LocalBounds),
1079 /*HandlerPreserveAllRegs=*/
1080 static_cast<bool>(CodeGenOpts.SanitizeHandlerPreserveAllRegs),
1081 };
1082 }
1083 FPM.addPass(BoundsCheckingPass(Options));
1084 });
1085
1086 if (!IsThinLTOPostLink) {
1087 // Most sanitizers only run during PreLink stage.
1088 addSanitizers(TargetTriple, CodeGenOpts, LangOpts, PB);
1089 addKCFIPass(TargetTriple, LangOpts, PB);
1090 addLowerAllowCheckPass(CodeGenOpts, LangOpts, PB);
1091
1092 PB.registerPipelineStartEPCallback(
1093 [&](ModulePassManager &MPM, OptimizationLevel Level) {
1094 if (Level == OptimizationLevel::O0 &&
1095 LangOpts.Sanitize.has(SanitizerKind::AllocToken)) {
1096 // With the default O0 pipeline, LibFunc attrs are not inferred,
1097 // so we insert it here because we need it for accurate memory
1098 // allocation function detection with -fsanitize=alloc-token.
1099 // Note: This could also be added to the default O0 pipeline, but
1100 // has a non-trivial effect on generated IR size (attributes).
1101 MPM.addPass(InferFunctionAttrsPass());
1102 }
1103 });
1104 }
1105
1106 if (std::optional<GCOVOptions> Options =
1107 getGCOVOptions(CodeGenOpts, LangOpts))
1108 PB.registerPipelineStartEPCallback(
1109 [this, Options](ModulePassManager &MPM, OptimizationLevel Level) {
1110 MPM.addPass(
1111 GCOVProfilerPass(*Options, CI.getVirtualFileSystemPtr()));
1112 });
1113 if (std::optional<InstrProfOptions> Options =
1114 getInstrProfOptions(CodeGenOpts, LangOpts))
1115 PB.registerPipelineStartEPCallback(
1116 [Options](ModulePassManager &MPM, OptimizationLevel Level) {
1117 MPM.addPass(InstrProfilingLoweringPass(*Options, false));
1118 });
1119
1120 // TODO: Consider passing the MemoryProfileOutput to the pass builder via
1121 // the PGOOptions, and set this up there.
1122 if (!CodeGenOpts.MemoryProfileOutput.empty()) {
1123 PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM,
1124 OptimizationLevel Level,
1125 ThinOrFullLTOPhase) {
1126 MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
1127 MPM.addPass(ModuleMemProfilerPass());
1128 });
1129 }
1130
1131 if (CodeGenOpts.FatLTO) {
1132 MPM.addPass(PB.buildFatLTODefaultPipeline(
1133 Level, PrepareForThinLTO,
1134 PrepareForThinLTO || shouldEmitRegularLTOSummary(),
1135 CodeGenOpts.VerifyModule));
1136 } else if (PrepareForThinLTO) {
1137 MPM.addPass(PB.buildThinLTOPreLinkDefaultPipeline(Level));
1138 } else if (PrepareForLTO) {
1139 MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(Level));
1140 } else {
1141 MPM.addPass(PB.buildPerModuleDefaultPipeline(Level));
1142 }
1143 }
1144
1145 // Link against bitcodes supplied via the -mlink-builtin-bitcode option
1146 if (CodeGenOpts.LinkBitcodePostopt) {
1147 MPM.addPass(LinkInModulesPass(BC));
1148 MPM.addPass(AssignGUIDPass());
1149 }
1150
1151 if (LangOpts.HIPStdPar && !LangOpts.CUDAIsDevice &&
1152 LangOpts.HIPStdParInterposeAlloc)
1153 MPM.addPass(HipStdParAllocationInterpositionPass());
1154
1155 // Add a verifier pass if requested. We don't have to do this if the action
1156 // requires code generation because there will already be a verifier pass in
1157 // the code-generation pipeline.
1158 // Since we already added a verifier pass above, this
1159 // might even not run the analysis, if previous passes caused no changes.
1160 if (!actionRequiresCodeGen(Action) && CodeGenOpts.VerifyModule)
1161 MPM.addPass(VerifierPass());
1162
1163 if (Action == Backend_EmitBC || Action == Backend_EmitLL ||
1164 CodeGenOpts.FatLTO) {
1165 if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) {
1166 if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
1167 TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
1168 CodeGenOpts.EnableSplitLTOUnit);
1169 if (Action == Backend_EmitBC) {
1170 if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
1171 ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
1172 if (!ThinLinkOS)
1173 return;
1174 }
1175 MPM.addPass(ThinLTOBitcodeWriterPass(
1176 *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
1177 } else if (Action == Backend_EmitLL) {
1178 MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
1179 /*EmitLTOSummary=*/true));
1180 }
1181 } else {
1182 // Emit a module summary by default for Regular LTO except for ld64
1183 // targets
1184 bool EmitLTOSummary = shouldEmitRegularLTOSummary();
1185 if (EmitLTOSummary) {
1186 if (!TheModule->getModuleFlag("ThinLTO") && !CodeGenOpts.UnifiedLTO)
1187 TheModule->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(0));
1188 if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
1189 TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
1190 uint32_t(1));
1191 }
1192 if (Action == Backend_EmitBC) {
1193 MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
1194 EmitLTOSummary));
1195 } else if (Action == Backend_EmitLL) {
1196 MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
1197 EmitLTOSummary));
1198 }
1199 }
1200
1201 if (shouldEmitUnifiedLTOModueFlag() &&
1202 !TheModule->getModuleFlag("UnifiedLTO"))
1203 TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));
1204 }
1205
1206 // FIXME: This should eventually be replaced by a first-class driver option.
1207 // This should be done for both clang and flang simultaneously.
1208 // Print a textual, '-passes=' compatible, representation of pipeline if
1209 // requested.
1210 if (PrintPipelinePasses) {
1211 MPM.printPipeline(outs(), [&PIC](StringRef ClassName) {
1212 auto PassName = PIC.getPassNameForClassName(ClassName);
1213 return PassName.empty() ? ClassName : PassName;
1214 });
1215 outs() << "\n";
1216 return;
1217 }
1218
1219 // Now that we have all of the passes ready, run them.
1220 {
1221 PrettyStackTraceString CrashInfo("Optimizer");
1222 llvm::TimeTraceScope TimeScope("Optimizer");
1223 Timer timer;
1224 if (CI.getCodeGenOpts().TimePasses) {
1225 timer.init("optimizer", "Optimizer", CI.getTimerGroup());
1226 CI.getFrontendTimer().yieldTo(timer);
1227 }
1228 MPM.run(*TheModule, MAM);
1229 if (CI.getCodeGenOpts().TimePasses)
1230 timer.yieldTo(CI.getFrontendTimer());
1231 }
1232}
1233
1234void EmitAssemblyHelper::RunCodegenPipeline(
1235 BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,
1236 std::unique_ptr<llvm::ToolOutputFile> &DwoOS) {
1237 if (!actionRequiresCodeGen(Action))
1238 return;
1239
1240 // Normal mode, emit a .s or .o file by running the code generator. Note,
1241 // this also adds codegenerator level optimization passes.
1242 CodeGenFileType CGFT = getCodeGenFileType(Action);
1243
1244 // Invoke pre-codegen callback from plugin, which might want to take over the
1245 // entire code generation itself.
1246 for (const std::unique_ptr<llvm::PassPlugin> &Plugin : CI.getPassPlugins()) {
1247 if (Plugin->invokePreCodeGenCallback(*TheModule, *TM, CGFT, *OS))
1248 return;
1249 }
1250
1251 if (!CodeGenOpts.SplitDwarfOutput.empty()) {
1252 DwoOS = openOutputFile(CodeGenOpts.SplitDwarfOutput);
1253 if (!DwoOS)
1254 return;
1255 }
1256
1257 if (CodeGenOpts.getEnableNewPMCodeGen() ==
1258 CodeGenOptions::NewPMEnablementLevel::ForceEnable ||
1259 (CodeGenOpts.getEnableNewPMCodeGen() ==
1260 CodeGenOptions::NewPMEnablementLevel::Auto &&
1261 TM->shouldDefaultToNewPM())) {
1262 RunCodegenPipelineNewPM(Action, OS, DwoOS, CGFT);
1263 } else {
1264 RunCodegenPipelineLegacy(Action, OS, DwoOS, CGFT);
1265 }
1266}
1267
1268void EmitAssemblyHelper::RunCodegenPipelineLegacy(
1269 BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,
1270 std::unique_ptr<llvm::ToolOutputFile> &DwoOS, CodeGenFileType CGFT) {
1271 // We still use the legacy PM to run the codegen pipeline since the new PM
1272 // does not work with the codegen pipeline.
1273 // FIXME: make the new PM work with the codegen pipeline.
1274 legacy::PassManager CodeGenPasses;
1275
1276 CodeGenPasses.add(
1277 createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
1278 // Add LibraryInfo.
1279 std::unique_ptr<TargetLibraryInfoImpl> TLII(
1280 llvm::driver::createTLII(TargetTriple, CodeGenOpts.getVecLib()));
1281 CodeGenPasses.add(new TargetLibraryInfoWrapperPass(*TLII));
1282
1283 const llvm::TargetOptions &Options = TM->Options;
1284 CodeGenPasses.add(new RuntimeLibraryInfoWrapper(
1285 TargetTriple, Options.ExceptionModel, Options.FloatABIType,
1286 Options.EABIVersion, Options.MCOptions.ABIName, Options.VecLib));
1287
1288 if (TM->addPassesToEmitFile(CodeGenPasses, *OS,
1289 DwoOS ? &DwoOS->os() : nullptr, CGFT,
1290 /*DisableVerify=*/!CodeGenOpts.VerifyModule)) {
1291 Diags.Report(diag::err_fe_unable_to_interface_with_target);
1292 return;
1293 }
1294
1295 // If -print-pipeline-passes is requested, don't run the legacy pass manager.
1296 // FIXME: when codegen is switched to use the new pass manager, it should also
1297 // emit pass names here.
1298 if (PrintPipelinePasses) {
1299 return;
1300 }
1301
1302 TimeCodegenPasses([&] { CodeGenPasses.run(*TheModule); });
1303}
1304
1305void EmitAssemblyHelper::RunCodegenPipelineNewPM(
1306 BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,
1307 std::unique_ptr<llvm::ToolOutputFile> &DwoOS, CodeGenFileType CGFT) {
1308 ModulePassManager MPM;
1309 MachineFunctionAnalysisManager MFAM;
1310 LoopAnalysisManager LAM;
1311 FunctionAnalysisManager FAM;
1312 CGSCCAnalysisManager CGAM;
1313 ModuleAnalysisManager MAM;
1314 CGPassBuilderOption Opt = getCGPassBuilderOption();
1315 Opt.DisableVerify = !CodeGenOpts.VerifyModule;
1316 MachineModuleInfo MMI(TM.get());
1317 PassInstrumentationCallbacks PIC;
1318 PipelineTuningOptions PTOptions;
1319 TargetMachine *TMPointer = TM.get();
1320 PassBuilder PB(TMPointer, PTOptions, std::nullopt, &PIC,
1322 PB.registerModuleAnalyses(MAM);
1323 PB.registerCGSCCAnalyses(CGAM);
1324 PB.registerFunctionAnalyses(FAM);
1325 PB.registerLoopAnalyses(LAM);
1326 PB.registerMachineFunctionAnalyses(MFAM);
1327 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM);
1328
1329 MAM.registerPass([&] { return MachineModuleAnalysis(MMI); });
1330
1331 Error BuildPipelineError =
1332 TM->buildCodeGenPipeline(MPM, MAM, *OS, DwoOS ? &DwoOS->os() : nullptr,
1333 CGFT, Opt, MMI.getContext(), &PIC);
1334 if (BuildPipelineError) {
1335 Diags.Report(diag::err_fe_unable_to_interface_with_target);
1336 return;
1337 }
1338
1339 TimeCodegenPasses([&] { MPM.run(*TheModule, MAM); });
1340}
1341
1342void EmitAssemblyHelper::TimeCodegenPasses(
1343 llvm::function_ref<void()> RunPasses) {
1344 PrettyStackTraceString CrashInfo("Code generation");
1345 llvm::TimeTraceScope TimeScope("CodeGenPasses");
1346 Timer timer;
1347 if (CI.getCodeGenOpts().TimePasses) {
1348 timer.init("codegen", "Machine code generation", CI.getTimerGroup());
1349 CI.getFrontendTimer().yieldTo(timer);
1350 }
1351 RunPasses();
1352 if (CI.getCodeGenOpts().TimePasses)
1353 timer.yieldTo(CI.getFrontendTimer());
1354}
1355
1356void EmitAssemblyHelper::emitAssembly(BackendAction Action,
1357 std::unique_ptr<raw_pwrite_stream> OS,
1358 BackendConsumer *BC) {
1359 setCommandLineOpts(CodeGenOpts, CI.getVirtualFileSystem());
1360
1361 bool RequiresCodeGen = actionRequiresCodeGen(Action);
1362 CreateTargetMachine(RequiresCodeGen);
1363
1364 if (RequiresCodeGen && !TM)
1365 return;
1366 if (TM)
1367 TheModule->setDataLayout(TM->createDataLayout());
1368
1369 // Before executing passes, print the final values of the LLVM options.
1370 cl::PrintOptionValues();
1371
1372 std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS;
1373 RunOptimizationPipeline(Action, OS, ThinLinkOS, BC);
1374 RunCodegenPipeline(Action, OS, DwoOS);
1375
1376 if (ThinLinkOS)
1377 ThinLinkOS->keep();
1378 if (DwoOS)
1379 DwoOS->keep();
1380}
1381
1382static void
1383runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex,
1384 llvm::Module *M, std::unique_ptr<raw_pwrite_stream> OS,
1385 std::string SampleProfile, std::string ProfileRemapping,
1386 BackendAction Action) {
1387 DiagnosticsEngine &Diags = CI.getDiagnostics();
1388 const auto &CGOpts = CI.getCodeGenOpts();
1389 const auto &TOpts = CI.getTargetOpts();
1390 DenseMap<StringRef, DenseMap<GlobalValue::GUID, GlobalValueSummary *>>
1391 ModuleToDefinedGVSummaries;
1392 CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
1393
1395
1396 // We can simply import the values mentioned in the combined index, since
1397 // we should only invoke this using the individual indexes written out
1398 // via a WriteIndexesThinBackend.
1399 FunctionImporter::ImportIDTable ImportIDs;
1400 FunctionImporter::ImportMapTy ImportList(ImportIDs);
1401 if (!lto::initImportList(*M, *CombinedIndex, ImportList))
1402 return;
1403
1404 auto AddStream = [&](size_t Task, const Twine &ModuleName) {
1405 return std::make_unique<CachedFileStream>(std::move(OS),
1406 CGOpts.ObjectFilenameForDebug);
1407 };
1408 lto::Config Conf;
1409 if (CGOpts.SaveTempsFilePrefix != "") {
1410 if (Error E = Conf.addSaveTemps(CGOpts.SaveTempsFilePrefix + ".",
1411 /* UseInputModulePath */ false)) {
1412 handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
1413 errs() << "Error setting up ThinLTO save-temps: " << EIB.message()
1414 << '\n';
1415 });
1416 }
1417 }
1418 Conf.CPU = TOpts.CPU;
1419 Conf.CodeModel = getCodeModel(CGOpts);
1420 Conf.MAttrs = TOpts.Features;
1421 Conf.RelocModel = CGOpts.RelocationModel;
1422 std::optional<CodeGenOptLevel> OptLevelOrNone =
1423 CodeGenOpt::getLevel(CGOpts.OptimizationLevel);
1424 assert(OptLevelOrNone && "Invalid optimization level!");
1425 Conf.CGOptLevel = *OptLevelOrNone;
1426 Conf.OptLevel = CGOpts.OptimizationLevel;
1427 initTargetOptions(CI, Diags, Conf.Options);
1428 Conf.SampleProfile = std::move(SampleProfile);
1429 Conf.PTO.LoopUnrolling = CGOpts.UnrollLoops;
1430 Conf.PTO.LoopInterchange = CGOpts.InterchangeLoops;
1431 Conf.PTO.LoopFusion = CGOpts.FuseLoops;
1432 // For historical reasons, loop interleaving is set to mirror setting for loop
1433 // unrolling.
1434 Conf.PTO.LoopInterleaving = CGOpts.UnrollLoops;
1435 Conf.PTO.LoopVectorization = CGOpts.VectorizeLoop;
1436 Conf.PTO.SLPVectorization = CGOpts.VectorizeSLP;
1437 // Only enable CGProfilePass when using integrated assembler, since
1438 // non-integrated assemblers don't recognize .cgprofile section.
1439 Conf.PTO.CallGraphProfile = !CGOpts.DisableIntegratedAS;
1440
1441 // Context sensitive profile.
1442 if (CGOpts.hasProfileCSIRInstr()) {
1443 Conf.RunCSIRInstr = true;
1444 Conf.CSIRProfile = getProfileGenName(CGOpts);
1445 } else if (CGOpts.hasProfileCSIRUse()) {
1446 Conf.RunCSIRInstr = false;
1447 Conf.CSIRProfile = std::move(CGOpts.ProfileInstrumentUsePath);
1448 }
1449
1450 Conf.ProfileRemapping = std::move(ProfileRemapping);
1451 Conf.DebugPassManager = CGOpts.DebugPassManager;
1452 Conf.VerifyEach = CGOpts.VerifyEach;
1453 Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness;
1454 Conf.RemarksFilename = CGOpts.OptRecordFile;
1455 Conf.RemarksPasses = CGOpts.OptRecordPasses;
1456 Conf.RemarksFormat = CGOpts.OptRecordFormat;
1457 Conf.SplitDwarfFile = CGOpts.SplitDwarfFile;
1458 Conf.SplitDwarfOutput = CGOpts.SplitDwarfOutput;
1459 for (auto &Plugin : CI.getPassPlugins())
1460 Conf.LoadedPassPlugins.push_back(Plugin.get());
1461 switch (Action) {
1463 Conf.PreCodeGenModuleHook = [](size_t Task, const llvm::Module &Mod) {
1464 return false;
1465 };
1466 break;
1467 case Backend_EmitLL:
1468 Conf.PreCodeGenModuleHook = [&](size_t Task, const llvm::Module &Mod) {
1469 M->print(*OS, nullptr, CGOpts.EmitLLVMUseLists);
1470 return false;
1471 };
1472 break;
1473 case Backend_EmitBC:
1474 Conf.PreCodeGenModuleHook = [&](size_t Task, const llvm::Module &Mod) {
1475 WriteBitcodeToFile(*M, *OS, CGOpts.EmitLLVMUseLists);
1476 return false;
1477 };
1478 break;
1479 default:
1480 Conf.CGFileType = getCodeGenFileType(Action);
1481 break;
1482 }
1483
1484 // FIXME: Both ExecuteAction and thinBackend set up optimization remarks for
1485 // the same context.
1486 // FIXME: This does not yet set the list of bitcode libfuncs that it isn't
1487 // safe to call. This precludes bitcode libc in distributed ThinLTO.
1488 finalizeLLVMOptimizationRemarks(M->getContext());
1489 if (Error E = thinBackend(
1490 Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
1491 ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
1492 /*ModuleMap=*/nullptr, Conf.CodeGenOnly, /*BitcodeLibFuncs=*/{},
1493 /*IRAddStream=*/nullptr, CGOpts.CmdArgs)) {
1494 handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
1495 errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';
1496 });
1497 }
1498}
1499
1501 CompilerInstance &CI, CodeGenOptions &CGOpts, llvm::Module *M,
1503 /// Helper for saving the module(s) at various dyndbg stages.
1504 auto SaveModule = [&](StringRef Name, llvm::Module &M) {
1505 if (CGOpts.SaveDynDbgTempsFilePrefix == "")
1506 return;
1507 std::error_code EC;
1508 std::string Path =
1509 Twine(CGOpts.SaveDynDbgTempsFilePrefix + "." + Name + ".ll").str();
1510 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None);
1511 if (EC) {
1512 // Copy -save-temps behaviour: this is a debugging option so we simply
1513 // exit if there's an issue.
1514 errs() << "failed to open " << Path << ": " << EC.message() << '\n';
1515 errs().flush();
1516 exit(1);
1517 }
1518 M.print(OS, nullptr);
1519 };
1520
1521 // Compute a hash suffix for promoting static globals (once per TU).
1522 std::string PromotionSuffix;
1523 {
1524 // LLVM's hash/hash_combine is not guaranteed to be stable.
1525 MD5 Hash;
1526 // Include args in the hash else preprocessor definitions used to alter
1527 // the same source file compiled twice won't generate unique hashes.
1528 Hash.update(CGOpts.CmdArgs);
1529 for (auto *CU : M->debug_compile_units()) {
1530 if (CU->getDirectory().size() > 0)
1531 Hash.update(CU->getDirectory());
1532
1533 Hash.update(CU->getFilename());
1534 }
1535
1536 MD5::MD5Result Result;
1537 Hash.final(Result);
1538 PromotionSuffix = ".dyndbg." + utohexstr(Result.low());
1539 }
1540
1541 SaveModule("dyndbg.0.input", *M);
1542 // Modify M as needed and create an "unoptimized" clone.
1543 auto UnoptM = prepareForDynamicDebugging(M, PromotionSuffix);
1544 SaveModule("dyndbg.1.inner", *UnoptM);
1545
1546 if (!CGOpts.DiscardDynamicDebuggingDebugModule) {
1547 CodeGenOptions UnoptOpts = CGOpts;
1548 UnoptOpts.OptimizationLevel = 0;
1549 UnoptOpts.OptimizeSize = 0;
1550 EmitAssemblyHelper AsmHelper(CI, UnoptOpts, UnoptM.get(), VFS);
1551
1552 // Create a buffer and ostream for the inner ELF.
1553 SmallVector<char, 0> UnoptBuf;
1554 std::unique_ptr<llvm::raw_pwrite_stream> UnoptOS =
1555 std::make_unique<llvm::raw_svector_ostream>(UnoptBuf);
1556
1557 // Always run the full codegen pipeline (Backend_EmitObj). This causes
1558 // assertion failures if there's no registered backend which is why we
1559 // disable the feature if that's the case (see
1560 // warn_dyndbg_unable_to_create_target above).
1561 AsmHelper.emitAssembly(Backend_EmitObj, std::move(UnoptOS), BC);
1562 assert(!UnoptBuf.empty() && "Expected emitAssembly to fill UnoptBuf");
1563
1564 // Inject the inner ELF into the outer module.
1565 StringRef SR(UnoptBuf.data(), UnoptBuf.size());
1566 std::unique_ptr<MemoryBuffer> Buf =
1567 MemoryBuffer::getMemBuffer(SR, "", false);
1568
1569 GlobalVariable *EmbeddedGV =
1570 llvm::embedBufferInModule(*M, *Buf, ".debug_llvm_dyndbg", Align(8),
1571 /*SectionExclude*/ false);
1572 // Add ELF section properties metadata.
1573 auto &C = M->getContext();
1574 auto getU32Metadata = [&C](unsigned Val) {
1575 return ConstantAsMetadata::get(ConstantInt::get(C, APInt(32, Val)));
1576 };
1577 EmbeddedGV->addMetadata(
1578 LLVMContext::MD_elf_section_properties,
1579 *MDTuple::get(C, {/*sh_type*/ getU32Metadata(ELF::SHT_LLVM_DYNDBG_ELF),
1580 /*sh_entsize*/ getU32Metadata(0)}));
1581 }
1582 SaveModule("dyndbg.2.outer", *M);
1583}
1584
1586 StringRef TDesc, llvm::Module *M,
1587 BackendAction Action,
1589 std::unique_ptr<raw_pwrite_stream> OS,
1590 BackendConsumer *BC) {
1591 llvm::TimeTraceScope TimeScope("Backend");
1592 DiagnosticsEngine &Diags = CI.getDiagnostics();
1593
1594 std::unique_ptr<llvm::Module> EmptyModule;
1595 if (!CGOpts.ThinLTOIndexFile.empty()) {
1596 // FIXME(sandboxing): Figure out how to support distributed indexing.
1597 auto BypassSandbox = sys::sandbox::scopedDisable();
1598 // If we are performing a ThinLTO importing compile, load the function index
1599 // into memory and pass it into runThinLTOBackend, which will run the
1600 // function importer and invoke LTO passes.
1601 std::unique_ptr<ModuleSummaryIndex> CombinedIndex;
1602 if (Error E = llvm::getModuleSummaryIndexForFile(
1603 CGOpts.ThinLTOIndexFile,
1604 /*IgnoreEmptyThinLTOIndexFile*/ true)
1605 .moveInto(CombinedIndex)) {
1606 logAllUnhandledErrors(std::move(E), errs(),
1607 "Error loading index file '" +
1608 CGOpts.ThinLTOIndexFile + "': ");
1609 return;
1610 }
1611
1612 // A null CombinedIndex means we should skip ThinLTO compilation
1613 // (LLVM will optionally ignore empty index files, returning null instead
1614 // of an error).
1615 if (CombinedIndex) {
1616 if (!CombinedIndex->skipModuleByDistributedBackend()) {
1617 runThinLTOBackend(CI, CombinedIndex.get(), M, std::move(OS),
1619 Action);
1620 return;
1621 }
1622 // Distributed indexing detected that nothing from the module is needed
1623 // for the final linking. So we can skip the compilation. We sill need to
1624 // output an empty object file to make sure that a linker does not fail
1625 // trying to read it. Also for some features, like CFI, we must skip
1626 // the compilation as CombinedIndex does not contain all required
1627 // information.
1628 EmptyModule = std::make_unique<llvm::Module>("empty", M->getContext());
1629 EmptyModule->setTargetTriple(M->getTargetTriple());
1630 M = EmptyModule.get();
1631 }
1632 }
1633
1634 bool EnableDynamicDebugging = CGOpts.DynamicDebugging;
1635 if (EnableDynamicDebugging) {
1636 // Disable dyndbg if the target isn't available as we're compiling to the
1637 // inner module (unless we're discarding it for debugging/testing).
1638 std::string Error;
1639 const llvm::Target *TheTarget =
1640 TargetRegistry::lookupTarget(M->getTargetTriple(), Error);
1641 if (!TheTarget && !CGOpts.DiscardDynamicDebuggingDebugModule) {
1642 Diags.Report(diag::warn_dyndbg_unable_to_create_target) << Error;
1643 EnableDynamicDebugging = false;
1644 }
1645
1646 // Instrumentation causes issues (parts of LLVM expect certain globals to
1647 // have initializers). Intrinsics may already have been added to IR by now,
1648 // so we can't just turn it off for the inner module (we'd have to strip
1649 // them out / not clone them). TODO: Support instrumentation.
1650 if (CGOpts.getProfileInstr() != driver::ProfileInstrKind::ProfileNone) {
1651 Diags.Report(diag::err_dyndbg_no_instrumentation);
1652 EnableDynamicDebugging = false;
1653 }
1654 }
1655 if (EnableDynamicDebugging)
1656 createAndEmbedModuleForDynamicDebugging(CI, CGOpts, M, VFS, BC);
1657
1658 EmitAssemblyHelper AsmHelper(CI, CGOpts, M, VFS);
1659 AsmHelper.emitAssembly(Action, std::move(OS), BC);
1660
1661 // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's
1662 // DataLayout.
1663 if (AsmHelper.TM) {
1664 std::string DLDesc = M->getDataLayout().getStringRepresentation();
1665 if (DLDesc != TDesc) {
1666 Diags.Report(diag::err_data_layout_mismatch) << DLDesc << TDesc;
1667 }
1668 }
1669}
1670
1671// With -fembed-bitcode, save a copy of the llvm IR as data in the
1672// __LLVM,__bitcode section.
1673void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
1674 llvm::MemoryBufferRef Buf) {
1675 if (CGOpts.getEmbedBitcode() == CodeGenOptions::Embed_Off)
1676 return;
1677 llvm::embedBitcodeInModule(
1678 *M, Buf, CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Marker,
1679 CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Bitcode,
1680 CGOpts.CmdArgs);
1681}
1682
1683void clang::EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts,
1684 llvm::vfs::FileSystem &VFS, DiagnosticsEngine &Diags) {
1685 if (CGOpts.OffloadObjects.empty())
1686 return;
1687
1688 for (StringRef OffloadObject : CGOpts.OffloadObjects) {
1689 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ObjectOrErr =
1690 VFS.getBufferForFile(OffloadObject);
1691 if (ObjectOrErr.getError()) {
1692 Diags.Report(diag::err_failed_to_open_for_embedding) << OffloadObject;
1693 return;
1694 }
1695
1696 llvm::embedBufferInModule(*M, **ObjectOrErr, ".llvm.offloading",
1697 Align(object::OffloadBinary::getAlignment()));
1698 }
1699}
static bool actionRequiresCodeGen(BackendAction Action)
static void addSanitizers(const Triple &TargetTriple, const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts, PassBuilder &PB)
static std::optional< llvm::CodeModel::Model > getCodeModel(const CodeGenOptions &CodeGenOpts)
static void runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex, llvm::Module *M, std::unique_ptr< raw_pwrite_stream > OS, std::string SampleProfile, std::string ProfileRemapping, BackendAction Action)
static void createAndEmbedModuleForDynamicDebugging(CompilerInstance &CI, CodeGenOptions &CGOpts, llvm::Module *M, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, BackendConsumer *BC)
static SanitizerBinaryMetadataOptions getSanitizerBinaryMetadataOptions(const CodeGenOptions &CGOpts)
static std::optional< GCOVOptions > getGCOVOptions(const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts)
static bool initTargetOptions(const CompilerInstance &CI, DiagnosticsEngine &Diags, llvm::TargetOptions &Options)
static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts, vfs::FileSystem &VFS)
static std::string getProfileGenName(const CodeGenOptions &CodeGenOpts)
static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts, PassBuilder &PB)
static SanitizerCoverageOptions getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts)
static OptimizationLevel mapToLevel(const CodeGenOptions &Opts)
static std::string flattenClangCommandLine(ArrayRef< std::string > Args, StringRef MainFilename, ArrayRef< StringRef > InputFiles)
static std::optional< InstrProfOptions > getInstrProfOptions(const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts)
static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts)
void addLowerAllowCheckPass(const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts, PassBuilder &PB)
static CodeGenFileType getCodeGenFileType(BackendAction Action)
Defines the Diagnostic-related interfaces.
Result
Implement __builtin_bit_cast and related operations.
Defines the clang::LangOptions interface.
This file provides a pass to link in Modules from a provided BackendConsumer.
static bool contains(const std::set< tok::TokenKind > &Terminators, const Token &Tok)
Defines the clang::TargetOptions class.
__DEVICE__ int max(int __a, int __b)
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
SanitizerSet SanitizeMergeHandlers
Set of sanitizer checks that can merge handlers (smaller code size at the expense of debuggability).
std::string StackUsageFile
Name of the stack usage file (i.e., .su file) if user passes -fstack-usage.
std::string InstrProfileOutput
Name of the profile file to use as output for -fprofile-instr-generate, -fprofile-generate,...
bool hasDWARFExceptions() const
bool hasProfileIRUse() const
Check if IR level profile use is on.
char CoverageVersion[4]
The version string to put into coverage files.
std::string FloatABI
The ABI to use for passing floating point arguments.
std::string ThinLinkBitcodeFile
Name of a file that can optionally be written with minimized bitcode to be used as input for the Thin...
bool hasProfileCSIRInstr() const
Check if CS IR level profile instrumentation is on.
std::string DebugPass
Enable additional debugging information.
llvm::Reloc::Model RelocationModel
The name of the relocation model to use.
std::string CoverageNotesFile
The filename with path we use for coverage notes files.
std::string ProfileInstrumentUsePath
Name of the profile file to use as input for -fprofile-instr-use.
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
uint64_t LargeDataThreshold
The code model-specific large data threshold to use (-mlarge-data-threshold).
std::string MemoryProfileOutput
Name of the profile file to use as output for with -fmemory-profile.
std::vector< std::function< void(llvm::PassBuilder &)> > PassBuilderCallbacks
List of pass builder callbacks.
std::string LimitFloatPrecision
The float precision limit to use, if non-empty.
std::string CodeModel
The code model to use (-mcmodel).
std::string CoverageDataFile
The filename with path we use for coverage data files.
bool hasProfileClangInstr() const
Check if Clang profile instrumenation is on.
std::vector< std::string > SanitizeCoverageAllowlistFiles
Path to allowlist file specifying which objects (files, functions) should exclusively be instrumented...
std::vector< std::string > SanitizeCoverageIgnorelistFiles
Path to ignorelist file specifying which objects (files, functions) listed for instrumentation by san...
bool hasSanitizeCoverage() const
std::string MainFileName
The user provided name for the "main file", if non-empty.
bool hasProfileIRInstr() const
Check if IR level profile instrumentation is on.
bool hasProfileCSIRUse() const
Check if CSIR profile use is on.
SanitizerSet SanitizeTrap
Set of sanitizer checks that trap rather than diagnose.
std::vector< std::string > SanitizeMetadataIgnorelistFiles
Path to ignorelist file specifying which objects (files, functions) listed for instrumentation by san...
SanitizerSet SanitizeRecover
Set of sanitizer checks that are non-fatal (i.e.
std::string ProfileExcludeFiles
Regexes separated by a semi-colon to filter the files to not instrument.
std::string AsSecureLogFile
The name of a file to use with .secure_log_unique directives.
std::string ProfileRemappingFile
Name of the profile remapping file to apply to the profile data supplied by -fprofile-sample-use or -...
bool hasSanitizeBinaryMetadata() const
std::string ThinLTOIndexFile
Name of the function summary index file to use for ThinLTO function importing.
const char * Argv0
Executable and command-line used to create a given CompilerInvocation.
bool hasWasmExceptions() const
bool hasSjLjExceptions() const
SanitizerMaskCutoffs SanitizeSkipHotCutoffs
Set of thresholds in a range [0.0, 1.0]: the top hottest code responsible for the given fraction of P...
std::string SplitDwarfFile
The name for the split debug info file used for the DW_AT_[GNU_]dwo_name attribute in the skeleton CU...
std::vector< uint8_t > CmdArgs
List of backend command-line options for -fembed-bitcode.
std::optional< double > AllowRuntimeCheckSkipHotCutoff
std::vector< std::string > CommandLineArgs
bool hasSEHExceptions() const
std::string MemoryProfileUsePath
Name of the profile file to use as input for -fmemory-profile-use.
std::vector< std::string > OffloadObjects
List of filenames passed in using the -fembed-offload-object option.
std::string ProfileFilterFiles
Regexes separated by a semi-colon to filter the files to instrument.
std::string ObjectFilenameForDebug
Output filename used in the COFF debug information.
std::string SplitDwarfOutput
Output filename for the split debug info, not used in the skeleton CU.
std::string DIBugsReportFilePath
The file to use for dumping bug report by Debugify for original debug info.
std::string SaveDynDbgTempsFilePrefix
Prefix to use for -save-dynamic-debugging-temps output.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
llvm::TimerGroup & getTimerGroup() const
llvm::Timer & getFrontendTimer() const
IntrusiveRefCntPtr< llvm::vfs::FileSystem > getVirtualFileSystemPtr() const
TargetOptions & getTargetOpts()
FrontendOptions & getFrontendOpts()
HeaderSearchOptions & getHeaderSearchOpts()
llvm::vfs::FileSystem & getVirtualFileSystem() const
llvm::ArrayRef< std::unique_ptr< llvm::PassPlugin > > getPassPlugins() const
CodeGenOptions & getCodeGenOpts()
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:234
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
@ Single
Single Threaded Environment.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
SanitizerSet Sanitize
Set of enabled sanitizers.
std::vector< std::string > NoSanitizeFiles
Paths to files specifying which objects (files, functions, variables) should not be instrumented.
std::optional< std::vector< unsigned > > getAllScaled(unsigned ScalingFactor) const
std::vector< std::string > Features
The list of target specific features to enable or disable – this should be a list of strings starting...
std::string ABI
If given, the name of the target ABI to use.
std::string CPU
If given, the name of the target CPU to generate code for.
llvm::EABI EABIVersion
The EABI version to use.
@ Angled
Paths for '#include <>' added by '-I'.
@ System
Like Angled, but marks system directories.
@ Quoted
'#include ""' paths, added by 'gcc -iquote'.
Top level wrappers for InstallAPI frontend operations.
@ Default
Set to the current date and time.
const FunctionProtoType * T
llvm::cl::opt< bool > ClSanitizeGuardChecks
void emitBackendOutput(CompilerInstance &CI, CodeGenOptions &CGOpts, StringRef TDesc, llvm::Module *M, BackendAction Action, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::unique_ptr< raw_pwrite_stream > OS, BackendConsumer *BC=nullptr)
void EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::vfs::FileSystem &VFS, DiagnosticsEngine &Diags)
void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::MemoryBufferRef Buf)
BackendAction
Definition BackendUtil.h:33
@ Backend_EmitAssembly
Emit native assembly files.
Definition BackendUtil.h:34
@ Backend_EmitLL
Emit human-readable LLVM assembly.
Definition BackendUtil.h:36
@ Backend_EmitBC
Emit LLVM bitcode files.
Definition BackendUtil.h:35
@ Backend_EmitObj
Emit native object files.
Definition BackendUtil.h:39
@ Backend_EmitMCNull
Run CodeGen, but don't emit anything.
Definition BackendUtil.h:38
@ Backend_EmitNothing
Don't emit anything (benchmarking mode)
Definition BackendUtil.h:37
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
LLVM_ABI cl::opt< InstrProfCorrelator::ProfCorrelatorKind > ProfileCorrelate
static cl::opt< PGOOptions::ColdFuncOpt > ClPGOColdFuncAttr("pgo-cold-func-opt", cl::init(PGOOptions::ColdFuncOpt::Default), cl::Hidden, cl::desc("Function attribute to apply to cold functions as determined by PGO"), cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default", "Default (no attribute)"), clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize", "Mark cold functions with optsize."), clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize", "Mark cold functions with minsize."), clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone", "Mark cold functions with optnone.")))
static cl::opt< bool > ClSanitizeOnOptimizerEarlyEP("sanitizer-early-opt-ep", cl::Optional, cl::desc("Insert sanitizers on OptimizerEarlyEP."))
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.
Definition Sanitizers.h:174
bool hasOneOf(SanitizerMask K) const
Check if one or more sanitizers are enabled.
Definition Sanitizers.h:184