Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/trunk' into dump
Browse files Browse the repository at this point in the history
  • Loading branch information
josh11b committed Jan 2, 2025
2 parents f307afb + 4a7aefe commit 8c7404a
Show file tree
Hide file tree
Showing 103 changed files with 2,646 additions and 12,716 deletions.
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";
}
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
23 changes: 16 additions & 7 deletions testing/file_test/file_test_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ auto FileTestBase::ProcessTestFileAndRun(TestContext& context)
// Process arguments.
if (context.test_args.empty()) {
context.test_args = GetDefaultArgs();
context.test_args.append(context.extra_args);
}
CARBON_RETURN_IF_ERROR(
DoArgReplacements(context.test_args, context.test_files));
Expand Down Expand Up @@ -767,24 +768,31 @@ static auto TryConsumeCheck(
return true;
}

// Processes ARGS lines when found. Returns true if the line is consumed.
// Processes ARGS and EXTRA-ARGS lines when found. Returns true if the line is
// consumed.
static auto TryConsumeArgs(llvm::StringRef line, llvm::StringRef line_trimmed,
llvm::SmallVector<std::string>* args)
llvm::SmallVector<std::string>* args,
llvm::SmallVector<std::string>* extra_args)
-> ErrorOr<bool> {
if (!line_trimmed.consume_front("// ARGS: ")) {
llvm::SmallVector<std::string>* arg_list = nullptr;
if (line_trimmed.consume_front("// ARGS: ")) {
arg_list = args;
} else if (line_trimmed.consume_front("// EXTRA-ARGS: ")) {
arg_list = extra_args;
} else {
return false;
}

if (!args->empty()) {
return ErrorBuilder() << "ARGS was specified multiple times: "
if (!args->empty() || !extra_args->empty()) {
return ErrorBuilder() << "ARGS / EXTRA-ARGS specified multiple times: "
<< line.str();
}

// Split the line into arguments.
std::pair<llvm::StringRef, llvm::StringRef> cursor =
llvm::getToken(line_trimmed);
while (!cursor.first.empty()) {
args->push_back(std::string(cursor.first));
arg_list->push_back(std::string(cursor.first));
cursor = llvm::getToken(cursor.second);
}

Expand Down Expand Up @@ -884,7 +892,8 @@ auto FileTestBase::ProcessTestFile(TestContext& context) -> ErrorOr<Success> {
FileTestLine(split.file_index, line_index, line));

CARBON_ASSIGN_OR_RETURN(
is_consumed, TryConsumeArgs(line, line_trimmed, &context.test_args));
is_consumed, TryConsumeArgs(line, line_trimmed, &context.test_args,
&context.extra_args));
if (is_consumed) {
continue;
}
Expand Down
4 changes: 4 additions & 0 deletions testing/file_test/file_test_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ class FileTestBase : public testing::Test {
// Arguments for the test, generated from ARGS.
llvm::SmallVector<std::string> test_args;

// Extra arguments for the test, generated from EXTRA-ARGS. Unlike ARGS,
// setting EXTRA-ARGS does not suppress the default arguments.
llvm::SmallVector<std::string> extra_args;

// Files in the test, generated by content and splits.
llvm::SmallVector<TestFile> test_files;

Expand Down
Loading

0 comments on commit 8c7404a

Please sign in to comment.