| /* |
| * Copyright (C) 2017 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| "use strict"; |
| |
| // NOTE: The next line is line 28, and we rely on this in Prepare.js. |
| let standardLibrary = ` |
| // This is the WSL standard library. Implementations of all of these things are in |
| // Intrinsics.js. |
| |
| // Need to bootstrap void first. |
| native typedef void; |
| |
| native typedef uint8; |
| native typedef int32; |
| native typedef uint32; |
| native typedef bool; |
| typedef int = int32; |
| typedef uint = uint32; |
| |
| native typedef float32; |
| native typedef float64; |
| typedef float = float32; |
| typedef double = float64; |
| |
| native operator int32(uint32); |
| native operator int32(uint8); |
| native operator int32(float); |
| native operator int32(double); |
| native operator uint32(int32); |
| native operator uint32(uint8); |
| native operator uint32(float); |
| native operator uint32(double); |
| native operator uint8(int32); |
| native operator uint8(uint32); |
| native operator uint8(float); |
| native operator uint8(double); |
| native operator float(int32); |
| native operator float(uint32); |
| native operator float(uint8); |
| native operator float(double); |
| native operator double(float); |
| native operator double(int32); |
| native operator double(uint32); |
| native operator double(uint8); |
| |
| native int operator+(int, int); |
| native uint operator+(uint, uint); |
| uint8 operator+(uint8 a, uint8 b) { return uint8(uint(a) + uint(b)); } |
| native float operator+(float, float); |
| native double operator+(double, double); |
| int operator++(int value) { return value + 1; } |
| uint operator++(uint value) { return value + 1; } |
| uint8 operator++(uint8 value) { return value + 1; } |
| native int operator-(int, int); |
| native uint operator-(uint, uint); |
| uint8 operator-(uint8 a, uint8 b) { return uint8(uint(a) - uint(b)); } |
| native float operator-(float, float); |
| native double operator-(double, double); |
| int operator--(int value) { return value - 1; } |
| uint operator--(uint value) { return value - 1; } |
| uint8 operator--(uint8 value) { return value - 1; } |
| native int operator*(int, int); |
| native uint operator*(uint, uint); |
| uint8 operator*(uint8 a, uint8 b) { return uint8(uint(a) * uint(b)); } |
| native float operator*(float, float); |
| native double operator*(double, double); |
| native int operator/(int, int); |
| native uint operator/(uint, uint); |
| uint8 operator/(uint8 a, uint8 b) { return uint8(uint(a) / uint(b)); } |
| native int operator&(int, int); |
| native int operator|(int, int); |
| native int operator^(int, int); |
| native int operator~(int); |
| native int operator<<(int, uint); |
| native int operator>>(int, uint); |
| native uint operator&(uint, uint); |
| native uint operator|(uint, uint); |
| native uint operator^(uint, uint); |
| native uint operator~(uint); |
| native uint operator<<(uint, uint); |
| native uint operator>>(uint, uint); |
| uint8 operator&(uint8 a, uint8 b) { return uint8(uint(a) & uint(b)); } |
| uint8 operator|(uint8 a, uint8 b) { return uint8(uint(a) | uint(b)); } |
| uint8 operator^(uint8 a, uint8 b) { return uint8(uint(a) ^ uint(b)); } |
| uint8 operator~(uint8 value) { return uint8(~uint(value)); } |
| uint8 operator<<(uint8 a, uint b) { return uint8(uint(a) << (b & 7)); } |
| uint8 operator>>(uint8 a, uint b) { return uint8(uint(a) >> (b & 7)); } |
| native float operator/(float, float); |
| native double operator/(double, double); |
| native bool operator==(int, int); |
| native bool operator==(uint, uint); |
| bool operator==(uint8 a, uint8 b) { return uint(a) == uint(b); } |
| native bool operator==(bool, bool); |
| native bool operator==(float, float); |
| native bool operator==(double, double); |
| native bool operator<(int, int); |
| native bool operator<(uint, uint); |
| bool operator<(uint8 a, uint8 b) { return uint(a) < uint(b); } |
| native bool operator<(float, float); |
| native bool operator<(double, double); |
| native bool operator<=(int, int); |
| native bool operator<=(uint, uint); |
| bool operator<=(uint8 a, uint8 b) { return uint(a) <= uint(b); } |
| native bool operator<=(float, float); |
| native bool operator<=(double, double); |
| native bool operator>(int, int); |
| native bool operator>(uint, uint); |
| bool operator>(uint8 a, uint8 b) { return uint(a) > uint(b); } |
| native bool operator>(float, float); |
| native bool operator>(double, double); |
| native bool operator>=(int, int); |
| native bool operator>=(uint, uint); |
| bool operator>=(uint8 a, uint8 b) { return uint(a) >= uint(b); } |
| native bool operator>=(float, float); |
| native bool operator>=(double, double); |
| |
| bool operator&(bool a, bool b) |
| { |
| if (a) |
| return b; |
| return false; |
| } |
| |
| bool operator|(bool a, bool b) |
| { |
| if (a) |
| return true; |
| if (b) |
| return true; |
| return false; |
| } |
| |
| bool operator^(bool a, bool b) |
| { |
| if (a) |
| return !b; |
| return b; |
| } |
| |
| bool operator~(bool value) |
| { |
| return !value; |
| } |
| |
| protocol Addable { |
| Addable operator+(Addable, Addable); |
| } |
| |
| protocol Equatable { |
| bool operator==(Equatable, Equatable); |
| } |
| |
| restricted operator<T> T() |
| { |
| T defaultValue; |
| return defaultValue; |
| } |
| |
| restricted operator<T> T(T x) |
| { |
| return x; |
| } |
| |
| operator<T:Equatable> bool(T x) |
| { |
| return x != T(); |
| } |
| |
| struct vec2<T> { |
| T x; |
| T y; |
| } |
| |
| typedef int2 = vec2<int>; |
| typedef uint2 = vec2<uint>; |
| typedef float2 = vec2<float>; |
| typedef double2 = vec2<double>; |
| |
| operator<T> vec2<T>(T x, T y) |
| { |
| vec2<T> result; |
| result.x = x; |
| result.y = y; |
| return result; |
| } |
| |
| bool operator==<T:Equatable>(vec2<T> a, vec2<T> b) |
| { |
| return a.x == b.x && a.y == b.y; |
| } |
| |
| thread T* operator&[]<T>(thread vec2<T>* foo, uint index) |
| { |
| if (index == 0) |
| return &foo->x; |
| if (index == 1) |
| return &foo->y; |
| trap; |
| } |
| |
| struct vec3<T> { |
| T x; |
| T y; |
| T z; |
| } |
| |
| typedef int3 = vec3<int>; |
| typedef uint3 = vec3<uint>; |
| typedef float3 = vec3<float>; |
| typedef double3 = vec3<double>; |
| |
| operator<T> vec3<T>(T x, T y, T z) |
| { |
| vec3<T> result; |
| result.x = x; |
| result.y = y; |
| result.z = z; |
| return result; |
| } |
| |
| operator<T> vec3<T>(vec2<T> v2, T z) |
| { |
| vec3<T> result; |
| result.x = v2.x; |
| result.y = v2.y; |
| result.z = z; |
| return result; |
| } |
| |
| operator<T> vec3<T>(T x, vec2<T> v2) |
| { |
| vec3<T> result; |
| result.x = x; |
| result.y = v2.x; |
| result.z = v2.y; |
| return result; |
| } |
| |
| bool operator==<T:Equatable>(vec3<T> a, vec3<T> b) |
| { |
| return a.x == b.x && a.y == b.y && a.z == b.z; |
| } |
| |
| thread T* operator&[]<T>(thread vec3<T>* foo, uint index) |
| { |
| if (index == 0) |
| return &foo->x; |
| if (index == 1) |
| return &foo->y; |
| if (index == 2) |
| return &foo->z; |
| trap; |
| } |
| |
| struct vec4<T> { |
| T x; |
| T y; |
| T z; |
| T w; |
| } |
| |
| typedef int4 = vec4<int>; |
| typedef uint4 = vec4<uint>; |
| typedef float4 = vec4<float>; |
| typedef double4 = vec4<double>; |
| |
| operator<T> vec4<T>(T x, T y, T z, T w) |
| { |
| vec4<T> result; |
| result.x = x; |
| result.y = y; |
| result.z = z; |
| result.w = w; |
| return result; |
| } |
| |
| operator<T> vec4<T>(vec2<T> v2, T z, T w) |
| { |
| vec4<T> result; |
| result.x = v2.x; |
| result.y = v2.y; |
| result.z = z; |
| result.w = w; |
| return result; |
| } |
| |
| operator<T> vec4<T>(T x, vec2<T> v2, T w) |
| { |
| vec4<T> result; |
| result.x = x; |
| result.y = v2.x; |
| result.z = v2.y; |
| result.w = w; |
| return result; |
| } |
| |
| operator<T> vec4<T>(T x, T y, vec2<T> v2) |
| { |
| vec4<T> result; |
| result.x = x; |
| result.y = y; |
| result.z = v2.x; |
| result.w = v2.y; |
| return result; |
| } |
| |
| operator<T> vec4<T>(vec2<T> v2a, vec2<T> v2b) |
| { |
| vec4<T> result; |
| result.x = v2a.x; |
| result.y = v2a.y; |
| result.z = v2b.x; |
| result.w = v2b.y; |
| return result; |
| } |
| |
| operator<T> vec4<T>(vec3<T> v3, T w) |
| { |
| vec4<T> result; |
| result.x = v3.x; |
| result.y = v3.y; |
| result.z = v3.z; |
| result.w = w; |
| return result; |
| } |
| |
| operator<T> vec4<T>(T x, vec3<T> v3) |
| { |
| vec4<T> result; |
| result.x = x; |
| result.y = v3.x; |
| result.z = v3.y; |
| result.w = v3.z; |
| return result; |
| } |
| |
| bool operator==<T:Equatable>(vec4<T> a, vec4<T> b) |
| { |
| return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; |
| } |
| |
| thread T* operator&[]<T>(thread vec4<T>* foo, uint index) |
| { |
| if (index == 0) |
| return &foo->x; |
| if (index == 1) |
| return &foo->y; |
| if (index == 2) |
| return &foo->z; |
| if (index == 3) |
| return &foo->w; |
| trap; |
| } |
| |
| native thread T* operator&[]<T>(thread T[], uint); |
| native threadgroup T* operator&[]<T>(threadgroup T[], uint); |
| native device T* operator&[]<T>(device T[], uint); |
| native constant T* operator&[]<T>(constant T[], uint); |
| |
| native uint operator.length<T>(thread T[]); |
| native uint operator.length<T>(threadgroup T[]); |
| native uint operator.length<T>(device T[]); |
| native uint operator.length<T>(constant T[]); |
| |
| uint operator.length<T, uint length>(T[length]) |
| { |
| return length; |
| } |
| `; |
| |
| function intToString(x) |
| { |
| switch (x) { |
| case 0: |
| return "x"; |
| case 1: |
| return "y"; |
| case 2: |
| return "z"; |
| case 3: |
| return "w"; |
| default: |
| throw new Error("Could not generate standard library."); |
| } |
| } |
| |
| // There are 481 swizzle operators. Let's not list them explicitly. |
| function _generateSwizzle(maxDepth, maxItems, array) |
| { |
| if (!array) |
| array = []; |
| if (array.length == maxDepth) { |
| let result = `vec${array.length}<T> operator.${array.join("")}<T>(vec${maxItems}<T> v) |
| { |
| vec${array.length}<T> result; |
| `; |
| for (let i = 0; i < array.length; ++i) { |
| result += ` result.${intToString(i)} = v.${array[i]}; |
| `; |
| } |
| result += ` return result; |
| } |
| `; |
| return result; |
| } |
| let result = ""; |
| for (let i = 0; i < maxItems; ++i) { |
| array.push(intToString(i)); |
| result += _generateSwizzle(maxDepth, maxItems, array); |
| array.pop(); |
| } |
| return result; |
| } |
| |
| for (let maxDepth = 2; maxDepth <= 4; maxDepth++) { |
| for (let maxItems = 2; maxItems <= 4; maxItems++) |
| standardLibrary += _generateSwizzle(maxDepth, maxItems); |
| } |