// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "toolchain/driver/tool_runner_base.h" #include #include "common/vlog.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" namespace Carbon { ToolRunnerBase::ToolRunnerBase(const InstallPaths* install_paths, llvm::raw_ostream* vlog_stream) : installation_(install_paths), vlog_stream_(vlog_stream) {} auto ToolRunnerBase::BuildCStrArgs(llvm::StringRef tool_name, llvm::StringRef tool_path, std::optional verbose_flag, llvm::ArrayRef args, llvm::OwningArrayRef& cstr_arg_storage) -> llvm::SmallVector { // TODO: Maybe handle response file expansion similar to the Clang CLI? // If we have a verbose logging stream, and that stream is the same as // `llvm::errs`, then add the `-v` flag so that the driver also prints verbose // information. bool inject_v_arg = verbose_flag.has_value() && vlog_stream_ == &llvm::errs(); std::array v_arg_storage; llvm::ArrayRef maybe_v_arg; if (inject_v_arg) { v_arg_storage[0] = *verbose_flag; maybe_v_arg = v_arg_storage; } CARBON_VLOG("Running {} driver with arguments:\n", tool_name); // Render the arguments into null-terminated C-strings. Command lines can get // quite long in build systems so this tries to minimize the memory allocation // overhead. // Provide the wrapped tool path as the synthetic `argv[0]`. std::array exe_arg = {tool_path}; auto args_range = llvm::concat(exe_arg, maybe_v_arg, args); int total_size = 0; for (llvm::StringRef arg : args_range) { // Accumulate both the string size and a null terminator byte. total_size += arg.size() + 1; } // Allocate one chunk of storage for the actual C-strings and a vector of // pointers into the storage. cstr_arg_storage = llvm::OwningArrayRef(total_size); llvm::SmallVector cstr_args; cstr_args.reserve(args.size() + inject_v_arg + 1); for (ssize_t i = 0; llvm::StringRef arg : args_range) { cstr_args.push_back(&cstr_arg_storage[i]); memcpy(&cstr_arg_storage[i], arg.data(), arg.size()); i += arg.size(); cstr_arg_storage[i] = '\0'; ++i; } for (const char* cstr_arg : llvm::ArrayRef(cstr_args)) { CARBON_VLOG(" '{0}'\n", cstr_arg); } return cstr_args; } } // namespace Carbon