/* * 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 defaultValue; return defaultValue; } restricted operator T(T x) { return x; } operator bool(T x) { return x != T(); } struct vec2 { T x; T y; } typedef int2 = vec2; typedef uint2 = vec2; typedef float2 = vec2; typedef double2 = vec2; operator vec2(T x, T y) { vec2 result; result.x = x; result.y = y; return result; } bool operator==(vec2 a, vec2 b) { return a.x == b.x && a.y == b.y; } thread T* operator&[](thread vec2* foo, uint index) { if (index == 0) return &foo->x; if (index == 1) return &foo->y; trap; } struct vec3 { T x; T y; T z; } typedef int3 = vec3; typedef uint3 = vec3; typedef float3 = vec3; typedef double3 = vec3; operator vec3(T x, T y, T z) { vec3 result; result.x = x; result.y = y; result.z = z; return result; } operator vec3(vec2 v2, T z) { vec3 result; result.x = v2.x; result.y = v2.y; result.z = z; return result; } operator vec3(T x, vec2 v2) { vec3 result; result.x = x; result.y = v2.x; result.z = v2.y; return result; } bool operator==(vec3 a, vec3 b) { return a.x == b.x && a.y == b.y && a.z == b.z; } thread T* operator&[](thread vec3* 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 x; T y; T z; T w; } typedef int4 = vec4; typedef uint4 = vec4; typedef float4 = vec4; typedef double4 = vec4; operator vec4(T x, T y, T z, T w) { vec4 result; result.x = x; result.y = y; result.z = z; result.w = w; return result; } operator vec4(vec2 v2, T z, T w) { vec4 result; result.x = v2.x; result.y = v2.y; result.z = z; result.w = w; return result; } operator vec4(T x, vec2 v2, T w) { vec4 result; result.x = x; result.y = v2.x; result.z = v2.y; result.w = w; return result; } operator vec4(T x, T y, vec2 v2) { vec4 result; result.x = x; result.y = y; result.z = v2.x; result.w = v2.y; return result; } operator vec4(vec2 v2a, vec2 v2b) { vec4 result; result.x = v2a.x; result.y = v2a.y; result.z = v2b.x; result.w = v2b.y; return result; } operator vec4(vec3 v3, T w) { vec4 result; result.x = v3.x; result.y = v3.y; result.z = v3.z; result.w = w; return result; } operator vec4(T x, vec3 v3) { vec4 result; result.x = x; result.y = v3.x; result.z = v3.y; result.w = v3.z; return result; } bool operator==(vec4 a, vec4 b) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; } thread T* operator&[](thread vec4* 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&[](thread T[], uint); native threadgroup T* operator&[](threadgroup T[], uint); native device T* operator&[](device T[], uint); native constant T* operator&[](constant T[], uint); native uint operator.length(thread T[]); native uint operator.length(threadgroup T[]); native uint operator.length(device T[]); native uint operator.length(constant T[]); uint operator.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} operator.${array.join("")}(vec${maxItems} v) { vec${array.length} 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); }