Files
carbon-lang/toolchain/driver/tool_runner_base.cpp
T
2025-04-17 15:37:57 +00:00

76 lines
2.7 KiB
C++

// 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