11template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
12struct CompilerBase<Adaptor, Derived, Config>::GenericValuePart {
14 std::variant<AsmReg, ScratchReg> base;
15 std::variant<AsmReg, ScratchReg> index;
19 explicit Expr() : base{AsmReg::make_invalid()}, scale{0}, disp{0} {}
21 explicit Expr(AsmReg base, i64 disp = 0)
22 : base(base), scale(0), disp(disp) {}
24 explicit Expr(ScratchReg &&base, i64 disp = 0)
25 : base(std::move(base)), scale(0), disp(disp) {}
27 AsmReg base_reg() const noexcept {
28 if (std::holds_alternative<AsmReg>(base)) {
29 return std::get<AsmReg>(base);
31 return std::get<ScratchReg>(base).cur_reg();
34 [[nodiscard]]
bool has_base() const noexcept {
35 if (std::holds_alternative<AsmReg>(base)) {
36 return std::get<AsmReg>(base).valid();
41 AsmReg index_reg() const noexcept {
42 assert(scale != 0 &&
"index_reg() called on invalid index");
43 assert((scale != 1 || has_base()) &&
44 "Expr with unscaled index must have base");
45 if (std::holds_alternative<AsmReg>(index)) {
46 return std::get<AsmReg>(index);
48 return std::get<ScratchReg>(index).cur_reg();
51 [[nodiscard]]
bool has_index() const noexcept {
return scale != 0; }
57 std::variant<std::monostate, ValuePartRef, ScratchReg, Expr> state;
59 GenericValuePart() =
default;
61 GenericValuePart(GenericValuePart &) =
delete;
63 GenericValuePart(GenericValuePart &&other)
noexcept {
64 state = std::move(other.state);
65 other.state = std::monostate{};
68 GenericValuePart &operator=(
const GenericValuePart &)
noexcept =
delete;
70 GenericValuePart &operator=(GenericValuePart &&other)
noexcept {
74 state = std::move(other.state);
75 other.state = std::monostate{};
80 GenericValuePart(ScratchReg &®)
noexcept {
81 assert(reg.has_reg());
82 state = std::move(reg);
86 GenericValuePart(ValuePartRef &&ref) noexcept : state{std::move(ref)} {}
88 GenericValuePart(Expr expr)
noexcept {
89 ScratchReg *base_scratch = std::get_if<ScratchReg>(&expr.base);
90 if (base_scratch && !expr.has_index() && expr.disp == 0) {
91 state = std::move(*base_scratch);
93 state = std::move(expr);
97 [[nodiscard]]
bool is_expr() const noexcept {
98 return std::holds_alternative<Expr>(state);
101 [[nodiscard]]
bool is_imm() const noexcept {
102 auto *ptr = std::get_if<ValuePartRef>(&state);
103 return ptr && ptr->is_const();
106 u32 imm_size() const noexcept {
108 return val_ref().part_size();
111 [[nodiscard]] u64 imm64() const noexcept {
112 assert(imm_size() <= 8);
113 return val_ref().const_data()[0];
116 [[nodiscard]]
const ValuePartRef &val_ref() const noexcept {
117 return std::get<ValuePartRef>(state);
120 [[nodiscard]] ValuePartRef &val_ref() noexcept {
121 return std::get<ValuePartRef>(state);
124 void reset() noexcept { state = std::monostate{}; }