mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:40:11 +01:00
76 lines
2.7 KiB
C++
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
|