//===-- cl_options.cpp ----------------------------------------------------===// // // LDC – the LLVM D compiler // // This file is distributed under the BSD-style LDC license. See the LICENSE // file for details. // //===----------------------------------------------------------------------===// #include "driver/cl_options.h" #include "mars.h" #include "gen/cl_helpers.h" #include "gen/logger.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetMachine.h" #include "llvm/IR/DataLayout.h" namespace opts { // This vector is filled by parseCommandLine in main.cpp. llvm::SmallVector allArguments; /* Option parser that defaults to zero when no explicit number is given. * i.e.: -cov --> value = 0 * -cov=9 --> value = 9 * -cov=101 --> error, value must be in range [0..100] */ struct CoverageParser : public cl::parser { #if LDC_LLVM_VER >= 307 explicit CoverageParser(cl::Option &O) : cl::parser(O) {} #endif bool parse(cl::Option &O, llvm::StringRef /*ArgName*/, llvm::StringRef Arg, unsigned char &Val) { if (Arg == "") { Val = 0; return false; } if (Arg.getAsInteger(0, Val)) { return O.error("'" + Arg + "' value invalid for required coverage percentage"); } if (Val > 100) { return O.error("Required coverage percentage must be <= 100"); } return false; } }; // Positional options first, in order: cl::list fileList(cl::Positional, cl::desc("files")); cl::list runargs( "run", cl::desc( "Runs the resulting program, passing the remaining arguments to it"), cl::Positional, cl::PositionalEatsArgs); static cl::opt useDeprecated( cl::desc("Allow deprecated code/language features:"), cl::ZeroOrMore, clEnumValues(clEnumValN(0, "de", "Do not allow deprecated features"), clEnumValN(1, "d", "Silently allow deprecated features"), clEnumValN(2, "dw", "Warn about the use of deprecated features")), cl::location(global.params.useDeprecated), cl::init(2)); cl::opt enforcePropertySyntax("property", cl::desc("Enforce property syntax"), cl::ZeroOrMore, cl::location(global.params.enforcePropertySyntax)); cl::opt compileOnly("c", cl::desc("Do not link"), cl::ZeroOrMore); static cl::opt createStaticLib("lib", cl::desc("Create static library"), cl::ZeroOrMore, cl::location(global.params.lib)); static cl::opt createSharedLib("shared", cl::desc("Create shared library"), cl::ZeroOrMore, cl::location(global.params.dll)); static cl::opt verbose("v", cl::desc("Verbose"), cl::ZeroOrMore, cl::location(global.params.verbose)); static cl::opt vcolumns("vcolumns", cl::desc("print character (column) numbers in diagnostics"), cl::ZeroOrMore, cl::location(global.params.showColumns)); static cl::opt vgc("vgc", cl::desc("list all gc allocations including hidden ones"), cl::ZeroOrMore, cl::location(global.params.vgc)); static cl::opt verbose_cg("v-cg", cl::desc("Verbose codegen"), cl::ZeroOrMore, cl::location(global.params.verbose_cg)); static cl::opt errorLimit( "verrors", cl::desc("limit the number of error messages (0 means unlimited)"), cl::location(global.errorLimit)); static cl::opt warnings(cl::desc("Warnings:"), cl::ZeroOrMore, clEnumValues(clEnumValN(1, "w", "Enable warnings"), clEnumValN(2, "wi", "Enable informational warnings")), cl::location(global.params.warnings), cl::init(0)); static cl::opt ignoreUnsupportedPragmas( "ignore", cl::desc("Ignore unsupported pragmas"), cl::ZeroOrMore, cl::location(global.params.ignoreUnsupportedPragmas)); static cl::opt debugInfo( cl::desc("Generating debug information:"), cl::ZeroOrMore, clEnumValues(clEnumValN(1, "g", "Generate debug information"), clEnumValN(2, "gc", "Same as -g, but pretend to be C")), cl::location(global.params.symdebug), cl::init(0)); static cl::opt dwarfVersion("dwarf-version", cl::desc("Dwarf version"), cl::location(global.params.dwarfVersion), cl::init(0), cl::Hidden); cl::opt noAsm("noasm", cl::desc("Disallow use of inline assembler")); // Output file options cl::opt dontWriteObj("o-", cl::desc("Do not write object file")); cl::opt objectFile("of", cl::value_desc("filename"), cl::Prefix, cl::desc("Use as output file name")); cl::opt objectDir("od", cl::value_desc("objdir"), cl::Prefix, cl::desc("Write object files to directory ")); cl::opt soname("soname", cl::value_desc("soname"), cl::Hidden, cl::Prefix, cl::desc("Use as output shared library soname")); // Output format options cl::opt output_bc("output-bc", cl::desc("Write LLVM bitcode")); cl::opt output_ll("output-ll", cl::desc("Write LLVM IR")); cl::opt output_s("output-s", cl::desc("Write native assembly")); cl::opt output_o("output-o", cl::desc("Write native object")); // Disabling Red Zone cl::opt disableRedZone("disable-red-zone", cl::desc("Do not emit code that uses the red zone."), cl::location(global.params.disableRedZone), cl::init(false)); // DDoc options static cl::opt doDdoc("D", cl::desc("Generate documentation"), cl::location(global.params.doDocComments)); cl::opt ddocDir("Dd", cl::desc("Write documentation file to directory"), cl::value_desc("docdir"), cl::Prefix); cl::opt ddocFile("Df", cl::desc("Write documentation file to "), cl::value_desc("filename"), cl::Prefix); // Json options static cl::opt doJson("X", cl::desc("Generate JSON file"), cl::location(global.params.doJsonGeneration)); cl::opt jsonFile("Xf", cl::desc("Write JSON file to "), cl::value_desc("filename"), cl::Prefix); // Header generation options static cl::opt doHdrGen("H", cl::desc("Generate 'header' file"), cl::location(global.params.doHdrGeneration)); cl::opt hdrDir("Hd", cl::desc("Write 'header' file to directory"), cl::value_desc("hdrdir"), cl::Prefix); cl::opt hdrFile("Hf", cl::desc("Write 'header' file to "), cl::value_desc("filename"), cl::Prefix); static cl::opt hdrKeepAllBodies( "Hkeep-all-bodies", cl::desc("Keep all function bodies in .di files"), cl::ZeroOrMore, cl::location(global.params.hdrKeepAllBodies)); static cl::opt unittest("unittest", cl::desc("Compile in unit tests"), cl::location(global.params.useUnitTests)); cl::opt ir2objCacheDir("ir2obj-cache", cl::desc("Use to cache object files for whole IR modules (experimental)"), cl::value_desc("cache dir")); static StringsAdapter strImpPathStore("J", global.params.fileImppath); static cl::list stringImportPaths("J", cl::desc("Where to look for string imports"), cl::value_desc("path"), cl::location(strImpPathStore), cl::Prefix); static cl::opt addMain("main", cl::desc("Add empty main() (e.g. for unittesting)"), cl::ZeroOrMore, cl::location(global.params.addMain)); // -d-debug is a bit messy, it has 3 modes: // -d-debug=ident, -d-debug=level and -d-debug (without argument) // That last of these must be acted upon immediately to ensure proper // interaction with other options, so it needs some special handling: std::vector debugArgs; struct D_DebugStorage { void push_back(const std::string &str) { if (str.empty()) { // Bare "-d-debug" has a special meaning. global.params.useAssert = true; global.params.useArrayBounds = BOUNDSCHECKon; global.params.useInvariants = true; global.params.useIn = true; global.params.useOut = true; debugArgs.push_back("1"); } else { debugArgs.push_back(str); } } }; static D_DebugStorage dds; // -debug is already declared in LLVM (at least, in debug builds), // so we need to be a bit more verbose. static cl::list debugVersionsOption( "d-debug", cl::desc("Compile in debug code >= or identified by ."), cl::value_desc("level/idents"), cl::location(dds), cl::CommaSeparated, cl::ValueOptional); // -version is also declared in LLVM, so again we need to be a bit more verbose. cl::list versions( "d-version", cl::desc("Compile in version code >= or identified by "), cl::value_desc("level/idents"), cl::CommaSeparated); cl::list transitions( "transition", cl::desc("help with language change identified by , use ? for list"), cl::value_desc("idents"), cl::CommaSeparated); static StringsAdapter linkSwitchStore("L", global.params.linkswitches); static cl::list linkerSwitches("L", cl::desc("Pass to the linker"), cl::value_desc("linkerflag"), cl::location(linkSwitchStore), cl::Prefix); cl::opt moduleDeps("deps", cl::desc("Write module dependencies to filename (only imports)"), cl::value_desc("filename"), cl::ValueOptional); cl::opt mArch("march", cl::desc("Architecture to generate code for:")); cl::opt m32bits("m32", cl::desc("32 bit target"), cl::ZeroOrMore); cl::opt m64bits("m64", cl::desc("64 bit target"), cl::ZeroOrMore); cl::opt mCPU("mcpu", cl::desc("Target a specific cpu type (-mcpu=help for details)"), cl::value_desc("cpu-name"), cl::init("")); cl::list mAttrs("mattr", cl::CommaSeparated, cl::desc("Target specific attributes (-mattr=help for details)"), cl::value_desc("a1,+a2,-a3,...")); cl::opt mTargetTriple("mtriple", cl::desc("Override target triple")); #if LDC_LLVM_VER >= 307 cl::opt mABI("mabi", cl::desc("The name of the ABI to be targeted from the backend"), cl::Hidden, cl::init("")); #endif cl::opt mRelocModel( "relocation-model", cl::desc("Relocation model"), #if LDC_LLVM_VER < 309 cl::init(llvm::Reloc::Default), #endif clEnumValues( #if LDC_LLVM_VER < 309 clEnumValN(llvm::Reloc::Default, "default", "Target default relocation model"), #endif clEnumValN(llvm::Reloc::Static, "static", "Non-relocatable code"), clEnumValN(llvm::Reloc::PIC_, "pic", "Fully relocatable, position independent code"), clEnumValN(llvm::Reloc::DynamicNoPIC, "dynamic-no-pic", "Relocatable external references, non-relocatable code"))); cl::opt mCodeModel( "code-model", cl::desc("Code model"), cl::init(llvm::CodeModel::Default), clEnumValues( clEnumValN(llvm::CodeModel::Default, "default", "Target default code model"), clEnumValN(llvm::CodeModel::Small, "small", "Small code model"), clEnumValN(llvm::CodeModel::Kernel, "kernel", "Kernel code model"), clEnumValN(llvm::CodeModel::Medium, "medium", "Medium code model"), clEnumValN(llvm::CodeModel::Large, "large", "Large code model"))); cl::opt mFloatABI( "float-abi", cl::desc("ABI/operations to use for floating-point types:"), cl::init(FloatABI::Default), clEnumValues( clEnumValN(FloatABI::Default, "default", "Target default floating-point ABI"), clEnumValN(FloatABI::Soft, "soft", "Software floating-point ABI and operations"), clEnumValN(FloatABI::SoftFP, "softfp", "Soft-float ABI, but hardware floating-point instructions"), clEnumValN(FloatABI::Hard, "hard", "Hardware floating-point ABI and instructions"))); cl::opt disableFpElim("disable-fp-elim", cl::desc("Disable frame pointer elimination optimization"), cl::init(false)); static cl::opt> asserts("asserts", cl::desc("(*) Enable assertions"), cl::value_desc("bool"), cl::location(global.params.useAssert), cl::init(true)); cl::opt boundsCheck( "boundscheck", cl::desc("Enable array bounds check"), clEnumValues(clEnumValN(BOUNDSCHECKoff, "off", "no array bounds checks"), clEnumValN(BOUNDSCHECKsafeonly, "safeonly", "array bounds checks for safe functions only"), clEnumValN(BOUNDSCHECKon, "on", "array bounds checks for all functions")), cl::init(BOUNDSCHECKdefault)); static cl::opt> invariants("invariants", cl::desc("(*) Enable invariants"), cl::location(global.params.useInvariants), cl::init(true)); static cl::opt> preconditions("preconditions", cl::desc("(*) Enable function preconditions"), cl::location(global.params.useIn), cl::init(true)); static cl::opt> postconditions("postconditions", cl::desc("(*) Enable function postconditions"), cl::location(global.params.useOut), cl::init(true)); static MultiSetter ContractsSetter(false, &global.params.useIn, &global.params.useOut, NULL); static cl::opt> contracts("contracts", cl::desc("(*) Enable function pre- and post-conditions"), cl::location(ContractsSetter)); bool nonSafeBoundsChecks = true; static MultiSetter ReleaseSetter(true, &global.params.useAssert, &nonSafeBoundsChecks, &global.params.useInvariants, &global.params.useOut, &global.params.useIn, NULL); static cl::opt> release("release", cl::desc("Disables asserts, invariants, contracts and boundscheck"), cl::location(ReleaseSetter), cl::ValueDisallowed); cl::opt singleObj("singleobj", cl::desc("Create only a single output object file"), cl::location(global.params.oneobj)); cl::opt hashThreshold( "hash-threshold", cl::desc("hash symbol names longer than this threshold (experimental)"), cl::location(global.params.hashThreshold), cl::init(0)); cl::opt linkonceTemplates( "linkonce-templates", cl::desc( "Use linkonce_odr linkage for template symbols instead of weak_odr"), cl::ZeroOrMore); cl::opt disableLinkerStripDead( "disable-linker-strip-dead", cl::desc("Do not try to remove unused symbols during linking"), cl::init(false)); cl::opt allinst("allinst", cl::desc("generate code for all template instantiations"), cl::location(global.params.allInst)); cl::opt nestedTemplateDepth( "template-depth", cl::desc( "(experimental) set maximum number of nested template instantiations"), cl::location(global.params.nestedTmpl), cl::init(500)); #if LDC_LLVM_VER < 307 cl::opt> color("color", cl::desc("Force colored console output"), cl::location(global.params.color)); #else void CreateColorOption() { new cl::opt>( "color", cl::desc("Force colored console output"), cl::location(global.params.color)); } #endif cl::opt useDIP25("dip25", cl::desc("implement http://wiki.dlang.org/DIP25 (experimental)"), cl::location(global.params.useDIP25)); cl::opt coverageAnalysis( "cov", cl::desc("Compile-in code coverage analysis\n(use -cov=n for n% " "minimum required coverage)"), cl::location(global.params.covPercent), cl::ValueOptional, cl::init(127)); #if LDC_WITH_PGO cl::opt genfileInstrProf("fprofile-instr-generate", cl::value_desc("filename"), cl::desc("Generate instrumented code to collect " "execution counts (e.g. for PGO)"), cl::ValueOptional); cl::opt usefileInstrProf( "fprofile-instr-use", cl::value_desc("filename"), cl::desc("Use instrumentation data for profile-guided optimization"), cl::ValueRequired); #endif static cl::extrahelp footer( "\n" "-d-debug can also be specified without options, in which case it enables " "all\n" "debug checks (i.e. (asserts, boundchecks, contracts and invariants) as " "well\n" "as acting as -d-debug=1\n\n" "Options marked with (*) also have a -disable-FOO variant with inverted\n" "meaning.\n"); } // namespace opts