mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-01 06:44:58 +01:00
The install directory contains the BUILD logic for creating an installable tree of data files and executables for the toolchain, and a library to facilitate toolchain code accessing the paths to their data within this installation. Then adds an installation of LLD in a synthetic LLVM installation, and teaches the Clang runner to configure this and use it for linking instead of the system linker. Currently, the install paths only really manage access to the LLVM binaries installed and used by the Clang runner for linking, but eventually other data files like the prelude and runtime libraries will be fleshed out as well. There are TODOs for moving more things over here such as the prelude. One interesting aspect of this is where to put helpers like parts of LLVM in our install. This PR suggests nesting those files under `lib/carbon`. While using a `lib` subdirectory isn't a perfect fit for the FHS (Filesystem Hierarchy Standard), having a single location where private data is collected is significantly superior to spreading them across the system. This also matches similar patterns used by Clang itself and several other language toolchains and standard libraries. The install directory also provides a natural place for us to build out packaging rules to create installable packages in various formats, but that remains future work. --------- Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
84 lines
2.6 KiB
C++
84 lines
2.6 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 <cstring>
|
|
#include <string>
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "testing/base/test_raw_ostream.h"
|
|
#include "toolchain/driver/driver.h"
|
|
#include "toolchain/install/install_paths.h"
|
|
|
|
namespace Carbon::Testing {
|
|
|
|
static auto Read(const unsigned char*& data, size_t& size, int& output)
|
|
-> bool {
|
|
if (size < sizeof(output)) {
|
|
return false;
|
|
}
|
|
std::memcpy(&output, data, sizeof(output));
|
|
size -= sizeof(output);
|
|
data += sizeof(output);
|
|
return true;
|
|
}
|
|
|
|
extern "C" auto LLVMFuzzerTestOneInput(const unsigned char* data, size_t size)
|
|
-> int {
|
|
// First use the data to compute the number of arguments. Note that for
|
|
// scaling reasons we don't allow 2^31 arguments, even empty ones. Simply
|
|
// creating the vector of those won't work. We limit this to 2^20 arguments
|
|
// total.
|
|
int num_args;
|
|
if (!Read(data, size, num_args) || num_args < 0 || num_args > (1 << 20)) {
|
|
return 0;
|
|
}
|
|
|
|
// Now use the data to compute the length of each argument. We don't want to
|
|
// exhaust all memory, so bound the search space to using 2^17 bytes of
|
|
// memory for the argument text itself.
|
|
size_t arg_length_sum = 0;
|
|
llvm::SmallVector<int> arg_lengths(num_args);
|
|
for (int& arg_length : arg_lengths) {
|
|
if (!Read(data, size, arg_length) || arg_length < 0) {
|
|
return 0;
|
|
}
|
|
arg_length_sum += arg_length;
|
|
if (arg_length_sum > (1 << 17)) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Ensure we have enough data for all the arguments.
|
|
if (size < arg_length_sum) {
|
|
return 0;
|
|
}
|
|
|
|
// Lastly, read the contents of each argument out of the data.
|
|
llvm::SmallVector<llvm::StringRef> args;
|
|
args.reserve(num_args);
|
|
for (int arg_length : arg_lengths) {
|
|
args.push_back(
|
|
llvm::StringRef(reinterpret_cast<const char*>(data), arg_length));
|
|
data += arg_length;
|
|
size -= arg_length;
|
|
}
|
|
|
|
llvm::vfs::InMemoryFileSystem fs;
|
|
// TODO: We should try to thread the executable path into here.
|
|
const auto install_paths = InstallPaths::Make("");
|
|
TestRawOstream error_stream;
|
|
llvm::raw_null_ostream dest;
|
|
Driver d(fs, &install_paths, "", dest, error_stream);
|
|
if (!d.RunCommand(args).success) {
|
|
if (error_stream.TakeStr().find("ERROR:") == std::string::npos) {
|
|
llvm::errs() << "No error message on a failure!\n";
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
} // namespace Carbon::Testing
|