Files
carbon-lang/common/array_stack.h
T
Jon Ross-PerkinsandChandler Carruth d437e4bffe Create an array stack type for a shared use-case (#4100)
Based on discussion around the region handling in generic_region_stack,
create a generic structure for the stack-of-vectors support. I also want
to add this to InstBlockStack, but that's a little more complex due to
GlobalInit, so cutting a PR here to check with review.

My work here is how I noticed #4099; I want to be sure that I'm correct
about the issue, but it's the difference between being able to use
PeekArray or not.

Note in scope_stack.h, I believe we could remove next_compile_time_index
and make it just based on elements_size(). However, I want to verify
with you before I make further changes there.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2024-07-03 16:58:47 +00:00

75 lines
2.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 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 PushValue.";
values_.push_back(value);
}
// Returns the current number of values in all arrays.
auto all_values_size() const -> size_t { return values_.size(); }
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_