Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions toolchain/driver/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@ filegroup(
]),
)

cc_test(
name = "carbon_runner_test",
size = "small",
srcs = ["carbon_runner_test.cpp"],
deps = [
":driver",
":llvm_runner",
":runtimes_cache",
"//common:all_llvm_targets",
"//common:raw_string_ostream",
"//testing/base:gtest_main",
"//testing/base:capture_std_streams",
"//testing/base:global_exe_path",
"//toolchain/install:install_paths",
"@googletest//:gtest",
"@llvm-project//llvm:TargetParser",
],
)

cc_library(
name = "clang_runner",
srcs = ["clang_runner.cpp"],
Expand Down Expand Up @@ -102,6 +121,8 @@ cc_library(
srcs = [
"build_runtimes_subcommand.cpp",
"build_runtimes_subcommand.h",
"carbon_runner.cpp",
"carbon_runner.h",
Comment on lines +124 to +125
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be split into a separate carbon_runner library? Is there something that goes wrong with that?

"clang_subcommand.cpp",
"clang_subcommand.h",
"codegen_options.cpp",
Expand Down
24 changes: 18 additions & 6 deletions toolchain/driver/build_runtimes_subcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

#include "toolchain/driver/build_runtimes_subcommand.h"

#include <utility>
#include <variant>

#include "common/error.h"
#include "llvm/TargetParser/Triple.h"
#include "toolchain/driver/carbon_runner.h"
#include "toolchain/driver/clang_runner.h"

namespace Carbon {
Expand Down Expand Up @@ -42,7 +45,10 @@ generation flags, and used explicitly when linking.
};

BuildRuntimesSubcommand::BuildRuntimesSubcommand()
: DriverSubcommand(SubcommandInfo) {}
: BuildRuntimesSubcommand({}) {}

BuildRuntimesSubcommand::BuildRuntimesSubcommand(BuildRuntimesOptions options)
: DriverSubcommand(SubcommandInfo), options_(std::move(options)) {}

auto BuildRuntimesSubcommand::Run(DriverEnv& driver_env) -> DriverResult {
// Don't run Clang when fuzzing, it is known to not be reliable under fuzzing
Expand All @@ -68,9 +74,6 @@ auto BuildRuntimesSubcommand::Run(DriverEnv& driver_env) -> DriverResult {

auto BuildRuntimesSubcommand::RunInternal(DriverEnv& driver_env)
-> ErrorOr<std::filesystem::path> {
ClangRunner runner(driver_env.installation, driver_env.fs,
driver_env.vlog_stream);

Runtimes::Cache::Features features = {
.target = options_.codegen_options.target.str()};

Expand All @@ -92,8 +95,17 @@ auto BuildRuntimesSubcommand::RunInternal(DriverEnv& driver_env)
: Runtimes::Make(explicit_output_path, driver_env.vlog_stream));
CARBON_ASSIGN_OR_RETURN(auto tmp_dir, Filesystem::MakeTmpDir());

return runner.BuildTargetResourceDir(features, runtimes, tmp_dir.abs_path(),
*driver_env.thread_pool);
ClangRunner clang_runner(driver_env.installation, driver_env.fs,
driver_env.vlog_stream);

CARBON_RETURN_IF_ERROR(clang_runner.BuildTargetResourceDir(
features, runtimes, tmp_dir.abs_path(), *driver_env.thread_pool));

CarbonRunner carbon_runner(&driver_env);

CARBON_RETURN_IF_ERROR(carbon_runner.BuildCoreLibraries(features, runtimes));

return runtimes.base_path();
}

} // namespace Carbon
6 changes: 6 additions & 0 deletions toolchain/driver/build_runtimes_subcommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "common/command_line.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "toolchain/driver/carbon_runner.h"
#include "toolchain/driver/codegen_options.h"
#include "toolchain/driver/driver_env.h"
#include "toolchain/driver/driver_subcommand.h"
Expand All @@ -26,6 +27,8 @@ struct BuildRuntimesOptions {

// Implements the link subcommand of the driver.
class BuildRuntimesSubcommand : public DriverSubcommand {
friend CarbonRunner;

Comment on lines +30 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? It doesn't seem like it should be...

public:
explicit BuildRuntimesSubcommand();

Expand All @@ -36,6 +39,9 @@ class BuildRuntimesSubcommand : public DriverSubcommand {
auto Run(DriverEnv& driver_env) -> DriverResult override;

private:
// For manual construction of subcommands.
explicit BuildRuntimesSubcommand(BuildRuntimesOptions options);

auto RunInternal(DriverEnv& driver_env) -> ErrorOr<std::filesystem::path>;

BuildRuntimesOptions options_;
Expand Down
169 changes: 169 additions & 0 deletions toolchain/driver/carbon_runner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// 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/carbon_runner.h"

#include <filesystem>
#include <utility>

#include "common/error.h"
#include "common/filesystem.h"
#include "common/vlog.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include "toolchain/driver/build_runtimes_subcommand.h"
#include "toolchain/driver/compile_subcommand.h"
#include "toolchain/driver/driver.h"
#include "toolchain/driver/driver_env.h"
#include "toolchain/driver/driver_subcommand.h"
#include "toolchain/driver/link_subcommand.h"
#include "toolchain/driver/runtimes_cache.h"
#include "toolchain/driver/tool_runner_base.h"
#include "toolchain/install/install_paths.h"

namespace Carbon {

CarbonRunner::CarbonRunner(DriverEnv* driver_env)
: ToolRunnerBase(driver_env->installation, driver_env->vlog_stream),
driver_env_(driver_env) {}

auto CarbonRunner::BuildCoreLibraries(const Runtimes::Cache::Features& features,
Runtimes& runtimes)
-> ErrorOr<std::filesystem::path> {
std::filesystem::path core_a_path = "carbon_core.a";

// Build directory for core libs.
CARBON_ASSIGN_OR_RETURN(auto build_dir,
runtimes.Build(Runtimes::CoreLibraries));
if (std::holds_alternative<std::filesystem::path>(build_dir)) {
// Found cached build.
return std::get<std::filesystem::path>(std::move(build_dir)) / core_a_path;
}

std::string target = features.target;
llvm::Triple target_triple(target);

CARBON_VLOG("Building Carbon core libraries for target '{0}'", target);

// Create temporary directory.
CARBON_ASSIGN_OR_RETURN(auto tmp_path, Filesystem::MakeTmpDir());
CARBON_ASSIGN_OR_RETURN(Filesystem::Dir tmp_dir,
Filesystem::Cwd().OpenDir(tmp_path.abs_path()));

// Collect Core source files.
std::filesystem::path core_src_dir = installation_->core_package();
llvm::SmallVector<std::filesystem::path> core_src_files;

for (const auto& entry :
std::filesystem::recursive_directory_iterator(core_src_dir)) {
const auto& src_path = entry.path();
if (std::filesystem::is_regular_file(src_path) &&
src_path.extension() == ".carbon") {
core_src_files.push_back(src_path);
}
}

// Copy files into the temporary directory.
llvm::SmallVector<std::filesystem::path> tmp_src_files;
for (const auto& core_src_file : core_src_files) {
// Add parent directories.
std::filesystem::path relative_core_src_file =
core_src_file.lexically_relative(core_src_dir);
if (relative_core_src_file.has_parent_path()) {
CARBON_RETURN_IF_ERROR(
tmp_dir.CreateDirectories(relative_core_src_file.parent_path()));
}

std::filesystem::path tmp_src_file =
tmp_path.abs_path() / relative_core_src_file;

// Add to files for compiling.
tmp_src_files.push_back(tmp_src_file);

// Copy file.
std::error_code ec = llvm::sys::fs::copy_file(
std::filesystem::absolute(core_src_file).string(),
tmp_src_file.string());
if (ec) {
return Error(ec.message());
}
}

// Compile object files.
DriverResult result =
Compile(tmp_src_files, Lower::OptimizationLevel::Debug, target_triple,
/*prelude_import=*/false);
if (!result.success) {
return Error("Failed to compile Core libraries.");
}

// Collect Core object files.
llvm::SmallVector<llvm::NewArchiveMember> objs;

for (const auto& entry :
std::filesystem::recursive_directory_iterator(tmp_path.abs_path())) {
const auto& obj_path = entry.path();
if (std::filesystem::is_regular_file(obj_path) &&
obj_path.extension() == ".o") {
auto obj_result = llvm::NewArchiveMember::getFile(obj_path.native(),
/*Deterministic=*/true);
CARBON_CHECK(obj_result, "TODO: Diagnose this: {0}",
llvm::fmt_consume(obj_result.takeError()));
objs.push_back(std::move(*obj_result));
}
}

// Build archive.
auto builder = std::get<Runtimes::Builder>(std::move(build_dir));

CARBON_ASSIGN_OR_RETURN(
Filesystem::WriteFile core_a_file,
builder.dir().OpenWriteOnly(core_a_path, Filesystem::CreateAlways));

{
llvm::raw_fd_ostream core_a_os = core_a_file.WriteStream();
llvm::Error archive_err = llvm::writeArchiveToStream(
core_a_os, objs, llvm::SymtabWritingMode::NormalSymtab,
target_triple.isOSDarwin() ? llvm::object::Archive::K_DARWIN
: llvm::object::Archive::K_GNU,
/*Deterministic=*/true, /*Thin=*/false);
// The presence of an error is `true`.
if (archive_err) {
return Error(llvm::toString(std::move(archive_err)));
}
}
CARBON_RETURN_IF_ERROR(std::move(core_a_file).Close());

CARBON_ASSIGN_OR_RETURN(std::filesystem::path cached_core_path,
std::move(builder).Commit());

return cached_core_path / core_a_path;
}

auto CarbonRunner::Compile(
llvm::SmallVector<std::filesystem::path> input_filenames,
Lower::OptimizationLevel opt_level, llvm::Triple target,
bool prelude_import) -> DriverResult {
// Convert to StringRef vector for options.
llvm::SmallVector<llvm::StringRef> input_filename_refs;
for (const auto& filename : input_filenames) {
// Keep StringRef valid by using c_str() and length().
input_filename_refs.push_back(
llvm::StringRef(filename.c_str(), filename.string().length()));
}

CompileOptions options = {.opt_level = opt_level,
.codegen_options = {.target = target.str()},
.input_filenames = input_filename_refs,
.prelude_import = prelude_import};
CompileSubcommand subcommand(std::move(options));
return subcommand.Run(*driver_env_);
}

} // namespace Carbon
42 changes: 42 additions & 0 deletions toolchain/driver/carbon_runner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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

#ifndef CARBON_TOOLCHAIN_DRIVER_CARBON_RUNNER_H_
#define CARBON_TOOLCHAIN_DRIVER_CARBON_RUNNER_H_

#include <filesystem>

#include "common/error.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/TargetParser/Triple.h"
#include "toolchain/driver/codegen_options.h"
#include "toolchain/driver/driver_env.h"
#include "toolchain/driver/driver_subcommand.h"
#include "toolchain/driver/tool_runner_base.h"
#include "toolchain/lower/options.h"

namespace Carbon {

// Helper class for cross-subcommand functionality.
// Allows type-safe calls of subcommands.
// TODO: May need to be adjusted once caching is refactored.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the refactorings are now landed, so hopefully can update all of this and address the TODOs.

class CarbonRunner : ToolRunnerBase {
public:
explicit CarbonRunner(DriverEnv* driver_env);

// TODO: Will need to be changed when compile subcommand is revised.
auto BuildCoreLibraries(const Runtimes::Cache::Features& features,
Runtimes& runtimes) -> ErrorOr<std::filesystem::path>;

private:
auto Compile(llvm::SmallVector<std::filesystem::path> input_filenames,
Lower::OptimizationLevel opt_level, llvm::Triple target,
bool prelude_import) -> DriverResult;
Comment on lines +33 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't expect this to be private, this seems like it should be part of the public API?


DriverEnv* driver_env_;
};
} // namespace Carbon

#endif // CARBON_TOOLCHAIN_DRIVER_CARBON_RUNNER_H_
Loading
Loading