Index: llvm/include/llvm-c/lto.h =================================================================== --- llvm/include/llvm-c/lto.h +++ llvm/include/llvm-c/lto.h @@ -46,7 +46,7 @@ * @{ */ -#define LTO_API_VERSION 27 +#define LTO_API_VERSION 28 /** * \since prior to LTO_API_VERSION=3 @@ -527,7 +527,23 @@ lto_api_version(void); /** - * Sets options to help debug codegen bugs. + * Parses options immediately, making them available as early as possible. For + * example during executing codegen::InitTargetOptionsFromCodeGenFlags. Since + * parsing shud only happen once, only one of lto_codegen_debug_options or + * lto_set_debug_options should be called. + * + * This function takes one or more options separated by spaces. + * Warning: passing file paths through this function may confuse the argument + * parser if the paths contain spaces. + * + * \since LTO_API_VERSION=28 + */ +extern void lto_set_debug_options(const char *const *options, int number); + +/** + * Sets options to help debug codegen bugs. Since parsing shud only happen once, + * only one of lto_codegen_debug_options or lto_set_debug_options + * should be called. * * This function takes one or more options separated by spaces. * Warning: passing file paths through this function may confuse the argument Index: llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h =================================================================== --- llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -240,5 +240,9 @@ lto::Config Config; }; + +/// A convenience function that calls cl::ParseCommandLineOptions on the given +/// set of options. +void parseCommandLineOptions(std::vector &Options); } #endif Index: llvm/lib/LTO/LTOCodeGenerator.cpp =================================================================== --- llvm/lib/LTO/LTOCodeGenerator.cpp +++ llvm/lib/LTO/LTOCodeGenerator.cpp @@ -598,17 +598,20 @@ } void LTOCodeGenerator::parseCodeGenDebugOptions() { - // if options were requested, set them - if (!CodegenOptions.empty()) { + if (!CodegenOptions.empty()) + llvm::parseCommandLineOptions(CodegenOptions); +} + +void llvm::parseCommandLineOptions(std::vector &Options) { + if (!Options.empty()) { // ParseCommandLineOptions() expects argv[0] to be program name. std::vector CodegenArgv(1, "libLLVMLTO"); - for (std::string &Arg : CodegenOptions) + for (std::string &Arg : Options) CodegenArgv.push_back(Arg.c_str()); cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data()); } } - void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI) { // Map the LLVM internal diagnostic severity to the LTO diagnostic severity. lto_codegen_diagnostic_severity_t Severity; Index: llvm/tools/lto/lto.cpp =================================================================== --- llvm/tools/lto/lto.cpp +++ llvm/tools/lto/lto.cpp @@ -63,8 +63,12 @@ // *** Not thread safe *** static bool initialized = false; -// Holds the command-line option parsing state of the LTO module. -static bool parsedOptions = false; +// Represent the state of parsing command line debug options. +static enum class OptParsingState { + NotParsed, // Initial state. + Early, // After lto_set_debug_options is called. + Done // After maybeParseOptions is called. +} optionParsingState = OptParsingState::NotParsed; static LLVMContext *LTOContext = nullptr; @@ -418,10 +422,11 @@ } static void maybeParseOptions(lto_code_gen_t cg) { - if (!parsedOptions) { + if (optionParsingState != OptParsingState::Done) { + // Parse options if any were set by the lto_codegen_debug_options* function. unwrap(cg)->parseCodeGenDebugOptions(); lto_add_attrs(cg); - parsedOptions = true; + optionParsingState = OptParsingState::Done; } } @@ -460,7 +465,22 @@ return !unwrap(cg)->compile_to_file(name); } +void lto_set_debug_options(const char *const *options, int number) { + assert(optionParsingState == OptParsingState::NotParsed && + "option processing already happened"); + // Need to put each suboption in a null-terminated string before passing to + // parseCommandLineOptions(). + std::vector Options; + for (int i = 0; i < number; ++i) + Options.push_back(options[i]); + + llvm::parseCommandLineOptions(Options); + optionParsingState = OptParsingState::Early; +} + void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) { + assert(optionParsingState != OptParsingState::Early && + "early option processing already happened"); SmallVector Options; for (std::pair o = getToken(opt); !o.first.empty(); o = getToken(o.second)) @@ -471,6 +491,8 @@ void lto_codegen_debug_options_array(lto_code_gen_t cg, const char *const *options, int number) { + assert(optionParsingState != OptParsingState::Early && + "early option processing already happened"); SmallVector Options; for (int i = 0; i < number; ++i) Options.push_back(options[i]); Index: llvm/tools/lto/lto.exports =================================================================== --- llvm/tools/lto/lto.exports +++ llvm/tools/lto/lto.exports @@ -43,6 +43,7 @@ lto_codegen_compile_optimized lto_codegen_set_should_internalize lto_codegen_set_should_embed_uselists +lto_set_debug_options LLVMCreateDisasm LLVMCreateDisasmCPU LLVMDisasmDispose