1 /*
2  * Copyright 2019 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkVM_DEFINED
9 #define SkVM_DEFINED
10 
11 #include "include/core/SkBlendMode.h"
12 #include "include/core/SkColor.h"
13 #include "include/private/SkMacros.h"
14 #include "include/private/SkTArray.h"
15 #include "include/private/SkTHash.h"
16 #include "src/core/SkSpan.h"
17 #include "src/core/SkVM_fwd.h"
18 #include <vector>      // std::vector
19 
20 class SkWStream;
21 
22 #if defined(SKVM_JIT_WHEN_POSSIBLE)
23     #if defined(__x86_64__) || defined(_M_X64)
24         #if defined(_WIN32) || defined(__linux) || defined(__APPLE__)
25             #if !defined(SK_BUILD_FOR_IOS)  // Exclude iOS simulator.
26                 #define SKVM_JIT
27             #endif
28         #endif
29     #endif
30     #if defined(__aarch64__)
31         #if defined(__ANDROID__)
32             #define SKVM_JIT
33         #endif
34     #endif
35 #endif
36 
37 #if 0
38     #define SKVM_LLVM
39 #endif
40 
41 #if 0
42     #undef SKVM_JIT
43 #endif
44 
45 namespace skvm {
46 
47     bool fma_supported();
48 
49     class Assembler {
50     public:
51         explicit Assembler(void* buf);
52 
53         size_t size() const;
54 
55         // Order matters... GP64, Xmm, Ymm values match 4-bit register encoding for each.
56         enum GP64 {
57             rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
58             r8 , r9 , r10, r11, r12, r13, r14, r15,
59         };
60         enum Xmm {
61             xmm0, xmm1, xmm2 , xmm3 , xmm4 , xmm5 , xmm6 , xmm7 ,
62             xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
63         };
64         enum Ymm {
65             ymm0, ymm1, ymm2 , ymm3 , ymm4 , ymm5 , ymm6 , ymm7 ,
66             ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15,
67         };
68 
69         // X and V values match 5-bit encoding for each (nothing tricky).
70         enum X {
71             x0 , x1 , x2 , x3 , x4 , x5 , x6 , x7 ,
72             x8 , x9 , x10, x11, x12, x13, x14, x15,
73             x16, x17, x18, x19, x20, x21, x22, x23,
74             x24, x25, x26, x27, x28, x29, x30, xzr, sp=xzr,
75         };
76         enum V {
77             v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 ,
78             v8 , v9 , v10, v11, v12, v13, v14, v15,
79             v16, v17, v18, v19, v20, v21, v22, v23,
80             v24, v25, v26, v27, v28, v29, v30, v31,
81         };
82 
83         void bytes(const void*, int);
84         void byte(uint8_t);
85         void word(uint32_t);
86 
87         struct Label {
88             int                                      offset = 0;
89             enum { NotYetSet, ARMDisp19, X86Disp32 } kind = NotYetSet;
90             SkSTArray<2, int>                        references;
91         };
92 
93         // x86-64
94 
95         void align(int mod);
96 
97         void int3();
98         void vzeroupper();
99         void ret();
100 
101         // Mem represents a value at base + disp + scale*index,
102         // or simply at base + disp if index=rsp.
103         enum Scale { ONE, TWO, FOUR, EIGHT };
104         struct Mem {
105             GP64  base;
106             int   disp  = 0;
107             GP64  index = rsp;
108             Scale scale = ONE;
109         };
110 
111         struct Operand {
112             union {
113                 int    reg;
114                 Mem    mem;
115                 Label* label;
116             };
117             enum { REG, MEM, LABEL } kind;
118 
OperandOperand119             Operand(GP64   r) : reg  (r), kind(REG  ) {}
OperandOperand120             Operand(Xmm    r) : reg  (r), kind(REG  ) {}
OperandOperand121             Operand(Ymm    r) : reg  (r), kind(REG  ) {}
OperandOperand122             Operand(Mem    m) : mem  (m), kind(MEM  ) {}
OperandOperand123             Operand(Label* l) : label(l), kind(LABEL) {}
124         };
125 
126         void vpand (Ymm dst, Ymm x, Operand y);
127         void vpandn(Ymm dst, Ymm x, Operand y);
128         void vpor  (Ymm dst, Ymm x, Operand y);
129         void vpxor (Ymm dst, Ymm x, Operand y);
130 
131         void vpaddd (Ymm dst, Ymm x, Operand y);
132         void vpsubd (Ymm dst, Ymm x, Operand y);
133         void vpmulld(Ymm dst, Ymm x, Operand y);
134 
135         void vpaddw   (Ymm dst, Ymm x, Operand y);
136         void vpsubw   (Ymm dst, Ymm x, Operand y);
137         void vpmullw  (Ymm dst, Ymm x, Operand y);
138 
139         void vpabsw   (Ymm dst, Operand x);
140         void vpavgw   (Ymm dst, Ymm x, Operand y);  // dst = (x+y+1)>>1, unsigned.
141         void vpmulhrsw(Ymm dst, Ymm x, Operand y);  // dst = (x*y + (1<<14)) >> 15, signed.
142         void vpminsw  (Ymm dst, Ymm x, Operand y);
143         void vpminuw  (Ymm dst, Ymm x, Operand y);
144         void vpmaxsw  (Ymm dst, Ymm x, Operand y);
145         void vpmaxuw  (Ymm dst, Ymm x, Operand y);
146 
147         void vaddps(Ymm dst, Ymm x, Operand y);
148         void vsubps(Ymm dst, Ymm x, Operand y);
149         void vmulps(Ymm dst, Ymm x, Operand y);
150         void vdivps(Ymm dst, Ymm x, Operand y);
151         void vminps(Ymm dst, Ymm x, Operand y);
152         void vmaxps(Ymm dst, Ymm x, Operand y);
153 
154         void vsqrtps(Ymm dst, Operand x);
155 
156         void vfmadd132ps(Ymm dst, Ymm x, Operand y);
157         void vfmadd213ps(Ymm dst, Ymm x, Operand y);
158         void vfmadd231ps(Ymm dst, Ymm x, Operand y);
159 
160         void vfmsub132ps(Ymm dst, Ymm x, Operand y);
161         void vfmsub213ps(Ymm dst, Ymm x, Operand y);
162         void vfmsub231ps(Ymm dst, Ymm x, Operand y);
163 
164         void vfnmadd132ps(Ymm dst, Ymm x, Operand y);
165         void vfnmadd213ps(Ymm dst, Ymm x, Operand y);
166         void vfnmadd231ps(Ymm dst, Ymm x, Operand y);
167 
168         void vpackusdw(Ymm dst, Ymm x, Operand y);
169         void vpackuswb(Ymm dst, Ymm x, Operand y);
170 
171         void vpunpckldq(Ymm dst, Ymm x, Operand y);
172         void vpunpckhdq(Ymm dst, Ymm x, Operand y);
173 
174         void vpcmpeqd(Ymm dst, Ymm x, Operand y);
175         void vpcmpgtd(Ymm dst, Ymm x, Operand y);
176         void vpcmpeqw(Ymm dst, Ymm x, Operand y);
177         void vpcmpgtw(Ymm dst, Ymm x, Operand y);
178 
179         void vcmpps   (Ymm dst, Ymm x, Operand y, int imm);
vcmpeqps(Ymm dst,Ymm x,Operand y)180         void vcmpeqps (Ymm dst, Ymm x, Operand y) { this->vcmpps(dst,x,y,0); }
vcmpltps(Ymm dst,Ymm x,Operand y)181         void vcmpltps (Ymm dst, Ymm x, Operand y) { this->vcmpps(dst,x,y,1); }
vcmpleps(Ymm dst,Ymm x,Operand y)182         void vcmpleps (Ymm dst, Ymm x, Operand y) { this->vcmpps(dst,x,y,2); }
vcmpneqps(Ymm dst,Ymm x,Operand y)183         void vcmpneqps(Ymm dst, Ymm x, Operand y) { this->vcmpps(dst,x,y,4); }
184 
185         // Sadly, the x parameter cannot be a general Operand for these shifts.
186         void vpslld(Ymm dst, Ymm x, int imm);
187         void vpsrld(Ymm dst, Ymm x, int imm);
188         void vpsrad(Ymm dst, Ymm x, int imm);
189 
190         void vpsllw(Ymm dst, Ymm x, int imm);
191         void vpsrlw(Ymm dst, Ymm x, int imm);
192         void vpsraw(Ymm dst, Ymm x, int imm);
193 
194         void vpermq    (Ymm dst, Operand x, int imm);
195         void vperm2f128(Ymm dst, Ymm x, Operand y, int imm);
196         void vpermps   (Ymm dst, Ymm ix, Operand src);        // dst[i] = src[ix[i]]
197 
198         enum Rounding { NEAREST, FLOOR, CEIL, TRUNC, CURRENT };
199         void vroundps(Ymm dst, Operand x, Rounding);
200 
201         void vmovdqa(Ymm dst, Operand x);
202         void vmovups(Ymm dst, Operand x);
203         void vmovups(Xmm dst, Operand x);
204         void vmovups(Operand dst, Ymm x);
205         void vmovups(Operand dst, Xmm x);
206 
207         void vcvtdq2ps (Ymm dst, Operand x);
208         void vcvttps2dq(Ymm dst, Operand x);
209         void vcvtps2dq (Ymm dst, Operand x);
210 
211         void vcvtps2ph(Operand dst, Ymm x, Rounding);
212         void vcvtph2ps(Ymm dst, Operand x);
213 
214         void vpblendvb(Ymm dst, Ymm x, Operand y, Ymm z);
215 
216         void vpshufb(Ymm dst, Ymm x, Operand y);
217 
218         void vptest(Ymm x, Operand y);
219 
220         void vbroadcastss(Ymm dst, Operand y);
221 
222         void vpmovzxwd(Ymm dst, Operand src);   // dst = src, 128-bit, uint16_t -> int
223         void vpmovzxbd(Ymm dst, Operand src);   // dst = src,  64-bit, uint8_t  -> int
224 
225         void vmovq(Operand dst, Xmm src);  // dst = src,  64-bit
226         void vmovd(Operand dst, Xmm src);  // dst = src,  32-bit
227         void vmovd(Xmm dst, Operand src);  // dst = src,  32-bit
228 
229         void vpinsrd(Xmm dst, Xmm src, Operand y, int imm);  // dst = src; dst[imm] = y, 32-bit
230         void vpinsrw(Xmm dst, Xmm src, Operand y, int imm);  // dst = src; dst[imm] = y, 16-bit
231         void vpinsrb(Xmm dst, Xmm src, Operand y, int imm);  // dst = src; dst[imm] = y,  8-bit
232 
233         void vextracti128(Operand dst, Ymm src, int imm);    // dst = src[imm], 128-bit
234         void vpextrd     (Operand dst, Xmm src, int imm);    // dst = src[imm],  32-bit
235         void vpextrw     (Operand dst, Xmm src, int imm);    // dst = src[imm],  16-bit
236         void vpextrb     (Operand dst, Xmm src, int imm);    // dst = src[imm],   8-bit
237 
238         // if (mask & 0x8000'0000) {
239         //     dst = base[scale*ix];
240         // }
241         // mask = 0;
242         void vgatherdps(Ymm dst, Scale scale, Ymm ix, GP64 base, Ymm mask);
243 
244 
245         void label(Label*);
246 
247         void jmp(Label*);
248         void je (Label*);
249         void jne(Label*);
250         void jl (Label*);
251         void jc (Label*);
252 
253         void add (Operand dst, int imm);
254         void sub (Operand dst, int imm);
255         void cmp (Operand dst, int imm);
256         void mov (Operand dst, int imm);
257         void movb(Operand dst, int imm);
258 
259         void add (Operand dst, GP64 x);
260         void sub (Operand dst, GP64 x);
261         void cmp (Operand dst, GP64 x);
262         void mov (Operand dst, GP64 x);
263         void movb(Operand dst, GP64 x);
264 
265         void add (GP64 dst, Operand x);
266         void sub (GP64 dst, Operand x);
267         void cmp (GP64 dst, Operand x);
268         void mov (GP64 dst, Operand x);
269         void movb(GP64 dst, Operand x);
270 
271         // Disambiguators... choice is arbitrary (but generates different code!).
add(GP64 dst,GP64 x)272         void add (GP64 dst, GP64 x) { this->add (Operand(dst), x); }
sub(GP64 dst,GP64 x)273         void sub (GP64 dst, GP64 x) { this->sub (Operand(dst), x); }
cmp(GP64 dst,GP64 x)274         void cmp (GP64 dst, GP64 x) { this->cmp (Operand(dst), x); }
mov(GP64 dst,GP64 x)275         void mov (GP64 dst, GP64 x) { this->mov (Operand(dst), x); }
movb(GP64 dst,GP64 x)276         void movb(GP64 dst, GP64 x) { this->movb(Operand(dst), x); }
277 
278         void movzbq(GP64 dst, Operand x);  // dst = x, uint8_t  -> int
279         void movzwq(GP64 dst, Operand x);  // dst = x, uint16_t -> int
280 
281         // aarch64
282 
283         // d = op(n,m)
284         using DOpNM = void(V d, V n, V m);
285         DOpNM  and16b, orr16b, eor16b, bic16b, bsl16b,
286                add4s,  sub4s,  mul4s,
287               cmeq4s, cmgt4s,
288                        sub8h,  mul8h,
289               fadd4s, fsub4s, fmul4s, fdiv4s, fmin4s, fmax4s,
290               fcmeq4s, fcmgt4s, fcmge4s,
291               tbl;
292 
293         // TODO: there are also float ==,<,<=,>,>= instructions with an immediate 0.0f,
294         // and the register comparison > and >= can also compare absolute values.  Interesting.
295 
296         // d += n*m
297         void fmla4s(V d, V n, V m);
298 
299         // d -= n*m
300         void fmls4s(V d, V n, V m);
301 
302         // d = op(n,imm)
303         using DOpNImm = void(V d, V n, int imm);
304         DOpNImm sli4s,
305                 shl4s, sshr4s, ushr4s,
306                                ushr8h;
307 
308         // d = op(n)
309         using DOpN = void(V d, V n);
310         DOpN not16b,    // d = ~n
311              fneg4s,    // d = -n
312              scvtf4s,   // int -> float
313              fcvtzs4s,  // truncate float -> int
314              fcvtns4s,  // round float -> int  (nearest even)
315              xtns2h,    // u32 -> u16
316              xtnh2b,    // u16 -> u8
317              uxtlb2h,   // u8 -> u16
318              uxtlh2s,   // u16 -> u32
319              uminv4s;   // dst[0] = min(n[0],n[1],n[2],n[3]), n as unsigned
320 
321         void brk (int imm16);
322         void ret (X);
323         void add (X d, X n, int imm12);
324         void sub (X d, X n, int imm12);
325         void subs(X d, X n, int imm12);  // subtract setting condition flags
326 
327         // There's another encoding for unconditional branches that can jump further,
328         // but this one encoded as b.al is simple to implement and should be fine.
b(Label * l)329         void b  (Label* l) { this->b(Condition::al, l); }
bne(Label * l)330         void bne(Label* l) { this->b(Condition::ne, l); }
blt(Label * l)331         void blt(Label* l) { this->b(Condition::lt, l); }
332 
333         // "cmp ..." is just an assembler mnemonic for "subs xzr, ..."!
cmp(X n,int imm12)334         void cmp(X n, int imm12) { this->subs(xzr, n, imm12); }
335 
336         // Compare and branch if zero/non-zero, as if
337         //      cmp(t,0)
338         //      beq/bne(l)
339         // but without setting condition flags.
340         void cbz (X t, Label* l);
341         void cbnz(X t, Label* l);
342 
343         void ldrq(V dst, Label*);  // 128-bit PC-relative load
344 
345         void ldrq(V dst, X src, int imm12=0);  // 128-bit dst = *(src+imm12*16)
346         void ldrs(V dst, X src, int imm12=0);  //  32-bit dst = *(src+imm12*4)
347         void ldrb(V dst, X src, int imm12=0);  //   8-bit dst = *(src+imm12)
348 
349         void strq(V src, X dst, int imm12=0);  // 128-bit *(dst+imm12*16) = src
350         void strs(V src, X dst, int imm12=0);  //  32-bit *(dst+imm12*4)  = src
351         void strb(V src, X dst, int imm12=0);  //   8-bit *(dst+imm12)    = src
352 
353         void fmovs(X dst, V src); // dst = 32-bit src[0]
354 
355     private:
356         // TODO: can probably track two of these three?
357         uint8_t* fCode;
358         uint8_t* fCurr;
359         size_t   fSize;
360 
361         // x86-64
362         enum W { W0, W1 };      // Are the lanes 64-bit (W1) or default (W0)?  Intel Vol 2A 2.3.5.5
363         enum L { L128, L256 };  // Is this a 128- or 256-bit operation?        Intel Vol 2A 2.3.6.2
364 
365         // Helpers for vector instructions.
366         void op(int prefix, int map, int opcode, int dst, int x, Operand y, W,L);
367         void op(int p, int m, int o, Ymm d, Ymm x, Operand y, W w=W0) { op(p,m,o, d,x,y,w,L256); }
368         void op(int p, int m, int o, Ymm d,        Operand y, W w=W0) { op(p,m,o, d,0,y,w,L256); }
369         void op(int p, int m, int o, Xmm d, Xmm x, Operand y, W w=W0) { op(p,m,o, d,x,y,w,L128); }
370         void op(int p, int m, int o, Xmm d,        Operand y, W w=W0) { op(p,m,o, d,0,y,w,L128); }
371 
372         // Helpers for GP64 instructions.
373         void op(int opcode, Operand dst, GP64 x);
374         void op(int opcode, int opcode_ext, Operand dst, int imm);
375 
376         void jump(uint8_t condition, Label*);
377         int disp32(Label*);
378         void imm_byte_after_operand(const Operand&, int byte);
379 
380         // aarch64
381 
382         // Opcode for 3-arguments ops is split between hi and lo:
383         //    [11 bits hi] [5 bits m] [6 bits lo] [5 bits n] [5 bits d]
384         void op(uint32_t hi, V m, uint32_t lo, V n, V d);
385 
386         // 0,1,2-argument ops, with or without an immediate:
387         //    [ 22 bits op ] [5 bits n] [5 bits d]
388         // Any immediate falls in the middle somewhere overlapping with either op, n, or both.
389         void op(uint32_t op22, V n, V d, int imm=0);
390         void op(uint32_t op22, X n, V d, int imm=0) { this->op(op22,(V)n,   d,imm); }
391         void op(uint32_t op22, V n, X d, int imm=0) { this->op(op22,   n,(V)d,imm); }
392         void op(uint32_t op22, X n, X d, int imm=0) { this->op(op22,(V)n,(V)d,imm); }
393         void op(uint32_t op22,           int imm=0) { this->op(op22,(V)0,(V)0,imm); }
394         // (1-argument ops don't seem to have a consistent convention of passing as n or d.)
395 
396 
397         // Order matters... value is 4-bit encoding for condition code.
398         enum class Condition { eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,al };
399         void b(Condition, Label*);
400         int disp19(Label*);
401     };
402 
403     // Order matters a little: Ops <=store128 are treated as having side effects.
404     #define SKVM_OPS(M)                                              \
405         M(assert_true)                                               \
406         M(store8)   M(store16)   M(store32) M(store64) M(store128)   \
407         M(index)                                                     \
408         M(load8)    M(load16)    M(load32)  M(load64) M(load128)     \
409         M(gather8)  M(gather16)  M(gather32)                         \
410         M(uniform8) M(uniform16) M(uniform32)                        \
411         M(splat) M(splat_q14)                                        \
412         M(add_f32) M(add_i32) M(add_q14)                             \
413         M(sub_f32) M(sub_i32) M(sub_q14)                             \
414         M(mul_f32) M(mul_i32) M(mul_q14)                             \
415         M(div_f32)                                                   \
416         M(min_f32) M(max_f32)                                        \
417         M(min_q14) M(max_q14) M(uavg_q14)                            \
418         M(fma_f32) M(fms_f32) M(fnma_f32)                            \
419         M(sqrt_f32)                                                  \
420         M(shl_i32) M(shr_i32) M(sra_i32)                             \
421         M(shl_q14) M(shr_q14) M(sra_q14)                             \
422         M(ceil) M(floor) M(trunc) M(round) M(to_half) M(from_half)   \
423         M(to_f32) M(to_q14) M(from_q14)                              \
424         M(neq_f32) M(eq_f32) M(eq_i32) M(eq_q14)                     \
425         M(gte_f32) M(gt_f32) M(gt_i32) M(gt_q14)                     \
426         M(bit_and)     M(bit_or)     M(bit_xor)     M(bit_clear)     \
427         M(bit_and_q14) M(bit_or_q14) M(bit_xor_q14) M(bit_clear_q14) \
428         M(select) M(select_q14) M(pack)                              \
429     // End of SKVM_OPS
430 
431     enum class Op : int {
432     #define M(op) op,
433         SKVM_OPS(M)
434     #undef M
435     };
436 
has_side_effect(Op op)437     static inline bool has_side_effect(Op op) {
438         return op <= Op::store128;
439     }
is_always_varying(Op op)440     static inline bool is_always_varying(Op op) {
441         return op <= Op::gather32 && op != Op::assert_true;
442     }
443 
444     using Val = int;
445     // We reserve an impossibe Val ID as a sentinel
446     // NA meaning none, n/a, null, nil, etc.
447     static const Val NA = -1;
448 
449     struct Arg { int ix; };
450 
451     struct I32 {
452         Builder* builder = nullptr;
453         Val      id      = NA;
454         explicit operator bool() const { return id != NA; }
455         Builder* operator->()    const { return builder; }
456     };
457 
458     struct F32 {
459         Builder* builder = nullptr;
460         Val      id      = NA;
461         explicit operator bool() const { return id != NA; }
462         Builder* operator->()    const { return builder; }
463     };
464 
465     struct Q14 {
466         Builder* builder = nullptr;
467         Val      id      = NA;
468         explicit operator bool() const { return id != NA; }
469         Builder* operator->()    const { return builder; }
470     };
471 
472     // Some operations make sense with immediate arguments,
473     // so we use I32a and F32a to receive them transparently.
474     //
475     // We omit overloads that may indicate a bug or performance issue.
476     // In general it does not make sense to pass immediates to unary operations,
477     // and even sometimes not for binary operations, e.g.
478     //
479     //   div(x,y)    -- normal every day divide
480     //   div(3.0f,y) -- yep, makes sense
481     //   div(x,3.0f) -- omitted as a reminder you probably want mul(x, 1/3.0f).
482     //
483     // You can of course always splat() to override these opinions.
484     struct I32a {
I32aI32a485         I32a(I32 v) : SkDEBUGCODE(builder(v.builder),) id(v.id) {}
I32aI32a486         I32a(int v) : imm(v) {}
487 
488         SkDEBUGCODE(Builder* builder = nullptr;)
489         Val id  = NA;
490         int imm = 0;
491     };
492 
493     struct F32a {
F32aF32a494         F32a(F32   v) : SkDEBUGCODE(builder(v.builder),) id(v.id) {}
F32aF32a495         F32a(float v) : imm(v) {}
496 
497         SkDEBUGCODE(Builder* builder = nullptr;)
498         Val   id  = NA;
499         float imm = 0;
500     };
501 
502     struct Q14a {
Q14aQ14a503         Q14a(Q14 v) : SkDEBUGCODE(builder(v.builder),) id(v.id) {}
Q14aQ14a504         Q14a(int bits) : imm{SkTo<int16_t>(bits)} {}   // 0x0000'4000 -> 0x4000
Q14aQ14a505         Q14a(float f) : Q14a{(int)(f * 16384.0f)} {}   //        1.0f -> 0x4000
506 
507         SkDEBUGCODE(Builder* builder = nullptr;)
508         Val     id  = NA;
509         int16_t imm = 0;
510     };
511 
512     struct Color {
513         F32 r,g,b,a;
514         explicit operator bool() const { return r && g && b && a; }
515         Builder* operator->()    const { return a.operator->(); }
516     };
517 
518     struct HSLA {
519         F32 h,s,l,a;
520         explicit operator bool() const { return h && s && l && a; }
521         Builder* operator->()    const { return a.operator->(); }
522     };
523 
524     struct Color_Q14 {
525         Q14 r,g,b,a;
526         explicit operator bool() const { return r && g && b && a; }
527         Builder* operator->()    const { return a.operator->(); }
528     };
529 
530     struct Coord {
531         F32 x,y;
532         explicit operator bool() const { return x && y; }
533         Builder* operator->()    const { return x.operator->(); }
534     };
535 
536     struct Uniform {
537         Arg ptr;
538         int offset;
539     };
540     struct Uniforms {
541         Arg              base;
542         std::vector<int> buf;
543 
UniformsUniforms544         explicit Uniforms(int init) : base(Arg{0}), buf(init) {}
545 
pushUniforms546         Uniform push(int val) {
547             buf.push_back(val);
548             return {base, (int)( sizeof(int)*(buf.size() - 1) )};
549         }
550 
pushFUniforms551         Uniform pushF(float val) {
552             int bits;
553             memcpy(&bits, &val, sizeof(int));
554             return this->push(bits);
555         }
556 
pushPtrUniforms557         Uniform pushPtr(const void* ptr) {
558             // Jam the pointer into 1 or 2 ints.
559             int ints[sizeof(ptr) / sizeof(int)];
560             memcpy(ints, &ptr, sizeof(ptr));
561             for (int bits : ints) {
562                 buf.push_back(bits);
563             }
564             return {base, (int)( sizeof(int)*(buf.size() - SK_ARRAY_COUNT(ints)) )};
565         }
566     };
567 
568     struct PixelFormat {
569         enum { UNORM, FLOAT} encoding;
570         int r_bits,  g_bits,  b_bits,  a_bits,
571             r_shift, g_shift, b_shift, a_shift;
572     };
573     bool SkColorType_to_PixelFormat(SkColorType, PixelFormat*);
574 
575     SK_BEGIN_REQUIRE_DENSE
576     struct Instruction {
577         Op  op;         // v* = op(x,y,z,imm), where * == index of this Instruction.
578         Val x,y,z;      // Enough arguments for mad().
579         int immy,immz;  // Immediate bit pattern, shift count, argument index, etc.
580     };
581     SK_END_REQUIRE_DENSE
582 
583     bool operator==(const Instruction&, const Instruction&);
584     struct InstructionHash {
585         uint32_t operator()(const Instruction&, uint32_t seed=0) const;
586     };
587 
588     struct OptimizedInstruction {
589         Op op;
590         Val x,y,z;
591         int immy,immz;
592 
593         Val  death;
594         bool can_hoist;
595     };
596 
597     class Builder {
598     public:
599 
600         Program done(const char* debug_name = nullptr) const;
601 
602         // Mostly for debugging, tests, etc.
program()603         std::vector<Instruction> program() const { return fProgram; }
604         std::vector<OptimizedInstruction> optimize() const;
605 
606         // Declare an argument with given stride (use stride=0 for uniforms).
607         // TODO: different types for varying and uniforms?
608         Arg arg(int stride);
609 
610         // Convenience arg() wrappers for most common strides, sizeof(T) and 0.
611         template <typename T>
varying()612         Arg varying() { return this->arg(sizeof(T)); }
uniform()613         Arg uniform() { return this->arg(0); }
614 
615         // TODO: allow uniform (i.e. Arg) offsets to store* and load*?
616         // TODO: sign extension (signed types) for <32-bit loads?
617         // TODO: unsigned integer operations where relevant (just comparisons?)?
618 
619         // Assert cond is true, printing debug when not.
620         void assert_true(I32 cond, I32 debug);
assert_true(I32 cond,F32 debug)621         void assert_true(I32 cond, F32 debug) { assert_true(cond, bit_cast(debug)); }
assert_true(I32 cond)622         void assert_true(I32 cond)            { assert_true(cond, cond); }
623 
624         // Store {8,16,32,64,128}-bit varying.
625         void store8  (Arg ptr, I32 val);
626         void store16 (Arg ptr, I32 val);
627         void store32 (Arg ptr, I32 val);
storeF(Arg ptr,F32 val)628         void storeF  (Arg ptr, F32 val) { store32(ptr, bit_cast(val)); }
629         void store64 (Arg ptr, I32 lo, I32 hi);            // *ptr = lo|(hi<<32)
630         void store128(Arg ptr, I32 lo, I32 hi, int lane);  // 64-bit lane 0-1 at ptr = lo|(hi<<32).
631 
632         // Returns varying {n, n-1, n-2, ..., 1}, where n is the argument to Program::eval().
633         I32 index();
634 
635         // Load {8,16,32,64,128}-bit varying.
636         I32 load8  (Arg ptr);
637         I32 load16 (Arg ptr);
638         I32 load32 (Arg ptr);
loadF(Arg ptr)639         F32 loadF  (Arg ptr) { return bit_cast(load32(ptr)); }
640         I32 load64 (Arg ptr, int lane);  // Load 32-bit lane 0-1 of  64-bit value.
641         I32 load128(Arg ptr, int lane);  // Load 32-bit lane 0-3 of 128-bit value.
642 
643         // Load u8,u16,i32 uniform with byte-count offset.
644         I32 uniform8 (Arg ptr, int offset);
645         I32 uniform16(Arg ptr, int offset);
646         I32 uniform32(Arg ptr, int offset);
uniformF(Arg ptr,int offset)647         F32 uniformF (Arg ptr, int offset) { return this->bit_cast(this->uniform32(ptr,offset)); }
648 
649         // Push and load this color as a uniform.
650         Color uniformColor(SkColor4f, Uniforms*);
651 
652         // Gather u8,u16,i32 with varying element-count index from *(ptr + byte-count offset).
653         I32 gather8 (Arg ptr, int offset, I32 index);
654         I32 gather16(Arg ptr, int offset, I32 index);
655         I32 gather32(Arg ptr, int offset, I32 index);
gatherF(Arg ptr,int offset,I32 index)656         F32 gatherF (Arg ptr, int offset, I32 index) {
657             return bit_cast(gather32(ptr, offset, index));
658         }
659 
660         // Convenience methods for working with skvm::Uniform(s).
uniform8(Uniform u)661         I32 uniform8 (Uniform u)            { return this->uniform8 (u.ptr, u.offset); }
uniform16(Uniform u)662         I32 uniform16(Uniform u)            { return this->uniform16(u.ptr, u.offset); }
uniform32(Uniform u)663         I32 uniform32(Uniform u)            { return this->uniform32(u.ptr, u.offset); }
uniformF(Uniform u)664         F32 uniformF (Uniform u)            { return this->uniformF (u.ptr, u.offset); }
gather8(Uniform u,I32 index)665         I32 gather8  (Uniform u, I32 index) { return this->gather8  (u.ptr, u.offset, index); }
gather16(Uniform u,I32 index)666         I32 gather16 (Uniform u, I32 index) { return this->gather16 (u.ptr, u.offset, index); }
gather32(Uniform u,I32 index)667         I32 gather32 (Uniform u, I32 index) { return this->gather32 (u.ptr, u.offset, index); }
gatherF(Uniform u,I32 index)668         F32 gatherF  (Uniform u, I32 index) { return this->gatherF  (u.ptr, u.offset, index); }
669 
670         // Load an immediate constant.
671         I32 splat(int      n);
splat(unsigned u)672         I32 splat(unsigned u) { return splat((int)u); }
splat(float f)673         F32 splat(float    f) {
674             int bits;
675             memcpy(&bits, &f, 4);
676             return bit_cast(splat(bits));
677         }
678 
679         // Load an immediate Q14, expressed as either integer (16384, 0x4000) or float (1.0f).
680         Q14 splat_q14(int      n);
splat_q14(unsigned u)681         Q14 splat_q14(unsigned u) { return splat_q14((int)u); }
splat_q14(float f)682         Q14 splat_q14(float    f) { return splat_q14(Q14a{f}.imm); }
683 
684         // float math, comparisons, etc.
add(F32a x,F32a y)685         F32 add(F32, F32);  F32 add(F32a x, F32a y) { return add(_(x), _(y)); }
sub(F32a x,F32a y)686         F32 sub(F32, F32);  F32 sub(F32a x, F32a y) { return sub(_(x), _(y)); }
mul(F32a x,F32a y)687         F32 mul(F32, F32);  F32 mul(F32a x, F32a y) { return mul(_(x), _(y)); }
div(F32a x,F32 y)688         F32 div(F32, F32);  F32 div(F32a x, F32  y) { return div(_(x),   y ); }
min(F32a x,F32a y)689         F32 min(F32, F32);  F32 min(F32a x, F32a y) { return min(_(x), _(y)); }
max(F32a x,F32a y)690         F32 max(F32, F32);  F32 max(F32a x, F32a y) { return max(_(x), _(y)); }
691 
mad(F32 x,F32 y,F32 z)692         F32 mad(F32  x, F32  y, F32  z) { return add(mul(x,y), z); }
mad(F32a x,F32a y,F32a z)693         F32 mad(F32a x, F32a y, F32a z) { return mad(_(x), _(y), _(z)); }
694 
695         F32        sqrt(F32);
696         F32 approx_log2(F32);
697         F32 approx_pow2(F32);
approx_log(F32 x)698         F32 approx_log (F32 x) { return mul(0.69314718f, approx_log2(x)); }
approx_exp(F32 x)699         F32 approx_exp (F32 x) { return approx_pow2(mul(x, 1.4426950408889634074f)); }
700 
701         F32 approx_powf(F32  base, F32  exp);
approx_powf(F32a base,F32a exp)702         F32 approx_powf(F32a base, F32a exp) { return approx_powf(_(base), _(exp)); }
703 
704         F32 approx_sin(F32 radians);
approx_cos(F32 radians)705         F32 approx_cos(F32 radians) { return approx_sin(add(radians, SK_ScalarPI/2)); }
706         F32 approx_tan(F32 radians);
707 
708         F32 approx_asin(F32 x);
approx_acos(F32 x)709         F32 approx_acos(F32 x) { return sub(SK_ScalarPI/2, approx_asin(x)); }
710         F32 approx_atan(F32 x);
711         F32 approx_atan2(F32 y, F32 x);
712 
713         F32 lerp(F32  lo, F32  hi, F32  t);
lerp(F32a lo,F32a hi,F32a t)714         F32 lerp(F32a lo, F32a hi, F32a t) { return lerp(_(lo), _(hi), _(t)); }
715 
clamp(F32 x,F32 lo,F32 hi)716         F32 clamp(F32  x, F32  lo, F32  hi) { return max(lo, min(x, hi)); }
clamp(F32a x,F32a lo,F32a hi)717         F32 clamp(F32a x, F32a lo, F32a hi) { return clamp(_(x), _(lo), _(hi)); }
clamp01(F32 x)718         F32 clamp01(F32 x) { return clamp(x, 0.0f, 1.0f); }
719 
abs(F32 x)720         F32    abs(F32 x) { return bit_cast(bit_and(bit_cast(x), 0x7fff'ffff)); }
721         F32  fract(F32 x) { return sub(x, floor(x)); }
722         F32   ceil(F32);
723         F32  floor(F32);
724         I32 is_NaN   (F32 x) { return neq(x,x); }
725         I32 is_finite(F32 x) { return lt(bit_and(bit_cast(x), 0x7f80'0000), 0x7f80'0000); }
726 
727         I32 trunc(F32 x);
728         I32 round(F32 x);  // Round to int using current rounding mode (as if lrintf()).
729         I32 bit_cast(F32 x) { return {x.builder, x.id}; }
730 
731         I32   to_half(F32 x);
732         F32 from_half(I32 x);
733 
734         F32 norm(F32 x, F32 y) {
735             return sqrt(add(mul(x,x),
736                             mul(y,y)));
737         }
738         F32 norm(F32a x, F32a y) { return norm(_(x), _(y)); }
739 
740         I32  eq(F32, F32);  I32  eq(F32a x, F32a y) { return  eq(_(x), _(y)); }
741         I32 neq(F32, F32);  I32 neq(F32a x, F32a y) { return neq(_(x), _(y)); }
742         I32 lt (F32, F32);  I32 lt (F32a x, F32a y) { return lt (_(x), _(y)); }
743         I32 lte(F32, F32);  I32 lte(F32a x, F32a y) { return lte(_(x), _(y)); }
744         I32 gt (F32, F32);  I32 gt (F32a x, F32a y) { return gt (_(x), _(y)); }
745         I32 gte(F32, F32);  I32 gte(F32a x, F32a y) { return gte(_(x), _(y)); }
746 
747         // int math, comparisons, etc.
748         I32 add(I32, I32);  I32 add(I32a x, I32a y) { return add(_(x), _(y)); }
749         I32 sub(I32, I32);  I32 sub(I32a x, I32a y) { return sub(_(x), _(y)); }
750         I32 mul(I32, I32);  I32 mul(I32a x, I32a y) { return mul(_(x), _(y)); }
751 
752         I32 shl(I32 x, int bits);
753         I32 shr(I32 x, int bits);
754         I32 sra(I32 x, int bits);
755 
756         I32 eq (I32 x, I32 y);  I32  eq(I32a x, I32a y) { return  eq(_(x), _(y)); }
757         I32 neq(I32 x, I32 y);  I32 neq(I32a x, I32a y) { return neq(_(x), _(y)); }
758         I32 lt (I32 x, I32 y);  I32 lt (I32a x, I32a y) { return lt (_(x), _(y)); }
759         I32 lte(I32 x, I32 y);  I32 lte(I32a x, I32a y) { return lte(_(x), _(y)); }
760         I32 gt (I32 x, I32 y);  I32 gt (I32a x, I32a y) { return gt (_(x), _(y)); }
761         I32 gte(I32 x, I32 y);  I32 gte(I32a x, I32a y) { return gte(_(x), _(y)); }
762 
763         F32 to_F32(I32 x);
764         F32 bit_cast(I32 x) { return {x.builder, x.id}; }
765 
766         // Bitwise operations.
767         I32 bit_and  (I32, I32);  I32 bit_and  (I32a x, I32a y) { return bit_and  (_(x), _(y)); }
768         I32 bit_or   (I32, I32);  I32 bit_or   (I32a x, I32a y) { return bit_or   (_(x), _(y)); }
769         I32 bit_xor  (I32, I32);  I32 bit_xor  (I32a x, I32a y) { return bit_xor  (_(x), _(y)); }
770         I32 bit_clear(I32, I32);  I32 bit_clear(I32a x, I32a y) { return bit_clear(_(x), _(y)); }
771 
772         I32 min(I32 x, I32 y) { return select(lte(x,y), x, y); }
773         I32 max(I32 x, I32 y) { return select(gte(x,y), x, y); }
774 
775         I32 min(I32a x, I32a y) { return min(_(x), _(y)); }
776         I32 max(I32a x, I32a y) { return max(_(x), _(y)); }
777 
778         I32 select(I32 cond, I32 t, I32 f);  // cond ? t : f
779         F32 select(I32 cond, F32 t, F32 f) {
780             return bit_cast(select(cond, bit_cast(t)
781                                        , bit_cast(f)));
782         }
783         Q14 select(Q14 cond, Q14 t, Q14 f);
784 
785         I32 select(I32a cond, I32a t, I32a f) { return select(_(cond), _(t), _(f)); }
786         F32 select(I32a cond, F32a t, F32a f) { return select(_(cond), _(t), _(f)); }
787         Q14 select(Q14a cond, Q14a t, Q14a f) { return select(_(cond), _(t), _(f)); }
788 
789         I32 extract(I32 x, int bits, I32 z);   // (x>>bits) & z
790         I32 pack   (I32 x, I32 y, int bits);   // x | (y << bits), assuming (x & (y << bits)) == 0
791 
792         I32 extract(I32a x, int bits, I32a z) { return extract(_(x), bits, _(z)); }
793         I32 pack   (I32a x, I32a y, int bits) { return pack   (_(x), _(y), bits); }
794 
795         Q14 add(Q14, Q14);  Q14 add(Q14a x, Q14a y) { return add(_(x), _(y)); }
796         Q14 sub(Q14, Q14);  Q14 sub(Q14a x, Q14a y) { return sub(_(x), _(y)); }
797         Q14 mul(Q14, Q14);  Q14 mul(Q14a x, Q14a y) { return mul(_(x), _(y)); }
798 
799         Q14 min(Q14, Q14);  Q14 min(Q14a x, Q14a y) { return min(_(x), _(y)); }
800         Q14 max(Q14, Q14);  Q14 max(Q14a x, Q14a y) { return max(_(x), _(y)); }
801 
802         Q14 shl(Q14, int bits);
803         Q14 shr(Q14, int bits);
804         Q14 sra(Q14, int bits);
805 
806         Q14 eq (Q14, Q14);  Q14  eq(Q14a x, Q14a y) { return  eq(_(x), _(y)); }
807         Q14 neq(Q14, Q14);  Q14 neq(Q14a x, Q14a y) { return neq(_(x), _(y)); }
808         Q14 lt (Q14, Q14);  Q14 lt (Q14a x, Q14a y) { return lt (_(x), _(y)); }
809         Q14 lte(Q14, Q14);  Q14 lte(Q14a x, Q14a y) { return lte(_(x), _(y)); }
810         Q14 gt (Q14, Q14);  Q14 gt (Q14a x, Q14a y) { return gt (_(x), _(y)); }
811         Q14 gte(Q14, Q14);  Q14 gte(Q14a x, Q14a y) { return gte(_(x), _(y)); }
812 
813         Q14 bit_and  (Q14, Q14);  Q14 bit_and  (Q14a x, Q14a y) { return bit_and  (_(x), _(y)); }
814         Q14 bit_or   (Q14, Q14);  Q14 bit_or   (Q14a x, Q14a y) { return bit_or   (_(x), _(y)); }
815         Q14 bit_xor  (Q14, Q14);  Q14 bit_xor  (Q14a x, Q14a y) { return bit_xor  (_(x), _(y)); }
816         Q14 bit_clear(Q14, Q14);  Q14 bit_clear(Q14a x, Q14a y) { return bit_clear(_(x), _(y)); }
817 
818         Q14 unsigned_avg(Q14  x, Q14  y);  // (x+y+1)>>1
819         Q14 unsigned_avg(Q14a x, Q14a y) { return unsigned_avg(_(x), _(y)); }
820 
821         Q14 to_Q14(F32); F32 to_F32(Q14);   // Converts values, e.g. 0x4000 <-> 1.0f
822         Q14 to_Q14(I32); I32 to_I32(Q14);   // Preserves bits, e.g. 0x4000 <-> 0x00004000
823 
824         // Common idioms used in several places, worth centralizing for consistency.
825         F32 from_unorm(int bits, I32);   // E.g. from_unorm(8, x) -> x * (1/255.0f)
826         I32   to_unorm(int bits, F32);   // E.g.   to_unorm(8, x) -> round(x * 255)
827 
828         Color   load(PixelFormat, Arg ptr);
829         bool   store(PixelFormat, Arg ptr, Color);
830         Color gather(PixelFormat, Arg ptr, int offset, I32 index);
831         Color gather(PixelFormat f, Uniform u, I32 index) {
832             return gather(f, u.ptr, u.offset, index);
833         }
834 
835         void   premul(F32* r, F32* g, F32* b, F32 a);
836         void unpremul(F32* r, F32* g, F32* b, F32 a);
837 
838         Color   premul(Color c) {   this->premul(&c.r, &c.g, &c.b, c.a); return c; }
839         Color unpremul(Color c) { this->unpremul(&c.r, &c.g, &c.b, c.a); return c; }
840 
841         Color lerp(Color lo, Color hi, F32 t);
842         Color blend(SkBlendMode, Color src, Color dst);
843 
844         Color clamp01(Color c) {
845             return { clamp01(c.r), clamp01(c.g), clamp01(c.b), clamp01(c.a) };
846         }
847 
848         HSLA  to_hsla(Color);
849         Color to_rgba(HSLA);
850 
851         void dump(SkWStream* = nullptr) const;
852         void dot (SkWStream* = nullptr) const;
853 
854         uint64_t hash() const;
855 
856         Val push(Instruction);
857     private:
858         Val push(Op op, Val x, Val y=NA, Val z=NA, int immy=0, int immz=0) {
859             return this->push(Instruction{op, x,y,z, immy,immz});
860         }
861 
862         I32 _(I32a x) {
863             if (x.id != NA) {
864                 SkASSERT(x.builder == this);
865                 return {this, x.id};
866             }
867             return splat(x.imm);
868         }
869 
870         F32 _(F32a x) {
871             if (x.id != NA) {
872                 SkASSERT(x.builder == this);
873                 return {this, x.id};
874             }
875             return splat(x.imm);
876         }
877 
878         Q14 _(Q14a x) {
879             if (x.id != NA) {
880                 SkASSERT(x.builder == this);
881                 return {this, x.id};
882             }
883             return splat_q14(x.imm);
884         }
885 
886         bool allImm() const;
887 
888         template <typename T, typename... Rest>
889         bool allImm(Val, T* imm, Rest...) const;
890 
891         template <typename T>
892         bool isImm(Val id, T want) const {
893             T imm = 0;
894             return this->allImm(id, &imm) && imm == want;
895         }
896 
897         SkTHashMap<Instruction, Val, InstructionHash> fIndex;
898         std::vector<Instruction>                      fProgram;
899         std::vector<int>                              fStrides;
900     };
901 
902     template <typename... Fs>
903     void dump_instructions(const std::vector<Instruction>& instructions,
904                            SkWStream* o = nullptr,
905                            Fs... fs);
906 
907     // Optimization passes and data structures normally used by Builder::optimize(),
908     // extracted here so they can be unit tested.
909     std::vector<Instruction>          eliminate_dead_code(std::vector<Instruction>);
910     std::vector<Instruction>          schedule           (std::vector<Instruction>);
911     std::vector<OptimizedInstruction> finalize           (std::vector<Instruction>);
912 
913     class Usage {
914     public:
915         Usage(const std::vector<Instruction>&);
916 
917         // Return a sorted span of Vals which use result of Instruction id.
918         SkSpan<const Val> operator[](Val id) const;
919 
920     private:
921         std::vector<int> fIndex;
922         std::vector<Val> fTable;
923     };
924 
925     using Reg = int;
926 
927     // d = op(x, y/imm, z/imm)
928     struct InterpreterInstruction {
929         Op  op;
930         Reg d,x;
931         union { Reg y; int immy; };
932         union { Reg z; int immz; };
933     };
934 
935     class Program {
936     public:
937         Program(const std::vector<OptimizedInstruction>& instructions,
938                 const std::vector<int>& strides,
939                 const char* debug_name);
940 
941         Program();
942         ~Program();
943 
944         Program(Program&&);
945         Program& operator=(Program&&);
946 
947         Program(const Program&) = delete;
948         Program& operator=(const Program&) = delete;
949 
950         void eval(int n, void* args[]) const;
951 
952         template <typename... T>
953         void eval(int n, T*... arg) const {
954             SkASSERT(sizeof...(arg) == this->nargs());
955             // This nullptr isn't important except that it makes args[] non-empty if you pass none.
956             void* args[] = { (void*)arg..., nullptr };
957             this->eval(n, args);
958         }
959 
960         std::vector<InterpreterInstruction> instructions() const;
961         int  nargs() const;
962         int  nregs() const;
963         int  loop () const;
964         bool empty() const;
965 
966         bool hasJIT() const;  // Has this Program been JITted?
967         void dropJIT();       // If hasJIT(), drop it, forcing interpreter fallback.
968 
969         void dump(SkWStream* = nullptr) const;
970 
971     private:
972         void setupInterpreter(const std::vector<OptimizedInstruction>&);
973         void setupJIT        (const std::vector<OptimizedInstruction>&, const char* debug_name);
974         void setupLLVM       (const std::vector<OptimizedInstruction>&, const char* debug_name);
975 
976         bool jit(const std::vector<OptimizedInstruction>&,
977                  int* stack_hint, uint32_t* registers_used,
978                  Assembler*) const;
979 
980         void waitForLLVM() const;
981 
982         struct Impl;
983         std::unique_ptr<Impl> fImpl;
984     };
985 
986     // TODO: control flow
987     // TODO: 64-bit values?
988 
989     static inline Q14 operator+(Q14   x, Q14a y) { return x->add(x,y); }
990     static inline Q14 operator+(float x, Q14  y) { return y->add(x,y); }
991 
992     static inline Q14 operator-(Q14   x, Q14a y) { return x->sub(x,y); }
993     static inline Q14 operator-(float x, Q14  y) { return y->sub(x,y); }
994 
995     static inline Q14 operator*(Q14   x, Q14a y) { return x->mul(x,y); }
996     static inline Q14 operator*(float x, Q14  y) { return y->mul(x,y); }
997 
min(Q14 x,Q14a y)998     static inline Q14 min(Q14   x, Q14a y) { return x->min(x,y); }
min(float x,Q14 y)999     static inline Q14 min(float x, Q14  y) { return y->min(x,y); }
1000 
max(Q14 x,Q14a y)1001     static inline Q14 max(Q14   x, Q14a y) { return x->max(x,y); }
max(float x,Q14 y)1002     static inline Q14 max(float x, Q14  y) { return y->max(x,y); }
1003 
unsigned_avg(Q14 x,Q14a y)1004     static inline Q14 unsigned_avg(Q14   x, Q14a y) { return x->unsigned_avg(x,y); }
unsigned_avg(float x,Q14 y)1005     static inline Q14 unsigned_avg(float x, Q14  y) { return y->unsigned_avg(x,y); }
1006 
1007     static inline Q14 operator==(Q14   x, Q14   y) { return x->eq(x,y); }
1008     static inline Q14 operator==(Q14   x, float y) { return x->eq(x,y); }
1009     static inline Q14 operator==(float x, Q14   y) { return y->eq(x,y); }
1010 
1011     static inline Q14 operator!=(Q14   x, Q14   y) { return x->neq(x,y); }
1012     static inline Q14 operator!=(Q14   x, float y) { return x->neq(x,y); }
1013     static inline Q14 operator!=(float x, Q14   y) { return y->neq(x,y); }
1014 
1015     static inline Q14 operator< (Q14   x, Q14a y) { return x->lt(x,y); }
1016     static inline Q14 operator< (float x, Q14  y) { return y->lt(x,y); }
1017 
1018     static inline Q14 operator<=(Q14   x, Q14a y) { return x->lte(x,y); }
1019     static inline Q14 operator<=(float x, Q14  y) { return y->lte(x,y); }
1020 
1021     static inline Q14 operator> (Q14   x, Q14a y) { return x->gt(x,y); }
1022     static inline Q14 operator> (float x, Q14  y) { return y->gt(x,y); }
1023 
1024     static inline Q14 operator>=(Q14   x, Q14a y) { return x->gte(x,y); }
1025     static inline Q14 operator>=(float x, Q14  y) { return y->gte(x,y); }
1026 
1027 
1028     static inline I32 operator+(I32 x, I32a y) { return x->add(x,y); }
1029     static inline I32 operator+(int x, I32  y) { return y->add(x,y); }
1030 
1031     static inline I32 operator-(I32 x, I32a y) { return x->sub(x,y); }
1032     static inline I32 operator-(int x, I32  y) { return y->sub(x,y); }
1033 
1034     static inline I32 operator*(I32 x, I32a y) { return x->mul(x,y); }
1035     static inline I32 operator*(int x, I32  y) { return y->mul(x,y); }
1036 
min(I32 x,I32a y)1037     static inline I32 min(I32 x, I32a y) { return x->min(x,y); }
min(int x,I32 y)1038     static inline I32 min(int x, I32  y) { return y->min(x,y); }
1039 
max(I32 x,I32a y)1040     static inline I32 max(I32 x, I32a y) { return x->max(x,y); }
max(int x,I32 y)1041     static inline I32 max(int x, I32  y) { return y->max(x,y); }
1042 
1043     static inline I32 operator==(I32 x, I32 y) { return x->eq(x,y); }
1044     static inline I32 operator==(I32 x, int y) { return x->eq(x,y); }
1045     static inline I32 operator==(int x, I32 y) { return y->eq(x,y); }
1046 
1047     static inline I32 operator!=(I32 x, I32 y) { return x->neq(x,y); }
1048     static inline I32 operator!=(I32 x, int y) { return x->neq(x,y); }
1049     static inline I32 operator!=(int x, I32 y) { return y->neq(x,y); }
1050 
1051     static inline I32 operator< (I32 x, I32a y) { return x->lt(x,y); }
1052     static inline I32 operator< (int x, I32  y) { return y->lt(x,y); }
1053 
1054     static inline I32 operator<=(I32 x, I32a y) { return x->lte(x,y); }
1055     static inline I32 operator<=(int x, I32  y) { return y->lte(x,y); }
1056 
1057     static inline I32 operator> (I32 x, I32a y) { return x->gt(x,y); }
1058     static inline I32 operator> (int x, I32  y) { return y->gt(x,y); }
1059 
1060     static inline I32 operator>=(I32 x, I32a y) { return x->gte(x,y); }
1061     static inline I32 operator>=(int x, I32  y) { return y->gte(x,y); }
1062 
1063 
1064     static inline F32 operator+(F32   x, F32a y) { return x->add(x,y); }
1065     static inline F32 operator+(float x, F32  y) { return y->add(x,y); }
1066 
1067     static inline F32 operator-(F32   x, F32a y) { return x->sub(x,y); }
1068     static inline F32 operator-(float x, F32  y) { return y->sub(x,y); }
1069 
1070     static inline F32 operator*(F32   x, F32a y) { return x->mul(x,y); }
1071     static inline F32 operator*(float x, F32  y) { return y->mul(x,y); }
1072 
1073     static inline F32 operator/(F32   x, F32  y) { return x->div(x,y); }
1074     static inline F32 operator/(float x, F32  y) { return y->div(x,y); }
1075 
min(F32 x,F32a y)1076     static inline F32 min(F32   x, F32a y) { return x->min(x,y); }
min(float x,F32 y)1077     static inline F32 min(float x, F32  y) { return y->min(x,y); }
1078 
max(F32 x,F32a y)1079     static inline F32 max(F32   x, F32a y) { return x->max(x,y); }
max(float x,F32 y)1080     static inline F32 max(float x, F32  y) { return y->max(x,y); }
1081 
1082     static inline I32 operator==(F32   x, F32   y) { return x->eq(x,y); }
1083     static inline I32 operator==(F32   x, float y) { return x->eq(x,y); }
1084     static inline I32 operator==(float x, F32   y) { return y->eq(x,y); }
1085 
1086     static inline I32 operator!=(F32   x, F32   y) { return x->neq(x,y); }
1087     static inline I32 operator!=(F32   x, float y) { return x->neq(x,y); }
1088     static inline I32 operator!=(float x, F32   y) { return y->neq(x,y); }
1089 
1090     static inline I32 operator< (F32   x, F32a y) { return x->lt(x,y); }
1091     static inline I32 operator< (float x, F32  y) { return y->lt(x,y); }
1092 
1093     static inline I32 operator<=(F32   x, F32a y) { return x->lte(x,y); }
1094     static inline I32 operator<=(float x, F32  y) { return y->lte(x,y); }
1095 
1096     static inline I32 operator> (F32   x, F32a y) { return x->gt(x,y); }
1097     static inline I32 operator> (float x, F32  y) { return y->gt(x,y); }
1098 
1099     static inline I32 operator>=(F32   x, F32a y) { return x->gte(x,y); }
1100     static inline I32 operator>=(float x, F32  y) { return y->gte(x,y); }
1101 
1102     static inline Q14& operator+=(Q14& x, Q14a y) { return (x = x + y); }
1103     static inline Q14& operator-=(Q14& x, Q14a y) { return (x = x - y); }
1104     static inline Q14& operator*=(Q14& x, Q14a y) { return (x = x * y); }
1105 
1106     static inline I32& operator+=(I32& x, I32a y) { return (x = x + y); }
1107     static inline I32& operator-=(I32& x, I32a y) { return (x = x - y); }
1108     static inline I32& operator*=(I32& x, I32a y) { return (x = x * y); }
1109 
1110     static inline F32& operator+=(F32& x, F32a y) { return (x = x + y); }
1111     static inline F32& operator-=(F32& x, F32a y) { return (x = x - y); }
1112     static inline F32& operator*=(F32& x, F32a y) { return (x = x * y); }
1113 
assert_true(I32 cond,I32 debug)1114     static inline void assert_true(I32 cond, I32 debug) { cond->assert_true(cond,debug); }
assert_true(I32 cond,F32 debug)1115     static inline void assert_true(I32 cond, F32 debug) { cond->assert_true(cond,debug); }
assert_true(I32 cond)1116     static inline void assert_true(I32 cond)            { cond->assert_true(cond); }
1117 
store8(Arg ptr,I32 val)1118     static inline void store8  (Arg ptr, I32 val)                { val->store8  (ptr, val); }
store16(Arg ptr,I32 val)1119     static inline void store16 (Arg ptr, I32 val)                { val->store16 (ptr, val); }
store32(Arg ptr,I32 val)1120     static inline void store32 (Arg ptr, I32 val)                { val->store32 (ptr, val); }
storeF(Arg ptr,F32 val)1121     static inline void storeF  (Arg ptr, F32 val)                { val->storeF  (ptr, val); }
store64(Arg ptr,I32 lo,I32 hi)1122     static inline void store64 (Arg ptr, I32 lo, I32 hi)         { lo ->store64 (ptr, lo,hi); }
store128(Arg ptr,I32 lo,I32 hi,int ix)1123     static inline void store128(Arg ptr, I32 lo, I32 hi, int ix) { lo ->store128(ptr, lo,hi, ix); }
1124 
gather8(Arg ptr,int off,I32 ix)1125     static inline I32 gather8 (Arg ptr, int off, I32 ix) { return ix->gather8 (ptr, off, ix); }
gather16(Arg ptr,int off,I32 ix)1126     static inline I32 gather16(Arg ptr, int off, I32 ix) { return ix->gather16(ptr, off, ix); }
gather32(Arg ptr,int off,I32 ix)1127     static inline I32 gather32(Arg ptr, int off, I32 ix) { return ix->gather32(ptr, off, ix); }
gatherF(Arg ptr,int off,I32 ix)1128     static inline F32 gatherF (Arg ptr, int off, I32 ix) { return ix->gatherF (ptr, off, ix); }
1129 
gather8(Uniform u,I32 ix)1130     static inline I32 gather8 (Uniform u, I32 ix) { return ix->gather8 (u, ix); }
gather16(Uniform u,I32 ix)1131     static inline I32 gather16(Uniform u, I32 ix) { return ix->gather16(u, ix); }
gather32(Uniform u,I32 ix)1132     static inline I32 gather32(Uniform u, I32 ix) { return ix->gather32(u, ix); }
gatherF(Uniform u,I32 ix)1133     static inline F32 gatherF (Uniform u, I32 ix) { return ix->gatherF (u, ix); }
1134 
sqrt(F32 x)1135     static inline F32        sqrt(F32 x) { return x->       sqrt(x); }
approx_log2(F32 x)1136     static inline F32 approx_log2(F32 x) { return x->approx_log2(x); }
approx_pow2(F32 x)1137     static inline F32 approx_pow2(F32 x) { return x->approx_pow2(x); }
approx_log(F32 x)1138     static inline F32 approx_log (F32 x) { return x->approx_log (x); }
approx_exp(F32 x)1139     static inline F32 approx_exp (F32 x) { return x->approx_exp (x); }
1140 
approx_powf(F32 base,F32a exp)1141     static inline F32 approx_powf(F32   base, F32a exp) { return base->approx_powf(base, exp); }
approx_powf(float base,F32 exp)1142     static inline F32 approx_powf(float base, F32  exp) { return  exp->approx_powf(base, exp); }
1143 
approx_sin(F32 radians)1144     static inline F32 approx_sin(F32 radians) { return radians->approx_sin(radians); }
approx_cos(F32 radians)1145     static inline F32 approx_cos(F32 radians) { return radians->approx_cos(radians); }
approx_tan(F32 radians)1146     static inline F32 approx_tan(F32 radians) { return radians->approx_tan(radians); }
1147 
approx_asin(F32 x)1148     static inline F32 approx_asin(F32 x) { return x->approx_asin(x); }
approx_acos(F32 x)1149     static inline F32 approx_acos(F32 x) { return x->approx_acos(x); }
approx_atan(F32 x)1150     static inline F32 approx_atan(F32 x) { return x->approx_atan(x); }
approx_atan2(F32 y,F32 x)1151     static inline F32 approx_atan2(F32 y, F32 x) { return x->approx_atan2(y, x); }
1152 
clamp01(F32 x)1153     static inline F32   clamp01(F32 x) { return x->  clamp01(x); }
abs(F32 x)1154     static inline F32       abs(F32 x) { return x->      abs(x); }
ceil(F32 x)1155     static inline F32      ceil(F32 x) { return x->     ceil(x); }
fract(F32 x)1156     static inline F32     fract(F32 x) { return x->    fract(x); }
floor(F32 x)1157     static inline F32     floor(F32 x) { return x->    floor(x); }
is_NaN(F32 x)1158     static inline I32    is_NaN(F32 x) { return x->   is_NaN(x); }
is_finite(F32 x)1159     static inline I32 is_finite(F32 x) { return x->is_finite(x); }
1160 
trunc(F32 x)1161     static inline I32     trunc(F32 x) { return x->    trunc(x); }
round(F32 x)1162     static inline I32     round(F32 x) { return x->    round(x); }
bit_cast(F32 x)1163     static inline I32  bit_cast(F32 x) { return x-> bit_cast(x); }
bit_cast(I32 x)1164     static inline F32  bit_cast(I32 x) { return x-> bit_cast(x); }
to_F32(I32 x)1165     static inline F32    to_F32(I32 x) { return x->   to_F32(x); }
to_half(F32 x)1166     static inline I32   to_half(F32 x) { return x->  to_half(x); }
from_half(I32 x)1167     static inline F32 from_half(I32 x) { return x->from_half(x); }
1168 
to_F32(Q14 x)1169     static inline F32 to_F32(Q14 x) { return x->to_F32(x); }
to_I32(Q14 x)1170     static inline I32 to_I32(Q14 x) { return x->to_I32(x); }
to_Q14(F32 x)1171     static inline Q14 to_Q14(F32 x) { return x->to_Q14(x); }
to_Q14(I32 x)1172     static inline Q14 to_Q14(I32 x) { return x->to_Q14(x); }
1173 
lerp(F32 lo,F32a hi,F32a t)1174     static inline F32 lerp(F32   lo, F32a  hi, F32a t) { return lo->lerp(lo,hi,t); }
lerp(float lo,F32 hi,F32a t)1175     static inline F32 lerp(float lo, F32   hi, F32a t) { return hi->lerp(lo,hi,t); }
lerp(float lo,float hi,F32 t)1176     static inline F32 lerp(float lo, float hi, F32  t) { return  t->lerp(lo,hi,t); }
1177 
clamp(F32 x,F32a lo,F32a hi)1178     static inline F32 clamp(F32   x, F32a  lo, F32a hi) { return  x->clamp(x,lo,hi); }
clamp(float x,F32 lo,F32a hi)1179     static inline F32 clamp(float x, F32   lo, F32a hi) { return lo->clamp(x,lo,hi); }
clamp(float x,float lo,F32 hi)1180     static inline F32 clamp(float x, float lo, F32  hi) { return hi->clamp(x,lo,hi); }
1181 
norm(F32 x,F32a y)1182     static inline F32 norm(F32   x, F32a y) { return x->norm(x,y); }
norm(float x,F32 y)1183     static inline F32 norm(float x, F32  y) { return y->norm(x,y); }
1184 
1185     static inline I32 operator<<(I32 x, int bits) { return x->shl(x, bits); }
shl(I32 x,int bits)1186     static inline I32        shl(I32 x, int bits) { return x->shl(x, bits); }
shr(I32 x,int bits)1187     static inline I32        shr(I32 x, int bits) { return x->shr(x, bits); }
sra(I32 x,int bits)1188     static inline I32        sra(I32 x, int bits) { return x->sra(x, bits); }
1189 
1190     static inline Q14 operator<<(Q14 x, int bits) { return x->shl(x, bits); }
shl(Q14 x,int bits)1191     static inline Q14        shl(Q14 x, int bits) { return x->shl(x, bits); }
shr(Q14 x,int bits)1192     static inline Q14        shr(Q14 x, int bits) { return x->shr(x, bits); }
sra(Q14 x,int bits)1193     static inline Q14        sra(Q14 x, int bits) { return x->sra(x, bits); }
1194     static inline Q14 operator>>(Q14 x, int bits) { return x->sra(x, bits); }
1195 
1196     static inline I32 operator&(I32 x, I32a y) { return x->bit_and(x,y); }
1197     static inline I32 operator&(int x, I32  y) { return y->bit_and(x,y); }
1198 
1199     static inline I32 operator|(I32 x, I32a y) { return x->bit_or (x,y); }
1200     static inline I32 operator|(int x, I32  y) { return y->bit_or (x,y); }
1201 
1202     static inline I32 operator^(I32 x, I32a y) { return x->bit_xor(x,y); }
1203     static inline I32 operator^(int x, I32  y) { return y->bit_xor(x,y); }
1204 
1205     static inline I32& operator&=(I32& x, I32a y) { return (x = x & y); }
1206     static inline I32& operator|=(I32& x, I32a y) { return (x = x | y); }
1207     static inline I32& operator^=(I32& x, I32a y) { return (x = x ^ y); }
1208 
1209     static inline Q14 operator&(Q14 x, Q14a y) { return x->bit_and(x,y); }
1210     static inline Q14 operator&(int x, Q14  y) { return y->bit_and(x,y); }
1211 
1212     static inline Q14 operator|(Q14 x, Q14a y) { return x->bit_or(x,y); }
1213     static inline Q14 operator|(int x, Q14  y) { return y->bit_or(x,y); }
1214 
1215     static inline Q14 operator^(Q14 x, Q14a y) { return x->bit_xor(x,y); }
1216     static inline Q14 operator^(int x, Q14  y) { return y->bit_xor(x,y); }
1217 
1218     static inline Q14& operator&=(Q14& x, Q14a y) { return (x = x & y); }
1219     static inline Q14& operator|=(Q14& x, Q14a y) { return (x = x | y); }
1220     static inline Q14& operator^=(Q14& x, Q14a y) { return (x = x ^ y); }
1221 
bit_clear(I32 x,I32a y)1222     static inline I32 bit_clear(I32 x, I32a y) { return x->bit_clear(x,y); }
bit_clear(int x,I32 y)1223     static inline I32 bit_clear(int x, I32  y) { return y->bit_clear(x,y); }
1224 
select(I32 cond,I32a t,I32a f)1225     static inline I32 select(I32 cond, I32a t, I32a f) { return cond->select(cond,t,f); }
select(I32 cond,F32a t,F32a f)1226     static inline F32 select(I32 cond, F32a t, F32a f) { return cond->select(cond,t,f); }
select(Q14 cond,Q14a t,Q14a f)1227     static inline Q14 select(Q14 cond, Q14a t, Q14a f) { return cond->select(cond,t,f); }
1228 
extract(I32 x,int bits,I32a z)1229     static inline I32 extract(I32 x, int bits, I32a z) { return x->extract(x,bits,z); }
extract(int x,int bits,I32 z)1230     static inline I32 extract(int x, int bits, I32  z) { return z->extract(x,bits,z); }
pack(I32 x,I32a y,int bits)1231     static inline I32 pack   (I32 x, I32a y, int bits) { return x->pack   (x,y,bits); }
pack(int x,I32 y,int bits)1232     static inline I32 pack   (int x, I32  y, int bits) { return y->pack   (x,y,bits); }
1233 
1234     static inline I32 operator~(I32 x) { return ~0 ^ x; }
1235     static inline Q14 operator~(Q14 x) { return ~0 ^ x; }
1236     static inline I32 operator-(I32 x) { return  0 - x; }
1237     static inline Q14 operator-(Q14 x) { return  0 - x; }
1238     static inline F32 operator-(F32 x) { return 0.0f - x; }
1239 
from_unorm(int bits,I32 x)1240     static inline F32 from_unorm(int bits, I32 x) { return x->from_unorm(bits,x); }
to_unorm(int bits,F32 x)1241     static inline I32   to_unorm(int bits, F32 x) { return x->  to_unorm(bits,x); }
1242 
store(PixelFormat f,Arg p,Color c)1243     static inline bool store(PixelFormat f, Arg p, Color c) { return c->store(f,p,c); }
gather(PixelFormat f,Arg p,int off,I32 ix)1244     static inline Color gather(PixelFormat f, Arg p, int off, I32 ix) {
1245         return ix->gather(f,p,off,ix);
1246     }
gather(PixelFormat f,Uniform u,I32 ix)1247     static inline Color gather(PixelFormat f, Uniform u, I32 ix) {
1248         return ix->gather(f,u,ix);
1249     }
1250 
premul(F32 * r,F32 * g,F32 * b,F32 a)1251     static inline void   premul(F32* r, F32* g, F32* b, F32 a) { a->  premul(r,g,b,a); }
unpremul(F32 * r,F32 * g,F32 * b,F32 a)1252     static inline void unpremul(F32* r, F32* g, F32* b, F32 a) { a->unpremul(r,g,b,a); }
1253 
premul(Color c)1254     static inline Color   premul(Color c) { return c->  premul(c); }
unpremul(Color c)1255     static inline Color unpremul(Color c) { return c->unpremul(c); }
1256 
lerp(Color lo,Color hi,F32 t)1257     static inline Color lerp(Color lo, Color hi, F32 t) { return t->lerp(lo,hi,t); }
1258 
blend(SkBlendMode m,Color s,Color d)1259     static inline Color blend(SkBlendMode m, Color s, Color d) { return s->blend(m,s,d); }
1260 
clamp01(Color c)1261     static inline Color clamp01(Color c) { return c->clamp01(c); }
1262 
to_hsla(Color c)1263     static inline HSLA  to_hsla(Color c) { return c->to_hsla(c); }
to_rgba(HSLA c)1264     static inline Color to_rgba(HSLA  c) { return c->to_rgba(c); }
1265 
1266     // Evaluate polynomials: ax^n + bx^(n-1) + ... for n >= 1
1267     template <typename... Rest>
poly(F32 x,F32a a,F32a b,Rest...rest)1268     static inline F32 poly(F32 x, F32a a, F32a b, Rest... rest) {
1269         if constexpr (sizeof...(rest) == 0) {
1270             return x*a+b;
1271         } else {
1272             return poly(x, x*a+b, rest...);
1273         }
1274     }
1275 }  // namespace skvm
1276 
1277 #endif//SkVM_DEFINED
1278