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