859 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains codegen-specific flags that are shared between different10// command line tools. The tools "llc" and "opt" both use this file to prevent11// flag duplication.12//13//===----------------------------------------------------------------------===//14 15#include "llvm/CodeGen/CommandFlags.h"16#include "llvm/ADT/SmallString.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/ADT/StringExtras.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/IR/Instructions.h"21#include "llvm/IR/Intrinsics.h"22#include "llvm/IR/Module.h"23#include "llvm/MC/MCTargetOptionsCommandFlags.h"24#include "llvm/MC/TargetRegistry.h"25#include "llvm/Support/CommandLine.h"26#include "llvm/Support/FileSystem.h"27#include "llvm/Support/MemoryBuffer.h"28#include "llvm/Support/Path.h"29#include "llvm/Support/WithColor.h"30#include "llvm/Support/raw_ostream.h"31#include "llvm/Target/TargetMachine.h"32#include "llvm/TargetParser/Host.h"33#include "llvm/TargetParser/SubtargetFeature.h"34#include "llvm/TargetParser/Triple.h"35#include <cassert>36#include <memory>37#include <optional>38#include <system_error>39 40using namespace llvm;41 42#define CGOPT(TY, NAME) \43 static cl::opt<TY> *NAME##View; \44 TY codegen::get##NAME() { \45 assert(NAME##View && "Flag not registered."); \46 return *NAME##View; \47 }48 49#define CGLIST(TY, NAME) \50 static cl::list<TY> *NAME##View; \51 std::vector<TY> codegen::get##NAME() { \52 assert(NAME##View && "Flag not registered."); \53 return *NAME##View; \54 }55 56// Temporary macro for incremental transition to std::optional.57#define CGOPT_EXP(TY, NAME) \58 CGOPT(TY, NAME) \59 std::optional<TY> codegen::getExplicit##NAME() { \60 if (NAME##View->getNumOccurrences()) { \61 TY res = *NAME##View; \62 return res; \63 } \64 return std::nullopt; \65 }66 67CGOPT(std::string, MArch)68CGOPT(std::string, MCPU)69CGLIST(std::string, MAttrs)70CGOPT_EXP(Reloc::Model, RelocModel)71CGOPT(ThreadModel::Model, ThreadModel)72CGOPT_EXP(CodeModel::Model, CodeModel)73CGOPT_EXP(uint64_t, LargeDataThreshold)74CGOPT(ExceptionHandling, ExceptionModel)75CGOPT_EXP(CodeGenFileType, FileType)76CGOPT(FramePointerKind, FramePointerUsage)77CGOPT(bool, EnableNoInfsFPMath)78CGOPT(bool, EnableNoNaNsFPMath)79CGOPT(bool, EnableNoSignedZerosFPMath)80CGOPT(bool, EnableNoTrappingFPMath)81CGOPT(bool, EnableAIXExtendedAltivecABI)82CGOPT(DenormalMode::DenormalModeKind, DenormalFPMath)83CGOPT(DenormalMode::DenormalModeKind, DenormalFP32Math)84CGOPT(bool, EnableHonorSignDependentRoundingFPMath)85CGOPT(FloatABI::ABIType, FloatABIForCalls)86CGOPT(FPOpFusion::FPOpFusionMode, FuseFPOps)87CGOPT(SwiftAsyncFramePointerMode, SwiftAsyncFramePointer)88CGOPT(bool, DontPlaceZerosInBSS)89CGOPT(bool, EnableGuaranteedTailCallOpt)90CGOPT(bool, DisableTailCalls)91CGOPT(bool, StackSymbolOrdering)92CGOPT(bool, StackRealign)93CGOPT(std::string, TrapFuncName)94CGOPT(bool, UseCtors)95CGOPT(bool, DisableIntegratedAS)96CGOPT_EXP(bool, DataSections)97CGOPT_EXP(bool, FunctionSections)98CGOPT(bool, IgnoreXCOFFVisibility)99CGOPT(bool, XCOFFTracebackTable)100CGOPT(bool, EnableBBAddrMap)101CGOPT(std::string, BBSections)102CGOPT(unsigned, TLSSize)103CGOPT_EXP(bool, EmulatedTLS)104CGOPT_EXP(bool, EnableTLSDESC)105CGOPT(bool, UniqueSectionNames)106CGOPT(bool, UniqueBasicBlockSectionNames)107CGOPT(bool, SeparateNamedSections)108CGOPT(EABI, EABIVersion)109CGOPT(DebuggerKind, DebuggerTuningOpt)110CGOPT(VectorLibrary, VectorLibrary)111CGOPT(bool, EnableStackSizeSection)112CGOPT(bool, EnableAddrsig)113CGOPT(bool, EnableCallGraphSection)114CGOPT(bool, EmitCallSiteInfo)115CGOPT(bool, EnableMachineFunctionSplitter)116CGOPT(bool, EnableStaticDataPartitioning)117CGOPT(bool, EnableDebugEntryValues)118CGOPT(bool, ForceDwarfFrameSection)119CGOPT(bool, XRayFunctionIndex)120CGOPT(bool, DebugStrictDwarf)121CGOPT(unsigned, AlignLoops)122CGOPT(bool, JMCInstrument)123CGOPT(bool, XCOFFReadOnlyPointers)124CGOPT(codegen::SaveStatsMode, SaveStats)125 126#define CGBINDOPT(NAME) \127 do { \128 NAME##View = std::addressof(NAME); \129 } while (0)130 131codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {132 static cl::opt<std::string> MArch(133 "march", cl::desc("Architecture to generate code for (see --version)"));134 CGBINDOPT(MArch);135 136 static cl::opt<std::string> MCPU(137 "mcpu", cl::desc("Target a specific cpu type (-mcpu=help for details)"),138 cl::value_desc("cpu-name"), cl::init(""));139 CGBINDOPT(MCPU);140 141 static cl::list<std::string> MAttrs(142 "mattr", cl::CommaSeparated,143 cl::desc("Target specific attributes (-mattr=help for details)"),144 cl::value_desc("a1,+a2,-a3,..."));145 CGBINDOPT(MAttrs);146 147 static cl::opt<Reloc::Model> RelocModel(148 "relocation-model", cl::desc("Choose relocation model"),149 cl::values(150 clEnumValN(Reloc::Static, "static", "Non-relocatable code"),151 clEnumValN(Reloc::PIC_, "pic",152 "Fully relocatable, position independent code"),153 clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",154 "Relocatable external references, non-relocatable code"),155 clEnumValN(156 Reloc::ROPI, "ropi",157 "Code and read-only data relocatable, accessed PC-relative"),158 clEnumValN(159 Reloc::RWPI, "rwpi",160 "Read-write data relocatable, accessed relative to static base"),161 clEnumValN(Reloc::ROPI_RWPI, "ropi-rwpi",162 "Combination of ropi and rwpi")));163 CGBINDOPT(RelocModel);164 165 static cl::opt<ThreadModel::Model> ThreadModel(166 "thread-model", cl::desc("Choose threading model"),167 cl::init(ThreadModel::POSIX),168 cl::values(169 clEnumValN(ThreadModel::POSIX, "posix", "POSIX thread model"),170 clEnumValN(ThreadModel::Single, "single", "Single thread model")));171 CGBINDOPT(ThreadModel);172 173 static cl::opt<CodeModel::Model> CodeModel(174 "code-model", cl::desc("Choose code model"),175 cl::values(clEnumValN(CodeModel::Tiny, "tiny", "Tiny code model"),176 clEnumValN(CodeModel::Small, "small", "Small code model"),177 clEnumValN(CodeModel::Kernel, "kernel", "Kernel code model"),178 clEnumValN(CodeModel::Medium, "medium", "Medium code model"),179 clEnumValN(CodeModel::Large, "large", "Large code model")));180 CGBINDOPT(CodeModel);181 182 static cl::opt<uint64_t> LargeDataThreshold(183 "large-data-threshold",184 cl::desc("Choose large data threshold for x86_64 medium code model"),185 cl::init(0));186 CGBINDOPT(LargeDataThreshold);187 188 static cl::opt<ExceptionHandling> ExceptionModel(189 "exception-model", cl::desc("exception model"),190 cl::init(ExceptionHandling::None),191 cl::values(192 clEnumValN(ExceptionHandling::None, "default",193 "default exception handling model"),194 clEnumValN(ExceptionHandling::DwarfCFI, "dwarf",195 "DWARF-like CFI based exception handling"),196 clEnumValN(ExceptionHandling::SjLj, "sjlj",197 "SjLj exception handling"),198 clEnumValN(ExceptionHandling::ARM, "arm", "ARM EHABI exceptions"),199 clEnumValN(ExceptionHandling::WinEH, "wineh",200 "Windows exception model"),201 clEnumValN(ExceptionHandling::Wasm, "wasm",202 "WebAssembly exception handling")));203 CGBINDOPT(ExceptionModel);204 205 static cl::opt<CodeGenFileType> FileType(206 "filetype", cl::init(CodeGenFileType::AssemblyFile),207 cl::desc(208 "Choose a file type (not all types are supported by all targets):"),209 cl::values(clEnumValN(CodeGenFileType::AssemblyFile, "asm",210 "Emit an assembly ('.s') file"),211 clEnumValN(CodeGenFileType::ObjectFile, "obj",212 "Emit a native object ('.o') file"),213 clEnumValN(CodeGenFileType::Null, "null",214 "Emit nothing, for performance testing")));215 CGBINDOPT(FileType);216 217 static cl::opt<FramePointerKind> FramePointerUsage(218 "frame-pointer",219 cl::desc("Specify frame pointer elimination optimization"),220 cl::init(FramePointerKind::None),221 cl::values(222 clEnumValN(FramePointerKind::All, "all",223 "Disable frame pointer elimination"),224 clEnumValN(FramePointerKind::NonLeaf, "non-leaf",225 "Disable frame pointer elimination for non-leaf frame but "226 "reserve the register in leaf functions"),227 clEnumValN(FramePointerKind::NonLeafNoReserve, "non-leaf-no-reserve",228 "Disable frame pointer elimination for non-leaf frame"),229 clEnumValN(FramePointerKind::Reserved, "reserved",230 "Enable frame pointer elimination, but reserve the frame "231 "pointer register"),232 clEnumValN(FramePointerKind::None, "none",233 "Enable frame pointer elimination")));234 CGBINDOPT(FramePointerUsage);235 236 static cl::opt<bool> EnableNoInfsFPMath(237 "enable-no-infs-fp-math",238 cl::desc("Enable FP math optimizations that assume no +-Infs"),239 cl::init(false));240 CGBINDOPT(EnableNoInfsFPMath);241 242 static cl::opt<bool> EnableNoNaNsFPMath(243 "enable-no-nans-fp-math",244 cl::desc("Enable FP math optimizations that assume no NaNs"),245 cl::init(false));246 CGBINDOPT(EnableNoNaNsFPMath);247 248 static cl::opt<bool> EnableNoSignedZerosFPMath(249 "enable-no-signed-zeros-fp-math",250 cl::desc("Enable FP math optimizations that assume "251 "the sign of 0 is insignificant"),252 cl::init(false));253 CGBINDOPT(EnableNoSignedZerosFPMath);254 255 static cl::opt<bool> EnableNoTrappingFPMath(256 "enable-no-trapping-fp-math",257 cl::desc("Enable setting the FP exceptions build "258 "attribute not to use exceptions"),259 cl::init(false));260 CGBINDOPT(EnableNoTrappingFPMath);261 262 static const auto DenormFlagEnumOptions = cl::values(263 clEnumValN(DenormalMode::IEEE, "ieee", "IEEE 754 denormal numbers"),264 clEnumValN(DenormalMode::PreserveSign, "preserve-sign",265 "the sign of a flushed-to-zero number is preserved "266 "in the sign of 0"),267 clEnumValN(DenormalMode::PositiveZero, "positive-zero",268 "denormals are flushed to positive zero"),269 clEnumValN(DenormalMode::Dynamic, "dynamic",270 "denormals have unknown treatment"));271 272 // FIXME: Doesn't have way to specify separate input and output modes.273 static cl::opt<DenormalMode::DenormalModeKind> DenormalFPMath(274 "denormal-fp-math",275 cl::desc("Select which denormal numbers the code is permitted to require"),276 cl::init(DenormalMode::IEEE),277 DenormFlagEnumOptions);278 CGBINDOPT(DenormalFPMath);279 280 static cl::opt<DenormalMode::DenormalModeKind> DenormalFP32Math(281 "denormal-fp-math-f32",282 cl::desc("Select which denormal numbers the code is permitted to require for float"),283 cl::init(DenormalMode::Invalid),284 DenormFlagEnumOptions);285 CGBINDOPT(DenormalFP32Math);286 287 static cl::opt<bool> EnableHonorSignDependentRoundingFPMath(288 "enable-sign-dependent-rounding-fp-math", cl::Hidden,289 cl::desc("Force codegen to assume rounding mode can change dynamically"),290 cl::init(false));291 CGBINDOPT(EnableHonorSignDependentRoundingFPMath);292 293 static cl::opt<FloatABI::ABIType> FloatABIForCalls(294 "float-abi", cl::desc("Choose float ABI type"),295 cl::init(FloatABI::Default),296 cl::values(clEnumValN(FloatABI::Default, "default",297 "Target default float ABI type"),298 clEnumValN(FloatABI::Soft, "soft",299 "Soft float ABI (implied by -soft-float)"),300 clEnumValN(FloatABI::Hard, "hard",301 "Hard float ABI (uses FP registers)")));302 CGBINDOPT(FloatABIForCalls);303 304 static cl::opt<FPOpFusion::FPOpFusionMode> FuseFPOps(305 "fp-contract", cl::desc("Enable aggressive formation of fused FP ops"),306 cl::init(FPOpFusion::Standard),307 cl::values(308 clEnumValN(FPOpFusion::Fast, "fast",309 "Fuse FP ops whenever profitable"),310 clEnumValN(FPOpFusion::Standard, "on", "Only fuse 'blessed' FP ops."),311 clEnumValN(FPOpFusion::Strict, "off",312 "Only fuse FP ops when the result won't be affected.")));313 CGBINDOPT(FuseFPOps);314 315 static cl::opt<SwiftAsyncFramePointerMode> SwiftAsyncFramePointer(316 "swift-async-fp",317 cl::desc("Determine when the Swift async frame pointer should be set"),318 cl::init(SwiftAsyncFramePointerMode::Always),319 cl::values(clEnumValN(SwiftAsyncFramePointerMode::DeploymentBased, "auto",320 "Determine based on deployment target"),321 clEnumValN(SwiftAsyncFramePointerMode::Always, "always",322 "Always set the bit"),323 clEnumValN(SwiftAsyncFramePointerMode::Never, "never",324 "Never set the bit")));325 CGBINDOPT(SwiftAsyncFramePointer);326 327 static cl::opt<bool> DontPlaceZerosInBSS(328 "nozero-initialized-in-bss",329 cl::desc("Don't place zero-initialized symbols into bss section"),330 cl::init(false));331 CGBINDOPT(DontPlaceZerosInBSS);332 333 static cl::opt<bool> EnableAIXExtendedAltivecABI(334 "vec-extabi", cl::desc("Enable the AIX Extended Altivec ABI."),335 cl::init(false));336 CGBINDOPT(EnableAIXExtendedAltivecABI);337 338 static cl::opt<bool> EnableGuaranteedTailCallOpt(339 "tailcallopt",340 cl::desc(341 "Turn fastcc calls into tail calls by (potentially) changing ABI."),342 cl::init(false));343 CGBINDOPT(EnableGuaranteedTailCallOpt);344 345 static cl::opt<bool> DisableTailCalls(346 "disable-tail-calls", cl::desc("Never emit tail calls"), cl::init(false));347 CGBINDOPT(DisableTailCalls);348 349 static cl::opt<bool> StackSymbolOrdering(350 "stack-symbol-ordering", cl::desc("Order local stack symbols."),351 cl::init(true));352 CGBINDOPT(StackSymbolOrdering);353 354 static cl::opt<bool> StackRealign(355 "stackrealign",356 cl::desc("Force align the stack to the minimum alignment"),357 cl::init(false));358 CGBINDOPT(StackRealign);359 360 static cl::opt<std::string> TrapFuncName(361 "trap-func", cl::Hidden,362 cl::desc("Emit a call to trap function rather than a trap instruction"),363 cl::init(""));364 CGBINDOPT(TrapFuncName);365 366 static cl::opt<bool> UseCtors("use-ctors",367 cl::desc("Use .ctors instead of .init_array."),368 cl::init(false));369 CGBINDOPT(UseCtors);370 371 static cl::opt<bool> DataSections(372 "data-sections", cl::desc("Emit data into separate sections"),373 cl::init(false));374 CGBINDOPT(DataSections);375 376 static cl::opt<bool> FunctionSections(377 "function-sections", cl::desc("Emit functions into separate sections"),378 cl::init(false));379 CGBINDOPT(FunctionSections);380 381 static cl::opt<bool> IgnoreXCOFFVisibility(382 "ignore-xcoff-visibility",383 cl::desc("Not emit the visibility attribute for asm in AIX OS or give "384 "all symbols 'unspecified' visibility in XCOFF object file"),385 cl::init(false));386 CGBINDOPT(IgnoreXCOFFVisibility);387 388 static cl::opt<bool> XCOFFTracebackTable(389 "xcoff-traceback-table", cl::desc("Emit the XCOFF traceback table"),390 cl::init(true));391 CGBINDOPT(XCOFFTracebackTable);392 393 static cl::opt<bool> EnableBBAddrMap(394 "basic-block-address-map",395 cl::desc("Emit the basic block address map section"), cl::init(false));396 CGBINDOPT(EnableBBAddrMap);397 398 static cl::opt<std::string> BBSections(399 "basic-block-sections",400 cl::desc("Emit basic blocks into separate sections"),401 cl::value_desc("all | <function list (file)> | labels | none"),402 cl::init("none"));403 CGBINDOPT(BBSections);404 405 static cl::opt<unsigned> TLSSize(406 "tls-size", cl::desc("Bit size of immediate TLS offsets"), cl::init(0));407 CGBINDOPT(TLSSize);408 409 static cl::opt<bool> EmulatedTLS(410 "emulated-tls", cl::desc("Use emulated TLS model"), cl::init(false));411 CGBINDOPT(EmulatedTLS);412 413 static cl::opt<bool> EnableTLSDESC(414 "enable-tlsdesc", cl::desc("Enable the use of TLS Descriptors"),415 cl::init(false));416 CGBINDOPT(EnableTLSDESC);417 418 static cl::opt<bool> UniqueSectionNames(419 "unique-section-names", cl::desc("Give unique names to every section"),420 cl::init(true));421 CGBINDOPT(UniqueSectionNames);422 423 static cl::opt<bool> UniqueBasicBlockSectionNames(424 "unique-basic-block-section-names",425 cl::desc("Give unique names to every basic block section"),426 cl::init(false));427 CGBINDOPT(UniqueBasicBlockSectionNames);428 429 static cl::opt<bool> SeparateNamedSections(430 "separate-named-sections",431 cl::desc("Use separate unique sections for named sections"),432 cl::init(false));433 CGBINDOPT(SeparateNamedSections);434 435 static cl::opt<EABI> EABIVersion(436 "meabi", cl::desc("Set EABI type (default depends on triple):"),437 cl::init(EABI::Default),438 cl::values(439 clEnumValN(EABI::Default, "default", "Triple default EABI version"),440 clEnumValN(EABI::EABI4, "4", "EABI version 4"),441 clEnumValN(EABI::EABI5, "5", "EABI version 5"),442 clEnumValN(EABI::GNU, "gnu", "EABI GNU")));443 CGBINDOPT(EABIVersion);444 445 static cl::opt<DebuggerKind> DebuggerTuningOpt(446 "debugger-tune", cl::desc("Tune debug info for a particular debugger"),447 cl::init(DebuggerKind::Default),448 cl::values(449 clEnumValN(DebuggerKind::GDB, "gdb", "gdb"),450 clEnumValN(DebuggerKind::LLDB, "lldb", "lldb"),451 clEnumValN(DebuggerKind::DBX, "dbx", "dbx"),452 clEnumValN(DebuggerKind::SCE, "sce", "SCE targets (e.g. PS4)")));453 CGBINDOPT(DebuggerTuningOpt);454 455 static cl::opt<VectorLibrary> VectorLibrary(456 "vector-library", cl::Hidden, cl::desc("Vector functions library"),457 cl::init(VectorLibrary::NoLibrary),458 cl::values(459 clEnumValN(VectorLibrary::NoLibrary, "none",460 "No vector functions library"),461 clEnumValN(VectorLibrary::Accelerate, "Accelerate",462 "Accelerate framework"),463 clEnumValN(VectorLibrary::DarwinLibSystemM, "Darwin_libsystem_m",464 "Darwin libsystem_m"),465 clEnumValN(VectorLibrary::LIBMVEC, "LIBMVEC",466 "GLIBC Vector Math library"),467 clEnumValN(VectorLibrary::MASSV, "MASSV", "IBM MASS vector library"),468 clEnumValN(VectorLibrary::SVML, "SVML", "Intel SVML library"),469 clEnumValN(VectorLibrary::SLEEFGNUABI, "sleefgnuabi",470 "SIMD Library for Evaluating Elementary Functions"),471 clEnumValN(VectorLibrary::ArmPL, "ArmPL",472 "Arm Performance Libraries"),473 clEnumValN(VectorLibrary::AMDLIBM, "AMDLIBM",474 "AMD vector math library")));475 CGBINDOPT(VectorLibrary);476 477 static cl::opt<bool> EnableStackSizeSection(478 "stack-size-section",479 cl::desc("Emit a section containing stack size metadata"),480 cl::init(false));481 CGBINDOPT(EnableStackSizeSection);482 483 static cl::opt<bool> EnableAddrsig(484 "addrsig", cl::desc("Emit an address-significance table"),485 cl::init(false));486 CGBINDOPT(EnableAddrsig);487 488 static cl::opt<bool> EnableCallGraphSection(489 "call-graph-section", cl::desc("Emit a call graph section"),490 cl::init(false));491 CGBINDOPT(EnableCallGraphSection);492 493 static cl::opt<bool> EmitCallSiteInfo(494 "emit-call-site-info",495 cl::desc(496 "Emit call site debug information, if debug information is enabled."),497 cl::init(false));498 CGBINDOPT(EmitCallSiteInfo);499 500 static cl::opt<bool> EnableDebugEntryValues(501 "debug-entry-values",502 cl::desc("Enable debug info for the debug entry values."),503 cl::init(false));504 CGBINDOPT(EnableDebugEntryValues);505 506 static cl::opt<bool> EnableMachineFunctionSplitter(507 "split-machine-functions",508 cl::desc("Split out cold basic blocks from machine functions based on "509 "profile information"),510 cl::init(false));511 CGBINDOPT(EnableMachineFunctionSplitter);512 513 static cl::opt<bool> EnableStaticDataPartitioning(514 "partition-static-data-sections",515 cl::desc("Partition data sections using profile information."),516 cl::init(false));517 CGBINDOPT(EnableStaticDataPartitioning);518 519 static cl::opt<bool> ForceDwarfFrameSection(520 "force-dwarf-frame-section",521 cl::desc("Always emit a debug frame section."), cl::init(false));522 CGBINDOPT(ForceDwarfFrameSection);523 524 static cl::opt<bool> XRayFunctionIndex("xray-function-index",525 cl::desc("Emit xray_fn_idx section"),526 cl::init(true));527 CGBINDOPT(XRayFunctionIndex);528 529 static cl::opt<bool> DebugStrictDwarf(530 "strict-dwarf", cl::desc("use strict dwarf"), cl::init(false));531 CGBINDOPT(DebugStrictDwarf);532 533 static cl::opt<unsigned> AlignLoops("align-loops",534 cl::desc("Default alignment for loops"));535 CGBINDOPT(AlignLoops);536 537 static cl::opt<bool> JMCInstrument(538 "enable-jmc-instrument",539 cl::desc("Instrument functions with a call to __CheckForDebuggerJustMyCode"),540 cl::init(false));541 CGBINDOPT(JMCInstrument);542 543 static cl::opt<bool> XCOFFReadOnlyPointers(544 "mxcoff-roptr",545 cl::desc("When set to true, const objects with relocatable address "546 "values are put into the RO data section."),547 cl::init(false));548 CGBINDOPT(XCOFFReadOnlyPointers);549 550 static cl::opt<bool> DisableIntegratedAS(551 "no-integrated-as", cl::desc("Disable integrated assembler"),552 cl::init(false));553 CGBINDOPT(DisableIntegratedAS);554 555 mc::RegisterMCTargetOptionsFlags();556}557 558codegen::RegisterSaveStatsFlag::RegisterSaveStatsFlag() {559 static cl::opt<SaveStatsMode> SaveStats(560 "save-stats",561 cl::desc(562 "Save LLVM statistics to a file in the current directory"563 "(`-save-stats`/`-save-stats=cwd`) or the directory of the output"564 "file (`-save-stats=obj`). (default: cwd)"),565 cl::values(clEnumValN(SaveStatsMode::Cwd, "cwd",566 "Save to the current working directory"),567 clEnumValN(SaveStatsMode::Cwd, "", ""),568 clEnumValN(SaveStatsMode::Obj, "obj",569 "Save to the output file directory")),570 cl::init(SaveStatsMode::None), cl::ValueOptional);571 CGBINDOPT(SaveStats);572}573 574llvm::BasicBlockSection575codegen::getBBSectionsMode(llvm::TargetOptions &Options) {576 if (getBBSections() == "all")577 return BasicBlockSection::All;578 else if (getBBSections() == "none")579 return BasicBlockSection::None;580 else {581 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =582 MemoryBuffer::getFile(getBBSections());583 if (!MBOrErr) {584 errs() << "Error loading basic block sections function list file: "585 << MBOrErr.getError().message() << "\n";586 } else {587 Options.BBSectionsFuncListBuf = std::move(*MBOrErr);588 }589 return BasicBlockSection::List;590 }591}592 593// Common utility function tightly tied to the options listed here. Initializes594// a TargetOptions object with CodeGen flags and returns it.595TargetOptions596codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {597 TargetOptions Options;598 Options.AllowFPOpFusion = getFuseFPOps();599 Options.NoInfsFPMath = getEnableNoInfsFPMath();600 Options.NoNaNsFPMath = getEnableNoNaNsFPMath();601 Options.NoSignedZerosFPMath = getEnableNoSignedZerosFPMath();602 Options.NoTrappingFPMath = getEnableNoTrappingFPMath();603 604 DenormalMode::DenormalModeKind DenormKind = getDenormalFPMath();605 606 // FIXME: Should have separate input and output flags607 Options.setFPDenormalMode(DenormalMode(DenormKind, DenormKind));608 609 Options.HonorSignDependentRoundingFPMathOption =610 getEnableHonorSignDependentRoundingFPMath();611 if (getFloatABIForCalls() != FloatABI::Default)612 Options.FloatABIType = getFloatABIForCalls();613 Options.EnableAIXExtendedAltivecABI = getEnableAIXExtendedAltivecABI();614 Options.NoZerosInBSS = getDontPlaceZerosInBSS();615 Options.GuaranteedTailCallOpt = getEnableGuaranteedTailCallOpt();616 Options.StackSymbolOrdering = getStackSymbolOrdering();617 Options.UseInitArray = !getUseCtors();618 Options.DisableIntegratedAS = getDisableIntegratedAS();619 Options.DataSections =620 getExplicitDataSections().value_or(TheTriple.hasDefaultDataSections());621 Options.FunctionSections = getFunctionSections();622 Options.IgnoreXCOFFVisibility = getIgnoreXCOFFVisibility();623 Options.XCOFFTracebackTable = getXCOFFTracebackTable();624 Options.BBAddrMap = getEnableBBAddrMap();625 Options.BBSections = getBBSectionsMode(Options);626 Options.UniqueSectionNames = getUniqueSectionNames();627 Options.UniqueBasicBlockSectionNames = getUniqueBasicBlockSectionNames();628 Options.SeparateNamedSections = getSeparateNamedSections();629 Options.TLSSize = getTLSSize();630 Options.EmulatedTLS =631 getExplicitEmulatedTLS().value_or(TheTriple.hasDefaultEmulatedTLS());632 Options.EnableTLSDESC =633 getExplicitEnableTLSDESC().value_or(TheTriple.hasDefaultTLSDESC());634 Options.ExceptionModel = getExceptionModel();635 Options.VecLib = getVectorLibrary();636 Options.EmitStackSizeSection = getEnableStackSizeSection();637 Options.EnableMachineFunctionSplitter = getEnableMachineFunctionSplitter();638 Options.EnableStaticDataPartitioning = getEnableStaticDataPartitioning();639 Options.EmitAddrsig = getEnableAddrsig();640 Options.EmitCallGraphSection = getEnableCallGraphSection();641 Options.EmitCallSiteInfo = getEmitCallSiteInfo();642 Options.EnableDebugEntryValues = getEnableDebugEntryValues();643 Options.ForceDwarfFrameSection = getForceDwarfFrameSection();644 Options.XRayFunctionIndex = getXRayFunctionIndex();645 Options.DebugStrictDwarf = getDebugStrictDwarf();646 Options.LoopAlignment = getAlignLoops();647 Options.JMCInstrument = getJMCInstrument();648 Options.XCOFFReadOnlyPointers = getXCOFFReadOnlyPointers();649 650 Options.MCOptions = mc::InitMCTargetOptionsFromFlags();651 652 Options.ThreadModel = getThreadModel();653 Options.EABIVersion = getEABIVersion();654 Options.DebuggerTuning = getDebuggerTuningOpt();655 Options.SwiftAsyncFramePointer = getSwiftAsyncFramePointer();656 return Options;657}658 659std::string codegen::getCPUStr() {660 // If user asked for the 'native' CPU, autodetect here. If autodection fails,661 // this will set the CPU to an empty string which tells the target to662 // pick a basic default.663 if (getMCPU() == "native")664 return std::string(sys::getHostCPUName());665 666 return getMCPU();667}668 669std::string codegen::getFeaturesStr() {670 SubtargetFeatures Features;671 672 // If user asked for the 'native' CPU, we need to autodetect features.673 // This is necessary for x86 where the CPU might not support all the674 // features the autodetected CPU name lists in the target. For example,675 // not all Sandybridge processors support AVX.676 if (getMCPU() == "native")677 for (const auto &[Feature, IsEnabled] : sys::getHostCPUFeatures())678 Features.AddFeature(Feature, IsEnabled);679 680 for (auto const &MAttr : getMAttrs())681 Features.AddFeature(MAttr);682 683 return Features.getString();684}685 686std::vector<std::string> codegen::getFeatureList() {687 SubtargetFeatures Features;688 689 // If user asked for the 'native' CPU, we need to autodetect features.690 // This is necessary for x86 where the CPU might not support all the691 // features the autodetected CPU name lists in the target. For example,692 // not all Sandybridge processors support AVX.693 if (getMCPU() == "native")694 for (const auto &[Feature, IsEnabled] : sys::getHostCPUFeatures())695 Features.AddFeature(Feature, IsEnabled);696 697 for (auto const &MAttr : getMAttrs())698 Features.AddFeature(MAttr);699 700 return Features.getFeatures();701}702 703void codegen::renderBoolStringAttr(AttrBuilder &B, StringRef Name, bool Val) {704 B.addAttribute(Name, Val ? "true" : "false");705}706 707#define HANDLE_BOOL_ATTR(CL, AttrName) \708 do { \709 if (CL->getNumOccurrences() > 0 && !F.hasFnAttribute(AttrName)) \710 renderBoolStringAttr(NewAttrs, AttrName, *CL); \711 } while (0)712 713/// Set function attributes of function \p F based on CPU, Features, and command714/// line flags.715void codegen::setFunctionAttributes(StringRef CPU, StringRef Features,716 Function &F) {717 auto &Ctx = F.getContext();718 AttributeList Attrs = F.getAttributes();719 AttrBuilder NewAttrs(Ctx);720 721 if (!CPU.empty() && !F.hasFnAttribute("target-cpu"))722 NewAttrs.addAttribute("target-cpu", CPU);723 if (!Features.empty()) {724 // Append the command line features to any that are already on the function.725 StringRef OldFeatures =726 F.getFnAttribute("target-features").getValueAsString();727 if (OldFeatures.empty())728 NewAttrs.addAttribute("target-features", Features);729 else {730 SmallString<256> Appended(OldFeatures);731 Appended.push_back(',');732 Appended.append(Features);733 NewAttrs.addAttribute("target-features", Appended);734 }735 }736 if (FramePointerUsageView->getNumOccurrences() > 0 &&737 !F.hasFnAttribute("frame-pointer")) {738 if (getFramePointerUsage() == FramePointerKind::All)739 NewAttrs.addAttribute("frame-pointer", "all");740 else if (getFramePointerUsage() == FramePointerKind::NonLeaf)741 NewAttrs.addAttribute("frame-pointer", "non-leaf");742 else if (getFramePointerUsage() == FramePointerKind::NonLeafNoReserve)743 NewAttrs.addAttribute("frame-pointer", "non-leaf-no-reserve");744 else if (getFramePointerUsage() == FramePointerKind::Reserved)745 NewAttrs.addAttribute("frame-pointer", "reserved");746 else if (getFramePointerUsage() == FramePointerKind::None)747 NewAttrs.addAttribute("frame-pointer", "none");748 }749 if (DisableTailCallsView->getNumOccurrences() > 0)750 NewAttrs.addAttribute("disable-tail-calls",751 toStringRef(getDisableTailCalls()));752 if (getStackRealign())753 NewAttrs.addAttribute("stackrealign");754 755 HANDLE_BOOL_ATTR(EnableNoInfsFPMathView, "no-infs-fp-math");756 HANDLE_BOOL_ATTR(EnableNoNaNsFPMathView, "no-nans-fp-math");757 HANDLE_BOOL_ATTR(EnableNoSignedZerosFPMathView, "no-signed-zeros-fp-math");758 759 if (DenormalFPMathView->getNumOccurrences() > 0 &&760 !F.hasFnAttribute("denormal-fp-math")) {761 DenormalMode::DenormalModeKind DenormKind = getDenormalFPMath();762 763 // FIXME: Command line flag should expose separate input/output modes.764 NewAttrs.addAttribute("denormal-fp-math",765 DenormalMode(DenormKind, DenormKind).str());766 }767 768 if (DenormalFP32MathView->getNumOccurrences() > 0 &&769 !F.hasFnAttribute("denormal-fp-math-f32")) {770 // FIXME: Command line flag should expose separate input/output modes.771 DenormalMode::DenormalModeKind DenormKind = getDenormalFP32Math();772 773 NewAttrs.addAttribute(774 "denormal-fp-math-f32",775 DenormalMode(DenormKind, DenormKind).str());776 }777 778 if (TrapFuncNameView->getNumOccurrences() > 0)779 for (auto &B : F)780 for (auto &I : B)781 if (auto *Call = dyn_cast<CallInst>(&I))782 if (const auto *F = Call->getCalledFunction())783 if (F->getIntrinsicID() == Intrinsic::debugtrap ||784 F->getIntrinsicID() == Intrinsic::trap)785 Call->addFnAttr(786 Attribute::get(Ctx, "trap-func-name", getTrapFuncName()));787 788 // Let NewAttrs override Attrs.789 F.setAttributes(Attrs.addFnAttributes(Ctx, NewAttrs));790}791 792/// Set function attributes of functions in Module M based on CPU,793/// Features, and command line flags.794void codegen::setFunctionAttributes(StringRef CPU, StringRef Features,795 Module &M) {796 for (Function &F : M)797 setFunctionAttributes(CPU, Features, F);798}799 800Expected<std::unique_ptr<TargetMachine>>801codegen::createTargetMachineForTriple(StringRef TargetTriple,802 CodeGenOptLevel OptLevel) {803 Triple TheTriple(TargetTriple);804 std::string Error;805 const auto *TheTarget =806 TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);807 if (!TheTarget)808 return createStringError(inconvertibleErrorCode(), Error);809 auto *Target = TheTarget->createTargetMachine(810 TheTriple, codegen::getCPUStr(), codegen::getFeaturesStr(),811 codegen::InitTargetOptionsFromCodeGenFlags(TheTriple),812 codegen::getExplicitRelocModel(), codegen::getExplicitCodeModel(),813 OptLevel);814 if (!Target)815 return createStringError(inconvertibleErrorCode(),816 Twine("could not allocate target machine for ") +817 TargetTriple);818 return std::unique_ptr<TargetMachine>(Target);819}820 821void codegen::MaybeEnableStatistics() {822 if (getSaveStats() == SaveStatsMode::None)823 return;824 825 llvm::EnableStatistics(false);826}827 828int codegen::MaybeSaveStatistics(StringRef OutputFilename, StringRef ToolName) {829 auto SaveStatsValue = getSaveStats();830 if (SaveStatsValue == codegen::SaveStatsMode::None)831 return 0;832 833 SmallString<128> StatsFilename;834 if (SaveStatsValue == codegen::SaveStatsMode::Obj) {835 StatsFilename = OutputFilename;836 llvm::sys::path::remove_filename(StatsFilename);837 } else {838 assert(SaveStatsValue == codegen::SaveStatsMode::Cwd &&839 "Should have been a valid --save-stats value");840 }841 842 auto BaseName = llvm::sys::path::filename(OutputFilename);843 llvm::sys::path::append(StatsFilename, BaseName);844 llvm::sys::path::replace_extension(StatsFilename, "stats");845 846 auto FileFlags = llvm::sys::fs::OF_TextWithCRLF;847 std::error_code EC;848 auto StatsOS =849 std::make_unique<llvm::raw_fd_ostream>(StatsFilename, EC, FileFlags);850 if (EC) {851 WithColor::error(errs(), ToolName)852 << "Unable to open statistics file: " << EC.message() << "\n";853 return 1;854 }855 856 llvm::PrintStatisticsJSON(*StatsOS);857 return 0;858}859