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