1 /* 2 * Copyright (C) 2017 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 #pragma once 18 19 #include "buffer.h" 20 #include "common.h" 21 #include "code_ir.h" 22 #include "dex_ir.h" 23 24 #include <assert.h> 25 #include <vector> 26 27 namespace lir { 28 29 // Generates .dex bytecode from code IR 30 class BytecodeEncoder : public Visitor { 31 public: BytecodeEncoder(const InstructionsList & instructions)32 explicit BytecodeEncoder(const InstructionsList& instructions) 33 : instructions_(instructions) { 34 } 35 36 ~BytecodeEncoder() = default; 37 38 void Encode(ir::Code* ir_code, std::shared_ptr<ir::DexFile> dex_ir); 39 40 private: 41 // the visitor interface 42 virtual bool Visit(Bytecode* bytecode) override; 43 virtual bool Visit(PackedSwitchPayload* packed_switch) override; 44 virtual bool Visit(SparseSwitchPayload* sparse_switch) override; 45 virtual bool Visit(ArrayData* array_data) override; 46 virtual bool Visit(Label* label) override; 47 virtual bool Visit(DbgInfoHeader* dbg_header) override; 48 virtual bool Visit(DbgInfoAnnotation* dbg_annotation) override; 49 virtual bool Visit(TryBlockBegin* try_begin) override; 50 virtual bool Visit(TryBlockEnd* try_end) override; 51 52 // fixup helpers 53 void FixupSwitchOffsets(); 54 void FixupPackedSwitch(dex::u4 base_offset, dex::u4 payload_offset); 55 void FixupSparseSwitch(dex::u4 base_offset, dex::u4 payload_offset); 56 void FixupLabels(); 57 58 private: 59 // Structure used to track code location fixups 60 struct LabelFixup { 61 dex::u4 offset; // instruction to be fixed up 62 const Label* label; // target label 63 bool short_fixup; // 16bit or 32bit fixup? 64 LabelFixupLabelFixup65 LabelFixup(dex::u4 offset, Label* label, bool short_fixup) : 66 offset(offset), label(label), short_fixup(short_fixup) {} 67 }; 68 69 private: 70 slicer::Buffer bytecode_; 71 std::vector<LabelFixup> fixups_; 72 73 // Current bytecode offset (in 16bit units) 74 dex::u4 offset_ = 0; 75 76 // Number of registers using for outgoing arguments 77 dex::u4 outs_count_ = 0; 78 79 // Keeping track of the switch payload instructions for late fixups 80 // (map encoded bytecode offset -> LIR instruction) 81 std::map<dex::u4, const PackedSwitchPayload*> packed_switches_; 82 std::map<dex::u4, const SparseSwitchPayload*> sparse_switches_; 83 84 const InstructionsList& instructions_; 85 }; 86 87 } // namespace lir 88 89