Skip to content

Commit

Permalink
Make driver find all prelude files. Add build rule for //examples:sie…
Browse files Browse the repository at this point in the history
…ve. (carbon-language#3895)

The driver now looks for all files under core/prelude/ and considers
them all to be part of the prelude. The driver also now only processes
the prelude in `--phase=check` and later, when it would actually be
imported.

With that done, add a simple `carbon_binary` build rule and use it to
build the example in `//examples`. This should cause the example to be
built as part of our continuous integration.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
  • Loading branch information
zygoloid and jonmeow authored Apr 19, 2024
1 parent cae6276 commit f5e386a
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 67 deletions.
3 changes: 3 additions & 0 deletions bazel/carbon_rules/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 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
47 changes: 47 additions & 0 deletions bazel/carbon_rules/defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 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

"""Provides rules for building Carbon files using the toolchain."""

load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_import")

def carbon_binary(name, srcs):
"""Compiles a Carbon binary.
Args:
name: The name of the build target.
srcs: List of Carbon source files to compile.
"""
for src in srcs:
# Build each source file. For now, we pass all sources to each compile
# because we don't have visibility into dependencies and have no way to
# specify multiple output files. Object code for each input is written
# into the output file in turn, so the final carbon source file
# specified ends up determining the contents of the object file.
#
# TODO: This is a hack; replace with something better once the toolchain
# supports doing so.
out = src + ".o"
srcs_reordered = [s for s in srcs if s != src] + [src]
run_binary(
name = src + ".compile",
tool = "//toolchain/driver:carbon",
args = (["compile"] +
["$(location %s)" % s for s in srcs_reordered] +
["--output=$(location %s)" % out]),
srcs = srcs,
outs = [out],
)
cc_import(
name = "%s.objs" % name,
objects = [src + ".compile" for src in srcs],
)

# For now, we assume that the prelude doesn't produce any necessary object
# code, and don't include the .o files for //core/prelude... in the final
# linked binary.
#
# TODO: This will need to be revisited eventually.
cc_binary(name = name, deps = ["%s.objs" % name])
5 changes: 3 additions & 2 deletions core/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
# Exceptions. See /LICENSE for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

# The prelude, and all of its dependencies.
filegroup(
name = "core",
data = glob(["**/*.carbon"]),
name = "prelude",
data = ["prelude.carbon"] + glob(["prelude/**/*.carbon"]),
visibility = ["//visibility:public"],
)
3 changes: 3 additions & 0 deletions core/prelude.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

package Core library "prelude" api;

import library "prelude/operators";
import library "prelude/types";

// TODO: Uncomment once name deduplication works.
// TODO: These are here for name lookup. Add a way to export import and move them out.
// fn Int32() -> type = "int.make_type_32";
Expand Down
12 changes: 12 additions & 0 deletions core/prelude/types.carbon
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 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

package Core library "prelude/types" api;

// TODO: Add a mechanism to re-export the names declared here.

// TODO: Start importing `prelude/types/i32` here once we stop eagerly importing
// all `impl`s from all imported files. Currently, this introduces too much
// noise in the toolchain tests.
// import library "prelude/types/i32";
12 changes: 6 additions & 6 deletions core/prelude/types/i32.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import library "prelude/operators/bitwise";
import library "prelude/operators/comparison";

impl i32 as Add {
fn Op[self: Self](other: Self) -> Self = "int.add";
fn Op[self: Self](other: Self) -> Self = "int.sadd";
}
impl i32 as AddAssign {
fn Op[addr self: Self*](other: Self) {
Expand Down Expand Up @@ -63,7 +63,7 @@ impl i32 as BitXorAssign {
}

impl i32 as Div {
fn Op[self: Self](other: Self) -> Self = "int.div";
fn Op[self: Self](other: Self) -> Self = "int.sdiv";
}
impl i32 as DivAssign {
fn Op[addr self: Self*](other: Self) {
Expand All @@ -88,7 +88,7 @@ impl i32 as LeftShiftAssign {
}

impl i32 as Mod {
fn Op[self: Self](other: Self) -> Self = "int.mod";
fn Op[self: Self](other: Self) -> Self = "int.smod";
}
impl i32 as ModAssign {
fn Op[addr self: Self*](other: Self) {
Expand All @@ -98,7 +98,7 @@ impl i32 as ModAssign {
}

impl i32 as Mul {
fn Op[self: Self](other: Self) -> Self = "int.mul";
fn Op[self: Self](other: Self) -> Self = "int.smul";
}
impl i32 as MulAssign {
fn Op[addr self: Self*](other: Self) {
Expand All @@ -108,7 +108,7 @@ impl i32 as MulAssign {
}

impl i32 as Negate {
fn Op[self: Self]() -> Self = "int.negate";
fn Op[self: Self]() -> Self = "int.snegate";
}

impl i32 as Ordered {
Expand All @@ -130,7 +130,7 @@ impl i32 as RightShiftAssign {
}

impl i32 as Sub {
fn Op[self: Self](other: Self) -> Self = "int.sub";
fn Op[self: Self](other: Self) -> Self = "int.ssub";
}
impl i32 as SubAssign {
fn Op[addr self: Self*](other: Self) {
Expand Down
10 changes: 10 additions & 0 deletions examples/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 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

load("//bazel/carbon_rules:defs.bzl", "carbon_binary")

carbon_binary(
name = "sieve",
srcs = ["sieve.carbon"],
)
17 changes: 9 additions & 8 deletions examples/sieve.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import Core library "prelude/operators/arithmetic";
import Core library "prelude/operators/comparison";

// TODO: Copied from core/prelude/types/i32.carbon.
// Remove the following, once we do cross-file impl lookup.
// import Core library "prelude/types/i32";
// Because we don't deduplicate interfaces, the implementations in that file are
// treated as implementing a different interface from the one we import above.
// Remove the following, once we deduplicate interfaces.

impl i32 as Core.Add {
fn Op[self: Self](other: Self) -> Self = "int.add";
fn Op[self: Self](other: Self) -> Self = "int.sadd";
}
impl i32 as Core.AddAssign {
fn Op[addr self: Self*](other: Self) {
Expand All @@ -26,7 +27,7 @@ impl i32 as Core.Inc {
}

impl i32 as Core.Div {
fn Op[self: Self](other: Self) -> Self = "int.div";
fn Op[self: Self](other: Self) -> Self = "int.sdiv";
}
impl i32 as Core.DivAssign {
fn Op[addr self: Self*](other: Self) {
Expand All @@ -40,7 +41,7 @@ impl i32 as Core.Eq {
}

impl i32 as Core.Mod {
fn Op[self: Self](other: Self) -> Self = "int.mod";
fn Op[self: Self](other: Self) -> Self = "int.smod";
}
impl i32 as Core.ModAssign {
fn Op[addr self: Self*](other: Self) {
Expand All @@ -49,7 +50,7 @@ impl i32 as Core.ModAssign {
}

impl i32 as Core.Mul {
fn Op[self: Self](other: Self) -> Self = "int.mul";
fn Op[self: Self](other: Self) -> Self = "int.smul";
}
impl i32 as Core.MulAssign {
fn Op[addr self: Self*](other: Self) {
Expand All @@ -58,7 +59,7 @@ impl i32 as Core.MulAssign {
}

impl i32 as Core.Negate {
fn Op[self: Self]() -> Self = "int.negate";
fn Op[self: Self]() -> Self = "int.snegate";
}

impl i32 as Core.Ordered {
Expand All @@ -70,7 +71,7 @@ impl i32 as Core.Ordered {
}

impl i32 as Core.Sub {
fn Op[self: Self](other: Self) -> Self = "int.sub";
fn Op[self: Self](other: Self) -> Self = "int.ssub";
}
impl i32 as Core.SubAssign {
fn Op[addr self: Self*](other: Self) {
Expand Down
2 changes: 1 addition & 1 deletion toolchain/driver/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ cc_library(
name = "driver",
srcs = ["driver.cpp"],
hdrs = ["driver.h"],
data = ["//core"],
data = ["//core:prelude"],
textual_hdrs = ["flags.def"],
deps = [
"//common:command_line",
Expand Down
92 changes: 67 additions & 25 deletions toolchain/driver/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,44 @@

namespace Carbon {

auto Driver::FindPreludeFiles(llvm::StringRef data_dir,
llvm::raw_ostream& error_stream)
-> llvm::SmallVector<std::string> {
llvm::SmallVector<std::string> result;

// Include <data>/core/prelude.carbon, which is the entry point into the
// prelude.
{
llvm::SmallString<256> prelude_file(data_dir);
llvm::sys::path::append(prelude_file, llvm::sys::path::Style::posix,
"core/prelude.carbon");
result.push_back(prelude_file.str().str());
}

// Glob for <data>/core/prelude/**/*.carbon and add all the files we find.
llvm::SmallString<256> prelude_dir(data_dir);
llvm::sys::path::append(prelude_dir, llvm::sys::path::Style::posix,
"core/prelude");
std::error_code ec;
for (llvm::sys::fs::recursive_directory_iterator prelude_files_it(
prelude_dir, ec, /*follow_symlinks=*/false);
prelude_files_it != llvm::sys::fs::recursive_directory_iterator();
prelude_files_it.increment(ec)) {
if (ec) {
error_stream << "ERROR: Could not find prelude: " << ec.message() << "\n";
result.clear();
return result;
}

auto prelude_file = prelude_files_it->path();
if (llvm::sys::path::extension(prelude_file) == ".carbon") {
result.push_back(prelude_file);
}
}

return result;
}

struct Driver::CompileOptions {
static constexpr CommandLine::CommandInfo Info = {
.name = "compile",
Expand Down Expand Up @@ -548,12 +586,17 @@ class Driver::CompilationUnit {
LogCall("CodeGen", [&] { success_ = RunCodeGenHelper(); });
}

// Flushes output.
auto Flush() -> void { consumer_->Flush(); }
// Runs post-compile logic. This is always called, and called after all other
// actions on the CompilationUnit.
auto PostCompile() const -> void {
if (options_.dump_shared_values && IncludeInDumps()) {
Yaml::Print(driver_->output_stream_,
value_stores_.OutputYaml(input_filename_));
}

auto PrintSharedValues() const -> void {
Yaml::Print(driver_->output_stream_,
value_stores_.OutputYaml(input_filename_));
// The diagnostics consumer must be flushed before compilation artifacts are
// destructed, because diagnostics can refer to their state.
consumer_->Flush();
}

auto input_filename() -> llvm::StringRef { return input_filename_; }
Expand Down Expand Up @@ -672,20 +715,26 @@ auto Driver::Compile(const CompileOptions& options) -> RunResult {
return {.success = false};
}

// Find the files comprising the prelude if we are importing it.
// TODO: Replace this with a search for library api files in a
// package-specific search path based on the library name.
bool want_prelude =
options.prelude_import && options.phase >= CompileOptions::Phase::Check;
auto prelude = want_prelude ? FindPreludeFiles(data_dir_, error_stream_)
: llvm::SmallVector<std::string>{};
if (want_prelude && prelude.empty()) {
return {.success = false};
}

// Prepare CompilationUnits before building scope exit handlers.
StreamDiagnosticConsumer stream_consumer(error_stream_);
llvm::SmallVector<std::unique_ptr<CompilationUnit>> units;
units.reserve(options.prelude_import + options.input_filenames.size());
units.reserve(prelude.size() + options.input_filenames.size());

// Directly insert the core package into the compilation units.
// TODO: Should expand this into a more rich system to search for the core
// package source code.
if (options.prelude_import) {
llvm::SmallString<256> prelude_file(data_dir_);
llvm::sys::path::append(prelude_file, llvm::sys::path::Style::posix,
"core/prelude.carbon");
// Add the prelude files.
for (const auto& input_filename : prelude) {
units.push_back(std::make_unique<CompilationUnit>(
this, options, &stream_consumer, prelude_file));
this, options, &stream_consumer, input_filename));
}

// Add the input source files.
Expand All @@ -695,19 +744,12 @@ auto Driver::Compile(const CompileOptions& options) -> RunResult {
}

auto on_exit = llvm::make_scope_exit([&]() {
// Shared values will always be printed after per-file printing.
if (options.dump_shared_values) {
for (const auto& unit : units) {
unit->PrintSharedValues();
}
}

// The diagnostics consumer must be flushed before compilation artifacts are
// destructed, because diagnostics can refer to their state. This ensures
// they're flushed in order of arguments, rather than order of destruction.
// Finish compilation units. This flushes their diagnostics in the order in
// which they were specified on the command line.
for (auto& unit : units) {
unit->Flush();
unit->PostCompile();
}

stream_consumer.Flush();
});

Expand Down
7 changes: 7 additions & 0 deletions toolchain/driver/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ class Driver {
// error stream (stderr by default).
auto RunCommand(llvm::ArrayRef<llvm::StringRef> args) -> RunResult;

// Finds the source files that define the prelude and returns a list of their
// filenames. On error, writes a message to `error_stream` and returns an
// empty list.
static auto FindPreludeFiles(llvm::StringRef data_dir,
llvm::raw_ostream& error_stream)
-> llvm::SmallVector<std::string>;

private:
struct Options;
struct CompileOptions;
Expand Down
9 changes: 0 additions & 9 deletions toolchain/driver/testdata/dump_shared_values.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,6 @@ var real3: f64 = 0.8e9;
var str1: String = "abc";
var str2: String = "ab'\"c";

// CHECK:STDOUT: ---
// CHECK:STDOUT: filename: 'core/prelude.carbon'
// CHECK:STDOUT: shared_values:
// CHECK:STDOUT: ints: {}
// CHECK:STDOUT: reals: {}
// CHECK:STDOUT: strings:
// CHECK:STDOUT: str0: Core
// CHECK:STDOUT: str1: prelude
// CHECK:STDOUT: ...
// CHECK:STDOUT: ---
// CHECK:STDOUT: filename: dump_shared_values.carbon
// CHECK:STDOUT: shared_values:
Expand Down
Loading

0 comments on commit f5e386a

Please sign in to comment.