Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
locations_helpers.h
Go to the documentation of this file.
1// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5// This file contains two helper functions MakeLocationSummaryFromEmitter
6// and InvokeEmitter which simplify the definition of MakeLocationSummary
7// and EmitNativeCode methods for instructions.
8//
9// Canonical way to define instruction backend would be to override:
10//
11// A) MakeLocationSummary method that creates and fills LocationSummary object
12// with location constraints for register allocator;
13//
14// B) EmitNativeCode method that unpacks results of register allocation from
15// LocationSummary and uses them to generate native code.
16//
17// Helpers contained in this file allow to "autogenerate" both of these methods
18// from a single *emitter* function that has the following signature:
19//
20// void Emitter(FlowGraphCompiler*,
21// Instr* instr,
22// OutType out,
23// InputType1 v1, ...)
24//
25// Here Instr is the type of the instruction, OutType is a type of an output
26// register and InputType1, InputType2, etc are register types for inputs or
27// temps.
28//
29// To create LocationSummary from emitter's signature invoke
30//
31// MakeLocationSummaryFromEmitter(zone, instr, &Emitter);
32//
33// To unpack allocation results from LocationSummary and call emitter write
34//
35// InvokeEmitter(zone, instr, &Emitter)
36//
37// See DEFINE_BACKEND macro below that can be used to do that.
38//
39// In addition to supporting Register and FpuRegister types several markers can
40// be used to denote various register constraints, e.g. SameAsFirstInput, Fixed
41// and Temp. See below.
42//
43#ifndef RUNTIME_VM_COMPILER_BACKEND_LOCATIONS_HELPERS_H_
44#define RUNTIME_VM_COMPILER_BACKEND_LOCATIONS_HELPERS_H_
45
46#if defined(DART_PRECOMPILED_RUNTIME)
47#error "AOT runtime should not use compiler sources (including header files)"
48#endif // defined(DART_PRECOMPILED_RUNTIME)
49
51
52namespace dart {
53
54// Forward declarations.
55class FlowGraphCompiler;
56
57#define DEFINE_BACKEND(Name, Args) \
58 static void EmitterFor##Name(FlowGraphCompiler* compiler, \
59 Name##Instr* instr, PP_APPLY(PP_UNPACK, Args)); \
60 LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt) \
61 const { \
62 return MakeLocationSummaryFromEmitter(zone, this, &EmitterFor##Name); \
63 } \
64 void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) { \
65 InvokeEmitter(compiler, this, &EmitterFor##Name); \
66 } \
67 static void EmitterFor##Name(FlowGraphCompiler* compiler, \
68 Name##Instr* instr, PP_APPLY(PP_UNPACK, Args))
69
70#define PP_UNPACK(...) __VA_ARGS__
71#define PP_APPLY(a, b) a b
72
73// Trait that specifies how different types of locations (e.g. Register,
74// FpuRegister) can be extracted from Location objects and how register
75// constraints can be created for different location types and markers like
76// Temp, Fixed and SameAsFirstInput.
77template <typename T>
79
80// Marker type used to signal that output has SameAsFirstInput register
81// constraint, which means that the first input needs to be in a writable
82// register and the instruction will produce output in the same register.
84
85// Marker type used to signal that output has NoLocation register
86// constraint.
87struct NoLocation {};
88
89// Marker type used to signal that this input, output or temp needs to
90// be in a fixed register `reg` of type `R` (either Register or FpuRegister).
91template <typename R, R reg>
92struct Fixed {
93 // Allow implicit coercion of Fixed<R, ...> to R.
94 operator R() { return reg; }
95};
96
97// Marker type to signal that emitter needs a temporary register of type R.
98template <typename R>
99class Temp {
100 private:
101 typedef typename LocationTrait<R>::RegisterType RegisterType;
102
103 public:
104 explicit Temp(R reg) : reg_(reg) {}
105
106 operator RegisterType() { return reg_; }
107
108 private:
109 R reg_;
110};
111
112// Implementation of MakeLocationSummaryFromEmitter and InvokeEmitter.
113
114template <>
117
118 static constexpr bool kIsTemp = false; // This is not a temporary.
119
120 static Register Unwrap(const Location& loc) { return loc.reg(); }
121
122 template <intptr_t arity, intptr_t index>
124 return Unwrap(locs->in(index));
125 }
126
127 template <intptr_t arity, intptr_t index>
129 locs->set_in(index, ToConstraint());
130 }
131
134 return Location::RegisterLocation(reg);
135 }
136};
137
138template <>
141
142 static constexpr bool kIsTemp = false; // This is not a temporary.
143
144 static FpuRegister Unwrap(const Location& loc) { return loc.fpu_reg(); }
145
146 template <intptr_t arity, intptr_t index>
148 return Unwrap(locs->in(index));
149 }
150
151 template <intptr_t arity, intptr_t index>
153 locs->set_in(index, ToConstraint());
154 }
155
160};
161
162template <typename R, R reg>
163struct LocationTrait<Fixed<R, reg> > {
165
166 static constexpr bool kIsTemp = false; // This is not a temporary.
167
168 static Fixed<R, reg> Unwrap(const Location& loc) {
169 ASSERT(LocationTrait<R>::Unwrap(loc) == reg);
170 return Fixed<R, reg>();
171 }
172
173 template <intptr_t arity, intptr_t index>
175 return Unwrap(locs->in(index));
176 }
177
178 template <intptr_t arity, intptr_t index>
180 locs->set_in(index, ToConstraint());
181 }
182
186};
187
188template <typename RegisterType>
189struct LocationTrait<Temp<RegisterType> > {
190 static constexpr bool kIsTemp = true; // This is a temporary.
191
195
196 template <intptr_t arity, intptr_t index>
198 return Unwrap(locs->temp(index - arity));
199 }
200
201 template <intptr_t arity, intptr_t index>
203 locs->set_temp(index - arity, ToConstraint());
204 }
205
209};
210
211template <>
213 static constexpr bool kIsTemp = false; // This is not a temporary.
214
215 static SameAsFirstInput Unwrap(const Location& loc) {
216 return SameAsFirstInput();
217 }
218
220};
221
222template <>
224 static constexpr bool kIsTemp = false; // This is not a temporary.
225
226 static NoLocation Unwrap(const Location& loc) { return NoLocation(); }
227
229};
230
231// Auxiliary types and macro helpers to construct lists of types.
232// TODO(vegorov) rewrite this using variadic templates when we enable C++11
233
234struct Nil;
235
236template <typename T, typename U>
237struct Cons {};
238
239#define TYPE_LIST_0() Nil
240#define TYPE_LIST_1(T0) Cons<T0, TYPE_LIST_0()>
241#define TYPE_LIST_2(T0, T1) Cons<T0, TYPE_LIST_1(T1)>
242#define TYPE_LIST_3(T0, T1, T2) Cons<T0, TYPE_LIST_2(T1, T2)>
243#define TYPE_LIST_4(T0, T1, T2, T3) Cons<T0, TYPE_LIST_3(T1, T2, T3)>
244#define TYPE_LIST_5(T0, T1, T2, T3, T4) Cons<T0, TYPE_LIST_4(T1, T2, T3, T4)>
245
246// SignatureTrait is a recursively defined type that calculates InputCount and
247// TempCount for a signature and can be used to invoke SetInputConstraint for
248// each type in a signature to populate location summary with correct
249// constraints.
250#define SIGNATURE_TRAIT(Arity, Args) \
251 SignatureTrait<PP_APPLY(TYPE_LIST_##Arity, Args)>
252
253template <typename T>
255
256template <>
257struct SignatureTrait<Nil> {
258 enum { kArity = 0, kTempCount = 0, kInputCount = kArity - kTempCount };
259
260 template <intptr_t kArity, intptr_t kOffset>
261 static void SetConstraints(LocationSummary* locs) {}
262};
263
264template <typename T0, typename Tx>
265struct SignatureTrait<Cons<T0, Tx> > {
267
268 enum {
269 kArity = 1 + Tail::kArity,
270 kTempCount = (LocationTrait<T0>::kIsTemp ? 1 : 0) + Tail::kTempCount,
271 kInputCount = kArity - kTempCount
272 };
273
274 template <intptr_t kArity, intptr_t kOffset>
275 static void SetConstraints(LocationSummary* locs) {
276 LocationTrait<T0>::template SetInputConstraint<kArity, kOffset>(locs);
277 Tail::template SetConstraints<kArity, kOffset + 1>(locs);
278 }
279};
280
281// MakeLocationSummaryFromEmitter overloadings below.
282
283template <typename Instr, typename Out>
285 const Instr* instr,
286 void (*Emit)(FlowGraphCompiler*,
287 Instr*,
288 Out)) {
289 typedef SIGNATURE_TRAIT(0, ()) S;
290 ASSERT(instr->InputCount() == S::kInputCount);
291 LocationSummary* summary = new (zone) LocationSummary(
292 zone, S::kInputCount, S::kTempCount, LocationSummary::kNoCall);
294 return summary;
295}
296
297#define DEFINE_MAKE_LOCATION_SUMMARY_SPECIALIZATION(Arity, Types) \
298 LocationSummary* MakeLocationSummaryFromEmitter( \
299 Zone* zone, const Instr* instr, \
300 void (*Emit)(FlowGraphCompiler*, Instr*, Out, \
301 PP_APPLY(PP_UNPACK, Types))) { \
302 typedef SIGNATURE_TRAIT(Arity, Types) S; \
303 ASSERT(instr->InputCount() == S::kInputCount); \
304 LocationSummary* summary = new (zone) LocationSummary( \
305 zone, S::kInputCount, S::kTempCount, LocationSummary::kNoCall); \
306 S::template SetConstraints<S::kInputCount, 0>(summary); \
307 summary->set_out(0, LocationTrait<Out>::ToConstraint()); \
308 return summary; \
309 }
310
311template <typename Instr, typename Out, typename T0>
313
314template <typename Instr, typename Out, typename T0, typename T1>
316
317template <typename Instr, typename Out, typename T0, typename T1, typename T2>
319
320template <typename Instr,
321 typename Out,
322 typename T0,
323 typename T1,
324 typename T2,
325 typename T3>
327
328template <typename Instr,
329 typename Out,
330 typename T0,
331 typename T1,
332 typename T2,
333 typename T3,
334 typename T4>
336
337// InvokeEmitter overloadings below.
338
339template <typename Instr, typename Out>
341 Instr* instr,
342 void (*Emit)(FlowGraphCompiler*, Instr*, Out)) {
343 typedef SIGNATURE_TRAIT(0, ()) S;
344 ASSERT(instr->InputCount() == S::kInputCount);
345 LocationSummary* locs = instr->locs();
346 Emit(compiler, instr, LocationTrait<Out>::Unwrap(locs->out(0)));
347}
348
349template <typename Instr, typename Out, typename T0>
351 Instr* instr,
352 void (*Emit)(FlowGraphCompiler*, Instr*, Out, T0)) {
353 typedef SIGNATURE_TRAIT(1, (T0)) S;
354 ASSERT(instr->InputCount() == S::kInputCount);
355 LocationSummary* locs = instr->locs();
356 Emit(compiler, instr, LocationTrait<Out>::Unwrap(locs->out(0)),
357 LocationTrait<T0>::template UnwrapInput<S::kInputCount, 0>(locs));
358}
359
360template <typename Instr, typename Out, typename T0, typename T1>
362 Instr* instr,
363 void (*Emit)(FlowGraphCompiler*, Instr*, Out, T0, T1)) {
364 typedef SIGNATURE_TRAIT(2, (T0, T1)) S;
365 ASSERT(instr->InputCount() == S::kInputCount);
366 LocationSummary* locs = instr->locs();
367 Emit(compiler, instr, LocationTrait<Out>::Unwrap(locs->out(0)),
368 LocationTrait<T0>::template UnwrapInput<S::kInputCount, 0>(locs),
369 LocationTrait<T1>::template UnwrapInput<S::kInputCount, 1>(locs));
370}
371
372template <typename Instr, typename Out, typename T0, typename T1, typename T2>
374 Instr* instr,
375 void (*Emit)(FlowGraphCompiler*, Instr*, Out, T0, T1, T2)) {
376 typedef SIGNATURE_TRAIT(3, (T0, T1, T2)) S;
377 ASSERT(instr->InputCount() == S::kInputCount);
378 LocationSummary* locs = instr->locs();
379 Emit(compiler, instr, LocationTrait<Out>::Unwrap(locs->out(0)),
380 LocationTrait<T0>::template UnwrapInput<S::kInputCount, 0>(locs),
381 LocationTrait<T1>::template UnwrapInput<S::kInputCount, 1>(locs),
382 LocationTrait<T2>::template UnwrapInput<S::kInputCount, 2>(locs));
383}
384
385template <typename Instr,
386 typename Out,
387 typename T0,
388 typename T1,
389 typename T2,
390 typename T3>
393 Instr* instr,
394 void (*Emit)(FlowGraphCompiler*, Instr*, Out, T0, T1, T2, T3)) {
395 typedef SIGNATURE_TRAIT(4, (T0, T1, T2, T3)) S;
396 ASSERT(instr->InputCount() == S::kInputCount);
397 LocationSummary* locs = instr->locs();
398 Emit(compiler, instr, LocationTrait<Out>::Unwrap(locs->out(0)),
399 LocationTrait<T0>::template UnwrapInput<S::kInputCount, 0>(locs),
400 LocationTrait<T1>::template UnwrapInput<S::kInputCount, 1>(locs),
401 LocationTrait<T2>::template UnwrapInput<S::kInputCount, 2>(locs),
402 LocationTrait<T3>::template UnwrapInput<S::kInputCount, 3>(locs));
403}
404
405template <typename Instr,
406 typename Out,
407 typename T0,
408 typename T1,
409 typename T2,
410 typename T3,
411 typename T4>
414 Instr* instr,
415 void (*Emit)(FlowGraphCompiler*, Instr*, Out, T0, T1, T2, T3, T4)) {
416 typedef SIGNATURE_TRAIT(5, (T0, T1, T2, T3, T4)) S;
417 ASSERT(instr->InputCount() == S::kInputCount);
418 LocationSummary* locs = instr->locs();
419 Emit(compiler, instr, LocationTrait<Out>::Unwrap(locs->out(0)),
420 LocationTrait<T0>::template UnwrapInput<S::kInputCount, 0>(locs),
421 LocationTrait<T1>::template UnwrapInput<S::kInputCount, 1>(locs),
422 LocationTrait<T2>::template UnwrapInput<S::kInputCount, 2>(locs),
423 LocationTrait<T3>::template UnwrapInput<S::kInputCount, 3>(locs),
424 LocationTrait<T4>::template UnwrapInput<S::kInputCount, 4>(locs));
425}
426
427} // namespace dart
428
429#if defined(TARGET_ARCH_IA32)
430
431#elif defined(TARGET_ARCH_X64)
432
433#elif defined(TARGET_ARCH_ARM)
435#elif defined(TARGET_ARCH_ARM64)
436
437#elif defined(TARGET_ARCH_RISCV32)
438
439#elif defined(TARGET_ARCH_RISCV64)
440
441#else
442#error Unknown architecture.
443#endif
444
445#endif // RUNTIME_VM_COMPILER_BACKEND_LOCATIONS_HELPERS_H_
Location temp(intptr_t index) const
Definition locations.h:882
Location out(intptr_t index) const
Definition locations.h:903
void set_temp(intptr_t index, Location loc)
Definition locations.h:894
void set_out(intptr_t index, Location loc)
Definition locations.cc:232
Location in(intptr_t index) const
Definition locations.h:866
void set_in(intptr_t index, Location loc)
Definition locations.cc:205
static Location NoLocation()
Definition locations.h:387
static Location SameAsFirstInput()
Definition locations.h:382
Register reg() const
Definition locations.h:404
static Location FpuRegisterLocation(FpuRegister reg)
Definition locations.h:410
static Location RegisterLocation(Register reg)
Definition locations.h:398
static Location RequiresRegister()
Definition locations.h:365
static Location RequiresFpuRegister()
Definition locations.h:369
FpuRegister fpu_reg() const
Definition locations.h:416
#define ASSERT(E)
#define R(r)
#define DEFINE_MAKE_LOCATION_SUMMARY_SPECIALIZATION(Arity, Types)
#define SIGNATURE_TRAIT(Arity, Args)
LocationSummary * MakeLocationSummaryFromEmitter(Zone *zone, const Instr *instr, void(*Emit)(FlowGraphCompiler *, Instr *, Out))
void InvokeEmitter(FlowGraphCompiler *compiler, Instr *instr, void(*Emit)(FlowGraphCompiler *, Instr *, Out))
static void SetInputConstraint(LocationSummary *locs)
static Fixed< R, reg > UnwrapInput(LocationSummary *locs)
static Fixed< R, reg > Unwrap(const Location &loc)
static FpuRegister UnwrapInput(LocationSummary *locs)
static Location ToFixedConstraint(FpuRegister reg)
static FpuRegister Unwrap(const Location &loc)
static void SetInputConstraint(LocationSummary *locs)
static NoLocation Unwrap(const Location &loc)
static void SetInputConstraint(LocationSummary *locs)
static Location ToFixedConstraint(Register reg)
static Register Unwrap(const Location &loc)
static Register UnwrapInput(LocationSummary *locs)
static SameAsFirstInput Unwrap(const Location &loc)
static Temp< RegisterType > Unwrap(const Location &loc)
static Temp< RegisterType > UnwrapInput(LocationSummary *locs)
static void SetInputConstraint(LocationSummary *locs)
static void SetConstraints(LocationSummary *locs)
static void SetConstraints(LocationSummary *locs)