xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/CommandFlags.cpp (revision 315ee00fa9616b0a192b6834911f98bcf5316a6b)
1  //===-- CommandFlags.cpp - Command Line Flags Interface ---------*- C++ -*-===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file contains codegen-specific flags that are shared between different
10  // command line tools. The tools "llc" and "opt" both use this file to prevent
11  // flag duplication.
12  //
13  //===----------------------------------------------------------------------===//
14  
15  #include "llvm/CodeGen/CommandFlags.h"
16  #include "llvm/ADT/StringExtras.h"
17  #include "llvm/ADT/Triple.h"
18  #include "llvm/IR/Instructions.h"
19  #include "llvm/IR/Intrinsics.h"
20  #include "llvm/IR/Module.h"
21  #include "llvm/MC/MCTargetOptionsCommandFlags.h"
22  #include "llvm/MC/SubtargetFeature.h"
23  #include "llvm/Support/CommandLine.h"
24  #include "llvm/Support/Host.h"
25  #include "llvm/Support/MemoryBuffer.h"
26  #include <optional>
27  
28  using namespace llvm;
29  
30  #define CGOPT(TY, NAME)                                                        \
31    static cl::opt<TY> *NAME##View;                                              \
32    TY codegen::get##NAME() {                                                    \
33      assert(NAME##View && "RegisterCodeGenFlags not created.");                 \
34      return *NAME##View;                                                        \
35    }
36  
37  #define CGLIST(TY, NAME)                                                       \
38    static cl::list<TY> *NAME##View;                                             \
39    std::vector<TY> codegen::get##NAME() {                                       \
40      assert(NAME##View && "RegisterCodeGenFlags not created.");                 \
41      return *NAME##View;                                                        \
42    }
43  
44  // Temporary macro for incremental transition to std::optional.
45  #define CGOPT_EXP(TY, NAME)                                                    \
46    CGOPT(TY, NAME)                                                              \
47    std::optional<TY> codegen::getExplicit##NAME() {                             \
48      if (NAME##View->getNumOccurrences()) {                                     \
49        TY res = *NAME##View;                                                    \
50        return res;                                                              \
51      }                                                                          \
52      return std::nullopt;                                                       \
53    }
54  
55  CGOPT(std::string, MArch)
56  CGOPT(std::string, MCPU)
57  CGLIST(std::string, MAttrs)
58  CGOPT_EXP(Reloc::Model, RelocModel)
59  CGOPT(ThreadModel::Model, ThreadModel)
60  CGOPT_EXP(CodeModel::Model, CodeModel)
61  CGOPT(ExceptionHandling, ExceptionModel)
62  CGOPT_EXP(CodeGenFileType, FileType)
63  CGOPT(FramePointerKind, FramePointerUsage)
64  CGOPT(bool, EnableUnsafeFPMath)
65  CGOPT(bool, EnableNoInfsFPMath)
66  CGOPT(bool, EnableNoNaNsFPMath)
67  CGOPT(bool, EnableNoSignedZerosFPMath)
68  CGOPT(bool, EnableApproxFuncFPMath)
69  CGOPT(bool, EnableNoTrappingFPMath)
70  CGOPT(bool, EnableAIXExtendedAltivecABI)
71  CGOPT(DenormalMode::DenormalModeKind, DenormalFPMath)
72  CGOPT(DenormalMode::DenormalModeKind, DenormalFP32Math)
73  CGOPT(bool, EnableHonorSignDependentRoundingFPMath)
74  CGOPT(FloatABI::ABIType, FloatABIForCalls)
75  CGOPT(FPOpFusion::FPOpFusionMode, FuseFPOps)
76  CGOPT(SwiftAsyncFramePointerMode, SwiftAsyncFramePointer)
77  CGOPT(bool, DontPlaceZerosInBSS)
78  CGOPT(bool, EnableGuaranteedTailCallOpt)
79  CGOPT(bool, DisableTailCalls)
80  CGOPT(bool, StackSymbolOrdering)
81  CGOPT(bool, StackRealign)
82  CGOPT(std::string, TrapFuncName)
83  CGOPT(bool, UseCtors)
84  CGOPT(bool, LowerGlobalDtorsViaCxaAtExit)
85  CGOPT(bool, RelaxELFRelocations)
86  CGOPT_EXP(bool, DataSections)
87  CGOPT_EXP(bool, FunctionSections)
88  CGOPT(bool, IgnoreXCOFFVisibility)
89  CGOPT(bool, XCOFFTracebackTable)
90  CGOPT(std::string, BBSections)
91  CGOPT(unsigned, TLSSize)
92  CGOPT(bool, EmulatedTLS)
93  CGOPT(bool, UniqueSectionNames)
94  CGOPT(bool, UniqueBasicBlockSectionNames)
95  CGOPT(EABI, EABIVersion)
96  CGOPT(DebuggerKind, DebuggerTuningOpt)
97  CGOPT(bool, EnableStackSizeSection)
98  CGOPT(bool, EnableAddrsig)
99  CGOPT(bool, EmitCallSiteInfo)
100  CGOPT(bool, EnableMachineFunctionSplitter)
101  CGOPT(bool, EnableDebugEntryValues)
102  CGOPT(bool, ForceDwarfFrameSection)
103  CGOPT(bool, XRayOmitFunctionIndex)
104  CGOPT(bool, DebugStrictDwarf)
105  CGOPT(unsigned, AlignLoops)
106  CGOPT(bool, JMCInstrument)
107  
108  codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
109  #define CGBINDOPT(NAME)                                                        \
110    do {                                                                         \
111      NAME##View = std::addressof(NAME);                                         \
112    } while (0)
113  
114    static cl::opt<std::string> MArch(
115        "march", cl::desc("Architecture to generate code for (see --version)"));
116    CGBINDOPT(MArch);
117  
118    static cl::opt<std::string> MCPU(
119        "mcpu", cl::desc("Target a specific cpu type (-mcpu=help for details)"),
120        cl::value_desc("cpu-name"), cl::init(""));
121    CGBINDOPT(MCPU);
122  
123    static cl::list<std::string> MAttrs(
124        "mattr", cl::CommaSeparated,
125        cl::desc("Target specific attributes (-mattr=help for details)"),
126        cl::value_desc("a1,+a2,-a3,..."));
127    CGBINDOPT(MAttrs);
128  
129    static cl::opt<Reloc::Model> RelocModel(
130        "relocation-model", cl::desc("Choose relocation model"),
131        cl::values(
132            clEnumValN(Reloc::Static, "static", "Non-relocatable code"),
133            clEnumValN(Reloc::PIC_, "pic",
134                       "Fully relocatable, position independent code"),
135            clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
136                       "Relocatable external references, non-relocatable code"),
137            clEnumValN(
138                Reloc::ROPI, "ropi",
139                "Code and read-only data relocatable, accessed PC-relative"),
140            clEnumValN(
141                Reloc::RWPI, "rwpi",
142                "Read-write data relocatable, accessed relative to static base"),
143            clEnumValN(Reloc::ROPI_RWPI, "ropi-rwpi",
144                       "Combination of ropi and rwpi")));
145    CGBINDOPT(RelocModel);
146  
147    static cl::opt<ThreadModel::Model> ThreadModel(
148        "thread-model", cl::desc("Choose threading model"),
149        cl::init(ThreadModel::POSIX),
150        cl::values(
151            clEnumValN(ThreadModel::POSIX, "posix", "POSIX thread model"),
152            clEnumValN(ThreadModel::Single, "single", "Single thread model")));
153    CGBINDOPT(ThreadModel);
154  
155    static cl::opt<CodeModel::Model> CodeModel(
156        "code-model", cl::desc("Choose code model"),
157        cl::values(clEnumValN(CodeModel::Tiny, "tiny", "Tiny code model"),
158                   clEnumValN(CodeModel::Small, "small", "Small code model"),
159                   clEnumValN(CodeModel::Kernel, "kernel", "Kernel code model"),
160                   clEnumValN(CodeModel::Medium, "medium", "Medium code model"),
161                   clEnumValN(CodeModel::Large, "large", "Large code model")));
162    CGBINDOPT(CodeModel);
163  
164    static cl::opt<ExceptionHandling> ExceptionModel(
165        "exception-model", cl::desc("exception model"),
166        cl::init(ExceptionHandling::None),
167        cl::values(
168            clEnumValN(ExceptionHandling::None, "default",
169                       "default exception handling model"),
170            clEnumValN(ExceptionHandling::DwarfCFI, "dwarf",
171                       "DWARF-like CFI based exception handling"),
172            clEnumValN(ExceptionHandling::SjLj, "sjlj",
173                       "SjLj exception handling"),
174            clEnumValN(ExceptionHandling::ARM, "arm", "ARM EHABI exceptions"),
175            clEnumValN(ExceptionHandling::WinEH, "wineh",
176                       "Windows exception model"),
177            clEnumValN(ExceptionHandling::Wasm, "wasm",
178                       "WebAssembly exception handling")));
179    CGBINDOPT(ExceptionModel);
180  
181    static cl::opt<CodeGenFileType> FileType(
182        "filetype", cl::init(CGFT_AssemblyFile),
183        cl::desc(
184            "Choose a file type (not all types are supported by all targets):"),
185        cl::values(
186            clEnumValN(CGFT_AssemblyFile, "asm", "Emit an assembly ('.s') file"),
187            clEnumValN(CGFT_ObjectFile, "obj",
188                       "Emit a native object ('.o') file"),
189            clEnumValN(CGFT_Null, "null",
190                       "Emit nothing, for performance testing")));
191    CGBINDOPT(FileType);
192  
193    static cl::opt<FramePointerKind> FramePointerUsage(
194        "frame-pointer",
195        cl::desc("Specify frame pointer elimination optimization"),
196        cl::init(FramePointerKind::None),
197        cl::values(
198            clEnumValN(FramePointerKind::All, "all",
199                       "Disable frame pointer elimination"),
200            clEnumValN(FramePointerKind::NonLeaf, "non-leaf",
201                       "Disable frame pointer elimination for non-leaf frame"),
202            clEnumValN(FramePointerKind::None, "none",
203                       "Enable frame pointer elimination")));
204    CGBINDOPT(FramePointerUsage);
205  
206    static cl::opt<bool> EnableUnsafeFPMath(
207        "enable-unsafe-fp-math",
208        cl::desc("Enable optimizations that may decrease FP precision"),
209        cl::init(false));
210    CGBINDOPT(EnableUnsafeFPMath);
211  
212    static cl::opt<bool> EnableNoInfsFPMath(
213        "enable-no-infs-fp-math",
214        cl::desc("Enable FP math optimizations that assume no +-Infs"),
215        cl::init(false));
216    CGBINDOPT(EnableNoInfsFPMath);
217  
218    static cl::opt<bool> EnableNoNaNsFPMath(
219        "enable-no-nans-fp-math",
220        cl::desc("Enable FP math optimizations that assume no NaNs"),
221        cl::init(false));
222    CGBINDOPT(EnableNoNaNsFPMath);
223  
224    static cl::opt<bool> EnableNoSignedZerosFPMath(
225        "enable-no-signed-zeros-fp-math",
226        cl::desc("Enable FP math optimizations that assume "
227                 "the sign of 0 is insignificant"),
228        cl::init(false));
229    CGBINDOPT(EnableNoSignedZerosFPMath);
230  
231    static cl::opt<bool> EnableApproxFuncFPMath(
232        "enable-approx-func-fp-math",
233        cl::desc("Enable FP math optimizations that assume approx func"),
234        cl::init(false));
235    CGBINDOPT(EnableApproxFuncFPMath);
236  
237    static cl::opt<bool> EnableNoTrappingFPMath(
238        "enable-no-trapping-fp-math",
239        cl::desc("Enable setting the FP exceptions build "
240                 "attribute not to use exceptions"),
241        cl::init(false));
242    CGBINDOPT(EnableNoTrappingFPMath);
243  
244    static const auto DenormFlagEnumOptions =
245    cl::values(clEnumValN(DenormalMode::IEEE, "ieee",
246                          "IEEE 754 denormal numbers"),
247               clEnumValN(DenormalMode::PreserveSign, "preserve-sign",
248                          "the sign of a  flushed-to-zero number is preserved "
249                          "in the sign of 0"),
250               clEnumValN(DenormalMode::PositiveZero, "positive-zero",
251                          "denormals are flushed to positive zero"));
252  
253    // FIXME: Doesn't have way to specify separate input and output modes.
254    static cl::opt<DenormalMode::DenormalModeKind> DenormalFPMath(
255      "denormal-fp-math",
256      cl::desc("Select which denormal numbers the code is permitted to require"),
257      cl::init(DenormalMode::IEEE),
258      DenormFlagEnumOptions);
259    CGBINDOPT(DenormalFPMath);
260  
261    static cl::opt<DenormalMode::DenormalModeKind> DenormalFP32Math(
262      "denormal-fp-math-f32",
263      cl::desc("Select which denormal numbers the code is permitted to require for float"),
264      cl::init(DenormalMode::Invalid),
265      DenormFlagEnumOptions);
266    CGBINDOPT(DenormalFP32Math);
267  
268    static cl::opt<bool> EnableHonorSignDependentRoundingFPMath(
269        "enable-sign-dependent-rounding-fp-math", cl::Hidden,
270        cl::desc("Force codegen to assume rounding mode can change dynamically"),
271        cl::init(false));
272    CGBINDOPT(EnableHonorSignDependentRoundingFPMath);
273  
274    static cl::opt<FloatABI::ABIType> FloatABIForCalls(
275        "float-abi", cl::desc("Choose float ABI type"),
276        cl::init(FloatABI::Default),
277        cl::values(clEnumValN(FloatABI::Default, "default",
278                              "Target default float ABI type"),
279                   clEnumValN(FloatABI::Soft, "soft",
280                              "Soft float ABI (implied by -soft-float)"),
281                   clEnumValN(FloatABI::Hard, "hard",
282                              "Hard float ABI (uses FP registers)")));
283    CGBINDOPT(FloatABIForCalls);
284  
285    static cl::opt<FPOpFusion::FPOpFusionMode> FuseFPOps(
286        "fp-contract", cl::desc("Enable aggressive formation of fused FP ops"),
287        cl::init(FPOpFusion::Standard),
288        cl::values(
289            clEnumValN(FPOpFusion::Fast, "fast",
290                       "Fuse FP ops whenever profitable"),
291            clEnumValN(FPOpFusion::Standard, "on", "Only fuse 'blessed' FP ops."),
292            clEnumValN(FPOpFusion::Strict, "off",
293                       "Only fuse FP ops when the result won't be affected.")));
294    CGBINDOPT(FuseFPOps);
295  
296    static cl::opt<SwiftAsyncFramePointerMode> SwiftAsyncFramePointer(
297        "swift-async-fp",
298        cl::desc("Determine when the Swift async frame pointer should be set"),
299        cl::init(SwiftAsyncFramePointerMode::Always),
300        cl::values(clEnumValN(SwiftAsyncFramePointerMode::DeploymentBased, "auto",
301                              "Determine based on deployment target"),
302                   clEnumValN(SwiftAsyncFramePointerMode::Always, "always",
303                              "Always set the bit"),
304                   clEnumValN(SwiftAsyncFramePointerMode::Never, "never",
305                              "Never set the bit")));
306    CGBINDOPT(SwiftAsyncFramePointer);
307  
308    static cl::opt<bool> DontPlaceZerosInBSS(
309        "nozero-initialized-in-bss",
310        cl::desc("Don't place zero-initialized symbols into bss section"),
311        cl::init(false));
312    CGBINDOPT(DontPlaceZerosInBSS);
313  
314    static cl::opt<bool> EnableAIXExtendedAltivecABI(
315        "vec-extabi", cl::desc("Enable the AIX Extended Altivec ABI."),
316        cl::init(false));
317    CGBINDOPT(EnableAIXExtendedAltivecABI);
318  
319    static cl::opt<bool> EnableGuaranteedTailCallOpt(
320        "tailcallopt",
321        cl::desc(
322            "Turn fastcc calls into tail calls by (potentially) changing ABI."),
323        cl::init(false));
324    CGBINDOPT(EnableGuaranteedTailCallOpt);
325  
326    static cl::opt<bool> DisableTailCalls(
327        "disable-tail-calls", cl::desc("Never emit tail calls"), cl::init(false));
328    CGBINDOPT(DisableTailCalls);
329  
330    static cl::opt<bool> StackSymbolOrdering(
331        "stack-symbol-ordering", cl::desc("Order local stack symbols."),
332        cl::init(true));
333    CGBINDOPT(StackSymbolOrdering);
334  
335    static cl::opt<bool> StackRealign(
336        "stackrealign",
337        cl::desc("Force align the stack to the minimum alignment"),
338        cl::init(false));
339    CGBINDOPT(StackRealign);
340  
341    static cl::opt<std::string> TrapFuncName(
342        "trap-func", cl::Hidden,
343        cl::desc("Emit a call to trap function rather than a trap instruction"),
344        cl::init(""));
345    CGBINDOPT(TrapFuncName);
346  
347    static cl::opt<bool> UseCtors("use-ctors",
348                                  cl::desc("Use .ctors instead of .init_array."),
349                                  cl::init(false));
350    CGBINDOPT(UseCtors);
351  
352    static cl::opt<bool> LowerGlobalDtorsViaCxaAtExit(
353        "lower-global-dtors-via-cxa-atexit",
354        cl::desc("Lower llvm.global_dtors (global destructors) via __cxa_atexit"),
355        cl::init(true));
356    CGBINDOPT(LowerGlobalDtorsViaCxaAtExit);
357  
358    static cl::opt<bool> RelaxELFRelocations(
359        "relax-elf-relocations",
360        cl::desc(
361            "Emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL on x86-64 ELF"),
362        cl::init(true));
363    CGBINDOPT(RelaxELFRelocations);
364  
365    static cl::opt<bool> DataSections(
366        "data-sections", cl::desc("Emit data into separate sections"),
367        cl::init(false));
368    CGBINDOPT(DataSections);
369  
370    static cl::opt<bool> FunctionSections(
371        "function-sections", cl::desc("Emit functions into separate sections"),
372        cl::init(false));
373    CGBINDOPT(FunctionSections);
374  
375    static cl::opt<bool> IgnoreXCOFFVisibility(
376        "ignore-xcoff-visibility",
377        cl::desc("Not emit the visibility attribute for asm in AIX OS or give "
378                 "all symbols 'unspecified' visibility in XCOFF object file"),
379        cl::init(false));
380    CGBINDOPT(IgnoreXCOFFVisibility);
381  
382    static cl::opt<bool> XCOFFTracebackTable(
383        "xcoff-traceback-table", cl::desc("Emit the XCOFF traceback table"),
384        cl::init(true));
385    CGBINDOPT(XCOFFTracebackTable);
386  
387    static cl::opt<std::string> BBSections(
388        "basic-block-sections",
389        cl::desc("Emit basic blocks into separate sections"),
390        cl::value_desc("all | <function list (file)> | labels | none"),
391        cl::init("none"));
392    CGBINDOPT(BBSections);
393  
394    static cl::opt<unsigned> TLSSize(
395        "tls-size", cl::desc("Bit size of immediate TLS offsets"), cl::init(0));
396    CGBINDOPT(TLSSize);
397  
398    static cl::opt<bool> EmulatedTLS(
399        "emulated-tls", cl::desc("Use emulated TLS model"), cl::init(false));
400    CGBINDOPT(EmulatedTLS);
401  
402    static cl::opt<bool> UniqueSectionNames(
403        "unique-section-names", cl::desc("Give unique names to every section"),
404        cl::init(true));
405    CGBINDOPT(UniqueSectionNames);
406  
407    static cl::opt<bool> UniqueBasicBlockSectionNames(
408        "unique-basic-block-section-names",
409        cl::desc("Give unique names to every basic block section"),
410        cl::init(false));
411    CGBINDOPT(UniqueBasicBlockSectionNames);
412  
413    static cl::opt<EABI> EABIVersion(
414        "meabi", cl::desc("Set EABI type (default depends on triple):"),
415        cl::init(EABI::Default),
416        cl::values(
417            clEnumValN(EABI::Default, "default", "Triple default EABI version"),
418            clEnumValN(EABI::EABI4, "4", "EABI version 4"),
419            clEnumValN(EABI::EABI5, "5", "EABI version 5"),
420            clEnumValN(EABI::GNU, "gnu", "EABI GNU")));
421    CGBINDOPT(EABIVersion);
422  
423    static cl::opt<DebuggerKind> DebuggerTuningOpt(
424        "debugger-tune", cl::desc("Tune debug info for a particular debugger"),
425        cl::init(DebuggerKind::Default),
426        cl::values(
427            clEnumValN(DebuggerKind::GDB, "gdb", "gdb"),
428            clEnumValN(DebuggerKind::LLDB, "lldb", "lldb"),
429            clEnumValN(DebuggerKind::DBX, "dbx", "dbx"),
430            clEnumValN(DebuggerKind::SCE, "sce", "SCE targets (e.g. PS4)")));
431    CGBINDOPT(DebuggerTuningOpt);
432  
433    static cl::opt<bool> EnableStackSizeSection(
434        "stack-size-section",
435        cl::desc("Emit a section containing stack size metadata"),
436        cl::init(false));
437    CGBINDOPT(EnableStackSizeSection);
438  
439    static cl::opt<bool> EnableAddrsig(
440        "addrsig", cl::desc("Emit an address-significance table"),
441        cl::init(false));
442    CGBINDOPT(EnableAddrsig);
443  
444    static cl::opt<bool> EmitCallSiteInfo(
445        "emit-call-site-info",
446        cl::desc(
447            "Emit call site debug information, if debug information is enabled."),
448        cl::init(false));
449    CGBINDOPT(EmitCallSiteInfo);
450  
451    static cl::opt<bool> EnableDebugEntryValues(
452        "debug-entry-values",
453        cl::desc("Enable debug info for the debug entry values."),
454        cl::init(false));
455    CGBINDOPT(EnableDebugEntryValues);
456  
457    static cl::opt<bool> EnableMachineFunctionSplitter(
458        "split-machine-functions",
459        cl::desc("Split out cold basic blocks from machine functions based on "
460                 "profile information"),
461        cl::init(false));
462    CGBINDOPT(EnableMachineFunctionSplitter);
463  
464    static cl::opt<bool> ForceDwarfFrameSection(
465        "force-dwarf-frame-section",
466        cl::desc("Always emit a debug frame section."), cl::init(false));
467    CGBINDOPT(ForceDwarfFrameSection);
468  
469    static cl::opt<bool> XRayOmitFunctionIndex(
470        "no-xray-index", cl::desc("Don't emit xray_fn_idx section"),
471        cl::init(false));
472    CGBINDOPT(XRayOmitFunctionIndex);
473  
474    static cl::opt<bool> DebugStrictDwarf(
475        "strict-dwarf", cl::desc("use strict dwarf"), cl::init(false));
476    CGBINDOPT(DebugStrictDwarf);
477  
478    static cl::opt<unsigned> AlignLoops("align-loops",
479                                        cl::desc("Default alignment for loops"));
480    CGBINDOPT(AlignLoops);
481  
482    static cl::opt<bool> JMCInstrument(
483        "enable-jmc-instrument",
484        cl::desc("Instrument functions with a call to __CheckForDebuggerJustMyCode"),
485        cl::init(false));
486    CGBINDOPT(JMCInstrument);
487  
488  #undef CGBINDOPT
489  
490    mc::RegisterMCTargetOptionsFlags();
491  }
492  
493  llvm::BasicBlockSection
494  codegen::getBBSectionsMode(llvm::TargetOptions &Options) {
495    if (getBBSections() == "all")
496      return BasicBlockSection::All;
497    else if (getBBSections() == "labels")
498      return BasicBlockSection::Labels;
499    else if (getBBSections() == "none")
500      return BasicBlockSection::None;
501    else {
502      ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
503          MemoryBuffer::getFile(getBBSections());
504      if (!MBOrErr) {
505        errs() << "Error loading basic block sections function list file: "
506               << MBOrErr.getError().message() << "\n";
507      } else {
508        Options.BBSectionsFuncListBuf = std::move(*MBOrErr);
509      }
510      return BasicBlockSection::List;
511    }
512  }
513  
514  // Common utility function tightly tied to the options listed here. Initializes
515  // a TargetOptions object with CodeGen flags and returns it.
516  TargetOptions
517  codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
518    TargetOptions Options;
519    Options.AllowFPOpFusion = getFuseFPOps();
520    Options.UnsafeFPMath = getEnableUnsafeFPMath();
521    Options.NoInfsFPMath = getEnableNoInfsFPMath();
522    Options.NoNaNsFPMath = getEnableNoNaNsFPMath();
523    Options.NoSignedZerosFPMath = getEnableNoSignedZerosFPMath();
524    Options.ApproxFuncFPMath = getEnableApproxFuncFPMath();
525    Options.NoTrappingFPMath = getEnableNoTrappingFPMath();
526  
527    DenormalMode::DenormalModeKind DenormKind = getDenormalFPMath();
528  
529    // FIXME: Should have separate input and output flags
530    Options.setFPDenormalMode(DenormalMode(DenormKind, DenormKind));
531  
532    Options.HonorSignDependentRoundingFPMathOption =
533        getEnableHonorSignDependentRoundingFPMath();
534    if (getFloatABIForCalls() != FloatABI::Default)
535      Options.FloatABIType = getFloatABIForCalls();
536    Options.EnableAIXExtendedAltivecABI = getEnableAIXExtendedAltivecABI();
537    Options.NoZerosInBSS = getDontPlaceZerosInBSS();
538    Options.GuaranteedTailCallOpt = getEnableGuaranteedTailCallOpt();
539    Options.StackSymbolOrdering = getStackSymbolOrdering();
540    Options.UseInitArray = !getUseCtors();
541    Options.LowerGlobalDtorsViaCxaAtExit = getLowerGlobalDtorsViaCxaAtExit();
542    Options.RelaxELFRelocations = getRelaxELFRelocations();
543    Options.DataSections =
544        getExplicitDataSections().value_or(TheTriple.hasDefaultDataSections());
545    Options.FunctionSections = getFunctionSections();
546    Options.IgnoreXCOFFVisibility = getIgnoreXCOFFVisibility();
547    Options.XCOFFTracebackTable = getXCOFFTracebackTable();
548    Options.BBSections = getBBSectionsMode(Options);
549    Options.UniqueSectionNames = getUniqueSectionNames();
550    Options.UniqueBasicBlockSectionNames = getUniqueBasicBlockSectionNames();
551    Options.TLSSize = getTLSSize();
552    Options.EmulatedTLS = getEmulatedTLS();
553    Options.ExplicitEmulatedTLS = EmulatedTLSView->getNumOccurrences() > 0;
554    Options.ExceptionModel = getExceptionModel();
555    Options.EmitStackSizeSection = getEnableStackSizeSection();
556    Options.EnableMachineFunctionSplitter = getEnableMachineFunctionSplitter();
557    Options.EmitAddrsig = getEnableAddrsig();
558    Options.EmitCallSiteInfo = getEmitCallSiteInfo();
559    Options.EnableDebugEntryValues = getEnableDebugEntryValues();
560    Options.ForceDwarfFrameSection = getForceDwarfFrameSection();
561    Options.XRayOmitFunctionIndex = getXRayOmitFunctionIndex();
562    Options.DebugStrictDwarf = getDebugStrictDwarf();
563    Options.LoopAlignment = getAlignLoops();
564    Options.JMCInstrument = getJMCInstrument();
565  
566    Options.MCOptions = mc::InitMCTargetOptionsFromFlags();
567  
568    Options.ThreadModel = getThreadModel();
569    Options.EABIVersion = getEABIVersion();
570    Options.DebuggerTuning = getDebuggerTuningOpt();
571    Options.SwiftAsyncFramePointer = getSwiftAsyncFramePointer();
572    return Options;
573  }
574  
575  std::string codegen::getCPUStr() {
576    // If user asked for the 'native' CPU, autodetect here. If autodection fails,
577    // this will set the CPU to an empty string which tells the target to
578    // pick a basic default.
579    if (getMCPU() == "native")
580      return std::string(sys::getHostCPUName());
581  
582    return getMCPU();
583  }
584  
585  std::string codegen::getFeaturesStr() {
586    SubtargetFeatures Features;
587  
588    // If user asked for the 'native' CPU, we need to autodetect features.
589    // This is necessary for x86 where the CPU might not support all the
590    // features the autodetected CPU name lists in the target. For example,
591    // not all Sandybridge processors support AVX.
592    if (getMCPU() == "native") {
593      StringMap<bool> HostFeatures;
594      if (sys::getHostCPUFeatures(HostFeatures))
595        for (const auto &[Feature, IsEnabled] : HostFeatures)
596          Features.AddFeature(Feature, IsEnabled);
597    }
598  
599    for (auto const &MAttr : getMAttrs())
600      Features.AddFeature(MAttr);
601  
602    return Features.getString();
603  }
604  
605  std::vector<std::string> codegen::getFeatureList() {
606    SubtargetFeatures Features;
607  
608    // If user asked for the 'native' CPU, we need to autodetect features.
609    // This is necessary for x86 where the CPU might not support all the
610    // features the autodetected CPU name lists in the target. For example,
611    // not all Sandybridge processors support AVX.
612    if (getMCPU() == "native") {
613      StringMap<bool> HostFeatures;
614      if (sys::getHostCPUFeatures(HostFeatures))
615        for (const auto &[Feature, IsEnabled] : HostFeatures)
616          Features.AddFeature(Feature, IsEnabled);
617    }
618  
619    for (auto const &MAttr : getMAttrs())
620      Features.AddFeature(MAttr);
621  
622    return Features.getFeatures();
623  }
624  
625  void codegen::renderBoolStringAttr(AttrBuilder &B, StringRef Name, bool Val) {
626    B.addAttribute(Name, Val ? "true" : "false");
627  }
628  
629  #define HANDLE_BOOL_ATTR(CL, AttrName)                                         \
630    do {                                                                         \
631      if (CL->getNumOccurrences() > 0 && !F.hasFnAttribute(AttrName))            \
632        renderBoolStringAttr(NewAttrs, AttrName, *CL);                           \
633    } while (0)
634  
635  /// Set function attributes of function \p F based on CPU, Features, and command
636  /// line flags.
637  void codegen::setFunctionAttributes(StringRef CPU, StringRef Features,
638                                      Function &F) {
639    auto &Ctx = F.getContext();
640    AttributeList Attrs = F.getAttributes();
641    AttrBuilder NewAttrs(Ctx);
642  
643    if (!CPU.empty() && !F.hasFnAttribute("target-cpu"))
644      NewAttrs.addAttribute("target-cpu", CPU);
645    if (!Features.empty()) {
646      // Append the command line features to any that are already on the function.
647      StringRef OldFeatures =
648          F.getFnAttribute("target-features").getValueAsString();
649      if (OldFeatures.empty())
650        NewAttrs.addAttribute("target-features", Features);
651      else {
652        SmallString<256> Appended(OldFeatures);
653        Appended.push_back(',');
654        Appended.append(Features);
655        NewAttrs.addAttribute("target-features", Appended);
656      }
657    }
658    if (FramePointerUsageView->getNumOccurrences() > 0 &&
659        !F.hasFnAttribute("frame-pointer")) {
660      if (getFramePointerUsage() == FramePointerKind::All)
661        NewAttrs.addAttribute("frame-pointer", "all");
662      else if (getFramePointerUsage() == FramePointerKind::NonLeaf)
663        NewAttrs.addAttribute("frame-pointer", "non-leaf");
664      else if (getFramePointerUsage() == FramePointerKind::None)
665        NewAttrs.addAttribute("frame-pointer", "none");
666    }
667    if (DisableTailCallsView->getNumOccurrences() > 0)
668      NewAttrs.addAttribute("disable-tail-calls",
669                            toStringRef(getDisableTailCalls()));
670    if (getStackRealign())
671      NewAttrs.addAttribute("stackrealign");
672  
673    HANDLE_BOOL_ATTR(EnableUnsafeFPMathView, "unsafe-fp-math");
674    HANDLE_BOOL_ATTR(EnableNoInfsFPMathView, "no-infs-fp-math");
675    HANDLE_BOOL_ATTR(EnableNoNaNsFPMathView, "no-nans-fp-math");
676    HANDLE_BOOL_ATTR(EnableNoSignedZerosFPMathView, "no-signed-zeros-fp-math");
677    HANDLE_BOOL_ATTR(EnableApproxFuncFPMathView, "approx-func-fp-math");
678  
679    if (DenormalFPMathView->getNumOccurrences() > 0 &&
680        !F.hasFnAttribute("denormal-fp-math")) {
681      DenormalMode::DenormalModeKind DenormKind = getDenormalFPMath();
682  
683      // FIXME: Command line flag should expose separate input/output modes.
684      NewAttrs.addAttribute("denormal-fp-math",
685                            DenormalMode(DenormKind, DenormKind).str());
686    }
687  
688    if (DenormalFP32MathView->getNumOccurrences() > 0 &&
689        !F.hasFnAttribute("denormal-fp-math-f32")) {
690      // FIXME: Command line flag should expose separate input/output modes.
691      DenormalMode::DenormalModeKind DenormKind = getDenormalFP32Math();
692  
693      NewAttrs.addAttribute(
694        "denormal-fp-math-f32",
695        DenormalMode(DenormKind, DenormKind).str());
696    }
697  
698    if (TrapFuncNameView->getNumOccurrences() > 0)
699      for (auto &B : F)
700        for (auto &I : B)
701          if (auto *Call = dyn_cast<CallInst>(&I))
702            if (const auto *F = Call->getCalledFunction())
703              if (F->getIntrinsicID() == Intrinsic::debugtrap ||
704                  F->getIntrinsicID() == Intrinsic::trap)
705                Call->addFnAttr(
706                    Attribute::get(Ctx, "trap-func-name", getTrapFuncName()));
707  
708    // Let NewAttrs override Attrs.
709    F.setAttributes(Attrs.addFnAttributes(Ctx, NewAttrs));
710  }
711  
712  /// Set function attributes of functions in Module M based on CPU,
713  /// Features, and command line flags.
714  void codegen::setFunctionAttributes(StringRef CPU, StringRef Features,
715                                      Module &M) {
716    for (Function &F : M)
717      setFunctionAttributes(CPU, Features, F);
718  }
719