• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef BERBERIS_LITE_TRANSLATOR_RISCV64_ALLOCATOR_H_
18 #define BERBERIS_LITE_TRANSLATOR_RISCV64_ALLOCATOR_H_
19 
20 #include <algorithm>  // std::max
21 #include <optional>
22 
23 #include "berberis/assembler/x86_64.h"
24 #include "berberis/base/dependent_false.h"
25 
26 namespace berberis {
27 
28 template <typename RegType>
29 inline constexpr auto kAllocatableRegisters = []() {
30   static_assert(kDependentTypeFalse<RegType>,
31                 "kAllocatableRegisters is only usable with x86_64::Assembler::Register or "
32                 "x86_64::Assembler::XMMRegister");
33   return true;
34 };
35 
36 // TODO(286261771): Add rdx to registers, push it on stack in all instances that are clobbering it.
37 template <>
38 inline constexpr x86_64::Assembler::Register kAllocatableRegisters<x86_64::Assembler::Register>[] =
39     {x86_64::Assembler::rbx,
40      x86_64::Assembler::rsi,
41      x86_64::Assembler::rdi,
42      x86_64::Assembler::r8,
43      x86_64::Assembler::r9,
44      x86_64::Assembler::r10,
45      x86_64::Assembler::r11,
46      x86_64::Assembler::r12,
47      x86_64::Assembler::r13,
48      x86_64::Assembler::r14,
49      x86_64::Assembler::r15};
50 
51 template <>
52 inline constexpr x86_64::Assembler::XMMRegister
53     kAllocatableRegisters<x86_64::Assembler::XMMRegister>[] = {x86_64::Assembler::xmm0,
54                                                                x86_64::Assembler::xmm1,
55                                                                x86_64::Assembler::xmm2,
56                                                                x86_64::Assembler::xmm3,
57                                                                x86_64::Assembler::xmm4,
58                                                                x86_64::Assembler::xmm5,
59                                                                x86_64::Assembler::xmm6,
60                                                                x86_64::Assembler::xmm7,
61                                                                x86_64::Assembler::xmm8,
62                                                                x86_64::Assembler::xmm9,
63                                                                x86_64::Assembler::xmm10,
64                                                                x86_64::Assembler::xmm11,
65                                                                x86_64::Assembler::xmm12,
66                                                                x86_64::Assembler::xmm13,
67                                                                x86_64::Assembler::xmm14,
68                                                                x86_64::Assembler::xmm15};
69 
70 template <typename RegType>
71 class Allocator {
72  public:
Alloc()73   std::optional<RegType> Alloc() {
74     if (regs_allocated_ + max_temp_regs_allocated >= kNumRegister) {
75       return std::nullopt;
76     }
77     return std::optional<RegType>(kAllocatableRegisters<RegType>[regs_allocated_++]);
78   }
79 
AllocTemp()80   std::optional<RegType> AllocTemp() {
81     if (regs_allocated_ + temp_regs_allocated >= kNumRegister) {
82       return std::nullopt;
83     }
84     auto res = std::optional<RegType>(
85         kAllocatableRegisters<RegType>[kNumRegister - 1 - temp_regs_allocated]);
86     temp_regs_allocated++;
87     max_temp_regs_allocated = std::max(max_temp_regs_allocated, temp_regs_allocated);
88     return res;
89   }
90 
FreeTemps()91   void FreeTemps() { temp_regs_allocated = 0; }
92 
93  private:
94   inline static const uint32_t kNumRegister = std::size(kAllocatableRegisters<RegType>);
95 
96   uint32_t regs_allocated_ = 0;
97   uint32_t temp_regs_allocated = 0;
98   uint32_t max_temp_regs_allocated = 0;
99 };
100 
101 }  // namespace berberis
102 
103 #endif  // BERBERIS_LITE_TRANSLATOR_RISCV64_ALLOCATOR_H_
104