| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- // 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 <array>
- #include <memory>
- #include <optional>
- #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<llvm::StringRef> verbose_flag,
- llvm::ArrayRef<llvm::StringRef> args,
- llvm::OwningArrayRef<char>& cstr_arg_storage)
- -> llvm::SmallVector<const char*, 64> {
- // 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<llvm::StringRef, 1> v_arg_storage;
- llvm::ArrayRef<llvm::StringRef> 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<llvm::StringRef, 1> exe_arg = {tool_path};
- auto args_range =
- llvm::concat<const llvm::StringRef>(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<char>(total_size);
- llvm::SmallVector<const char*, 64> 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
|