TPDE
Loading...
Searching...
No Matches
AssignmentPartRef.hpp
1// SPDX-FileCopyrightText: 2025 Contributors to TPDE <https://tpde.org>
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4#pragma once
5
6#include "tpde/RegisterFile.hpp"
7#include "tpde/ValueAssignment.hpp"
8
9#include <cstdint>
10
11namespace tpde {
12
13class AssignmentPartRef {
14 ValueAssignment *va;
15 uint32_t part;
16
17 // note for how parts are structured:
18 // |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
19 // | | PS |RV| |IM|FA| bank | reg_id |
20 // | full_reg_id |
21 //
22 // PS: 1 << PS = part size (TODO(ts): maybe swap with NP so that it can be
23 // extracted easier?)
24 // RV: Register Valid
25 // IM: Is the current register value not on the stack?
26 // FA: Is the assignment a fixed assignment?
27 //
28 // RV + IM form a unit describing the following states:
29 // - !RV + IM: value uninitialized (default state)
30 // - RV + IM: register dirty, must be spilled before evicting
31 // - !RV + !IM: register invalid, value stored only in stack slot
32 // - RV + !IM: register identical to value in stack slot
33
34public:
35 AssignmentPartRef(ValueAssignment *va, const uint32_t part)
36 : va(va), part(part) {}
37
38 void reset() noexcept {
39 va->parts[part] = 0;
40 set_modified(true);
41 }
42
43 ValueAssignment *assignment() noexcept { return va; }
44
45 [[nodiscard]] RegBank bank() const noexcept {
46 return RegBank((va->parts[part] >> 5) & 0b111);
47 }
48
49 void set_bank(const RegBank bank) noexcept {
50 assert(bank.id() <= 0b111);
51 auto data = va->parts[part] & ~0b1110'0000;
52 data |= bank.id() << 5;
53 va->parts[part] = data;
54 }
55
56 [[nodiscard]] Reg get_reg() const noexcept {
57 return Reg(va->parts[part] & 0xFF);
58 }
59
60 void set_reg(Reg reg) noexcept {
61 assert(bank().id() == ((reg.id() >> 5) & 0b111));
62 va->parts[part] = (va->parts[part] & 0xFF00) | reg.id();
63 }
64
65 [[nodiscard]] bool modified() const noexcept {
66 return (va->parts[part] & (1u << 9)) != 0;
67 }
68
69 void set_modified(const bool val) noexcept {
70 if (val) {
71 va->parts[part] |= (1u << 9);
72 } else {
73 va->parts[part] &= ~(1u << 9);
74 }
75 }
76
77 [[nodiscard]] bool fixed_assignment() const noexcept {
78 return (va->parts[part] & (1u << 8)) != 0;
79 }
80
81 void set_fixed_assignment(const bool val) noexcept {
82 if (val) {
83 va->parts[part] |= (1u << 8);
84 } else {
85 va->parts[part] &= ~(1u << 8);
86 }
87 }
88
89 [[nodiscard]] bool variable_ref() const noexcept { return va->variable_ref; }
90
91 [[nodiscard]] bool is_stack_variable() const noexcept {
92 return va->stack_variable;
93 }
94
95 [[nodiscard]] bool register_valid() const noexcept {
96 return (va->parts[part] & (1u << 11)) != 0;
97 }
98
99 void set_register_valid(const bool val) noexcept {
100 if (val) {
101 va->parts[part] |= (1u << 11);
102 } else {
103 va->parts[part] &= ~(1u << 11);
104 }
105 }
106
107 [[nodiscard]] bool stack_valid() const noexcept {
108 return (va->parts[part] & (1u << 9)) == 0;
109 }
110
111 void set_stack_valid() noexcept { set_modified(false); }
112
113 [[nodiscard]] uint32_t part_size() const noexcept {
114 return 1u << ((va->parts[part] >> 12) & 0b111);
115 }
116
117 void set_part_size(const uint32_t part_size) noexcept {
118 assert((part_size & (part_size - 1)) == 0);
119 const uint32_t shift = util::cnt_tz(part_size);
120 assert(shift <= 0b111);
121 auto data = va->parts[part] & ~(0b111 << 12);
122 data |= (shift << 12);
123 va->parts[part] = data;
124 }
125
126 [[nodiscard]] int32_t frame_off() const noexcept {
127 assert(!variable_ref());
128 assert(va->frame_off != 0 && "attempt to access uninitialized stack slot");
129 return va->frame_off + part_off();
130 }
131
132 [[nodiscard]] int32_t variable_stack_off() const noexcept {
133 assert(variable_ref() && va->stack_variable);
134 assert(part == 0);
135 return va->frame_off;
136 }
137
138 [[nodiscard]] uint32_t variable_ref_data() const noexcept {
139 assert(variable_ref() && !va->stack_variable);
140 assert(part == 0);
141 return va->var_ref_custom_idx;
142 }
143
144 [[nodiscard]] uint32_t part_off() const noexcept {
145 return va->max_part_size * part;
146 }
147};
148
149} // namespace tpde