Mike Klein | b9c4a6f | 2017-04-03 13:54:55 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2017 Google Inc. |
| 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 SkJumper_misc_DEFINED |
| 9 | #define SkJumper_misc_DEFINED |
| 10 | |
Mike Klein | 376fd31 | 2017-12-11 16:53:26 -0500 | [diff] [blame] | 11 | #include <string.h> // for memcpy() |
Mike Klein | b9c4a6f | 2017-04-03 13:54:55 -0400 | [diff] [blame] | 12 | |
Mike Klein | adc78d5 | 2018-01-01 09:06:37 -0500 | [diff] [blame] | 13 | // Miscellany used by SkJumper_stages.cpp and SkJumper_stages_lowp.cpp. |
Mike Klein | b9c4a6f | 2017-04-03 13:54:55 -0400 | [diff] [blame] | 14 | |
| 15 | // Every function in this file should be marked static and inline using SI. |
Mike Klein | be22636 | 2017-12-12 11:30:36 -0500 | [diff] [blame] | 16 | #if defined(__clang__) |
Herb Derby | 4de1304 | 2017-05-15 10:49:39 -0400 | [diff] [blame] | 17 | #define SI __attribute__((always_inline)) static inline |
| 18 | #else |
| 19 | #define SI static inline |
| 20 | #endif |
| 21 | |
Mike Klein | b9c4a6f | 2017-04-03 13:54:55 -0400 | [diff] [blame] | 22 | |
| 23 | template <typename T, typename P> |
| 24 | SI T unaligned_load(const P* p) { // const void* would work too, but const P* helps ARMv7 codegen. |
| 25 | T v; |
| 26 | memcpy(&v, p, sizeof(v)); |
| 27 | return v; |
| 28 | } |
| 29 | |
Mike Klein | c33aa90 | 2017-05-15 10:20:48 -0400 | [diff] [blame] | 30 | template <typename T, typename P> |
| 31 | SI void unaligned_store(P* p, T v) { |
| 32 | memcpy(p, &v, sizeof(v)); |
| 33 | } |
| 34 | |
Mike Klein | b9c4a6f | 2017-04-03 13:54:55 -0400 | [diff] [blame] | 35 | template <typename Dst, typename Src> |
| 36 | SI Dst bit_cast(const Src& src) { |
| 37 | static_assert(sizeof(Dst) == sizeof(Src), ""); |
| 38 | return unaligned_load<Dst>(&src); |
| 39 | } |
| 40 | |
Mike Klein | 95f53be | 2017-04-04 10:24:56 -0400 | [diff] [blame] | 41 | template <typename Dst, typename Src> |
| 42 | SI Dst widen_cast(const Src& src) { |
| 43 | static_assert(sizeof(Dst) > sizeof(Src), ""); |
| 44 | Dst dst; |
| 45 | memcpy(&dst, &src, sizeof(Src)); |
| 46 | return dst; |
| 47 | } |
| 48 | |
Mike Klein | 0d93010 | 2017-06-02 11:08:39 -0400 | [diff] [blame] | 49 | // Our program is an array of void*, either |
| 50 | // - 1 void* per stage with no context pointer, the next stage; |
| 51 | // - 2 void* per stage with a context pointer, first the context pointer, then the next stage. |
| 52 | |
| 53 | // load_and_inc() steps the program forward by 1 void*, returning that pointer. |
| 54 | SI void* load_and_inc(void**& program) { |
| 55 | #if defined(__GNUC__) && defined(__x86_64__) |
| 56 | // If program is in %rsi (we try to make this likely) then this is a single instruction. |
| 57 | void* rax; |
| 58 | asm("lodsq" : "=a"(rax), "+S"(program)); // Write-only %rax, read-write %rsi. |
| 59 | return rax; |
| 60 | #else |
| 61 | // On ARM *program++ compiles into pretty ideal code without any handholding. |
| 62 | return *program++; |
| 63 | #endif |
| 64 | } |
| 65 | |
Mike Klein | 7c55726 | 2017-09-15 14:02:08 -0400 | [diff] [blame] | 66 | // Lazily resolved on first cast. Does nothing if cast to Ctx::None. |
| 67 | struct Ctx { |
Mike Klein | f7729c2 | 2017-09-27 11:42:30 -0400 | [diff] [blame] | 68 | struct None {}; |
Mike Klein | 7c55726 | 2017-09-15 14:02:08 -0400 | [diff] [blame] | 69 | |
Mike Klein | 0d93010 | 2017-06-02 11:08:39 -0400 | [diff] [blame] | 70 | void* ptr; |
| 71 | void**& program; |
| 72 | |
Mike Klein | 7c55726 | 2017-09-15 14:02:08 -0400 | [diff] [blame] | 73 | explicit Ctx(void**& p) : ptr(nullptr), program(p) {} |
Mike Klein | 0d93010 | 2017-06-02 11:08:39 -0400 | [diff] [blame] | 74 | |
| 75 | template <typename T> |
| 76 | operator T*() { |
| 77 | if (!ptr) { ptr = load_and_inc(program); } |
| 78 | return (T*)ptr; |
| 79 | } |
Mike Klein | f7729c2 | 2017-09-27 11:42:30 -0400 | [diff] [blame] | 80 | operator None() { return None{}; } |
Mike Klein | 0d93010 | 2017-06-02 11:08:39 -0400 | [diff] [blame] | 81 | }; |
| 82 | |
Mike Klein | b9c4a6f | 2017-04-03 13:54:55 -0400 | [diff] [blame] | 83 | #endif//SkJumper_misc_DEFINED |