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_BACKEND_CODE_EMITTER_H_
18 #define BERBERIS_BACKEND_CODE_EMITTER_H_
19 
20 #include <cstdint>
21 
22 #include "berberis/assembler/machine_code.h"
23 #include "berberis/base/arena_vector.h"
24 #include "berberis/intrinsics/macro_assembler.h"
25 
26 #if defined(__x86_64__)
27 
28 #include "berberis/assembler/x86_64.h"
29 using CodeEmitterBase = berberis::MacroAssembler<berberis::x86_64::Assembler>;
30 
31 #elif defined(__i386__)
32 
33 #include "berberis/assembler/x86_32.h"
34 using CodeEmitterBase = berberis::MacroAssembler<berberis::x86_32::Assembler>;
35 
36 #else
37 
38 #error "Unsupported architecture"
39 
40 #endif  // defined(__x86_64__)
41 
42 namespace berberis {
43 
44 class CompilerHooks;
45 
46 class CodeEmitter : public CodeEmitterBase {
47  public:
CodeEmitter(MachineCode * mc,uint32_t frame_size)48   CodeEmitter(MachineCode* mc, uint32_t frame_size)
49       : CodeEmitterBase(mc),
50         frame_size_{frame_size},
51         next_label_{nullptr},
52         exit_label_for_testing_{nullptr},
53         labels_(nullptr) {}
54 
CodeEmitter(MachineCode * mc,uint32_t frame_size,size_t max_ids,Arena * arena)55   CodeEmitter(MachineCode* mc, uint32_t frame_size, size_t max_ids, Arena* arena)
56       : CodeEmitterBase(mc),
57         frame_size_{frame_size},
58         next_label_{nullptr},
59         exit_label_for_testing_{nullptr},
60         labels_(max_ids, nullptr, arena) {}
61 
set_next_label(const Label * label)62   void set_next_label(const Label* label) { next_label_ = label; }
63 
next_label()64   [[nodiscard]] const Label* next_label() const { return next_label_; }
65 
GetLabelAt(int id)66   [[nodiscard]] Label* GetLabelAt(int id) {
67     if (labels_.at(id) == nullptr) {
68       labels_.at(id) = MakeLabel();
69     }
70 
71     return labels_.at(id);
72   }
73 
frame_size()74   [[nodiscard]] uint32_t frame_size() const { return frame_size_; }
75 
set_exit_label_for_testing(const Label * label)76   void set_exit_label_for_testing(const Label* label) { exit_label_for_testing_ = label; }
77 
exit_label_for_testing()78   [[nodiscard]] const Label* exit_label_for_testing() const { return exit_label_for_testing_; }
79 
80  private:
81   const uint32_t frame_size_;
82 
83   // Used by PseudoBranch and PseudoCondBranch to avoid emitting jumps
84   // to the next instruction.
85   const Label* next_label_;
86 
87   // We use it in tests to avoid exiting using runtime library.
88   const Label* exit_label_for_testing_;
89 
90   // The vector of labels indexed by integer IDs. The IDs are most
91   // likely basic block IDs, but we don't really care exactly what
92   // they are.
93   ArenaVector<Label*> labels_;
94 };
95 
96 }  // namespace berberis
97 
98 #endif  // BERBERIS_BACKEND_CODE_EMITTER_H_
99