blob: 06059c8c6e568d3420dc414a7f6c74bbfcd88667 [file] [log] [blame]
Eric Holkdbc36e22018-09-20 12:03:10 -07001/*
2 * Copyright (C) 2018 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#ifndef DEX_BUILDER_H_
17#define DEX_BUILDER_H_
18
Eric Holkd62c5aa2018-11-01 15:50:24 -070019#include <forward_list>
Eric Holkdbc36e22018-09-20 12:03:10 -070020#include <map>
Eric Holkfaefd4f2018-10-11 16:25:57 -070021#include <optional>
Eric Holkdbc36e22018-09-20 12:03:10 -070022#include <string>
Eric Holkfaefd4f2018-10-11 16:25:57 -070023#include <unordered_map>
Eric Holkdbc36e22018-09-20 12:03:10 -070024#include <vector>
25
Eric Holkd62c5aa2018-11-01 15:50:24 -070026#include "dex/dex_instruction.h"
Eric Holkdbc36e22018-09-20 12:03:10 -070027#include "slicer/dex_ir.h"
28#include "slicer/writer.h"
29
30namespace startop {
31namespace dex {
32
33// TODO: remove this once the dex generation code is complete.
34void WriteTestDexFile(const std::string& filename);
35
36//////////////////////////
37// Forward declarations //
38//////////////////////////
39class DexBuilder;
40
41// Our custom allocator for dex::Writer
42//
43// This keeps track of all allocations and ensures they are freed when
44// TrackingAllocator is destroyed. Pointers to memory allocated by this
45// allocator must not outlive the allocator.
46class TrackingAllocator : public ::dex::Writer::Allocator {
47 public:
48 virtual void* Allocate(size_t size);
49 virtual void Free(void* ptr);
50
51 private:
Eric Holkfaefd4f2018-10-11 16:25:57 -070052 std::unordered_map<void*, std::unique_ptr<uint8_t[]>> allocations_;
Eric Holkdbc36e22018-09-20 12:03:10 -070053};
54
55// Represents a DEX type descriptor.
56//
57// TODO: add a way to create a descriptor for a reference of a class type.
58class TypeDescriptor {
59 public:
60 // Named constructors for base type descriptors.
61 static const TypeDescriptor Int();
62 static const TypeDescriptor Void();
63
Eric Holkfaefd4f2018-10-11 16:25:57 -070064 // Creates a type descriptor from a fully-qualified class name. For example, it turns the class
65 // name java.lang.Object into the descriptor Ljava/lang/Object.
66 static TypeDescriptor FromClassname(const std::string& name);
67
Eric Holkdbc36e22018-09-20 12:03:10 -070068 // Return the full descriptor, such as I or Ljava/lang/Object
69 const std::string& descriptor() const { return descriptor_; }
70 // Return the shorty descriptor, such as I or L
71 std::string short_descriptor() const { return descriptor().substr(0, 1); }
72
Eric Holkfaefd4f2018-10-11 16:25:57 -070073 bool operator<(const TypeDescriptor& rhs) const { return descriptor_ < rhs.descriptor_; }
74
Eric Holkdbc36e22018-09-20 12:03:10 -070075 private:
76 TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {}
77
78 const std::string descriptor_;
79};
80
81// Defines a function signature. For example, Prototype{TypeDescriptor::VOID, TypeDescriptor::Int}
82// represents the function type (Int) -> Void.
83class Prototype {
84 public:
85 template <typename... TypeDescriptors>
86 Prototype(TypeDescriptor return_type, TypeDescriptors... param_types)
87 : return_type_{return_type}, param_types_{param_types...} {}
88
89 // Encode this prototype into the dex file.
90 ir::Proto* Encode(DexBuilder* dex) const;
91
92 // Get the shorty descriptor, such as VII for (Int, Int) -> Void
93 std::string Shorty() const;
94
Eric Holkfaefd4f2018-10-11 16:25:57 -070095 bool operator<(const Prototype& rhs) const {
96 return std::make_tuple(return_type_, param_types_) <
97 std::make_tuple(rhs.return_type_, rhs.param_types_);
98 }
99
Eric Holkdbc36e22018-09-20 12:03:10 -0700100 private:
101 const TypeDescriptor return_type_;
102 const std::vector<TypeDescriptor> param_types_;
103};
104
Eric Holkfaefd4f2018-10-11 16:25:57 -0700105// Represents a DEX register or constant. We separate regular registers and parameters
106// because we will not know the real parameter id until after all instructions
107// have been generated.
108class Value {
109 public:
110 static constexpr Value Local(size_t id) { return Value{id, Kind::kLocalRegister}; }
111 static constexpr Value Parameter(size_t id) { return Value{id, Kind::kParameter}; }
112 static constexpr Value Immediate(size_t value) { return Value{value, Kind::kImmediate}; }
Eric Holk3cc4afc2018-11-08 14:16:20 -0800113 static constexpr Value String(size_t value) { return Value{value, Kind::kString}; }
Eric Holkd62c5aa2018-11-01 15:50:24 -0700114 static constexpr Value Label(size_t id) { return Value{id, Kind::kLabel}; }
Eric Holkb3927582018-11-08 16:40:16 -0800115 static constexpr Value Type(size_t id) { return Value{id, Kind::kType}; }
Eric Holkfaefd4f2018-10-11 16:25:57 -0700116
117 bool is_register() const { return kind_ == Kind::kLocalRegister; }
118 bool is_parameter() const { return kind_ == Kind::kParameter; }
Eric Holkd62c5aa2018-11-01 15:50:24 -0700119 bool is_variable() const { return is_register() || is_parameter(); }
Eric Holkfaefd4f2018-10-11 16:25:57 -0700120 bool is_immediate() const { return kind_ == Kind::kImmediate; }
Eric Holk3cc4afc2018-11-08 14:16:20 -0800121 bool is_string() const { return kind_ == Kind::kString; }
Eric Holkd62c5aa2018-11-01 15:50:24 -0700122 bool is_label() const { return kind_ == Kind::kLabel; }
Eric Holkb3927582018-11-08 16:40:16 -0800123 bool is_type() const { return kind_ == Kind::kType; }
Eric Holkfaefd4f2018-10-11 16:25:57 -0700124
125 size_t value() const { return value_; }
126
127 private:
Eric Holkb3927582018-11-08 16:40:16 -0800128 enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel, kType };
Eric Holkfaefd4f2018-10-11 16:25:57 -0700129
130 const size_t value_;
131 const Kind kind_;
132
133 constexpr Value(size_t value, Kind kind) : value_{value}, kind_{kind} {}
134};
135
136// A virtual instruction. We convert these to real instructions in MethodBuilder::Encode.
137// Virtual instructions are needed to keep track of information that is not known until all of the
138// code is generated. This information includes things like how many local registers are created and
139// branch target locations.
140class Instruction {
141 public:
142 // The operation performed by this instruction. These are virtual instructions that do not
143 // correspond exactly to DEX instructions.
Eric Holkb3927582018-11-08 16:40:16 -0800144 enum class Op {
Eric Holkb3927582018-11-08 16:40:16 -0800145 kBindLabel,
146 kBranchEqz,
Eric Holkc69449d2018-12-13 11:35:58 -0800147 kBranchNEqz,
Eric Holk44d8cdf2018-12-17 13:35:34 -0800148 kCheckCast,
149 kInvokeDirect,
150 kInvokeInterface,
151 kInvokeStatic,
152 kInvokeVirtual,
153 kMove,
154 kNew,
155 kReturn,
156 kReturnObject,
Eric Holkb3927582018-11-08 16:40:16 -0800157 };
Eric Holkfaefd4f2018-10-11 16:25:57 -0700158
159 ////////////////////////
160 // Named Constructors //
161 ////////////////////////
162
163 // For instructions with no return value and no arguments.
164 static inline Instruction OpNoArgs(Op opcode) {
165 return Instruction{opcode, /*method_id*/ 0, /*dest*/ {}};
166 }
167 // For most instructions, which take some number of arguments and have an optional return value.
168 template <typename... T>
169 static inline Instruction OpWithArgs(Op opcode, std::optional<const Value> dest, T... args) {
Eric Holkc69449d2018-12-13 11:35:58 -0800170 return Instruction{opcode, /*method_id=*/0, /*result_is_object=*/false, dest, args...};
Eric Holkfaefd4f2018-10-11 16:25:57 -0700171 }
Eric Holk44d8cdf2018-12-17 13:35:34 -0800172
173 // A cast instruction. Basically, `(type)val`
174 static inline Instruction Cast(Value val, Value type) {
175 DCHECK(type.is_type());
176 return OpWithArgs(Op::kCheckCast, val, type);
177 }
178
Eric Holkfaefd4f2018-10-11 16:25:57 -0700179 // For method calls.
180 template <typename... T>
181 static inline Instruction InvokeVirtual(size_t method_id, std::optional<const Value> dest,
182 Value this_arg, T... args) {
Eric Holkc69449d2018-12-13 11:35:58 -0800183 return Instruction{
184 Op::kInvokeVirtual, method_id, /*result_is_object=*/false, dest, this_arg, args...};
185 }
186 // Returns an object
187 template <typename... T>
188 static inline Instruction InvokeVirtualObject(size_t method_id, std::optional<const Value> dest,
189 Value this_arg, T... args) {
190 return Instruction{
191 Op::kInvokeVirtual, method_id, /*result_is_object=*/true, dest, this_arg, args...};
Eric Holkfaefd4f2018-10-11 16:25:57 -0700192 }
Eric Holkb3927582018-11-08 16:40:16 -0800193 // For direct calls (basically, constructors).
194 template <typename... T>
195 static inline Instruction InvokeDirect(size_t method_id, std::optional<const Value> dest,
196 Value this_arg, T... args) {
Eric Holkc69449d2018-12-13 11:35:58 -0800197 return Instruction{
198 Op::kInvokeDirect, method_id, /*result_is_object=*/false, dest, this_arg, args...};
199 }
200 // Returns an object
201 template <typename... T>
202 static inline Instruction InvokeDirectObject(size_t method_id, std::optional<const Value> dest,
203 Value this_arg, T... args) {
204 return Instruction{
205 Op::kInvokeDirect, method_id, /*result_is_object=*/true, dest, this_arg, args...};
206 }
207 // For static calls.
208 template <typename... T>
209 static inline Instruction InvokeStatic(size_t method_id, std::optional<const Value> dest,
210 T... args) {
211 return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/false, dest, args...};
212 }
213 // Returns an object
214 template <typename... T>
215 static inline Instruction InvokeStaticObject(size_t method_id, std::optional<const Value> dest,
216 T... args) {
217 return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/true, dest, args...};
218 }
219 // For static calls.
220 template <typename... T>
221 static inline Instruction InvokeInterface(size_t method_id, std::optional<const Value> dest,
222 T... args) {
223 return Instruction{Op::kInvokeInterface, method_id, /*result_is_object=*/false, dest, args...};
Eric Holkb3927582018-11-08 16:40:16 -0800224 }
Eric Holkfaefd4f2018-10-11 16:25:57 -0700225
226 ///////////////
227 // Accessors //
228 ///////////////
229
230 Op opcode() const { return opcode_; }
231 size_t method_id() const { return method_id_; }
Eric Holkc69449d2018-12-13 11:35:58 -0800232 bool result_is_object() const { return result_is_object_; }
Eric Holkfaefd4f2018-10-11 16:25:57 -0700233 const std::optional<const Value>& dest() const { return dest_; }
234 const std::vector<const Value>& args() const { return args_; }
235
236 private:
237 inline Instruction(Op opcode, size_t method_id, std::optional<const Value> dest)
Eric Holkc69449d2018-12-13 11:35:58 -0800238 : opcode_{opcode}, method_id_{method_id}, result_is_object_{false}, dest_{dest}, args_{} {}
Eric Holkfaefd4f2018-10-11 16:25:57 -0700239
240 template <typename... T>
Eric Holkc69449d2018-12-13 11:35:58 -0800241 inline constexpr Instruction(Op opcode, size_t method_id, bool result_is_object,
242 std::optional<const Value> dest, T... args)
243 : opcode_{opcode},
244 method_id_{method_id},
245 result_is_object_{result_is_object},
246 dest_{dest},
247 args_{args...} {}
Eric Holkfaefd4f2018-10-11 16:25:57 -0700248
249 const Op opcode_;
250 // The index of the method to invoke, for kInvokeVirtual and similar opcodes.
251 const size_t method_id_{0};
Eric Holkc69449d2018-12-13 11:35:58 -0800252 const bool result_is_object_;
Eric Holkfaefd4f2018-10-11 16:25:57 -0700253 const std::optional<const Value> dest_;
254 const std::vector<const Value> args_;
255};
256
257// Needed for CHECK_EQ, DCHECK_EQ, etc.
258std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode);
259
Eric Holkb3927582018-11-08 16:40:16 -0800260// Keeps track of information needed to manipulate or call a method.
261struct MethodDeclData {
262 size_t id;
263 ir::MethodDecl* decl;
264};
265
Eric Holkdbc36e22018-09-20 12:03:10 -0700266// Tools to help build methods and their bodies.
267class MethodBuilder {
268 public:
269 MethodBuilder(DexBuilder* dex, ir::Class* class_def, ir::MethodDecl* decl);
270
271 // Encode the method into DEX format.
272 ir::EncodedMethod* Encode();
273
Eric Holkdbc36e22018-09-20 12:03:10 -0700274 // Create a new register to be used to storing values. Note that these are not SSA registers, like
275 // might be expected in similar code generators. This does no liveness tracking or anything, so
276 // it's up to the caller to reuse registers as appropriate.
Eric Holkfaefd4f2018-10-11 16:25:57 -0700277 Value MakeRegister();
Eric Holkdbc36e22018-09-20 12:03:10 -0700278
Eric Holkd62c5aa2018-11-01 15:50:24 -0700279 Value MakeLabel();
280
Eric Holkdbc36e22018-09-20 12:03:10 -0700281 /////////////////////////////////
282 // Instruction builder methods //
283 /////////////////////////////////
284
Eric Holkfaefd4f2018-10-11 16:25:57 -0700285 void AddInstruction(Instruction instruction);
286
Eric Holkdbc36e22018-09-20 12:03:10 -0700287 // return-void
288 void BuildReturn();
Eric Holk3cc4afc2018-11-08 14:16:20 -0800289 void BuildReturn(Value src, bool is_object = false);
Eric Holkdbc36e22018-09-20 12:03:10 -0700290 // const/4
Eric Holkfaefd4f2018-10-11 16:25:57 -0700291 void BuildConst4(Value target, int value);
Eric Holk3cc4afc2018-11-08 14:16:20 -0800292 void BuildConstString(Value target, const std::string& value);
Eric Holkb3927582018-11-08 16:40:16 -0800293 template <typename... T>
294 void BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args);
Eric Holkdbc36e22018-09-20 12:03:10 -0700295
296 // TODO: add builders for more instructions
297
Eric Holkc69449d2018-12-13 11:35:58 -0800298 DexBuilder* dex_file() const { return dex_; }
299
Eric Holkdbc36e22018-09-20 12:03:10 -0700300 private:
Eric Holkfaefd4f2018-10-11 16:25:57 -0700301 void EncodeInstructions();
302 void EncodeInstruction(const Instruction& instruction);
Eric Holk3cc4afc2018-11-08 14:16:20 -0800303
304 // Encodes a return instruction. For instructions with no return value, the opcode field is
305 // ignored. Otherwise, this specifies which return instruction will be used (return,
306 // return-object, etc.)
307 void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode);
308
Eric Holkfaefd4f2018-10-11 16:25:57 -0700309 void EncodeMove(const Instruction& instruction);
Eric Holkb3927582018-11-08 16:40:16 -0800310 void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode);
Eric Holkd62c5aa2018-11-01 15:50:24 -0700311 void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
Eric Holkb3927582018-11-08 16:40:16 -0800312 void EncodeNew(const Instruction& instruction);
Eric Holk44d8cdf2018-12-17 13:35:34 -0800313 void EncodeCast(const Instruction& instruction);
Eric Holkfaefd4f2018-10-11 16:25:57 -0700314
Eric Holk1c0f3f02018-11-09 13:48:59 -0800315 // Low-level instruction format encoding. See
316 // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of
317 // formats.
318
319 inline void Encode10x(art::Instruction::Code opcode) {
320 // 00|op
321 buffer_.push_back(opcode);
322 }
323
324 inline void Encode11x(art::Instruction::Code opcode, uint8_t a) {
325 // aa|op
326 buffer_.push_back((a << 8) | opcode);
327 }
328
329 inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) {
330 // b|a|op
331
332 // Make sure the fields are in bounds (4 bits for a, 4 bits for b).
333 CHECK_LT(a, 16);
334 CHECK_LE(-8, b);
335 CHECK_LT(b, 8);
336
337 buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode);
338 }
339
340 inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) {
341 // aa|op|bbbb
342 buffer_.push_back((a << 8) | opcode);
343 buffer_.push_back(b);
344 }
345
346 inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
347 uint8_t e, uint8_t f, uint8_t g) {
348 // a|g|op|bbbb|f|e|d|c
349
350 CHECK_LE(a, 5);
351 CHECK_LT(c, 16);
352 CHECK_LT(d, 16);
353 CHECK_LT(e, 16);
354 CHECK_LT(f, 16);
355 CHECK_LT(g, 16);
356 buffer_.push_back((a << 12) | (g << 8) | opcode);
357 buffer_.push_back(b);
358 buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c);
359 }
360
Eric Holkfaefd4f2018-10-11 16:25:57 -0700361 // Converts a register or parameter to its DEX register number.
Eric Holkd62c5aa2018-11-01 15:50:24 -0700362 size_t RegisterValue(const Value& value) const;
363
364 // Sets a label's address to the current position in the instruction buffer. If there are any
365 // forward references to the label, this function will back-patch them.
366 void BindLabel(const Value& label);
367
368 // Returns the offset of the label relative to the given instruction offset. If the label is not
369 // bound, a reference will be saved and it will automatically be patched when the label is bound.
370 ::dex::u2 LabelValue(const Value& label, size_t instruction_offset, size_t field_offset);
Eric Holkfaefd4f2018-10-11 16:25:57 -0700371
Eric Holkdbc36e22018-09-20 12:03:10 -0700372 DexBuilder* dex_;
373 ir::Class* class_;
374 ir::MethodDecl* decl_;
375
Eric Holkfaefd4f2018-10-11 16:25:57 -0700376 // A list of the instructions we will eventually encode.
377 std::vector<Instruction> instructions_;
378
379 // A buffer to hold instructions that have been encoded.
Eric Holkdbc36e22018-09-20 12:03:10 -0700380 std::vector<::dex::u2> buffer_;
381
382 // How many registers we've allocated
Eric Holkfaefd4f2018-10-11 16:25:57 -0700383 size_t num_registers_{0};
Eric Holkd62c5aa2018-11-01 15:50:24 -0700384
385 // Stores information needed to back-patch a label once it is bound. We need to know the start of
386 // the instruction that refers to the label, and the offset to where the actual label value should
387 // go.
388 struct LabelReference {
389 size_t instruction_offset;
390 size_t field_offset;
391 };
392
393 struct LabelData {
394 std::optional<size_t> bound_address;
395 std::forward_list<LabelReference> references;
396 };
397
398 std::vector<LabelData> labels_;
Eric Holkb3927582018-11-08 16:40:16 -0800399
400 // During encoding, keep track of the largest number of arguments needed, so we can use it for our
401 // outs count
402 size_t max_args_{0};
Eric Holkdbc36e22018-09-20 12:03:10 -0700403};
404
405// A helper to build class definitions.
406class ClassBuilder {
407 public:
Eric Holkfaefd4f2018-10-11 16:25:57 -0700408 ClassBuilder(DexBuilder* parent, const std::string& name, ir::Class* class_def);
Eric Holkdbc36e22018-09-20 12:03:10 -0700409
410 void set_source_file(const std::string& source);
411
412 // Create a method with the given name and prototype. The returned MethodBuilder can be used to
413 // fill in the method body.
414 MethodBuilder CreateMethod(const std::string& name, Prototype prototype);
415
416 private:
Eric Holkfaefd4f2018-10-11 16:25:57 -0700417 DexBuilder* const parent_;
418 const TypeDescriptor type_descriptor_;
419 ir::Class* const class_;
420};
421
Eric Holkdbc36e22018-09-20 12:03:10 -0700422// Builds Dex files from scratch.
423class DexBuilder {
424 public:
425 DexBuilder();
426
427 // Create an in-memory image of the DEX file that can either be loaded directly or written to a
428 // file.
429 slicer::MemView CreateImage();
430
431 template <typename T>
432 T* Alloc() {
433 return dex_file_->Alloc<T>();
434 }
435
436 // Find the ir::String that matches the given string, creating it if it does not exist.
437 ir::String* GetOrAddString(const std::string& string);
438 // Create a new class of the given name.
439 ClassBuilder MakeClass(const std::string& name);
440
441 // Add a type for the given descriptor, or return the existing one if it already exists.
Eric Holkfaefd4f2018-10-11 16:25:57 -0700442 // See the TypeDescriptor class for help generating these. GetOrAddType can be used to declare
443 // imported classes.
Eric Holkdbc36e22018-09-20 12:03:10 -0700444 ir::Type* GetOrAddType(const std::string& descriptor);
445
Eric Holkfaefd4f2018-10-11 16:25:57 -0700446 // Returns the method id for the method, creating it if it has not been created yet.
447 const MethodDeclData& GetOrDeclareMethod(TypeDescriptor type, const std::string& name,
448 Prototype prototype);
449
Eric Holkdbc36e22018-09-20 12:03:10 -0700450 private:
Eric Holkfaefd4f2018-10-11 16:25:57 -0700451 // Looks up the ir::Proto* corresponding to this given prototype, or creates one if it does not
452 // exist.
453 ir::Proto* GetOrEncodeProto(Prototype prototype);
454
Eric Holkdbc36e22018-09-20 12:03:10 -0700455 std::shared_ptr<ir::DexFile> dex_file_;
456
457 // allocator_ is needed to be able to encode the image.
458 TrackingAllocator allocator_;
459
460 // We'll need to allocate buffers for all of the encoded strings we create. This is where we store
461 // all of them.
462 std::vector<std::unique_ptr<uint8_t[]>> string_data_;
463
464 // Keep track of what types we've defined so we can look them up later.
Eric Holkfaefd4f2018-10-11 16:25:57 -0700465 std::unordered_map<std::string, ir::Type*> types_by_descriptor_;
466
467 struct MethodDescriptor {
468 TypeDescriptor type;
469 std::string name;
470 Prototype prototype;
471
472 inline bool operator<(const MethodDescriptor& rhs) const {
473 return std::make_tuple(type, name, prototype) <
474 std::make_tuple(rhs.type, rhs.name, rhs.prototype);
475 }
476 };
477
478 // Maps method declarations to their method index. This is needed to encode references to them.
479 // When we go to actually write the DEX file, slicer will re-assign these after correctly sorting
480 // the methods list.
481 std::map<MethodDescriptor, MethodDeclData> method_id_map_;
Eric Holkdbc36e22018-09-20 12:03:10 -0700482
483 // Keep track of what strings we've defined so we can look them up later.
Eric Holkfaefd4f2018-10-11 16:25:57 -0700484 std::unordered_map<std::string, ir::String*> strings_;
485
486 // Keep track of already-encoded protos.
487 std::map<Prototype, ir::Proto*> proto_map_;
Eric Holkdbc36e22018-09-20 12:03:10 -0700488};
489
Eric Holkb3927582018-11-08 16:40:16 -0800490template <typename... T>
491void MethodBuilder::BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args) {
492 MethodDeclData constructor_data{dex_->GetOrDeclareMethod(type, "<init>", constructor)};
493 // allocate the object
494 ir::Type* type_def = dex_->GetOrAddType(type.descriptor());
495 AddInstruction(
496 Instruction::OpWithArgs(Instruction::Op::kNew, target, Value::Type(type_def->orig_index)));
497 // call the constructor
498 AddInstruction(Instruction::InvokeDirect(constructor_data.id, /*dest=*/{}, target, args...));
499};
500
Eric Holkdbc36e22018-09-20 12:03:10 -0700501} // namespace dex
502} // namespace startop
503
504#endif // DEX_BUILDER_H_