Files
carbon-lang/toolchain/sem_ir/block_value_store.h
T
Jon Ross-Perkins d2056ef4b9 Split classes in file.h and value_stores.* to separate files (#3725)
I'm proposing a different split, along the line of "what does this
relate to". I view impl.h as having started down this route. Moving the
inst store stuff to inst.h feels odd to me given how much else is there
right now, but maybe it's still the best approach. Some files only
contain a store, no structured class, but I felt the consistency in file
naming (without _store suffixes) might help.
2024-02-26 20:24:51 +00:00

111 lines
3.8 KiB
C++

// 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_SEM_IR_BLOCK_VALUE_STORE_H_
#define CARBON_TOOLCHAIN_SEM_IR_BLOCK_VALUE_STORE_H_
#include <type_traits>
#include "llvm/ADT/DenseMap.h"
#include "toolchain/base/value_store.h"
#include "toolchain/base/yaml.h"
namespace Carbon::SemIR {
// Provides a block-based ValueStore, which uses slab allocation of added
// blocks. This allows references to values to outlast vector resizes that might
// otherwise invalidate references.
//
// BlockValueStore is used as-is, but there are also children that expose the
// protected members for type-specific functionality.
//
// On IdT, this requires:
// - IdT::ElementType to represent the underlying type in the block.
// - IdT::ValueType to be llvm::MutableArrayRef<IdT::ElementType> for
// compatibility with ValueStore.
template <typename IdT>
class BlockValueStore : public Yaml::Printable<BlockValueStore<IdT>> {
public:
using ElementType = IdT::ElementType;
explicit BlockValueStore(llvm::BumpPtrAllocator& allocator)
: allocator_(&allocator) {}
// Adds a block with the given content, returning an ID to reference it.
auto Add(llvm::ArrayRef<ElementType> content) -> IdT {
return values_.Add(AllocateCopy(content));
}
// Returns the requested block.
auto Get(IdT id) const -> llvm::ArrayRef<ElementType> {
return values_.Get(id);
}
// Returns the requested block.
auto Get(IdT id) -> llvm::MutableArrayRef<ElementType> {
return values_.Get(id);
}
auto OutputYaml() const -> Yaml::OutputMapping {
return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
for (auto block_index : llvm::seq(values_.size())) {
auto block_id = IdT(block_index);
map.Add(PrintToString(block_id),
Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
auto block = Get(block_id);
for (auto i : llvm::seq(block.size())) {
map.Add(llvm::itostr(i), Yaml::OutputScalar(block[i]));
}
}));
}
});
}
auto size() const -> int { return values_.size(); }
protected:
// Reserves and returns a block ID. The contents of the block
// should be specified by calling Set, or similar.
auto AddDefaultValue() -> IdT { return values_.AddDefaultValue(); }
// Adds an uninitialized block of the given size.
auto AddUninitialized(size_t size) -> IdT {
return values_.Add(AllocateUninitialized(size));
}
// Sets the contents of an empty block to the given content.
auto Set(IdT block_id, llvm::ArrayRef<ElementType> content) -> void {
CARBON_CHECK(Get(block_id).empty())
<< "inst block content set more than once";
values_.Get(block_id) = AllocateCopy(content);
}
private:
// Allocates an uninitialized array using our slab allocator.
auto AllocateUninitialized(std::size_t size)
-> llvm::MutableArrayRef<ElementType> {
// We're not going to run a destructor, so ensure that's OK.
static_assert(std::is_trivially_destructible_v<ElementType>);
auto storage = static_cast<ElementType*>(
allocator_->Allocate(size * sizeof(ElementType), alignof(ElementType)));
return llvm::MutableArrayRef<ElementType>(storage, size);
}
// Allocates a copy of the given data using our slab allocator.
auto AllocateCopy(llvm::ArrayRef<ElementType> data)
-> llvm::MutableArrayRef<ElementType> {
auto result = AllocateUninitialized(data.size());
std::uninitialized_copy(data.begin(), data.end(), result.begin());
return result;
}
llvm::BumpPtrAllocator* allocator_;
ValueStore<IdT> values_;
};
} // namespace Carbon::SemIR
#endif // CARBON_TOOLCHAIN_SEM_IR_BLOCK_VALUE_STORE_H_