Factor out C-string argv building and simplify vlogs (#6478)

This extracts the C-string `argv`-like building routine to a more
broadly reusable location. It also sinks the verbose logging logic out
of it and into the relevant runners. In turn, it simplifies the verbose
logging logic significantly.

The biggest functional change is removing the implicit synthesis of a
tool's `-v` verbose flag from the presence of a `vlog` stream. I thought
this would be helpful, but in practice of debugging these layers it has
been more of a hindrance than a help -- I pretty often only want verbose
logging on one side or the other, and we have ways of explicitly passing
a `-v` flag to the underlying tools already. I think my instinct to do
this was just wrong, so rip it out and simplify.

This does add an unused feature -- prepending a prefix of arguments
while building the C-string variant. This isn't used in this PR but will
be used in subsequent PRs and it seemed more disruptive to undo that
logic and then re-do it in a later PR. Let me know if it's too confusing
here.

Assisted-by: Gemini Code Assist

---------

Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
Chandler Carruth
2025-12-10 22:07:01 +00:00
committed by GitHub
co-authored by Geoff Romer
parent 1c3d3e9284
commit ff8ce31e1b
9 changed files with 180 additions and 82 deletions
+55
View File
@@ -4,11 +4,18 @@
#include "common/string_helpers.h"
#include <string.h>
#include <sys/types.h>
#include <algorithm>
#include <array>
#include <optional>
#include <string>
#include "common/check.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
@@ -202,4 +209,52 @@ auto StringRefContainsPointer(llvm::StringRef ref, const char* ptr) -> bool {
return le(ref.begin(), ptr) && le(ptr, ref.end());
}
auto BuildCStrArgs(llvm::StringRef tool_path,
llvm::ArrayRef<llvm::StringRef> args,
llvm::OwningArrayRef<char>& cstr_arg_storage)
-> llvm::SmallVector<const char*, 64> {
return BuildCStrArgs(tool_path, /*prefix_args=*/{}, args, cstr_arg_storage);
}
auto BuildCStrArgs(llvm::StringRef tool_path,
llvm::ArrayRef<std::string> prefix_args,
llvm::ArrayRef<llvm::StringRef> args,
llvm::OwningArrayRef<char>& cstr_arg_storage)
-> llvm::SmallVector<const char*, 64> {
// 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.
// Precompute the total C-string data size needed.
int total_size = tool_path.size() + 1;
for (llvm::StringRef arg : args) {
// 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 reserve a
// vector of pointers into the storage.
cstr_arg_storage = llvm::OwningArrayRef<char>(total_size);
ssize_t i = 0;
auto make_cstr = [&](llvm::StringRef arg) {
char* cstr = &cstr_arg_storage[i];
memcpy(cstr, arg.data(), arg.size());
cstr[arg.size()] = '\0';
i += arg.size() + 1;
return cstr;
};
llvm::SmallVector<const char*, 64> cstr_args;
cstr_args.reserve(1 + prefix_args.size() + args.size());
cstr_args.push_back(make_cstr(tool_path));
for (const std::string& prefix_arg : prefix_args) {
cstr_args.push_back(prefix_arg.c_str());
}
for (llvm::StringRef arg : args) {
cstr_args.push_back(make_cstr(arg));
}
return cstr_args;
}
} // namespace Carbon