Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/trunk' into witness
Browse files Browse the repository at this point in the history
  • Loading branch information
josh11b committed Jan 2, 2025
2 parents 2a49a77 + 4a7aefe commit a19c40f
Show file tree
Hide file tree
Showing 352 changed files with 5,160 additions and 111,775 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/nightly_release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ jobs:
- name: Extract the release version
run: |
# Make sure we can run the toolchain to get the version.
./bazel-bin/toolchain/install/run_carbon version
./bazel-bin/toolchain/carbon version
# Now stash it in a variable and export it.
VERSION=$( \
./bazel-bin/toolchain/install/run_carbon version \
./bazel-bin/toolchain/carbon version \
| cut -d' ' -f5 | cut -d'+' -f1)
echo "release_version=$VERSION" >> $GITHUB_ENV
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ wget https://github.com/carbon-language/carbon-lang/releases/download/v${VERSION
tar -xvf carbon_toolchain-${VERSION}.tar.gz

# Create a simple Carbon source file:
echo "fn Run() { Core.Print(42); }" > forty_two.carbon
echo "import Core library \"io\"; fn Run() { Core.Print(42); }" > forty_two.carbon

# Compile to an object file:
./carbon_toolchain-${VERSION}/bin/carbon compile \
Expand Down
16 changes: 12 additions & 4 deletions common/hashing.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,14 @@ class Hasher {
return data;
}

// As above, but for small offsets, we can use aligned loads, which are
// faster. The offset must be in the range [0, 8).
static auto SampleAlignedRandomData(ssize_t offset) -> uint64_t {
CARBON_DCHECK(static_cast<size_t>(offset) <
sizeof(StaticRandomData) / sizeof(uint64_t));
return StaticRandomData[offset];
}

// Random data taken from the hexadecimal digits of Pi's fractional component,
// written in lexical order for convenience of reading. The resulting
// byte-stream will be different due to little-endian integers. These can be
Expand All @@ -408,7 +416,7 @@ class Hasher {
// | sed -e "s/.\{4\}/&'/g" \
// | sed -e "s/\(.\{4\}'.\{4\}'.\{4\}'.\{4\}\)'/0x\1,\n/g"
// ```
static constexpr std::array<uint64_t, 8> StaticRandomData = {
alignas(64) static constexpr std::array<uint64_t, 8> StaticRandomData = {
0x243f'6a88'85a3'08d3, 0x1319'8a2e'0370'7344, 0xa409'3822'299f'31d0,
0x082e'fa98'ec4e'6c89, 0x4528'21e6'38d0'1377, 0xbe54'66cf'34e9'0c6c,
0xc0ac'29b7'c97c'50dd, 0x3f84'd5b5'b547'0917,
Expand Down Expand Up @@ -703,15 +711,15 @@ inline auto Hasher::Read1To3(const std::byte* data, ssize_t size) -> uint64_t {
uint64_t byte0 = static_cast<uint8_t>(data[0]);
uint64_t byte1 = static_cast<uint8_t>(data[size - 1]);
uint64_t byte2 = static_cast<uint8_t>(data[size >> 1]);
return byte0 | (byte1 << 16) | (byte2 << 8);
return (byte0 << 8) | (byte1 << 16) | byte2;
}

inline auto Hasher::Read4To8(const std::byte* data, ssize_t size) -> uint64_t {
uint32_t low;
std::memcpy(&low, data, sizeof(low));
uint32_t high;
std::memcpy(&high, data + size - sizeof(high), sizeof(high));
return low | (static_cast<uint64_t>(high) << 32);
return (static_cast<uint64_t>(low) << 32) | high;
}

inline auto Hasher::Read8To16(const std::byte* data, ssize_t size)
Expand Down Expand Up @@ -950,7 +958,7 @@ inline auto Hasher::HashSizedBytes(llvm::ArrayRef<std::byte> bytes) -> void {
// Note that we don't drop to the `WeakMix` routine here because we want
// to use sampled random data to encode the size, which may not be as
// effective without the full 128-bit folded result.
buffer = Mix(data ^ buffer, SampleRandomData(size));
buffer = Mix(data ^ buffer, SampleAlignedRandomData(size - 1));
CARBON_MCA_END("dynamic-8b");
return;
}
Expand Down
35 changes: 14 additions & 21 deletions common/raw_hashtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -570,16 +570,13 @@ class BaseImpl {
auto CopySlotsFrom(const BaseImpl& arg) -> void;
auto MoveFrom(BaseImpl&& arg, Storage* small_storage) -> void;

template <typename LookupKeyT>
auto InsertIntoEmpty(LookupKeyT lookup_key, KeyContextT key_context)
-> EntryT*;
auto InsertIntoEmpty(HashCode hash) -> EntryT*;

static auto ComputeNextAllocSize(ssize_t old_alloc_size) -> ssize_t;
static auto GrowthThresholdForAllocSize(ssize_t alloc_size) -> ssize_t;

auto GrowToNextAllocSize(KeyContextT key_context) -> void;
template <typename LookupKeyT>
auto GrowAndInsert(LookupKeyT lookup_key, KeyContextT key_context) -> EntryT*;
auto GrowAndInsert(HashCode hash, KeyContextT key_context) -> EntryT*;

ViewImplT view_impl_;
int growth_budget_;
Expand Down Expand Up @@ -974,7 +971,7 @@ auto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::InsertImpl(
// empty slot. Without the growth budget we'll have to completely rehash and
// so we can just bail here.
if (LLVM_UNLIKELY(growth_budget_ == 0)) {
return {GrowAndInsert(lookup_key, key_context), true};
return {GrowAndInsert(hash, key_context), true};
}

--growth_budget_;
Expand Down Expand Up @@ -1029,8 +1026,9 @@ BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowToAllocSizeImpl(
for (ssize_t byte_index : present_matched_range) {
++count;
ssize_t index = group_index + byte_index;
EntryT* new_entry =
InsertIntoEmpty(old_entries[index].key(), key_context);
HashCode hash =
key_context.HashKey(old_entries[index].key(), ComputeSeed());
EntryT* new_entry = InsertIntoEmpty(hash);
new_entry->MoveFrom(std::move(old_entries[index]));
}
}
Expand Down Expand Up @@ -1291,11 +1289,8 @@ auto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::MoveFrom(
// these are true, typically just after growth, we can dramatically simplify the
// insert position search.
template <typename InputKeyT, typename InputValueT, typename InputKeyContextT>
template <typename LookupKeyT>
[[clang::noinline]] auto
BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::InsertIntoEmpty(
LookupKeyT lookup_key, KeyContextT key_context) -> EntryT* {
HashCode hash = key_context.HashKey(lookup_key, ComputeSeed());
auto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::InsertIntoEmpty(
HashCode hash) -> EntryT* {
auto [hash_index, tag] = hash.ExtractIndexAndTag<7>();
uint8_t* local_metadata = metadata();
EntryT* local_entries = entries();
Expand Down Expand Up @@ -1375,7 +1370,7 @@ auto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowToNextAllocSize(
// the group walk rather than after the group walk. In practice, between the
// statistical rareness and using a large small size buffer here on the stack,
// we can handle this most efficiently with temporary, additional storage.
llvm::SmallVector<ssize_t, 128> probed_indices;
llvm::SmallVector<std::pair<ssize_t, HashCode>, 128> probed_indices;

// Create locals for the old state of the table.
ssize_t old_size = alloc_size();
Expand Down Expand Up @@ -1449,7 +1444,7 @@ auto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowToNextAllocSize(
ssize_t old_hash_index = hash.ExtractIndexAndTag<7>().first &
ComputeProbeMaskFromSize(old_size);
if (LLVM_UNLIKELY(old_hash_index != group_index)) {
probed_indices.push_back(old_index);
probed_indices.push_back({old_index, hash});
if constexpr (MetadataGroup::FastByteClear) {
low_g.ClearByte(byte_index);
high_g.ClearByte(byte_index);
Expand Down Expand Up @@ -1510,9 +1505,8 @@ auto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowToNextAllocSize(

// We then need to do a normal insertion for anything that was probed before
// growth, but we know we'll find an empty slot, so leverage that.
for (ssize_t old_index : probed_indices) {
EntryT* new_entry =
InsertIntoEmpty(old_entries[old_index].key(), key_context);
for (auto [old_index, hash] : probed_indices) {
EntryT* new_entry = InsertIntoEmpty(hash);
new_entry->MoveFrom(std::move(old_entries[old_index]));
}
CARBON_DCHECK(count ==
Expand All @@ -1538,16 +1532,15 @@ auto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowToNextAllocSize(
// that this function can be directly called and the result returned from
// `InsertImpl`.
template <typename InputKeyT, typename InputValueT, typename InputKeyContextT>
template <typename LookupKeyT>
[[clang::noinline]] auto
BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowAndInsert(
LookupKeyT lookup_key, KeyContextT key_context) -> EntryT* {
HashCode hash, KeyContextT key_context) -> EntryT* {
GrowToNextAllocSize(key_context);

// And insert the lookup_key into an index in the newly grown map and return
// that index for use.
--growth_budget_;
return InsertIntoEmpty(lookup_key, key_context);
return InsertIntoEmpty(hash);
}

template <typename InputBaseT, ssize_t SmallSize>
Expand Down
3 changes: 1 addition & 2 deletions core/io.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ fn PrintChar(x: i32) -> i32 = "print.char";
fn ReadChar() -> i32 = "read.char";

// TODO: Change this to a global constant once they are fully supported.
// TODO: Use simply -1 once we support negate on an IntLiteral.
fn EOF() -> i32 { return -(1 as i32); }
fn EOF() -> i32 { return -1; }
29 changes: 29 additions & 0 deletions core/prelude/operators/arithmetic.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package Core library "prelude/operators/arithmetic";

import library "prelude/types/int_literal";

// Addition: `a + b`.
interface Add {
fn Op[self: Self](other: Self) -> Self;
Expand Down Expand Up @@ -68,3 +70,30 @@ interface Mod {
interface ModAssign {
fn Op[addr self: Self*](other: Self);
}


// Operations for IntLiteral. These need to be here because IntLiteral has no
// associated library of its own.
impl IntLiteral() as Add {
fn Op[self: Self](other: Self) -> Self = "int.sadd";
}

impl IntLiteral() as Div {
fn Op[self: Self](other: Self) -> Self = "int.sdiv";
}

impl IntLiteral() as Mod {
fn Op[self: Self](other: Self) -> Self = "int.smod";
}

impl IntLiteral() as Mul {
fn Op[self: Self](other: Self) -> Self = "int.smul";
}

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

impl IntLiteral() as Sub {
fn Op[self: Self](other: Self) -> Self = "int.ssub";
}
29 changes: 29 additions & 0 deletions core/prelude/operators/bitwise.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package Core library "prelude/operators/bitwise";

import library "prelude/types/int_literal";

// Bit complement: `^a`.
interface BitComplement {
fn Op[self: Self]() -> Self;
Expand Down Expand Up @@ -58,3 +60,30 @@ interface RightShift {
interface RightShiftAssign {
fn Op[addr self: Self*](other: Self);
}


// Operations for IntLiteral. These need to be here because IntLiteral has no
// associated library of its own.
impl IntLiteral() as BitAnd {
fn Op[self: Self](other: Self) -> Self = "int.and";
}

impl IntLiteral() as BitComplement {
fn Op[self: Self]() -> Self = "int.complement";
}

impl IntLiteral() as BitOr {
fn Op[self: Self](other: Self) -> Self = "int.or";
}

impl IntLiteral() as BitXor {
fn Op[self: Self](other: Self) -> Self = "int.xor";
}

impl IntLiteral() as LeftShift {
fn Op[self: Self](other: Self) -> Self = "int.left_shift";
}

impl IntLiteral() as RightShift {
fn Op[self: Self](other: Self) -> Self = "int.right_shift";
}
17 changes: 17 additions & 0 deletions core/prelude/operators/comparison.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package Core library "prelude/operators/comparison";

export import library "prelude/types/bool";
import library "prelude/types/int_literal";

// Equality comparison: `a == b` and `a != b`.
interface Eq {
Expand All @@ -28,3 +29,19 @@ impl bool as Eq {
fn Equal[self: Self](other: Self) -> bool = "bool.eq";
fn NotEqual[self: Self](other: Self) -> bool = "bool.neq";
}


// Operations for IntLiteral. These need to be here because IntLiteral has no
// associated library of its own.
impl IntLiteral() as Eq {
fn Equal[self: Self](other: Self) -> bool = "int.eq";
fn NotEqual[self: Self](other: Self) -> bool = "int.neq";
}

impl IntLiteral() as Ordered {
// TODO: fn Compare
fn Less[self: Self](other: Self) -> bool = "int.less";
fn LessOrEquivalent[self: Self](other: Self) -> bool = "int.less_eq";
fn Greater[self: Self](other: Self) -> bool = "int.greater";
fn GreaterOrEquivalent[self: Self](other: Self) -> bool = "int.greater_eq";
}
12 changes: 6 additions & 6 deletions core/prelude/types/uint.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,27 @@ impl forall [N:! IntLiteral()] UInt(N) as Ordered {
// Arithmetic.

impl forall [N:! IntLiteral()] UInt(N) as Add {
fn Op[self: Self](other: Self) -> Self = "int.sadd";
fn Op[self: Self](other: Self) -> Self = "int.uadd";
}

impl forall [N:! IntLiteral()] UInt(N) as Div {
fn Op[self: Self](other: Self) -> Self = "int.sdiv";
fn Op[self: Self](other: Self) -> Self = "int.udiv";
}

impl forall [N:! IntLiteral()] UInt(N) as Mod {
fn Op[self: Self](other: Self) -> Self = "int.smod";
fn Op[self: Self](other: Self) -> Self = "int.umod";
}

impl forall [N:! IntLiteral()] UInt(N) as Mul {
fn Op[self: Self](other: Self) -> Self = "int.smul";
fn Op[self: Self](other: Self) -> Self = "int.umul";
}

impl forall [N:! IntLiteral()] UInt(N) as Negate {
fn Op[self: Self]() -> Self = "int.snegate";
fn Op[self: Self]() -> Self = "int.unegate";
}

impl forall [N:! IntLiteral()] UInt(N) as Sub {
fn Op[self: Self](other: Self) -> Self = "int.ssub";
fn Op[self: Self](other: Self) -> Self = "int.usub";
}

// Bitwise operators.
Expand Down
7 changes: 0 additions & 7 deletions explorer/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,6 @@ file_test(
),
)

filegroup(
name = "carbon_files",
srcs = glob(["testdata/**/*.carbon"]),
# Files are used for validating fuzzer completeness.
visibility = ["//explorer/fuzzing:__pkg__"],
)

filegroup(
name = "treesitter_testdata",
srcs = glob(
Expand Down
5 changes: 0 additions & 5 deletions explorer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,6 @@ To explain this boilerplate:
- `bazel run testdata/DIR/FILE.carbon.verbose` -- Runs explorer on the file
with tracing enabled.

### Updating fuzzer logic after making AST changes

Please refer to
[Fuzzer documentation](https://github.com/carbon-language/carbon-lang/blob/trunk/explorer/fuzzing/README.md).

## Explorer's Trace Output

Explorer's Trace Output refers to a detailed record of program phases and their
Expand Down
1 change: 0 additions & 1 deletion explorer/parse_and_execute/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")

package(default_visibility = [
"//explorer:__pkg__",
"//explorer/fuzzing:__pkg__",
])

cc_library(
Expand Down
1 change: 0 additions & 1 deletion explorer/syntax/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ cc_library(
# don't spend time linting it.
tags = ["no-clang-tidy"],
visibility = [
"//explorer/fuzzing:__pkg__",
"//explorer/parse_and_execute:__pkg__",
],
deps = [
Expand Down
10 changes: 10 additions & 0 deletions testing/file_test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ Supported comment markers are:
ARGS can be specified at most once. If not provided, the FileTestBase child
is responsible for providing default arguments.
- ```
// EXTRA-ARGS: <arguments>
```
Same as `ARGS`, including substitution behavior, but appends to the default
argument list instead of replacing it.
`EXTRA-ARGS` can be specified at most once, and a test cannot specify both
`ARGS` and `EXTRA-ARGS`.
- ```
// SET-CAPTURE-CONSOLE-OUTPUT
```
Expand Down
Loading

0 comments on commit a19c40f

Please sign in to comment.