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 "common.h"
20 #include "code_ir.h"
21 #include "dex_ir.h"
22 #include "buffer.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