Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceClFlags.cpp - Command line flags and parsing --------===// | 1 //===- subzero/src/IceClFlags.cpp - Command line flags and parsing --------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| 11 /// \brief Defines commandline flags parsing of class Ice::ClFlags. | 11 /// \brief Defines commandline flags parsing of class Ice::ClFlags. |
| 12 /// | 12 /// |
| 13 /// This currently relies on llvm::cl to parse. In the future, the minimal build | 13 /// This currently relies on llvm::cl to parse. In the future, the minimal build |
| 14 /// can have a simpler parser. | 14 /// can have a simpler parser. |
| 15 /// | 15 /// |
| 16 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// |
| 17 | 17 |
| 18 #include "IceClFlags.h" | 18 #include "IceClFlags.h" |
| 19 | 19 |
| 20 #include "IceClFlagsExtra.h" | 20 #include "IceClFlags.def" |
| 21 | 21 |
| 22 #ifdef __clang__ | 22 #ifdef __clang__ |
| 23 #pragma clang diagnostic push | 23 #pragma clang diagnostic push |
| 24 #pragma clang diagnostic ignored "-Wunused-parameter" | 24 #pragma clang diagnostic ignored "-Wunused-parameter" |
| 25 #endif // __clang__ | 25 #endif // __clang__ |
| 26 | 26 |
| 27 #include "llvm/Support/CommandLine.h" | 27 #include "llvm/Support/CommandLine.h" |
| 28 | 28 |
| 29 #ifdef __clang__ | 29 #ifdef __clang__ |
| 30 #pragma clang diagnostic pop | 30 #pragma clang diagnostic pop |
| 31 #endif // __clang__ | 31 #endif // __clang__ |
| 32 | 32 |
| 33 namespace cl = llvm::cl; | 33 #include <utility> |
| 34 | 34 #include <iostream> |
|
Jim Stichnoth
2016/03/21 15:44:47
alphabetize includes
Also, any issues with http:/
John
2016/03/21 17:06:36
apart from the fact that the llvm coding style is
| |
| 35 /// Options which are captured in Ice::ClFlags and propagated. | |
| 36 | 35 |
| 37 namespace { | 36 namespace { |
| 37 // cl is used to alias the llvm::cl types and functions that we need. | |
| 38 namespace cl { | |
| 38 | 39 |
| 39 /// Allow error recovery when reading PNaCl bitcode. | 40 using alias = llvm::cl::alias; |
| 40 cl::opt<bool> AllowErrorRecovery( | |
| 41 "allow-pnacl-reader-error-recovery", | |
| 42 cl::desc("Allow error recovery when reading PNaCl bitcode."), | |
| 43 cl::init(false)); | |
| 44 | 41 |
| 45 /// Allow global symbols to be externally defined (other than _start and | 42 using aliasopt = llvm::cl::aliasopt; |
| 46 /// __pnacl_pso_root). | |
| 47 cl::opt<bool> AllowExternDefinedSymbols( | |
| 48 "allow-externally-defined-symbols", | |
| 49 cl::desc("Allow global symbols to be externally defined (other than _start " | |
| 50 "and __pnacl_pso_root)."), | |
| 51 cl::init(false)); | |
| 52 | 43 |
| 53 /// Alias for --allow-externally-defined-symbols. | 44 using llvm::cl::CommaSeparated; |
| 45 | |
| 46 using desc = llvm::cl::desc; | |
| 47 | |
| 48 template <typename T> using initializer = llvm::cl::initializer<T>; | |
| 49 | |
| 50 template <typename T> initializer<T> init(const T &Val) { | |
| 51 return initializer<T>(Val); | |
| 52 } | |
| 53 | |
| 54 template <typename T> using list = llvm::cl::list<T>; | |
| 55 | |
| 56 using llvm::cl::NotHidden; | |
| 57 | |
| 58 template <typename T> using opt = llvm::cl::opt<T>; | |
| 59 | |
| 60 using llvm::cl::ParseCommandLineOptions; | |
| 61 | |
| 62 using llvm::cl::Positional; | |
| 63 | |
| 64 template <typename T> using ValuesClass = llvm::cl::ValuesClass<T>; | |
| 65 | |
| 66 template <typename T, typename... A> | |
| 67 ValuesClass<T> values(const char *Arg, T Val, const char *Desc, A &&... Args) { | |
| 68 return llvm::cl::values(Arg, Val, Desc, std::forward<A>(Args)..., nullptr); | |
| 69 } | |
| 70 | |
| 71 using llvm::cl::value_desc; | |
| 72 } // end of namespace cl | |
| 73 | |
| 74 // cl_type_traits is used to convert between a tuple of <T, cl_detail::*flag> to | |
| 75 // the appropriate (llvm::)cl object. | |
| 76 template <typename B, typename CL> struct cl_type_traits {}; | |
| 77 | |
| 78 template <typename T> | |
| 79 struct cl_type_traits<T, ::Ice::cl_detail::dev_list_flag> { | |
| 80 using cl_type = cl::list<T>; | |
| 81 }; | |
| 82 | |
| 83 template <typename T> struct cl_type_traits<T, ::Ice::cl_detail::dev_opt_flag> { | |
| 84 using cl_type = cl::opt<T>; | |
| 85 }; | |
| 86 | |
| 87 template <typename T> | |
| 88 struct cl_type_traits<T, ::Ice::cl_detail::release_opt_flag> { | |
| 89 using cl_type = cl::opt<T>; | |
| 90 }; | |
| 91 | |
| 92 #define X(Name, Type, ClType, ...) \ | |
| 93 cl_type_traits<Type, Ice::cl_detail::ClType>::cl_type Name##Obj(__VA_ARGS__); | |
| 94 COMMAND_LINE_FLAGS | |
| 95 #undef X | |
| 96 | |
| 97 // Add declarations that do not need to add members to ClFlags below. | |
| 54 cl::alias AllowExternDefinedSymbolsA( | 98 cl::alias AllowExternDefinedSymbolsA( |
| 55 "allow-extern", cl::desc("Alias for --allow-externally-defined-symbols"), | 99 "allow-extern", cl::desc("Alias for --allow-externally-defined-symbols"), |
| 56 cl::NotHidden, cl::aliasopt(AllowExternDefinedSymbols)); | 100 cl::NotHidden, cl::aliasopt(AllowExternDefinedSymbolsObj)); |
| 57 | 101 |
| 58 /// Allow IACA (Intel Architecture Code Analyzer) marks to be inserted. These | 102 std::string AppNameObj; |
| 59 /// binaries are not executable. | |
| 60 cl::opt<bool> AllowIacaMarks( | |
| 61 "allow-iaca-marks", | |
| 62 cl::desc("Allow IACA (Intel Architecture Code Analyzer) marks to be " | |
| 63 "inserted. These binaries are not executable."), | |
| 64 cl::init(false)); | |
| 65 | 103 |
| 66 /// Allow global variables to be uninitialized. This is currently needed by the | |
| 67 /// cross tests. | |
| 68 cl::opt<bool> AllowUninitializedGlobals( | |
| 69 "allow-uninitialized-globals", | |
| 70 cl::desc("Allow global variables to be uninitialized")); | |
| 71 | |
| 72 /// Emit (global) data into separate sections. | |
| 73 cl::opt<bool> | |
| 74 DataSections("fdata-sections", | |
| 75 cl::desc("Emit (global) data into separate sections")); | |
| 76 | |
| 77 /// Decorate textual asm output with register liveness info. | |
| 78 cl::opt<bool> DecorateAsm( | |
| 79 "asm-verbose", | |
| 80 cl::desc("Decorate textual asm output with register liveness info")); | |
| 81 | |
| 82 /// Define default function prefix for naming unnamed functions. | |
| 83 cl::opt<std::string> | |
| 84 DefaultFunctionPrefix("default-function-prefix", | |
| 85 cl::desc("Define default function prefix for naming " | |
| 86 "unnamed functions"), | |
| 87 cl::init(Ice::BuildDefs::dump() ? "Function" : "F")); | |
| 88 | |
| 89 /// Define default global prefix for naming unnamed globals. | |
| 90 cl::opt<std::string> | |
| 91 DefaultGlobalPrefix("default-global-prefix", | |
| 92 cl::desc("Define default global prefix for naming " | |
| 93 "unnamed globals"), | |
| 94 cl::init(Ice::BuildDefs::dump() ? "Global" : "G")); | |
| 95 | |
| 96 /// Disable hybrid assembly when -filetype=iasm. | |
| 97 cl::opt<bool> DisableHybridAssembly( | |
| 98 "no-hybrid-asm", cl::desc("Disable hybrid assembly when -filetype=iasm"), | |
| 99 cl::init(false)); | |
| 100 | |
| 101 /// Externalize all symbols. | |
| 102 cl::opt<bool> DisableInternal("externalize", | |
| 103 cl::desc("Externalize all symbols")); | |
| 104 | |
| 105 /// Disable Subzero translation. | |
| 106 cl::opt<bool> DisableTranslation("notranslate", | |
| 107 cl::desc("Disable Subzero translation")); | |
| 108 | |
| 109 /// Print statistics after translating each function. | |
| 110 cl::opt<bool> | |
| 111 DumpStats("szstats", | |
| 112 cl::desc("Print statistics after translating each function")); | |
| 113 | |
| 114 // TODO(stichnot): The implementation of block profiling introduces some | |
| 115 // oddities to be aware of. First, empty basic blocks that don't normally | |
| 116 // appear in the asm output, may be profiled anyway, so one might see profile | |
| 117 // counts for blocks not in the original asm output. Second, edge-split nodes | |
| 118 // for advanced phi lowering are added too late, at which point it is not | |
| 119 // practical to add profiling. | |
| 120 | |
| 121 /// Instrument basic blocks, and output profiling information to stdout at the | |
| 122 /// end of program execution. | |
| 123 cl::opt<bool> EnableBlockProfile( | |
| 124 "enable-block-profile", | |
| 125 cl::desc("Instrument basic blocks, and output profiling " | |
| 126 "information to stdout at the end of program execution."), | |
| 127 cl::init(false)); | |
| 128 | |
| 129 /// Force optimization of memory intrinsics. | |
| 130 cl::opt<bool> | |
| 131 ForceMemIntrinOpt("fmem-intrin-opt", | |
| 132 cl::desc("Force optimization of memory intrinsics.")); | |
| 133 | |
| 134 /// Emit functions into separate sections. | |
| 135 cl::opt<bool> | |
| 136 FunctionSections("ffunction-sections", | |
| 137 cl::desc("Emit functions into separate sections")); | |
| 138 | |
| 139 /// Retain deleted instructions in the Cfg. Defaults to true in DUMP-enabled | |
| 140 /// build, and false in a non-DUMP build, but is ignored in a MINIMAL build. | |
| 141 /// This flag allows overriding the default primarily for debugging. | |
| 142 cl::opt<bool> | |
| 143 KeepDeletedInsts("keep-deleted-insts", | |
| 144 cl::desc("Retain deleted instructions in the Cfg"), | |
| 145 cl::init(Ice::BuildDefs::dump())); | |
| 146 | |
| 147 /// Mock bounds checking on loads/stores. | |
| 148 cl::opt<bool> MockBoundsCheck("mock-bounds-check", | |
| 149 cl::desc("Mock bounds checking on loads/stores")); | |
| 150 | |
| 151 /// Number of translation threads (in addition to the parser thread and the | |
| 152 /// emitter thread). The special case of 0 means purely sequential, i.e. parser, | |
| 153 /// translator, and emitter all within the same single thread. (This may need a | |
| 154 /// slight rework if we expand to multiple parser or emitter threads.) | |
| 155 cl::opt<uint32_t> NumThreads( | |
| 156 "threads", | |
| 157 cl::desc("Number of translation threads (0 for purely sequential)"), | |
| 158 // TODO(stichnot): Settle on a good default. Consider something related to | |
| 159 // std::thread::hardware_concurrency(). | |
| 160 cl::init(2)); | |
| 161 | |
| 162 /// Optimization level Om1, O-1, O0, O0, O1, O2. | |
| 163 cl::opt<Ice::OptLevel> OLevel(cl::desc("Optimization level"), | |
| 164 cl::init(Ice::Opt_m1), cl::value_desc("level"), | |
| 165 cl::values(clEnumValN(Ice::Opt_m1, "Om1", "-1"), | |
| 166 clEnumValN(Ice::Opt_m1, "O-1", "-1"), | |
| 167 clEnumValN(Ice::Opt_0, "O0", "0"), | |
| 168 clEnumValN(Ice::Opt_1, "O1", "1"), | |
| 169 clEnumValN(Ice::Opt_2, "O2", "2"), | |
| 170 clEnumValEnd)); | |
| 171 | |
| 172 /// Enable edge splitting for Phi lowering. | |
| 173 cl::opt<bool> | |
| 174 EnablePhiEdgeSplit("phi-edge-split", | |
| 175 cl::desc("Enable edge splitting for Phi lowering"), | |
| 176 cl::init(true)); | |
| 177 | |
| 178 /// TODO(stichnot): See if we can easily use LLVM's -rng-seed option and | |
| 179 /// implementation. I expect the implementation is different and therefore the | |
| 180 /// tests would need to be changed. | |
| 181 cl::opt<unsigned long long> | |
| 182 RandomSeed("sz-seed", cl::desc("Seed the random number generator"), | |
| 183 cl::init(1)); | |
| 184 | |
| 185 /// Randomly insert NOPs. | |
| 186 cl::opt<bool> ShouldDoNopInsertion("nop-insertion", | |
| 187 cl::desc("Randomly insert NOPs"), | |
| 188 cl::init(false)); | |
| 189 | |
| 190 /// Randomize register allocation. | |
| 191 cl::opt<bool> | |
| 192 RandomizeRegisterAllocation("randomize-regalloc", | |
| 193 cl::desc("Randomize register allocation"), | |
| 194 cl::init(false)); | |
| 195 | |
| 196 /// Allow failsafe access to registers that were restricted via -reg-use or | |
| 197 /// -reg-exclude. | |
| 198 cl::opt<bool> | |
| 199 RegAllocReserve("reg-reserve", | |
| 200 cl::desc("Let register allocation use reserve registers"), | |
| 201 cl::init(false)); | |
| 202 | |
| 203 /// Repeat register allocation until convergence. | |
| 204 cl::opt<bool> | |
| 205 RepeatRegAlloc("regalloc-repeat", | |
| 206 cl::desc("Repeat register allocation until convergence"), | |
| 207 cl::init(true)); | |
| 208 | |
| 209 /// Skip through unimplemented lowering code instead of aborting. | |
| 210 cl::opt<bool> SkipUnimplemented( | |
| 211 "skip-unimplemented", | |
| 212 cl::desc("Skip through unimplemented lowering code instead of aborting."), | |
| 213 cl::init(false)); | |
| 214 | |
| 215 /// Enable breakdown timing of Subzero translation. | |
| 216 cl::opt<bool> SubzeroTimingEnabled( | |
| 217 "timing", cl::desc("Enable breakdown timing of Subzero translation")); | |
| 218 | |
| 219 /// Target architecture. | |
| 220 cl::opt<Ice::TargetArch> TargetArch( | |
| 221 "target", cl::desc("Target architecture:"), cl::init(Ice::Target_X8632), | |
| 222 cl::values( | |
| 223 clEnumValN(Ice::Target_X8632, "x8632", "x86-32"), | |
| 224 clEnumValN(Ice::Target_X8632, "x86-32", "x86-32 (same as x8632)"), | |
| 225 clEnumValN(Ice::Target_X8632, "x86_32", "x86-32 (same as x8632)"), | |
| 226 clEnumValN(Ice::Target_X8664, "x8664", "x86-64"), | |
| 227 clEnumValN(Ice::Target_X8664, "x86-64", "x86-64 (same as x8664)"), | |
| 228 clEnumValN(Ice::Target_X8664, "x86_64", "x86-64 (same as x8664)"), | |
| 229 clEnumValN(Ice::Target_ARM32, "arm", "arm32"), | |
| 230 clEnumValN(Ice::Target_ARM32, "arm32", "arm32 (same as arm)"), | |
| 231 clEnumValN(Ice::Target_ARM64, "arm64", "arm64"), | |
| 232 clEnumValN(Ice::Target_MIPS32, "mips", "mips32"), | |
| 233 clEnumValN(Ice::Target_MIPS32, "mips32", "mips32 (same as mips)"), | |
| 234 clEnumValEnd)); | |
| 235 | |
| 236 /// Extra amount of stack to add to the frame in bytes (for testing). | |
| 237 cl::opt<uint32_t> TestStackExtra( | |
| 238 "test-stack-extra", | |
| 239 cl::desc( | |
| 240 "Extra amount of stack to add to the frame in bytes (for testing)."), | |
| 241 cl::init(0)); | |
| 242 | |
| 243 /// Target architecture attributes. | |
| 244 cl::opt<Ice::TargetInstructionSet> TargetInstructionSet( | |
| 245 "mattr", cl::desc("Target architecture attributes"), | |
| 246 cl::init(Ice::BaseInstructionSet), | |
| 247 cl::values(clEnumValN(Ice::BaseInstructionSet, "base", | |
| 248 "Target chooses baseline instruction set (default)"), | |
| 249 clEnumValN(Ice::X86InstructionSet_SSE2, "sse2", | |
| 250 "Enable X86 SSE2 instructions"), | |
| 251 clEnumValN(Ice::X86InstructionSet_SSE4_1, "sse4.1", | |
| 252 "Enable X86 SSE 4.1 instructions"), | |
| 253 clEnumValN(Ice::ARM32InstructionSet_Neon, "neon", | |
| 254 "Enable ARM Neon instructions"), | |
| 255 clEnumValN(Ice::ARM32InstructionSet_HWDivArm, "hwdiv-arm", | |
| 256 "Enable ARM integer divide instructions in ARM mode"), | |
| 257 clEnumValEnd)); | |
| 258 | |
| 259 /// Prepend a prefix to symbol names for testing. | |
| 260 cl::opt<std::string> | |
| 261 TestPrefix("prefix", | |
| 262 cl::desc("Prepend a prefix to symbol names for testing"), | |
| 263 cl::init(""), cl::value_desc("prefix")); | |
| 264 | |
| 265 /// Print total translation time for each function. | |
| 266 cl::opt<bool> TimeEachFunction( | |
| 267 "timing-funcs", cl::desc("Print total translation time for each function")); | |
| 268 | |
| 269 /// Break down timing for a specific function (use '*' for all). | |
| 270 cl::opt<std::string> TimingFocusOn( | |
| 271 "timing-focus", | |
| 272 cl::desc("Break down timing for a specific function (use '*' for all)"), | |
| 273 cl::init("")); | |
| 274 | |
| 275 /// Translate only the given function. | |
| 276 cl::opt<std::string> | |
| 277 TranslateOnly("translate-only", | |
| 278 cl::desc("Translate only the given function"), cl::init("")); | |
| 279 | |
| 280 /// Enable Non-SFI mode. | |
| 281 cl::opt<bool> UseNonsfi("nonsfi", cl::desc("Enable Non-SFI mode")); | |
| 282 | |
| 283 /// Use sandboxing. | |
| 284 cl::opt<bool> UseSandboxing("sandbox", cl::desc("Use sandboxing")); | |
| 285 | |
| 286 /// Override with -verbose=none except for the specified function. | |
| 287 cl::opt<std::string> VerboseFocusOn( | |
| 288 "verbose-focus", | |
| 289 cl::desc("Override with -verbose=none except for the specified function"), | |
| 290 cl::init("")); | |
| 291 | |
| 292 /// Output file type. | |
| 293 cl::opt<Ice::FileType> OutFileType( | |
| 294 "filetype", cl::desc("Output file type"), cl::init(Ice::FT_Iasm), | |
| 295 cl::values(clEnumValN(Ice::FT_Elf, "obj", "Native ELF object ('.o') file"), | |
| 296 clEnumValN(Ice::FT_Asm, "asm", "Assembly ('.s') file"), | |
| 297 clEnumValN(Ice::FT_Iasm, "iasm", | |
| 298 "Low-level integrated assembly ('.s') file"), | |
| 299 clEnumValEnd)); | |
| 300 | |
| 301 /// Max number of nops to insert per instruction. | |
| 302 cl::opt<int> MaxNopsPerInstruction( | |
| 303 "max-nops-per-instruction", | |
| 304 cl::desc("Max number of nops to insert per instruction"), cl::init(1)); | |
| 305 | |
| 306 /// Nop insertion probability as percentage. | |
| 307 cl::opt<int> NopProbabilityAsPercentage( | |
| 308 "nop-insertion-percentage", | |
| 309 cl::desc("Nop insertion probability as percentage"), cl::init(10)); | |
| 310 | |
| 311 /// Restricts registers in corresponding register classes to specified list. | |
| 312 cl::list<std::string> UseRestrictedRegisters( | |
| 313 "reg-use", cl::CommaSeparated, | |
| 314 cl::desc( | |
| 315 "Only use specified registers for corresponding register classes")); | |
| 316 | |
| 317 /// List of excluded registers. | |
| 318 cl::list<std::string> | |
| 319 ExcludedRegisters("reg-exclude", cl::CommaSeparated, | |
| 320 cl::desc("Don't use specified registers")); | |
| 321 | |
| 322 /// Verbose options (can be comma-separated). | |
| 323 cl::list<Ice::VerboseItem> VerboseList( | |
| 324 "verbose", cl::CommaSeparated, | |
| 325 cl::desc("Verbose options (can be comma-separated):"), | |
| 326 cl::values( | |
| 327 clEnumValN(Ice::IceV_Instructions, "inst", "Print basic instructions"), | |
| 328 clEnumValN(Ice::IceV_Deleted, "del", "Include deleted instructions"), | |
| 329 clEnumValN(Ice::IceV_InstNumbers, "instnum", | |
| 330 "Print instruction numbers"), | |
| 331 clEnumValN(Ice::IceV_Preds, "pred", "Show predecessors"), | |
| 332 clEnumValN(Ice::IceV_Succs, "succ", "Show successors"), | |
| 333 clEnumValN(Ice::IceV_Liveness, "live", "Liveness information"), | |
| 334 clEnumValN(Ice::IceV_RegOrigins, "orig", "Physical register origins"), | |
| 335 clEnumValN(Ice::IceV_LinearScan, "regalloc", "Linear scan details"), | |
| 336 clEnumValN(Ice::IceV_Frame, "frame", "Stack frame layout details"), | |
| 337 clEnumValN(Ice::IceV_AddrOpt, "addropt", "Address mode optimization"), | |
| 338 clEnumValN(Ice::IceV_Random, "random", "Randomization details"), | |
| 339 clEnumValN(Ice::IceV_Folding, "fold", "Instruction folding details"), | |
| 340 clEnumValN(Ice::IceV_RMW, "rmw", "ReadModifyWrite optimization"), | |
| 341 clEnumValN(Ice::IceV_Loop, "loop", "Loop nest depth analysis"), | |
| 342 clEnumValN(Ice::IceV_Mem, "mem", "Memory usage details"), | |
| 343 clEnumValN(Ice::IceV_Status, "status", | |
| 344 "Print the name of the function being translated"), | |
| 345 clEnumValN(Ice::IceV_AvailableRegs, "registers", | |
| 346 "Show available registers for register allocation"), | |
| 347 clEnumValN(Ice::IceV_GlobalInit, "global_init", "Global initializers"), | |
| 348 clEnumValN(Ice::IceV_ConstPoolStats, "cpool", "Constant pool counters"), | |
| 349 clEnumValN(Ice::IceV_All, "all", "Use all verbose options"), | |
| 350 clEnumValN(Ice::IceV_Most, "most", | |
| 351 "Use all verbose options except 'regalloc,global_init'"), | |
| 352 clEnumValN(Ice::IceV_None, "none", "No verbosity"), clEnumValEnd)); | |
| 353 | |
| 354 // Options not captured in Ice::ClFlags and propagated. | |
| 355 | |
| 356 /// Exit with success status, even if errors found. | |
| 357 cl::opt<bool> AlwaysExitSuccess( | |
| 358 "exit-success", cl::desc("Exit with success status, even if errors found"), | |
| 359 cl::init(false)); | |
| 360 | |
| 361 /// Note: While this flag isn't used in the minimal build, we keep this flag so | |
| 362 /// that tests can set this command-line flag without concern to the type of | |
| 363 /// build. We double check this flag at runtime to make sure the | |
| 364 /// consistency is maintained. | |
| 365 cl::opt<bool> | |
| 366 BuildOnRead("build-on-read", | |
| 367 cl::desc("Build ICE instructions when reading bitcode"), | |
| 368 cl::init(true)); | |
| 369 | |
| 370 /// Define format of input file. | |
| 371 cl::opt<llvm::NaClFileFormat> InputFileFormat( | |
| 372 "bitcode-format", cl::desc("Define format of input file:"), | |
| 373 cl::values(clEnumValN(llvm::LLVMFormat, "llvm", "LLVM file (default)"), | |
| 374 clEnumValN(llvm::PNaClFormat, "pnacl", "PNaCl bitcode file"), | |
| 375 clEnumValEnd), | |
| 376 cl::init(llvm::LLVMFormat)); | |
| 377 | |
| 378 /// Generate list of build attributes associated with this executable. | |
| 379 cl::opt<bool> GenerateBuildAtts( | |
| 380 "build-atts", cl::desc("Generate list of build attributes associated with " | |
| 381 "this executable."), | |
| 382 cl::init(false)); | |
| 383 | |
| 384 /// <Input file> | |
| 385 cl::opt<std::string> IRFilename(cl::Positional, cl::desc("<IR file>"), | |
| 386 cl::init("-")); | |
| 387 | |
| 388 /// Set log filename. | |
| 389 cl::opt<std::string> LogFilename("log", cl::desc("Set log filename"), | |
| 390 cl::init("-"), cl::value_desc("filename")); | |
| 391 | |
| 392 /// Print out more descriptive PNaCl bitcode parse errors when building LLVM | |
| 393 /// IR first. | |
| 394 cl::opt<bool> LLVMVerboseErrors( | |
| 395 "verbose-llvm-parse-errors", | |
| 396 cl::desc("Print out more descriptive PNaCl bitcode parse errors when " | |
| 397 "building LLVM IR first"), | |
| 398 cl::init(false)); | |
| 399 cl::opt<std::string> OutputFilename("o", cl::desc("Override output filename"), | |
| 400 cl::init("-"), cl::value_desc("filename")); | |
| 401 | |
| 402 Ice::IceString AppName; | |
| 403 | |
| 404 /// Define the command line options for immediates pooling and randomization. | |
| 405 cl::opt<Ice::RandomizeAndPoolImmediatesEnum> RandomizeAndPoolImmediatesOption( | |
| 406 "randomize-pool-immediates", | |
| 407 cl::desc("Randomize or pooling the representation of immediates"), | |
| 408 cl::init(Ice::RPI_None), | |
| 409 cl::values(clEnumValN(Ice::RPI_None, "none", | |
| 410 "Do not randomize or pooling immediates (default)"), | |
| 411 clEnumValN(Ice::RPI_Randomize, "randomize", | |
| 412 "Turn on immediate constants blinding"), | |
| 413 clEnumValN(Ice::RPI_Pool, "pool", | |
| 414 "Turn on immediate constants pooling"), | |
| 415 clEnumValEnd)); | |
| 416 /// Command line option for x86 immediate integer randomization/pooling | |
| 417 /// threshold. Immediates whose representation are between: | |
| 418 /// -RandomizeAndPoolImmediatesThreshold/2 and | |
| 419 /// +RandomizeAndPoolImmediatesThreshold/2 will be randomized or pooled. | |
| 420 cl::opt<uint32_t> RandomizeAndPoolImmediatesThreshold( | |
| 421 "randomize-pool-threshold", | |
| 422 cl::desc("The threshold for immediates randomization and pooling"), | |
| 423 cl::init(0xffff)); | |
| 424 | |
| 425 /// Shuffle the layout of basic blocks in each functions. | |
| 426 cl::opt<bool> ReorderBasicBlocks( | |
| 427 "reorder-basic-blocks", | |
| 428 cl::desc("Shuffle the layout of basic blocks in each function"), | |
| 429 cl::init(false)); | |
| 430 | |
| 431 /// Randomize function ordering. | |
| 432 cl::opt<bool> ReorderFunctions("reorder-functions", | |
| 433 cl::desc("Randomize function ordering"), | |
| 434 cl::init(false)); | |
| 435 | |
| 436 /// The shuffling window size for function reordering. 1 or 0 means no effective | |
| 437 /// shuffling. The default size is 8. | |
| 438 cl::opt<uint32_t> ReorderFunctionsWindowSize( | |
| 439 "reorder-functions-window-size", | |
| 440 cl::desc("The shuffling window size for function reordering. 1 or 0 means " | |
| 441 "no effective shuffling."), | |
| 442 cl::init(8)); | |
| 443 | |
| 444 /// Randomize global data ordering. | |
| 445 cl::opt<bool> ReorderGlobalVariables("reorder-global-variables", | |
| 446 cl::desc("Randomize global data ordering"), | |
| 447 cl::init(false)); | |
| 448 | |
| 449 /// Randomize constant pool entry ordering. | |
| 450 cl::opt<bool> | |
| 451 ReorderPooledConstants("reorder-pooled-constants", | |
| 452 cl::desc("Randomize constant pool entry ordering"), | |
| 453 cl::init(false)); | |
| 454 | |
| 455 /// Command line option for accepting textual bitcode. | |
| 456 cl::opt<bool> BitcodeAsText( | |
| 457 "bitcode-as-text", | |
| 458 cl::desc( | |
| 459 "Accept textual form of PNaCl bitcode records (i.e. not .ll assembly)"), | |
| 460 cl::init(false)); | |
| 461 } // end of anonymous namespace | 104 } // end of anonymous namespace |
| 462 | 105 |
| 463 namespace Ice { | 106 namespace Ice { |
| 464 | 107 |
| 465 void ClFlags::parseFlags(int argc, char **argv) { | 108 void ClFlags::parseFlags(int argc, char **argv) { |
| 466 cl::ParseCommandLineOptions(argc, argv); | 109 cl::ParseCommandLineOptions(argc, argv); |
| 467 AppName = IceString(argv[0]); | 110 AppNameObj = IceString(argv[0]); |
| 468 } | 111 } |
| 469 | 112 |
| 470 void ClFlags::resetClFlags(ClFlags &OutFlags) { | 113 namespace { |
| 471 // bool fields | 114 // flagInitOrStorageTypeDefault is some template voodoo for peeling off the |
| 472 OutFlags.AllowErrorRecovery = false; | 115 // llvm::cl modifiers from a flag's declaration, until its initial value is |
| 473 OutFlags.AllowExternDefinedSymbols = false; | 116 // found. If none is found, then the default value for the storage type is |
| 474 OutFlags.AllowIacaMarks = false; | 117 // returned. |
| 475 OutFlags.AllowUninitializedGlobals = false; | 118 template <typename Ty> Ty flagInitOrStorageTypeDefault() { return Ty(); } |
| 476 OutFlags.DataSections = false; | 119 |
| 477 OutFlags.DecorateAsm = false; | 120 template <typename Ty, typename T, typename... A> |
| 478 OutFlags.DisableHybridAssembly = false; | 121 Ty flagInitOrStorageTypeDefault(cl::initializer<T> &&Value, A &&...) { |
| 479 OutFlags.DisableInternal = false; | 122 return Value.Init; |
| 480 OutFlags.DisableTranslation = false; | |
| 481 OutFlags.DumpStats = false; | |
| 482 OutFlags.EnableBlockProfile = false; | |
| 483 OutFlags.ForceMemIntrinOpt = false; | |
| 484 OutFlags.FunctionSections = false; | |
| 485 OutFlags.GenerateUnitTestMessages = false; | |
| 486 OutFlags.KeepDeletedInsts = Ice::BuildDefs::dump(); | |
| 487 OutFlags.MockBoundsCheck = false; | |
| 488 OutFlags.PhiEdgeSplit = false; | |
| 489 OutFlags.RandomNopInsertion = false; | |
| 490 OutFlags.RandomRegAlloc = false; | |
| 491 OutFlags.RepeatRegAlloc = false; | |
| 492 OutFlags.ReorderBasicBlocks = false; | |
| 493 OutFlags.ReorderFunctions = false; | |
| 494 OutFlags.ReorderGlobalVariables = false; | |
| 495 OutFlags.ReorderPooledConstants = false; | |
| 496 OutFlags.SkipUnimplemented = false; | |
| 497 OutFlags.SubzeroTimingEnabled = false; | |
| 498 OutFlags.TimeEachFunction = false; | |
| 499 OutFlags.UseNonsfi = false; | |
| 500 OutFlags.UseSandboxing = false; | |
| 501 // Enum and integer fields. | |
| 502 OutFlags.Opt = Opt_m1; | |
| 503 OutFlags.OutFileType = FT_Iasm; | |
| 504 OutFlags.RandomMaxNopsPerInstruction = 0; | |
| 505 OutFlags.RandomNopProbabilityAsPercentage = 0; | |
| 506 OutFlags.RandomizeAndPoolImmediatesOption = RPI_None; | |
| 507 OutFlags.RandomizeAndPoolImmediatesThreshold = 0xffff; | |
| 508 OutFlags.ReorderFunctionsWindowSize = 8; | |
| 509 OutFlags.TArch = TargetArch_NUM; | |
| 510 OutFlags.TestStackExtra = 0; | |
| 511 OutFlags.VMask = IceV_None; | |
| 512 // IceString fields. | |
| 513 OutFlags.DefaultFunctionPrefix = ""; | |
| 514 OutFlags.DefaultGlobalPrefix = ""; | |
| 515 OutFlags.TestPrefix = ""; | |
| 516 OutFlags.TimingFocusOn = ""; | |
| 517 OutFlags.TranslateOnly = ""; | |
| 518 OutFlags.VerboseFocusOn = ""; | |
| 519 // size_t and 64-bit fields. | |
| 520 OutFlags.NumTranslationThreads = 0; | |
| 521 OutFlags.RandomSeed = 0; | |
| 522 // Unordered set fields. | |
| 523 OutFlags.clearExcludedRegisters(); | |
| 524 OutFlags.clearUseRestrictedRegisters(); | |
| 525 } | 123 } |
| 526 | 124 |
| 527 void ClFlags::getParsedClFlags(ClFlags &OutFlags) { | 125 // is_cl_initializer is used to prevent an ambiguous call between the previous |
| 126 // version of flagInitOrStorageTypeDefault, and the next, which is flagged by | |
| 127 // g++. | |
| 128 template <typename T> struct is_cl_initializer { | |
| 129 static constexpr bool value = false; | |
| 130 }; | |
| 131 | |
| 132 template <typename T> struct is_cl_initializer<cl::initializer<T>> { | |
| 133 static constexpr bool value = true; | |
| 134 }; | |
| 135 | |
| 136 template <typename Ty, typename T, typename... A> | |
| 137 typename std::enable_if<!is_cl_initializer<T>::value, Ty>::type | |
| 138 flagInitOrStorageTypeDefault(T &&, A &&... Other) { | |
| 139 return flagInitOrStorageTypeDefault<Ty>(std::forward<A>(Other)...); | |
| 140 } | |
| 141 | |
| 142 } // end of anonymous namespace | |
| 143 | |
| 144 void ClFlags::resetClFlags() { | |
| 145 #define X(Name, Type, ClType, ...) \ | |
| 146 Name = flagInitOrStorageTypeDefault< \ | |
| 147 detail::cl_type_traits<Type, cl_detail::ClType>::storage_type>( \ | |
| 148 __VA_ARGS__); | |
| 149 COMMAND_LINE_FLAGS | |
| 150 #undef X | |
| 151 } | |
| 152 | |
| 153 namespace { | |
| 154 | |
| 155 // toSetterParam is template magic that is needed to convert between (llvm::)cl | |
| 156 // objects and the arguments to ClFlags' setters. ToSetterParam is a traits | |
| 157 // object that we need in order for the multiple specializations to | |
| 158 // toSetterParam to agree on their return type. | |
| 159 template <typename T> struct ToSetterParam { using ReturnType = const T &; }; | |
| 160 | |
| 161 template <> struct ToSetterParam<cl::list<Ice::VerboseItem>> { | |
| 162 using ReturnType = Ice::VerboseMask; | |
| 163 }; | |
| 164 | |
| 165 template <typename T> | |
| 166 typename ToSetterParam<T>::ReturnType toSetterParam(const T &Param) { | |
| 167 return Param; | |
| 168 } | |
| 169 | |
| 170 template <> | |
| 171 ToSetterParam<cl::list<Ice::VerboseItem>>::ReturnType | |
| 172 toSetterParam(const cl::list<Ice::VerboseItem> &Param) { | |
| 528 Ice::VerboseMask VMask = Ice::IceV_None; | 173 Ice::VerboseMask VMask = Ice::IceV_None; |
| 529 // Don't generate verbose messages if routines to dump messages are not | 174 // Don't generate verbose messages if routines to dump messages are not |
| 530 // available. | 175 // available. |
| 531 if (BuildDefs::dump()) { | 176 if (BuildDefs::dump()) { |
| 532 for (unsigned i = 0; i != VerboseList.size(); ++i) | 177 for (unsigned i = 0; i != Param.size(); ++i) |
| 533 VMask |= VerboseList[i]; | 178 VMask |= Param[i]; |
| 534 } | 179 } |
| 535 | 180 return VMask; |
| 536 OutFlags.setAllowErrorRecovery(::AllowErrorRecovery); | |
| 537 OutFlags.setAllowExternDefinedSymbols(::AllowExternDefinedSymbols || | |
| 538 ::DisableInternal); | |
| 539 OutFlags.setAllowIacaMarks(::AllowIacaMarks); | |
| 540 OutFlags.setAllowUninitializedGlobals(::AllowUninitializedGlobals); | |
| 541 OutFlags.setDataSections(::DataSections); | |
| 542 OutFlags.setDecorateAsm(::DecorateAsm); | |
| 543 OutFlags.setDefaultFunctionPrefix(::DefaultFunctionPrefix); | |
| 544 OutFlags.setDefaultGlobalPrefix(::DefaultGlobalPrefix); | |
| 545 OutFlags.setDisableHybridAssembly(::DisableHybridAssembly || | |
| 546 (::OutFileType != Ice::FT_Iasm)); | |
| 547 OutFlags.setDisableInternal(::DisableInternal); | |
| 548 OutFlags.setDisableTranslation(::DisableTranslation); | |
| 549 OutFlags.setDumpStats(::DumpStats); | |
| 550 OutFlags.setEnableBlockProfile(::EnableBlockProfile); | |
| 551 OutFlags.setExcludedRegisters(::ExcludedRegisters); | |
| 552 OutFlags.setForceMemIntrinOpt(::ForceMemIntrinOpt); | |
| 553 OutFlags.setFunctionSections(::FunctionSections); | |
| 554 OutFlags.setNumTranslationThreads(::NumThreads); | |
| 555 OutFlags.setOptLevel(::OLevel); | |
| 556 OutFlags.setKeepDeletedInsts(::KeepDeletedInsts); | |
| 557 OutFlags.setMockBoundsCheck(::MockBoundsCheck); | |
| 558 OutFlags.setPhiEdgeSplit(::EnablePhiEdgeSplit); | |
| 559 OutFlags.setRandomSeed(::RandomSeed); | |
| 560 OutFlags.setRandomizeAndPoolImmediatesOption( | |
| 561 ::RandomizeAndPoolImmediatesOption); | |
| 562 OutFlags.setRandomizeAndPoolImmediatesThreshold( | |
| 563 ::RandomizeAndPoolImmediatesThreshold); | |
| 564 OutFlags.setReorderFunctionsWindowSize(::ReorderFunctionsWindowSize); | |
| 565 OutFlags.setShouldReorderBasicBlocks(::ReorderBasicBlocks); | |
| 566 OutFlags.setShouldDoNopInsertion(::ShouldDoNopInsertion); | |
| 567 OutFlags.setShouldRandomizeRegAlloc(::RandomizeRegisterAllocation); | |
| 568 OutFlags.setRegAllocReserve(::RegAllocReserve); | |
| 569 OutFlags.setShouldRepeatRegAlloc(::RepeatRegAlloc); | |
| 570 OutFlags.setShouldReorderFunctions(::ReorderFunctions); | |
| 571 OutFlags.setShouldReorderGlobalVariables(::ReorderGlobalVariables); | |
| 572 OutFlags.setShouldReorderPooledConstants(::ReorderPooledConstants); | |
| 573 OutFlags.setSkipUnimplemented(::SkipUnimplemented); | |
| 574 OutFlags.setSubzeroTimingEnabled(::SubzeroTimingEnabled); | |
| 575 OutFlags.setTargetArch(::TargetArch); | |
| 576 OutFlags.setTargetInstructionSet(::TargetInstructionSet); | |
| 577 OutFlags.setTestPrefix(::TestPrefix); | |
| 578 OutFlags.setTestStackExtra(::TestStackExtra); | |
| 579 OutFlags.setTimeEachFunction(::TimeEachFunction); | |
| 580 OutFlags.setTimingFocusOn(::TimingFocusOn); | |
| 581 OutFlags.setTranslateOnly(::TranslateOnly); | |
| 582 OutFlags.setUseNonsfi(::UseNonsfi); | |
| 583 OutFlags.setUseRestrictedRegisters(::UseRestrictedRegisters); | |
| 584 OutFlags.setUseSandboxing(::UseSandboxing); | |
| 585 OutFlags.setVerboseFocusOn(::VerboseFocusOn); | |
| 586 OutFlags.setOutFileType(::OutFileType); | |
| 587 OutFlags.setMaxNopsPerInstruction(::MaxNopsPerInstruction); | |
| 588 OutFlags.setNopProbabilityAsPercentage(::NopProbabilityAsPercentage); | |
| 589 OutFlags.setVerbose(VMask); | |
| 590 } | 181 } |
| 591 | 182 |
| 592 void ClFlags::getParsedClFlagsExtra(ClFlagsExtra &OutFlagsExtra) { | 183 } // end of anonymous namespace |
| 593 OutFlagsExtra.setAlwaysExitSuccess(AlwaysExitSuccess); | 184 |
| 594 OutFlagsExtra.setBitcodeAsText(BitcodeAsText); | 185 void ClFlags::getParsedClFlags(ClFlags &OutFlags) { |
| 595 OutFlagsExtra.setBuildOnRead(BuildOnRead); | 186 #define X(Name, Type, ClType, ...) OutFlags.set##Name(toSetterParam(Name##Obj)); |
| 596 OutFlagsExtra.setGenerateBuildAtts(GenerateBuildAtts); | 187 COMMAND_LINE_FLAGS |
| 597 OutFlagsExtra.setLLVMVerboseErrors(LLVMVerboseErrors); | 188 #undef X |
| 598 OutFlagsExtra.setAppName(AppName); | 189 |
| 599 OutFlagsExtra.setInputFileFormat(InputFileFormat); | 190 // If any value needs a non-trivial parsed value, set it below. |
| 600 OutFlagsExtra.setIRFilename(IRFilename); | 191 OutFlags.setAllowExternDefinedSymbols(AllowExternDefinedSymbolsObj || |
| 601 OutFlagsExtra.setLogFilename(LogFilename); | 192 DisableInternalObj); |
| 602 OutFlagsExtra.setOutputFilename(OutputFilename); | 193 OutFlags.setDisableHybridAssembly(DisableHybridAssemblyObj || |
| 194 (OutFileTypeObj != Ice::FT_Iasm)); | |
| 603 } | 195 } |
| 604 | 196 |
| 605 } // end of namespace Ice | 197 } // end of namespace Ice |
| OLD | NEW |