7template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
8struct CompilerBase<Adaptor, Derived, Config>::ScratchReg {
12 AsmReg reg = AsmReg::make_invalid();
15 explicit ScratchReg(CompilerBase *compiler) : compiler(compiler) {}
17 explicit ScratchReg(
const ScratchReg &) =
delete;
18 ScratchReg(ScratchReg &&) noexcept;
20 ~ScratchReg() noexcept {
reset(); }
22 ScratchReg &operator=(
const ScratchReg &) =
delete;
23 ScratchReg &operator=(ScratchReg &&) noexcept;
25 bool has_reg() const noexcept {
return reg.valid(); }
27 AsmReg cur_reg() const noexcept {
32 AsmReg alloc_specific(AsmReg reg)
noexcept;
34 AsmReg alloc_gp() noexcept {
return alloc(Config::GP_BANK); }
39 AsmReg alloc(RegBank bank)
noexcept;
41 void reset() noexcept;
44 void force_set_reg(AsmReg reg) noexcept { this->reg = reg; }
47template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
48CompilerBase<Adaptor, Derived, Config>::ScratchReg::ScratchReg(
49 ScratchReg &&other)
noexcept {
50 this->compiler = other.compiler;
51 this->reg = other.reg;
52 other.reg = AsmReg::make_invalid();
55template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
56typename CompilerBase<Adaptor, Derived, Config>::ScratchReg &
57 CompilerBase<Adaptor, Derived, Config>::ScratchReg::operator=(
58 ScratchReg &&other)
noexcept {
64 this->compiler = other.compiler;
65 this->reg = other.reg;
66 other.reg = AsmReg::make_invalid();
70template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
71typename CompilerBase<Adaptor, Derived, Config>::AsmReg
72 CompilerBase<Adaptor, Derived, Config>::ScratchReg::alloc_specific(
73 AsmReg reg)
noexcept {
74 assert(compiler->may_change_value_state());
75 assert(!compiler->register_file.is_fixed(reg));
78 if (compiler->register_file.is_used(reg)) {
79 compiler->evict_reg(reg);
82 compiler->register_file.mark_used(reg, INVALID_VAL_LOCAL_IDX, 0);
83 compiler->register_file.mark_clobbered(reg);
84 compiler->register_file.mark_fixed(reg);
89template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
90CompilerBase<Adaptor, Derived, Config>::AsmReg
91 CompilerBase<Adaptor, Derived, Config>::ScratchReg::alloc(
92 RegBank bank)
noexcept {
93 assert(compiler->may_change_value_state());
95 auto ®_file = compiler->register_file;
97 assert(bank == reg_file.reg_bank(reg));
102 auto reg = reg_file.find_first_free_excluding(bank, 0);
105 reg = reg_file.find_first_nonfixed_excluding(bank, 0);
106 if (reg.invalid()) [[unlikely]] {
107 TPDE_FATAL(
"ran out of registers for scratch registers");
109 compiler->evict_reg(reg);
112 reg_file.mark_used(reg, INVALID_VAL_LOCAL_IDX, 0);
113 reg_file.mark_clobbered(reg);
114 reg_file.mark_fixed(reg);
119template <IRAdaptor Adaptor,
typename Derived, CompilerConfig Config>
120void CompilerBase<Adaptor, Derived, Config>::ScratchReg::reset() noexcept {
125 compiler->register_file.unmark_fixed(reg);
126 compiler->register_file.unmark_used(reg);
127 reg = AsmReg::make_invalid();
CompilerBase(Adaptor *adaptor)
Initialize a CompilerBase, should be called by the derived classes.