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_COMMON_MACHINE_IR_BUILDER_H_ 18 #define BERBERIS_BACKEND_COMMON_MACHINE_IR_BUILDER_H_ 19 20 #include <optional> 21 #include <utility> 22 23 #include "berberis/backend/common/machine_ir.h" 24 #include "berberis/guest_state/guest_addr.h" 25 26 namespace berberis { 27 28 using MachineInsnPosition = std::pair<MachineBasicBlock*, std::optional<MachineInsnList::iterator>>; 29 30 // Syntax sugar for building machine IR. 31 template <typename MachineIRType> 32 class MachineIRBuilderBase { 33 public: MachineIRBuilderBase(MachineIRType * ir)34 explicit MachineIRBuilderBase(MachineIRType* ir) : ir_(ir), bb_(nullptr) {} 35 ir()36 [[nodiscard]] MachineIRType* ir() { return ir_; } ir()37 [[nodiscard]] const MachineIRType* ir() const { return ir_; } 38 39 template <typename InsnType, typename... Args> Gen(Args...args)40 /*may_discard*/ InsnType* Gen(Args... args) { 41 InsnType* insn = ir_->template NewInsn<InsnType>(args...); 42 InsertInsn(insn); 43 return insn; 44 } 45 SetRecoveryPointAtLastInsn(MachineBasicBlock * recovery_bb)46 void SetRecoveryPointAtLastInsn(MachineBasicBlock* recovery_bb) { 47 bb_->insn_list().back()->set_recovery_bb(recovery_bb); 48 recovery_bb->MarkAsRecovery(); 49 } 50 SetRecoveryWithGuestPCAtLastInsn(GuestAddr pc)51 void SetRecoveryWithGuestPCAtLastInsn(GuestAddr pc) { 52 bb_->insn_list().back()->set_recovery_pc(pc); 53 } 54 GetMachineInsnPosition()55 [[nodiscard]] MachineInsnPosition GetMachineInsnPosition() { 56 if (bb_->insn_list().empty()) { 57 return std::make_pair(bb_, std::nullopt); 58 } 59 60 return std::make_pair( 61 bb_, std::optional<MachineInsnList::iterator>(std::prev(bb_->insn_list().end()))); 62 } 63 bb()64 [[nodiscard]] MachineBasicBlock* bb() const { return bb_; } 65 66 private: 67 MachineIRType* ir_; 68 69 protected: InsertInsn(MachineInsn * insn)70 void InsertInsn(MachineInsn* insn) { bb_->insn_list().push_back(insn); } 71 72 MachineBasicBlock* bb_; 73 }; 74 75 } // namespace berberis 76 77 #endif // BERBERIS_BACKEND_COMMON_MACHINE_IR_BUILDER_H_ 78