5#include "tpde/ValueAssignment.hpp"
11template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
13 struct AssignmentData {
16 ValLocalIdx local_idx;
17 ValueAssignment *assignment;
19 static_assert(ValRefSpecialStruct<AssignmentData>);
23 Derived::ValRefSpecial s;
29 : state{AssignmentData()}, compiler(compiler) {}
34 .local_idx = local_idx,
35 .assignment = compiler->val_assignment(local_idx),
39 assert(!state.a.assignment->pending_free &&
"access of free'd assignment");
42 if constexpr (WithAsserts) {
43 if (!variable_ref()) {
44 const auto &liveness =
45 compiler->analyzer.liveness_info(state.a.local_idx);
46 assert(liveness.last >= compiler->cur_block_idx &&
47 "ref-counted value used outside of its live range");
48 assert(state.a.assignment->references_left != 0);
49 if (state.a.assignment->references_left == 1 && !liveness.last_full) {
50 assert(liveness.last == compiler->cur_block_idx &&
51 "liveness of non-last-full value must end at last use");
58 }
else if (state.a.assignment->references_left <= 1 &&
59 !state.a.assignment->delay_free) {
66 template <
typename... T>
68 : state{.s = typename Derived::
ValRefSpecial(std::forward<T>(args)...)},
70 assert(state.a.mode >= 4);
75 ValueRef(
const ValueRef &other) =
default;
78 ValueRef(ValueRef &&other) : state{other.state}, compiler(other.compiler) {
79 other.state.a = AssignmentData{};
82 ~ValueRef() {
reset(); }
84 ValueRef &operator=(
const ValueRef &) =
delete;
86 ValueRef &operator=(ValueRef &&other) {
91 assert(compiler == other.compiler);
92 this->state = other.state;
93 other.state.a.mode = 0;
97 bool has_assignment()
const {
return state.a.mode < 4; }
99 [[nodiscard]] ValueAssignment *assignment()
const {
100 assert(has_assignment());
101 assert(state.a.assignment !=
nullptr);
102 return state.a.assignment;
106 bool is_owned() {
return state.a.mode == 2; }
111 if (has_assignment()) {
118 ValueRef disowned() {
119 ValueRef res = *
this;
124 ValLocalIdx local_idx()
const {
125 assert(has_assignment());
126 return state.a.local_idx;
129 ValuePartRef part(
unsigned part) TPDE_LIFETIMEBOUND {
130 if (has_assignment()) {
132 compiler, local_idx(), state.a.assignment, part, is_owned()};
135 compiler, compiler->derived()->val_part_ref_special(state.s, part)};
140 ValuePartRef part_unowned(
unsigned part) TPDE_LIFETIMEBOUND {
141 if (has_assignment()) {
143 compiler, local_idx(), state.a.assignment, part,
false};
146 compiler, compiler->derived()->val_part_ref_special(state.s, part)};
152 bool variable_ref()
const {
153 assert(has_assignment());
154 return state.a.assignment->variable_ref;
158template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
159void CompilerBase<Adaptor, Derived, Config>::ValueRef::reset() {
160 if (state.a.mode == 1 || state.a.mode == 2) {
163 assert(!state.a.assignment->pending_free &&
"access of free'd assignment");
165 auto &ref_count = state.a.assignment->references_left;
166 assert(ref_count != 0);
167 if (--ref_count == 0) {
168 compiler->release_assignment(state.a.local_idx, state.a.assignment);
172 if constexpr (WithAsserts) {
173 state.a.assignment =
nullptr;
174 state.a.local_idx = INVALID_VAL_LOCAL_IDX;
A default implementation for ValRefSpecial.
The base class for the compiler.
void reset()
Reset any leftover data from the previous compilation such that it will not affect the next compilati...
CompilerBase(Adaptor *adaptor)
Initialize a CompilerBase, should be called by the derived classes.