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