Skip to content

Commit e89bd87

Browse files
committed
WIP
1 parent 8d08e77 commit e89bd87

21 files changed

+574
-483
lines changed

toolchain/base/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ cc_library(
6565
hdrs = ["fixed_size_value_store.h"],
6666
deps = [
6767
":mem_usage",
68+
":value_store",
6869
":value_store_types",
6970
"//common:check",
7071
"@llvm-project//llvm:Support",

toolchain/base/fixed_size_value_store.h

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "llvm/ADT/StringRef.h"
1111
#include "llvm/ADT/iterator_range.h"
1212
#include "toolchain/base/mem_usage.h"
13+
#include "toolchain/base/value_store.h"
1314
#include "toolchain/base/value_store_types.h"
1415

1516
namespace Carbon {
@@ -44,9 +45,11 @@ class FixedSizeValueStore {
4445
}
4546

4647
// Makes a ValueStore of the specified size, initialized to a default.
47-
static auto MakeWithExplicitSize(size_t size, ConstRefType default_value)
48+
static auto MakeWithExplicitSize(CheckIRIdTag tag, size_t size,
49+
ConstRefType default_value)
4850
-> FixedSizeValueStore {
4951
FixedSizeValueStore store;
52+
store.tag_ = tag;
5053
store.values_.resize(size, default_value);
5154
return store;
5255
}
@@ -57,7 +60,8 @@ class FixedSizeValueStore {
5760
template <typename ValueStoreT>
5861
requires std::same_as<IdT, typename ValueStoreT::IdType>
5962
explicit FixedSizeValueStore(const ValueStoreT& size_source,
60-
ConstRefType default_value) {
63+
ConstRefType default_value)
64+
: tag_(GetCheckIRIdTag(size_source)) {
6165
values_.resize(size_source.size(), default_value);
6266
}
6367

@@ -70,7 +74,8 @@ class FixedSizeValueStore {
7074
llvm::function_ref<
7175
auto(IdT, typename ValueStoreT::ConstRefType)->ValueType>
7276
factory_fn)
73-
: values_(llvm::map_range(source.enumerate(), factory_fn)) {}
77+
: values_(llvm::map_range(source.enumerate(), factory_fn)),
78+
tag_(GetCheckIRIdTag(source)) {}
7479

7580
// Move-only.
7681
FixedSizeValueStore(FixedSizeValueStore&&) noexcept = default;
@@ -79,20 +84,23 @@ class FixedSizeValueStore {
7984

8085
// Sets the value for an ID.
8186
auto Set(IdT id, ValueType value) -> void {
82-
CARBON_DCHECK(id.index >= 0, "{0}", id);
83-
values_[id.index] = value;
87+
auto index = tag_.Remove(id.index);
88+
CARBON_DCHECK(index >= 0, "{0}", id);
89+
values_[index] = value;
8490
}
8591

8692
// Returns a mutable value for an ID.
8793
auto Get(IdT id) -> RefType {
88-
CARBON_DCHECK(id.index >= 0, "{0}", id);
89-
return values_[id.index];
94+
auto index = tag_.Remove(id.index);
95+
CARBON_DCHECK(index >= 0, "{0}", id);
96+
return values_[index];
9097
}
9198

9299
// Returns the value for an ID.
93100
auto Get(IdT id) const -> ConstRefType {
94-
CARBON_DCHECK(id.index >= 0, "{0}", id);
95-
return values_[id.index];
101+
auto index = tag_.Remove(id.index);
102+
CARBON_DCHECK(index >= 0, "{0}", id);
103+
return values_[index];
96104
}
97105

98106
// Collects memory usage of the values.
@@ -119,6 +127,8 @@ class FixedSizeValueStore {
119127

120128
// Storage for the `ValueT` objects, indexed by the id.
121129
llvm::SmallVector<ValueT, 0> values_;
130+
131+
CheckIRIdTag tag_;
122132
};
123133

124134
} // namespace Carbon

toolchain/base/value_store.h

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,42 @@ class ValueStoreNotPrintable {};
3232

3333
} // namespace Internal
3434

35+
struct CheckIRIdTag {
36+
CheckIRIdTag()
37+
: check_id_tag_(0),
38+
initial_reserved_ids_(std::numeric_limits<int32_t>::max()) {}
39+
explicit CheckIRIdTag(int32_t check_id_index, int32_t initial_reserved_ids)
40+
: initial_reserved_ids_(initial_reserved_ids) {
41+
// Shift down by 1 to get out of the high bit to avoid using any negative
42+
// ids, since they have special uses.
43+
check_id_tag_ = llvm::reverseBits((((check_id_index + 1) << 1) | 1) << 1);
44+
}
45+
auto Apply(int32_t index) const -> int32_t {
46+
if (index < initial_reserved_ids_) {
47+
return index;
48+
}
49+
// assert that check_id_tag_ doesn't have the second highest bit set
50+
return index ^ check_id_tag_;
51+
}
52+
auto Remove(int32_t tagged_index) const -> int32_t {
53+
if ((llvm::reverseBits(2) & tagged_index) == 0) {
54+
CARBON_CHECK(tagged_index < initial_reserved_ids_);
55+
return tagged_index;
56+
}
57+
auto index = tagged_index ^ check_id_tag_;
58+
CARBON_CHECK(index >= initial_reserved_ids_);
59+
return index;
60+
}
61+
int32_t check_id_tag_;
62+
int32_t initial_reserved_ids_;
63+
};
64+
65+
template <typename ValueStoreT>
66+
auto GetCheckIRIdTag(const ValueStoreT& value_store) {
67+
(void)value_store;
68+
return CheckIRIdTag();
69+
}
70+
3571
// A simple wrapper for accumulating values, providing IDs to later retrieve the
3672
// value. This does not do deduplication.
3773
template <typename IdT, typename ValueT>
@@ -74,6 +110,7 @@ class ValueStore
74110
};
75111

76112
ValueStore() = default;
113+
explicit ValueStore(CheckIRIdTag tag) : tag_(tag) {}
77114

78115
// Stores the value and returns an ID to reference it.
79116
auto Add(ValueType value) -> IdType {
@@ -82,8 +119,8 @@ class ValueStore
82119
// tracking down issues easier.
83120
CARBON_DCHECK(size_ < std::numeric_limits<int32_t>::max(), "Id overflow");
84121

85-
IdType id(size_);
86-
auto [chunk_index, pos] = IdToChunkIndices(id);
122+
IdType id(tag_.Apply(size_));
123+
auto [chunk_index, pos] = IdToChunkIndices(size_);
87124
++size_;
88125

89126
CARBON_DCHECK(static_cast<size_t>(chunk_index) <= chunks_.size(),
@@ -99,17 +136,19 @@ class ValueStore
99136

100137
// Returns a mutable value for an ID.
101138
auto Get(IdType id) -> RefType {
102-
CARBON_DCHECK(id.index >= 0, "{0}", id);
103-
CARBON_DCHECK(id.index < size_, "{0}", id);
104-
auto [chunk_index, pos] = IdToChunkIndices(id);
139+
auto index = tag_.Remove(id.index);
140+
CARBON_DCHECK(index >= 0, "{0}", index);
141+
CARBON_DCHECK(index < size_, "{0}", index);
142+
auto [chunk_index, pos] = IdToChunkIndices(index);
105143
return chunks_[chunk_index].Get(pos);
106144
}
107145

108146
// Returns the value for an ID.
109147
auto Get(IdType id) const -> ConstRefType {
110-
CARBON_DCHECK(id.index >= 0, "{0}", id);
111-
CARBON_DCHECK(id.index < size_, "{0}", id);
112-
auto [chunk_index, pos] = IdToChunkIndices(id);
148+
auto index = tag_.Remove(id.index);
149+
CARBON_DCHECK(index >= 0, "{0}", index);
150+
CARBON_DCHECK(index < size_, "{0}", index);
151+
auto [chunk_index, pos] = IdToChunkIndices(index);
113152
return chunks_[chunk_index].Get(pos);
114153
}
115154

@@ -118,7 +157,7 @@ class ValueStore
118157
if (size <= size_) {
119158
return;
120159
}
121-
auto [final_chunk_index, _] = IdToChunkIndices(IdType(size - 1));
160+
auto [final_chunk_index, _] = IdToChunkIndices(size - 1);
122161
chunks_.resize(final_chunk_index + 1);
123162
}
124163

@@ -128,10 +167,10 @@ class ValueStore
128167
return;
129168
}
130169

131-
auto [begin_chunk_index, begin_pos] = IdToChunkIndices(IdType(size_));
170+
auto [begin_chunk_index, begin_pos] = IdToChunkIndices(size_);
132171
// Use an inclusive range so that if `size` would be the next chunk, we
133172
// don't try doing something with it.
134-
auto [end_chunk_index, end_pos] = IdToChunkIndices(IdType(size - 1));
173+
auto [end_chunk_index, end_pos] = IdToChunkIndices(size - 1);
135174
chunks_.resize(end_chunk_index + 1);
136175

137176
// If the begin and end chunks are the same, we only fill from begin to end.
@@ -192,7 +231,8 @@ class ValueStore
192231
// `mapped_iterator` incorrectly infers the pointer type for `PointerProxy`.
193232
// NOLINTNEXTLINE(readability-const-return-type)
194233
auto index_to_id = [&](int32_t i) -> const std::pair<IdType, ConstRefType> {
195-
return std::pair<IdType, ConstRefType>(IdType(i), Get(IdType(i)));
234+
IdType id(tag_.Apply(i));
235+
return std::pair<IdType, ConstRefType>(id, Get(id));
196236
};
197237
// Because indices into `ValueStore` are all sequential values from 0, we
198238
// can use llvm::seq to walk all indices in the store.
@@ -314,7 +354,7 @@ class ValueStore
314354

315355
// Converts an id into an index into the set of chunks, and an offset into
316356
// that specific chunk. Looks for index overflow in non-optimized builds.
317-
static auto IdToChunkIndices(IdType id) -> std::pair<int32_t, int32_t> {
357+
static auto IdToChunkIndices(int32_t index) -> std::pair<int32_t, int32_t> {
318358
constexpr auto LowBits = Chunk::IndexBits();
319359

320360
// Verify there are no unused bits when indexing up to the `Capacity`. This
@@ -328,16 +368,20 @@ class ValueStore
328368
static_assert(LowBits < 30);
329369

330370
// The index of the chunk is the high bits.
331-
auto chunk = id.index >> LowBits;
371+
auto chunk = index >> LowBits;
332372
// The index into the chunk is the low bits.
333-
auto pos = id.index & ((1 << LowBits) - 1);
373+
auto pos = index & ((1 << LowBits) - 1);
334374
return {chunk, pos};
335375
}
336376

337377
// Number of elements added to the store. The number should never exceed what
338378
// fits in an `int32_t`, which is checked in non-optimized builds in Add().
339379
int32_t size_ = 0;
340380

381+
public:
382+
CheckIRIdTag tag_;
383+
384+
private:
341385
// Storage for the `ValueType` objects, indexed by the id. We use a vector of
342386
// chunks of `ValueType` instead of just a vector of `ValueType` so that
343387
// addresses of `ValueType` objects are stable. This allows the rest of the

toolchain/check/check_unit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ auto CheckUnit::CollectTransitiveImports(SemIR::InstId import_decl_id,
195195
// exported to this IR.
196196
auto ir_to_result_index =
197197
FixedSizeValueStore<SemIR::CheckIRId, int>::MakeWithExplicitSize(
198-
total_ir_count_, -1);
198+
CheckIRIdTag(), total_ir_count_, -1);
199199

200200
// First add direct imports. This means that if an entity is imported both
201201
// directly and indirectly, the import path will reflect the direct import.

toolchain/check/context.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ Context::Context(DiagnosticEmitterBase* emitter,
3131
scope_stack_(sem_ir_),
3232
deferred_definition_worklist_(vlog_stream),
3333
vtable_stack_("vtable_stack_", *sem_ir, vlog_stream),
34-
check_ir_map_(
35-
FixedSizeValueStore<SemIR::CheckIRId, SemIR::ImportIRId>::
36-
MakeWithExplicitSize(total_ir_count, SemIR::ImportIRId::None)),
34+
check_ir_map_(FixedSizeValueStore<SemIR::CheckIRId, SemIR::ImportIRId>::
35+
MakeWithExplicitSize(CheckIRIdTag(), total_ir_count,
36+
SemIR::ImportIRId::None)),
3737
global_init_(this),
3838
region_stack_([this](SemIR::LocId loc_id, std::string label) {
3939
TODO(loc_id, label);

toolchain/check/import_ref.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ namespace Carbon::Check {
3535
// Adds the ImportIR, excluding the update to the check_ir_map.
3636
static auto InternalAddImportIR(Context& context, SemIR::ImportIR import_ir)
3737
-> SemIR::ImportIRId {
38-
context.import_ir_constant_values().push_back(
39-
SemIR::ConstantValueStore(SemIR::ConstantId::None));
38+
context.import_ir_constant_values().push_back(SemIR::ConstantValueStore(
39+
SemIR::ConstantId::None,
40+
import_ir.sem_ir ? CheckIRIdTag(import_ir.sem_ir->check_ir_id().index,
41+
SemIR::SingletonInstKinds.size() + 1)
42+
: CheckIRIdTag(0, std::numeric_limits<int32_t>::max())));
4043
return context.import_irs().Add(import_ir);
4144
}
4245

@@ -642,6 +645,7 @@ static auto AddImportRef(ImportContext& context, SemIR::InstId inst_id,
642645
static auto AddLoadedImportRef(ImportContext& context, SemIR::TypeId type_id,
643646
SemIR::InstId inst_id,
644647
SemIR::ConstantId const_id) -> SemIR::InstId {
648+
context.import_insts().Get(inst_id);
645649
return AddLoadedImportRef(
646650
context.local_context(), type_id,
647651
SemIR::ImportIRInst(context.import_ir_id(), inst_id), const_id);
@@ -2088,7 +2092,8 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
20882092
resolver,
20892093
GetSingletonType(resolver.local_context(),
20902094
SemIR::SpecificFunctionType::TypeInstId),
2091-
import_vtable_entry_inst_id, local_attached_constant_id);
2095+
/* bad: local_vtable_entry_inst_id */ import_vtable_entry_inst_id,
2096+
local_attached_constant_id);
20922097
}
20932098
}
20942099

0 commit comments

Comments
 (0)