Files
carbon-lang/common/array_stack.h
T
Jon Ross-Perkins be56ff87c6 Convert StructTypeField to a specific type. (#4492)
This converts `StructTypeField` from an instruction to a dedicated type,
with its own store. This had originated from discussing how
`.GetAs<SemIR::StructTypeField>` was more prevalent than for other
instructions, but is probably more interesting for the storage savings
(16 bytes StructTypeField + 4 byte LocId + 4 byte InstId -> 8 byte
StructTypeField).

Due to the different structure, these now have their own stack during
construction, reducing (but not eliminating) `args_type_info_stack_`
use-cases.

The test changes of different InstIds is expected because structs and
classes generate fewer instructions now. Other than that, results should
remain the same.

I'm generally trying to avoid unrelated cleanup here due to the PR size,
though I did scrutinize the `VerifyOnFinish` calls, adding one and
commenting others (putting them in member order because that's how I was
checking what was verified and what wasn't).
2024-11-06 21:38:27 +00:00

101 lines
3.3 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_COMMON_ARRAY_STACK_H_
#define CARBON_COMMON_ARRAY_STACK_H_
#include "common/check.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
namespace Carbon {
// Provides a stack of arrays. Only the array at the top of the stack can have
// elements added.
//
// Example usage:
// // Push to start.
// PushArray();
// // Add values.
// AppendToTop(3);
// // Look at values.
// PeekArray();
// // Pop when done.
// PopArray();
//
// By using a single vector for elements, the intent is that as arrays are
// pushed and popped, the same storage will be reused. This should yield
// efficiencies for heap allocations. For example, in the toolchain we
// frequently have an array per scope, and only add to the current scope's
// array; this allows better reuse when entering and leaving scopes.
template <typename ValueT>
class ArrayStack {
public:
// Pushes a new array onto the stack.
auto PushArray() -> void { array_offsets_.push_back(values_.size()); }
// Pops the top array from the stack.
auto PopArray() -> void {
auto region = array_offsets_.pop_back_val();
values_.truncate(region);
}
// Returns the top array from the stack.
auto PeekArray() const -> llvm::ArrayRef<ValueT> {
CARBON_CHECK(!array_offsets_.empty());
return llvm::ArrayRef(values_).slice(array_offsets_.back());
}
// Returns the array at a specific index.
auto PeekArrayAt(int index) const -> llvm::ArrayRef<ValueT> {
auto ref = llvm::ArrayRef(values_).slice(array_offsets_[index]);
if (index + 1 < static_cast<int>(array_offsets_.size())) {
ref = ref.take_front(array_offsets_[index + 1] - array_offsets_[index]);
}
return ref;
}
// Returns the full set of values on the stack, regardless of whether any
// arrays are pushed.
auto PeekAllValues() const -> llvm::ArrayRef<ValueT> { return values_; }
// Appends a value to the top array on the stack.
auto AppendToTop(ValueT value) -> void {
CARBON_CHECK(!array_offsets_.empty(),
"Must call PushArray before AppendToTop.");
values_.push_back(value);
}
// Prepends a value to the top array on the stack.
auto PrependToTop(ValueT value) -> void {
CARBON_CHECK(!array_offsets_.empty(),
"Must call PushArray before PrependToTop.");
values_.insert(values_.begin() + array_offsets_.back(), value);
}
// Adds multiple values to the top array on the stack.
auto AppendToTop(llvm::ArrayRef<ValueT> values) -> void {
CARBON_CHECK(!array_offsets_.empty(),
"Must call PushArray before PushValues.");
values_.append(values.begin(), values.end());
}
// Returns the current number of values in all arrays.
auto all_values_size() const -> size_t { return values_.size(); }
// Returns true if the stack has no arrays pushed.
auto empty() const -> bool { return array_offsets_.empty(); }
private:
// For each pushed array, the start index in elements_.
llvm::SmallVector<int32_t> array_offsets_;
// The full set of elements in all arrays.
llvm::SmallVector<ValueT> values_;
};
} // namespace Carbon
#endif // CARBON_COMMON_ARRAY_STACK_H_