blob: cdae8d2d24b35d22eda4bceaaee555b86bdc3f0b [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Brian Carlstrom3320cf42011-10-04 14:58:28 -070016
Mathieu Chartier193bad92013-08-29 18:46:00 -070017#ifndef ART_COMPILER_COMPILED_METHOD_H_
18#define ART_COMPILER_COMPILED_METHOD_H_
Brian Carlstrom3320cf42011-10-04 14:58:28 -070019
Ian Rogers700a4022014-05-19 16:49:03 -070020#include <memory>
Brian Carlstrom265091e2013-01-30 14:08:26 -080021#include <string>
Brian Carlstrom3320cf42011-10-04 14:58:28 -070022#include <vector>
23
Elliott Hughes0f3c5532012-03-30 14:51:51 -070024#include "instruction_set.h"
Vladimir Markof4da6752014-08-01 19:04:18 +010025#include "method_reference.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070026#include "utils.h"
Vladimir Markof4da6752014-08-01 19:04:18 +010027#include "utils/array_ref.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070028
Shih-wei Liaod1fec812012-02-13 09:51:10 -080029namespace llvm {
30 class Function;
Ian Rogersa1827042013-04-18 16:36:43 -070031} // namespace llvm
Shih-wei Liaod1fec812012-02-13 09:51:10 -080032
Brian Carlstrom3320cf42011-10-04 14:58:28 -070033namespace art {
34
Mathieu Chartier193bad92013-08-29 18:46:00 -070035class CompilerDriver;
36
Logan Chien598c5132012-04-28 22:00:44 +080037class CompiledCode {
38 public:
Brian Carlstrom265091e2013-01-30 14:08:26 -080039 // For Quick to supply an code blob
Mathieu Chartier193bad92013-08-29 18:46:00 -070040 CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
Dave Allisond6ed6422014-04-09 23:36:15 +000041 const std::vector<uint8_t>& quick_code);
Logan Chien598c5132012-04-28 22:00:44 +080042
Brian Carlstrom265091e2013-01-30 14:08:26 -080043 // For Portable to supply an ELF object
Mathieu Chartier193bad92013-08-29 18:46:00 -070044 CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
45 const std::string& elf_object, const std::string &symbol);
Logan Chien598c5132012-04-28 22:00:44 +080046
Logan Chien598c5132012-04-28 22:00:44 +080047 InstructionSet GetInstructionSet() const {
48 return instruction_set_;
49 }
50
Ian Rogersef7d42f2014-01-06 12:55:46 -080051 const std::vector<uint8_t>* GetPortableCode() const {
52 return portable_code_;
Logan Chien598c5132012-04-28 22:00:44 +080053 }
54
Ian Rogersef7d42f2014-01-06 12:55:46 -080055 const std::vector<uint8_t>* GetQuickCode() const {
56 return quick_code_;
Logan Chien598c5132012-04-28 22:00:44 +080057 }
58
Ian Rogersef7d42f2014-01-06 12:55:46 -080059 void SetCode(const std::vector<uint8_t>* quick_code, const std::vector<uint8_t>* portable_code);
60
61 bool operator==(const CompiledCode& rhs) const;
62
Logan Chien598c5132012-04-28 22:00:44 +080063 // To align an offset from a page-aligned value to make it suitable
64 // for code storage. For example on ARM, to ensure that PC relative
65 // valu computations work out as expected.
66 uint32_t AlignCode(uint32_t offset) const;
67 static uint32_t AlignCode(uint32_t offset, InstructionSet instruction_set);
68
69 // returns the difference between the code address and a usable PC.
70 // mainly to cope with kThumb2 where the lower bit must be set.
71 size_t CodeDelta() const;
Dave Allison50abf0a2014-06-23 13:19:59 -070072 static size_t CodeDelta(InstructionSet instruction_set);
Logan Chien598c5132012-04-28 22:00:44 +080073
74 // Returns a pointer suitable for invoking the code at the argument
75 // code_pointer address. Mainly to cope with kThumb2 where the
76 // lower bit must be set to indicate Thumb mode.
77 static const void* CodePointer(const void* code_pointer,
78 InstructionSet instruction_set);
79
Brian Carlstrom265091e2013-01-30 14:08:26 -080080 const std::string& GetSymbol() const;
81 const std::vector<uint32_t>& GetOatdataOffsetsToCompliledCodeOffset() const;
82 void AddOatdataOffsetToCompliledCodeOffset(uint32_t offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -080083
Logan Chien598c5132012-04-28 22:00:44 +080084 private:
Ian Rogersef7d42f2014-01-06 12:55:46 -080085 CompilerDriver* const compiler_driver_;
Mathieu Chartier193bad92013-08-29 18:46:00 -070086
Logan Chien598c5132012-04-28 22:00:44 +080087 const InstructionSet instruction_set_;
Brian Carlstrom8227cc12013-03-06 14:26:48 -080088
Ian Rogersef7d42f2014-01-06 12:55:46 -080089 // The ELF image for portable.
90 std::vector<uint8_t>* portable_code_;
91
92 // Used to store the PIC code for Quick.
93 std::vector<uint8_t>* quick_code_;
Brian Carlstrom265091e2013-01-30 14:08:26 -080094
95 // Used for the Portable ELF symbol name.
Ian Rogersa1827042013-04-18 16:36:43 -070096 const std::string symbol_;
Brian Carlstrom265091e2013-01-30 14:08:26 -080097
98 // There are offsets from the oatdata symbol to where the offset to
99 // the compiled method will be found. These are computed by the
100 // OatWriter and then used by the ElfWriter to add relocations so
101 // that MCLinker can update the values to the location in the linked .so.
102 std::vector<uint32_t> oatdata_offsets_to_compiled_code_offset_;
Logan Chien598c5132012-04-28 22:00:44 +0800103};
104
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700105class SrcMapElem {
106 public:
107 uint32_t from_;
108 int32_t to_;
109
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700110 explicit operator int64_t() const {
111 return (static_cast<int64_t>(to_) << 32) | from_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700112 }
113
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700114 bool operator<(const SrcMapElem& sme) const {
115 return int64_t(*this) < int64_t(sme);
116 }
117
118 bool operator==(const SrcMapElem& sme) const {
119 return int64_t(*this) == int64_t(sme);
120 }
121
122 explicit operator uint8_t() const {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700123 return static_cast<uint8_t>(from_ + to_);
124 }
125};
126
127class SrcMap FINAL : public std::vector<SrcMapElem> {
128 public:
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700129 void SortByFrom() {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700130 std::sort(begin(), end(), [] (const SrcMapElem& lhs, const SrcMapElem& rhs) -> bool {
131 return lhs.from_ < rhs.from_;
132 });
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700133 }
134
135 const_iterator FindByTo(int32_t to) const {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700136 return std::lower_bound(begin(), end(), SrcMapElem({0, to}));
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700137 }
138
139 SrcMap& Arrange() {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700140 if (!empty()) {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700141 std::sort(begin(), end());
142 resize(std::unique(begin(), end()) - begin());
143 shrink_to_fit();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700144 }
145 return *this;
146 }
147
148 void DeltaFormat(const SrcMapElem& start, uint32_t highest_pc) {
149 // Convert from abs values to deltas.
150 if (!empty()) {
151 SortByFrom();
152
153 // TODO: one PC can be mapped to several Java src lines.
154 // do we want such a one-to-many correspondence?
155
156 // get rid of the highest values
157 size_t i = size() - 1;
158 for (; i > 0 ; i--) {
Yevgeny Rouban1127b122014-09-16 11:29:26 +0700159 if ((*this)[i].from_ < highest_pc) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700160 break;
161 }
162 }
163 this->resize(i + 1);
164
165 for (size_t i = size(); --i >= 1; ) {
166 (*this)[i].from_ -= (*this)[i-1].from_;
167 (*this)[i].to_ -= (*this)[i-1].to_;
168 }
169 DCHECK((*this)[0].from_ >= start.from_);
170 (*this)[0].from_ -= start.from_;
171 (*this)[0].to_ -= start.to_;
172 }
173 }
174};
175
Vladimir Markof4da6752014-08-01 19:04:18 +0100176enum LinkerPatchType {
177 kLinkerPatchMethod,
178 kLinkerPatchCall,
179 kLinkerPatchCallRelative, // NOTE: Actual patching is instruction_set-dependent.
180 kLinkerPatchType,
181};
182
183class LinkerPatch {
184 public:
185 static LinkerPatch MethodPatch(size_t literal_offset,
186 const DexFile* target_dex_file,
187 uint32_t target_method_idx) {
188 return LinkerPatch(literal_offset, kLinkerPatchMethod,
189 target_method_idx, target_dex_file);
190 }
191
192 static LinkerPatch CodePatch(size_t literal_offset,
193 const DexFile* target_dex_file,
194 uint32_t target_method_idx) {
195 return LinkerPatch(literal_offset, kLinkerPatchCall,
196 target_method_idx, target_dex_file);
197 }
198
199 static LinkerPatch RelativeCodePatch(size_t literal_offset,
200 const DexFile* target_dex_file,
201 uint32_t target_method_idx) {
202 return LinkerPatch(literal_offset, kLinkerPatchCallRelative,
203 target_method_idx, target_dex_file);
204 }
205
206 static LinkerPatch TypePatch(size_t literal_offset,
207 const DexFile* target_dex_file,
208 uint32_t target_type_idx) {
209 return LinkerPatch(literal_offset, kLinkerPatchType, target_type_idx, target_dex_file);
210 }
211
212 LinkerPatch(const LinkerPatch& other) = default;
213 LinkerPatch& operator=(const LinkerPatch& other) = default;
214
215 size_t LiteralOffset() const {
216 return literal_offset_;
217 }
218
219 LinkerPatchType Type() const {
220 return patch_type_;
221 }
222
223 MethodReference TargetMethod() const {
224 DCHECK(patch_type_ == kLinkerPatchMethod ||
225 patch_type_ == kLinkerPatchCall || patch_type_ == kLinkerPatchCallRelative);
226 return MethodReference(target_dex_file_, target_idx_);
227 }
228
229 const DexFile* TargetTypeDexFile() const {
230 DCHECK(patch_type_ == kLinkerPatchType);
231 return target_dex_file_;
232 }
233
234 uint32_t TargetTypeIndex() const {
235 DCHECK(patch_type_ == kLinkerPatchType);
236 return target_idx_;
237 }
238
239 private:
240 LinkerPatch(size_t literal_offset, LinkerPatchType patch_type,
241 uint32_t target_idx, const DexFile* target_dex_file)
242 : literal_offset_(literal_offset),
243 patch_type_(patch_type),
244 target_idx_(target_idx),
245 target_dex_file_(target_dex_file) {
246 }
247
248 size_t literal_offset_;
249 LinkerPatchType patch_type_;
250 uint32_t target_idx_; // Method index (Call/Method patches) or type index (Type patches).
251 const DexFile* target_dex_file_;
252
253 friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs);
254 friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs);
255};
256
257inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) {
258 return lhs.literal_offset_ == rhs.literal_offset_ &&
259 lhs.patch_type_ == rhs.patch_type_ &&
260 lhs.target_idx_ == rhs.target_idx_ &&
261 lhs.target_dex_file_ == rhs.target_dex_file_;
262}
263
264inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) {
265 return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_
266 : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_
267 : (lhs.target_idx_ != rhs.target_idx_) ? lhs.target_idx_ < rhs.target_idx_
268 : lhs.target_dex_file_ < rhs.target_dex_file_;
269}
270
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700271class CompiledMethod FINAL : public CompiledCode {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700272 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100273 // Constructs a CompiledMethod for Quick.
Ian Rogers72d32622014-05-06 16:20:11 -0700274 CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700275 InstructionSet instruction_set,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800276 const std::vector<uint8_t>& quick_code,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700277 const size_t frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700278 const uint32_t core_spill_mask,
279 const uint32_t fp_spill_mask,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700280 SrcMap* src_mapping_table,
Ian Rogers96faf5b2013-08-09 22:05:32 -0700281 const std::vector<uint8_t>& mapping_table,
282 const std::vector<uint8_t>& vmap_table,
Mark Mendellae9fd932014-02-10 16:14:35 -0800283 const std::vector<uint8_t>& native_gc_map,
Vladimir Markof4da6752014-08-01 19:04:18 +0100284 const std::vector<uint8_t>* cfi_info,
285 const ArrayRef<LinkerPatch>& patches = ArrayRef<LinkerPatch>());
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700286
Nicolas Geoffray39468442014-09-02 15:17:15 +0100287 // Constructs a CompiledMethod for Optimizing.
288 CompiledMethod(CompilerDriver* driver,
289 InstructionSet instruction_set,
290 const std::vector<uint8_t>& quick_code,
291 const size_t frame_size_in_bytes,
292 const uint32_t core_spill_mask,
293 const uint32_t fp_spill_mask,
294 const std::vector<uint8_t>& mapping_table,
295 const std::vector<uint8_t>& vmap_table);
296
Ian Rogersef7d42f2014-01-06 12:55:46 -0800297 // Constructs a CompiledMethod for the QuickJniCompiler.
Ian Rogers72d32622014-05-06 16:20:11 -0700298 CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700299 InstructionSet instruction_set,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800300 const std::vector<uint8_t>& quick_code,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700301 const size_t frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700302 const uint32_t core_spill_mask,
Tong Shen547cdfd2014-08-05 01:54:19 -0700303 const uint32_t fp_spill_mask,
304 const std::vector<uint8_t>* cfi_info);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700305
Brian Carlstrom265091e2013-01-30 14:08:26 -0800306 // Constructs a CompiledMethod for the Portable compiler.
Ian Rogers72d32622014-05-06 16:20:11 -0700307 CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, const std::string& code,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700308 const std::vector<uint8_t>& gc_map, const std::string& symbol);
TDYa127ce4cc0d2012-11-18 16:59:53 -0800309
Brian Carlstrom265091e2013-01-30 14:08:26 -0800310 // Constructs a CompiledMethod for the Portable JniCompiler.
Ian Rogers72d32622014-05-06 16:20:11 -0700311 CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, const std::string& code,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700312 const std::string& symbol);
Logan Chien6920bce2012-03-17 21:44:01 +0800313
Ian Rogers0c7abda2012-09-19 13:33:42 -0700314 ~CompiledMethod() {}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700315
Ian Rogers0c7abda2012-09-19 13:33:42 -0700316 size_t GetFrameSizeInBytes() const {
317 return frame_size_in_bytes_;
Logan Chien110bcba2012-04-16 19:11:28 +0800318 }
Ian Rogers0c7abda2012-09-19 13:33:42 -0700319
320 uint32_t GetCoreSpillMask() const {
321 return core_spill_mask_;
322 }
323
324 uint32_t GetFpSpillMask() const {
325 return fp_spill_mask_;
326 }
327
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700328 const SrcMap& GetSrcMappingTable() const {
329 DCHECK(src_mapping_table_ != nullptr);
330 return *src_mapping_table_;
331 }
332
Ian Rogers96faf5b2013-08-09 22:05:32 -0700333 const std::vector<uint8_t>& GetMappingTable() const {
Mathieu Chartier193bad92013-08-29 18:46:00 -0700334 DCHECK(mapping_table_ != nullptr);
335 return *mapping_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700336 }
337
Ian Rogers96faf5b2013-08-09 22:05:32 -0700338 const std::vector<uint8_t>& GetVmapTable() const {
Mathieu Chartier193bad92013-08-29 18:46:00 -0700339 DCHECK(vmap_table_ != nullptr);
340 return *vmap_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700341 }
342
Nicolas Geoffray39468442014-09-02 15:17:15 +0100343 std::vector<uint8_t> const* GetGcMap() const {
344 return gc_map_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700345 }
Logan Chien110bcba2012-04-16 19:11:28 +0800346
Mark Mendellae9fd932014-02-10 16:14:35 -0800347 const std::vector<uint8_t>* GetCFIInfo() const {
348 return cfi_info_;
349 }
350
Vladimir Markof4da6752014-08-01 19:04:18 +0100351 const std::vector<LinkerPatch>& GetPatches() const {
352 return patches_;
353 }
354
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700355 private:
Ian Rogersa1827042013-04-18 16:36:43 -0700356 // For quick code, the size of the activation used by the code.
Ian Rogers0c7abda2012-09-19 13:33:42 -0700357 const size_t frame_size_in_bytes_;
Ian Rogersa1827042013-04-18 16:36:43 -0700358 // For quick code, a bit mask describing spilled GPR callee-save registers.
Ian Rogers169c9a72011-11-13 20:13:17 -0800359 const uint32_t core_spill_mask_;
Ian Rogersa1827042013-04-18 16:36:43 -0700360 // For quick code, a bit mask describing spilled FPR callee-save registers.
Ian Rogers169c9a72011-11-13 20:13:17 -0800361 const uint32_t fp_spill_mask_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700362 // For quick code, a set of pairs (PC, Line) mapping from native PC offset to Java line
363 SrcMap* src_mapping_table_;
Ian Rogers96faf5b2013-08-09 22:05:32 -0700364 // For quick code, a uleb128 encoded map from native PC offset to dex PC aswell as dex PC to
365 // native PC offset. Size prefixed.
Mathieu Chartier193bad92013-08-29 18:46:00 -0700366 std::vector<uint8_t>* mapping_table_;
Ian Rogers96faf5b2013-08-09 22:05:32 -0700367 // For quick code, a uleb128 encoded map from GPR/FPR register to dex register. Size prefixed.
Mathieu Chartier193bad92013-08-29 18:46:00 -0700368 std::vector<uint8_t>* vmap_table_;
Ian Rogersa1827042013-04-18 16:36:43 -0700369 // For quick code, a map keyed by native PC indices to bitmaps describing what dalvik registers
370 // are live. For portable code, the key is a dalvik PC.
Mathieu Chartier193bad92013-08-29 18:46:00 -0700371 std::vector<uint8_t>* gc_map_;
Mark Mendellae9fd932014-02-10 16:14:35 -0800372 // For quick code, a FDE entry for the debug_frame section.
373 std::vector<uint8_t>* cfi_info_;
Vladimir Markof4da6752014-08-01 19:04:18 +0100374 // For quick code, linker patches needed by the method.
375 std::vector<LinkerPatch> patches_;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700376};
377
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700378} // namespace art
379
Mathieu Chartier193bad92013-08-29 18:46:00 -0700380#endif // ART_COMPILER_COMPILED_METHOD_H_