// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef rr_Reactor_hpp #define rr_Reactor_hpp #include "Nucleus.hpp" #include "Pragma.hpp" #include "Routine.hpp" #include "Traits.hpp" #include #include #include #include #include #include #ifdef ENABLE_RR_DEBUG_INFO // Functions used for generating JIT debug info. // See docs/ReactorDebugInfo.md for more information. namespace rr { // Update the current source location for debug. void EmitDebugLocation(); // Bind value to its symbolic name taken from the backtrace. void EmitDebugVariable(class Value *value); // Flush any pending variable bindings before the line ends. void FlushDebug(); } // namespace rr # define RR_DEBUG_INFO_UPDATE_LOC() rr::EmitDebugLocation() # define RR_DEBUG_INFO_EMIT_VAR(value) rr::EmitDebugVariable(value) # define RR_DEBUG_INFO_FLUSH() rr::FlushDebug() #else # define RR_DEBUG_INFO_UPDATE_LOC() # define RR_DEBUG_INFO_EMIT_VAR(value) # define RR_DEBUG_INFO_FLUSH() #endif // ENABLE_RR_DEBUG_INFO #ifdef ENABLE_RR_PRINT namespace rr { int DebugPrintf(const char *format, ...); } #endif // A Clang extension to determine compiler features. // We use it to detect Sanitizer builds (e.g. -fsanitize=memory). #ifndef __has_feature # define __has_feature(x) 0 #endif // Whether Reactor routine instrumentation is enabled for MSan builds. // TODO(b/155148722): Remove when unconditionally instrumenting for all build systems. #if !defined REACTOR_ENABLE_MEMORY_SANITIZER_INSTRUMENTATION # define REACTOR_ENABLE_MEMORY_SANITIZER_INSTRUMENTATION 0 #endif namespace rr { // These generally map to the precision types as specified by the Vulkan specification. // See https://www.khronos.org/registry/vulkan/specs/1.2/html/chap37.html#spirvenv-precision-operation enum class Precision { /*Exact,*/ // 0 ULP with correct rounding (i.e. Math.h) Full, // Single precision, but not relaxed Relaxed, // Single precision, relaxed /*Half,*/ // Half precision }; std::string BackendName(); struct Capabilities { bool CoroutinesSupported; // Support for rr::Coroutine }; extern const Capabilities Caps; class Bool; class Byte; class SByte; class Byte4; class SByte4; class Byte8; class SByte8; class Byte16; class SByte16; class Short; class UShort; class Short2; class UShort2; class Short4; class UShort4; class Short8; class UShort8; class Int; class UInt; class Int2; class UInt2; class Int4; class UInt4; class Long; class Half; class Float; class Float2; class Float4; class Void { public: static Type *type(); }; template class RValue; template class Pointer; class Variable { friend class Nucleus; Variable() = delete; Variable &operator=(const Variable &) = delete; public: void materialize() const; Value *loadValue() const; Value *storeValue(Value *value) const; Value *getBaseAddress() const; Value *getElementPointer(Value *index, bool unsignedIndex) const; Type *getType() const { return type; } int getArraySize() const { return arraySize; } // This function is only public for testing purposes, as it affects performance. // It is not considered part of Reactor's public API. static void materializeAll(); protected: Variable(Type *type, int arraySize); Variable(const Variable &) = default; virtual ~Variable(); private: static void killUnmaterialized(); // Set of variables that do not have a stack location yet. class UnmaterializedVariables { public: void add(const Variable *v); void remove(const Variable *v); void clear(); void materializeAll(); private: int counter = 0; std::unordered_map variables; }; // This has to be a raw pointer because glibc 2.17 doesn't support __cxa_thread_atexit_impl // for destructing objects at exit. See crbug.com/1074222 static thread_local UnmaterializedVariables *unmaterializedVariables; Type *const type; const int arraySize; mutable Value *rvalue = nullptr; mutable Value *address = nullptr; }; template class LValue : public Variable { public: LValue(int arraySize = 0); RValue> operator&(); RValue load() const { return RValue(this->loadValue()); } RValue store(RValue rvalue) const { this->storeValue(rvalue.value()); return rvalue; } // self() returns the this pointer to this LValue object. // This function exists because operator&() is overloaded. inline LValue *self() { return this; } }; template class Reference { public: using reference_underlying_type = T; explicit Reference(Value *pointer, int alignment = 1); Reference(const Reference &ref) = default; RValue operator=(RValue rhs) const; RValue operator=(const Reference &ref) const; RValue operator+=(RValue rhs) const; RValue> operator&() const { return RValue>(address); } Value *loadValue() const; RValue load() const; int getAlignment() const; private: Value *const address; const int alignment; }; template struct BoolLiteral { struct type; }; template<> struct BoolLiteral { typedef bool type; }; template struct IntLiteral { struct type; }; template<> struct IntLiteral { typedef int type; }; template<> struct IntLiteral { typedef unsigned int type; }; template<> struct IntLiteral { typedef int64_t type; }; template struct FloatLiteral { struct type; }; template<> struct FloatLiteral { typedef float type; }; template class RValue { public: using rvalue_underlying_type = T; explicit RValue(Value *rvalue); RValue(const RValue &rvalue); RValue(const T &lvalue); RValue(typename BoolLiteral::type i); RValue(typename IntLiteral::type i); RValue(typename FloatLiteral::type f); RValue(const Reference &rhs); // Rvalues cannot be assigned to: "(a + b) = c;" RValue &operator=(const RValue &) = delete; Value *value() const { return val; } private: Value *const val; }; template class Argument { public: explicit Argument(Value *val) : val(val) {} RValue rvalue() const { return RValue(val); } private: Value *const val; }; class Bool : public LValue { public: Bool(Argument argument); Bool() = default; Bool(bool x); Bool(RValue rhs); Bool(const Bool &rhs); Bool(const Reference &rhs); // RValue operator=(bool rhs); // FIXME: Implement RValue operator=(RValue rhs); RValue operator=(const Bool &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator!(RValue val); RValue operator&&(RValue lhs, RValue rhs); RValue operator||(RValue lhs, RValue rhs); RValue operator!=(RValue lhs, RValue rhs); RValue operator==(RValue lhs, RValue rhs); class Byte : public LValue { public: Byte(Argument argument); explicit Byte(RValue cast); explicit Byte(RValue cast); explicit Byte(RValue cast); Byte() = default; Byte(int x); Byte(unsigned char x); Byte(RValue rhs); Byte(const Byte &rhs); Byte(const Reference &rhs); // RValue operator=(unsigned char rhs); // FIXME: Implement RValue operator=(RValue rhs); RValue operator=(const Byte &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(Byte &lhs, RValue rhs); RValue operator-=(Byte &lhs, RValue rhs); RValue operator*=(Byte &lhs, RValue rhs); RValue operator/=(Byte &lhs, RValue rhs); RValue operator%=(Byte &lhs, RValue rhs); RValue operator&=(Byte &lhs, RValue rhs); RValue operator|=(Byte &lhs, RValue rhs); RValue operator^=(Byte &lhs, RValue rhs); RValue operator<<=(Byte &lhs, RValue rhs); RValue operator>>=(Byte &lhs, RValue rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); RValue operator++(Byte &val, int); // Post-increment const Byte &operator++(Byte &val); // Pre-increment RValue operator--(Byte &val, int); // Post-decrement const Byte &operator--(Byte &val); // Pre-decrement RValue operator<(RValue lhs, RValue rhs); RValue operator<=(RValue lhs, RValue rhs); RValue operator>(RValue lhs, RValue rhs); RValue operator>=(RValue lhs, RValue rhs); RValue operator!=(RValue lhs, RValue rhs); RValue operator==(RValue lhs, RValue rhs); class SByte : public LValue { public: SByte(Argument argument); explicit SByte(RValue cast); explicit SByte(RValue cast); SByte() = default; SByte(signed char x); SByte(RValue rhs); SByte(const SByte &rhs); SByte(const Reference &rhs); // RValue operator=(signed char rhs); // FIXME: Implement RValue operator=(RValue rhs); RValue operator=(const SByte &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(SByte &lhs, RValue rhs); RValue operator-=(SByte &lhs, RValue rhs); RValue operator*=(SByte &lhs, RValue rhs); RValue operator/=(SByte &lhs, RValue rhs); RValue operator%=(SByte &lhs, RValue rhs); RValue operator&=(SByte &lhs, RValue rhs); RValue operator|=(SByte &lhs, RValue rhs); RValue operator^=(SByte &lhs, RValue rhs); RValue operator<<=(SByte &lhs, RValue rhs); RValue operator>>=(SByte &lhs, RValue rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); RValue operator++(SByte &val, int); // Post-increment const SByte &operator++(SByte &val); // Pre-increment RValue operator--(SByte &val, int); // Post-decrement const SByte &operator--(SByte &val); // Pre-decrement RValue operator<(RValue lhs, RValue rhs); RValue operator<=(RValue lhs, RValue rhs); RValue operator>(RValue lhs, RValue rhs); RValue operator>=(RValue lhs, RValue rhs); RValue operator!=(RValue lhs, RValue rhs); RValue operator==(RValue lhs, RValue rhs); class Short : public LValue { public: Short(Argument argument); explicit Short(RValue cast); Short() = default; Short(short x); Short(RValue rhs); Short(const Short &rhs); Short(const Reference &rhs); // RValue operator=(short rhs); // FIXME: Implement RValue operator=(RValue rhs); RValue operator=(const Short &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(Short &lhs, RValue rhs); RValue operator-=(Short &lhs, RValue rhs); RValue operator*=(Short &lhs, RValue rhs); RValue operator/=(Short &lhs, RValue rhs); RValue operator%=(Short &lhs, RValue rhs); RValue operator&=(Short &lhs, RValue rhs); RValue operator|=(Short &lhs, RValue rhs); RValue operator^=(Short &lhs, RValue rhs); RValue operator<<=(Short &lhs, RValue rhs); RValue operator>>=(Short &lhs, RValue rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); RValue operator++(Short &val, int); // Post-increment const Short &operator++(Short &val); // Pre-increment RValue operator--(Short &val, int); // Post-decrement const Short &operator--(Short &val); // Pre-decrement RValue operator<(RValue lhs, RValue rhs); RValue operator<=(RValue lhs, RValue rhs); RValue operator>(RValue lhs, RValue rhs); RValue operator>=(RValue lhs, RValue rhs); RValue operator!=(RValue lhs, RValue rhs); RValue operator==(RValue lhs, RValue rhs); class UShort : public LValue { public: UShort(Argument argument); explicit UShort(RValue cast); explicit UShort(RValue cast); UShort() = default; UShort(unsigned short x); UShort(RValue rhs); UShort(const UShort &rhs); UShort(const Reference &rhs); // RValue operator=(unsigned short rhs); // FIXME: Implement RValue operator=(RValue rhs); RValue operator=(const UShort &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(UShort &lhs, RValue rhs); RValue operator-=(UShort &lhs, RValue rhs); RValue operator*=(UShort &lhs, RValue rhs); RValue operator/=(UShort &lhs, RValue rhs); RValue operator%=(UShort &lhs, RValue rhs); RValue operator&=(UShort &lhs, RValue rhs); RValue operator|=(UShort &lhs, RValue rhs); RValue operator^=(UShort &lhs, RValue rhs); RValue operator<<=(UShort &lhs, RValue rhs); RValue operator>>=(UShort &lhs, RValue rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); RValue operator++(UShort &val, int); // Post-increment const UShort &operator++(UShort &val); // Pre-increment RValue operator--(UShort &val, int); // Post-decrement const UShort &operator--(UShort &val); // Pre-decrement RValue operator<(RValue lhs, RValue rhs); RValue operator<=(RValue lhs, RValue rhs); RValue operator>(RValue lhs, RValue rhs); RValue operator>=(RValue lhs, RValue rhs); RValue operator!=(RValue lhs, RValue rhs); RValue operator==(RValue lhs, RValue rhs); class Byte4 : public LValue { public: explicit Byte4(RValue cast); explicit Byte4(RValue cast); explicit Byte4(RValue cast); explicit Byte4(RValue cast); explicit Byte4(RValue cast); Byte4() = default; // Byte4(int x, int y, int z, int w); Byte4(RValue rhs); Byte4(const Byte4 &rhs); Byte4(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const Byte4 &rhs); // RValue operator=(const Reference &rhs); static Type *type(); }; // RValue operator+(RValue lhs, RValue rhs); // RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); // RValue operator&(RValue lhs, RValue rhs); // RValue operator|(RValue lhs, RValue rhs); // RValue operator^(RValue lhs, RValue rhs); // RValue operator<<(RValue lhs, RValue rhs); // RValue operator>>(RValue lhs, RValue rhs); // RValue operator+=(Byte4 &lhs, RValue rhs); // RValue operator-=(Byte4 &lhs, RValue rhs); // RValue operator*=(Byte4 &lhs, RValue rhs); // RValue operator/=(Byte4 &lhs, RValue rhs); // RValue operator%=(Byte4 &lhs, RValue rhs); // RValue operator&=(Byte4 &lhs, RValue rhs); // RValue operator|=(Byte4 &lhs, RValue rhs); // RValue operator^=(Byte4 &lhs, RValue rhs); // RValue operator<<=(Byte4 &lhs, RValue rhs); // RValue operator>>=(Byte4 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); // RValue operator~(RValue val); // RValue operator++(Byte4 &val, int); // Post-increment // const Byte4 &operator++(Byte4 &val); // Pre-increment // RValue operator--(Byte4 &val, int); // Post-decrement // const Byte4 &operator--(Byte4 &val); // Pre-decrement class SByte4 : public LValue { public: SByte4() = default; // SByte4(int x, int y, int z, int w); // SByte4(RValue rhs); // SByte4(const SByte4 &rhs); // SByte4(const Reference &rhs); // RValue operator=(RValue rhs); // RValue operator=(const SByte4 &rhs); // RValue operator=(const Reference &rhs); static Type *type(); }; // RValue operator+(RValue lhs, RValue rhs); // RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); // RValue operator&(RValue lhs, RValue rhs); // RValue operator|(RValue lhs, RValue rhs); // RValue operator^(RValue lhs, RValue rhs); // RValue operator<<(RValue lhs, RValue rhs); // RValue operator>>(RValue lhs, RValue rhs); // RValue operator+=(SByte4 &lhs, RValue rhs); // RValue operator-=(SByte4 &lhs, RValue rhs); // RValue operator*=(SByte4 &lhs, RValue rhs); // RValue operator/=(SByte4 &lhs, RValue rhs); // RValue operator%=(SByte4 &lhs, RValue rhs); // RValue operator&=(SByte4 &lhs, RValue rhs); // RValue operator|=(SByte4 &lhs, RValue rhs); // RValue operator^=(SByte4 &lhs, RValue rhs); // RValue operator<<=(SByte4 &lhs, RValue rhs); // RValue operator>>=(SByte4 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); // RValue operator~(RValue val); // RValue operator++(SByte4 &val, int); // Post-increment // const SByte4 &operator++(SByte4 &val); // Pre-increment // RValue operator--(SByte4 &val, int); // Post-decrement // const SByte4 &operator--(SByte4 &val); // Pre-decrement class Byte8 : public LValue { public: Byte8() = default; Byte8(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7); Byte8(RValue rhs); Byte8(const Byte8 &rhs); Byte8(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const Byte8 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); // RValue operator<<(RValue lhs, RValue rhs); // RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(Byte8 &lhs, RValue rhs); RValue operator-=(Byte8 &lhs, RValue rhs); // RValue operator*=(Byte8 &lhs, RValue rhs); // RValue operator/=(Byte8 &lhs, RValue rhs); // RValue operator%=(Byte8 &lhs, RValue rhs); RValue operator&=(Byte8 &lhs, RValue rhs); RValue operator|=(Byte8 &lhs, RValue rhs); RValue operator^=(Byte8 &lhs, RValue rhs); // RValue operator<<=(Byte8 &lhs, RValue rhs); // RValue operator>>=(Byte8 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(Byte8 &val, int); // Post-increment // const Byte8 &operator++(Byte8 &val); // Pre-increment // RValue operator--(Byte8 &val, int); // Post-decrement // const Byte8 &operator--(Byte8 &val); // Pre-decrement RValue AddSat(RValue x, RValue y); RValue SubSat(RValue x, RValue y); RValue Unpack(RValue x); RValue Unpack(RValue x, RValue y); RValue UnpackLow(RValue x, RValue y); RValue UnpackHigh(RValue x, RValue y); RValue SignMask(RValue x); // RValue CmpGT(RValue x, RValue y); RValue CmpEQ(RValue x, RValue y); RValue Swizzle(RValue x, uint32_t select); class SByte8 : public LValue { public: SByte8() = default; SByte8(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7); SByte8(RValue rhs); SByte8(const SByte8 &rhs); SByte8(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const SByte8 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); // RValue operator<<(RValue lhs, RValue rhs); // RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(SByte8 &lhs, RValue rhs); RValue operator-=(SByte8 &lhs, RValue rhs); // RValue operator*=(SByte8 &lhs, RValue rhs); // RValue operator/=(SByte8 &lhs, RValue rhs); // RValue operator%=(SByte8 &lhs, RValue rhs); RValue operator&=(SByte8 &lhs, RValue rhs); RValue operator|=(SByte8 &lhs, RValue rhs); RValue operator^=(SByte8 &lhs, RValue rhs); // RValue operator<<=(SByte8 &lhs, RValue rhs); // RValue operator>>=(SByte8 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(SByte8 &val, int); // Post-increment // const SByte8 &operator++(SByte8 &val); // Pre-increment // RValue operator--(SByte8 &val, int); // Post-decrement // const SByte8 &operator--(SByte8 &val); // Pre-decrement RValue AddSat(RValue x, RValue y); RValue SubSat(RValue x, RValue y); RValue UnpackLow(RValue x, RValue y); RValue UnpackHigh(RValue x, RValue y); RValue SignMask(RValue x); RValue CmpGT(RValue x, RValue y); RValue CmpEQ(RValue x, RValue y); class Byte16 : public LValue { public: Byte16() = default; Byte16(RValue rhs); Byte16(const Byte16 &rhs); Byte16(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const Byte16 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; // RValue operator+(RValue lhs, RValue rhs); // RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); // RValue operator&(RValue lhs, RValue rhs); // RValue operator|(RValue lhs, RValue rhs); // RValue operator^(RValue lhs, RValue rhs); // RValue operator<<(RValue lhs, RValue rhs); // RValue operator>>(RValue lhs, RValue rhs); // RValue operator+=(Byte16 &lhs, RValue rhs); // RValue operator-=(Byte16 &lhs, RValue rhs); // RValue operator*=(Byte16 &lhs, RValue rhs); // RValue operator/=(Byte16 &lhs, RValue rhs); // RValue operator%=(Byte16 &lhs, RValue rhs); // RValue operator&=(Byte16 &lhs, RValue rhs); // RValue operator|=(Byte16 &lhs, RValue rhs); // RValue operator^=(Byte16 &lhs, RValue rhs); // RValue operator<<=(Byte16 &lhs, RValue rhs); // RValue operator>>=(Byte16 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); // RValue operator~(RValue val); // RValue operator++(Byte16 &val, int); // Post-increment // const Byte16 &operator++(Byte16 &val); // Pre-increment // RValue operator--(Byte16 &val, int); // Post-decrement // const Byte16 &operator--(Byte16 &val); // Pre-decrement RValue Swizzle(RValue x, uint64_t select); class SByte16 : public LValue { public: SByte16() = default; // SByte16(int x, int y, int z, int w); // SByte16(RValue rhs); // SByte16(const SByte16 &rhs); // SByte16(const Reference &rhs); // RValue operator=(RValue rhs); // RValue operator=(const SByte16 &rhs); // RValue operator=(const Reference &rhs); static Type *type(); }; // RValue operator+(RValue lhs, RValue rhs); // RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); // RValue operator&(RValue lhs, RValue rhs); // RValue operator|(RValue lhs, RValue rhs); // RValue operator^(RValue lhs, RValue rhs); // RValue operator<<(RValue lhs, RValue rhs); // RValue operator>>(RValue lhs, RValue rhs); // RValue operator+=(SByte16 &lhs, RValue rhs); // RValue operator-=(SByte16 &lhs, RValue rhs); // RValue operator*=(SByte16 &lhs, RValue rhs); // RValue operator/=(SByte16 &lhs, RValue rhs); // RValue operator%=(SByte16 &lhs, RValue rhs); // RValue operator&=(SByte16 &lhs, RValue rhs); // RValue operator|=(SByte16 &lhs, RValue rhs); // RValue operator^=(SByte16 &lhs, RValue rhs); // RValue operator<<=(SByte16 &lhs, RValue rhs); // RValue operator>>=(SByte16 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); // RValue operator~(RValue val); // RValue operator++(SByte16 &val, int); // Post-increment // const SByte16 &operator++(SByte16 &val); // Pre-increment // RValue operator--(SByte16 &val, int); // Post-decrement // const SByte16 &operator--(SByte16 &val); // Pre-decrement class Short2 : public LValue { public: explicit Short2(RValue cast); static Type *type(); }; class UShort2 : public LValue { public: explicit UShort2(RValue cast); static Type *type(); }; class Short4 : public LValue { public: explicit Short4(RValue cast); explicit Short4(RValue cast); // explicit Short4(RValue cast); explicit Short4(RValue cast); Short4() = default; Short4(short xyzw); Short4(short x, short y, short z, short w); Short4(RValue rhs); Short4(const Short4 &rhs); Short4(const Reference &rhs); Short4(RValue rhs); Short4(const UShort4 &rhs); Short4(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const Short4 &rhs); RValue operator=(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const UShort4 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, unsigned char rhs); RValue operator>>(RValue lhs, unsigned char rhs); RValue operator+=(Short4 &lhs, RValue rhs); RValue operator-=(Short4 &lhs, RValue rhs); RValue operator*=(Short4 &lhs, RValue rhs); // RValue operator/=(Short4 &lhs, RValue rhs); // RValue operator%=(Short4 &lhs, RValue rhs); RValue operator&=(Short4 &lhs, RValue rhs); RValue operator|=(Short4 &lhs, RValue rhs); RValue operator^=(Short4 &lhs, RValue rhs); RValue operator<<=(Short4 &lhs, unsigned char rhs); RValue operator>>=(Short4 &lhs, unsigned char rhs); // RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(Short4 &val, int); // Post-increment // const Short4 &operator++(Short4 &val); // Pre-increment // RValue operator--(Short4 &val, int); // Post-decrement // const Short4 &operator--(Short4 &val); // Pre-decrement // RValue operator<(RValue lhs, RValue rhs); // RValue operator<=(RValue lhs, RValue rhs); // RValue operator>(RValue lhs, RValue rhs); // RValue operator>=(RValue lhs, RValue rhs); // RValue operator!=(RValue lhs, RValue rhs); // RValue operator==(RValue lhs, RValue rhs); RValue RoundShort4(RValue cast); RValue Max(RValue x, RValue y); RValue Min(RValue x, RValue y); RValue AddSat(RValue x, RValue y); RValue SubSat(RValue x, RValue y); RValue MulHigh(RValue x, RValue y); RValue MulAdd(RValue x, RValue y); RValue PackSigned(RValue x, RValue y); RValue PackUnsigned(RValue x, RValue y); RValue UnpackLow(RValue x, RValue y); RValue UnpackHigh(RValue x, RValue y); RValue Swizzle(RValue x, uint16_t select); RValue Insert(RValue val, RValue element, int i); RValue Extract(RValue val, int i); RValue CmpGT(RValue x, RValue y); RValue CmpEQ(RValue x, RValue y); class UShort4 : public LValue { public: explicit UShort4(RValue cast); explicit UShort4(RValue cast, bool saturate = false); UShort4() = default; UShort4(unsigned short xyzw); UShort4(unsigned short x, unsigned short y, unsigned short z, unsigned short w); UShort4(RValue rhs); UShort4(const UShort4 &rhs); UShort4(const Reference &rhs); UShort4(RValue rhs); UShort4(const Short4 &rhs); UShort4(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const UShort4 &rhs); RValue operator=(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const Short4 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, unsigned char rhs); RValue operator>>(RValue lhs, unsigned char rhs); // RValue operator+=(UShort4 &lhs, RValue rhs); // RValue operator-=(UShort4 &lhs, RValue rhs); // RValue operator*=(UShort4 &lhs, RValue rhs); // RValue operator/=(UShort4 &lhs, RValue rhs); // RValue operator%=(UShort4 &lhs, RValue rhs); // RValue operator&=(UShort4 &lhs, RValue rhs); // RValue operator|=(UShort4 &lhs, RValue rhs); // RValue operator^=(UShort4 &lhs, RValue rhs); RValue operator<<=(UShort4 &lhs, unsigned char rhs); RValue operator>>=(UShort4 &lhs, unsigned char rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(UShort4 &val, int); // Post-increment // const UShort4 &operator++(UShort4 &val); // Pre-increment // RValue operator--(UShort4 &val, int); // Post-decrement // const UShort4 &operator--(UShort4 &val); // Pre-decrement RValue Max(RValue x, RValue y); RValue Min(RValue x, RValue y); RValue AddSat(RValue x, RValue y); RValue SubSat(RValue x, RValue y); RValue MulHigh(RValue x, RValue y); RValue Average(RValue x, RValue y); class Short8 : public LValue { public: Short8() = default; Short8(short c); Short8(short c0, short c1, short c2, short c3, short c4, short c5, short c6, short c7); Short8(RValue rhs); // Short8(const Short8 &rhs); Short8(const Reference &rhs); Short8(RValue lo, RValue hi); RValue operator=(RValue rhs); RValue operator=(const Short8 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); // RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); // RValue operator|(RValue lhs, RValue rhs); // RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, unsigned char rhs); RValue operator>>(RValue lhs, unsigned char rhs); // RValue operator<<(RValue lhs, RValue rhs); // RValue operator>>(RValue lhs, RValue rhs); // RValue operator+=(Short8 &lhs, RValue rhs); // RValue operator-=(Short8 &lhs, RValue rhs); // RValue operator*=(Short8 &lhs, RValue rhs); // RValue operator/=(Short8 &lhs, RValue rhs); // RValue operator%=(Short8 &lhs, RValue rhs); // RValue operator&=(Short8 &lhs, RValue rhs); // RValue operator|=(Short8 &lhs, RValue rhs); // RValue operator^=(Short8 &lhs, RValue rhs); // RValue operator<<=(Short8 &lhs, RValue rhs); // RValue operator>>=(Short8 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); // RValue operator~(RValue val); // RValue operator++(Short8 &val, int); // Post-increment // const Short8 &operator++(Short8 &val); // Pre-increment // RValue operator--(Short8 &val, int); // Post-decrement // const Short8 &operator--(Short8 &val); // Pre-decrement // RValue operator<(RValue lhs, RValue rhs); // RValue operator<=(RValue lhs, RValue rhs); // RValue operator>(RValue lhs, RValue rhs); // RValue operator>=(RValue lhs, RValue rhs); // RValue operator!=(RValue lhs, RValue rhs); // RValue operator==(RValue lhs, RValue rhs); RValue MulHigh(RValue x, RValue y); RValue MulAdd(RValue x, RValue y); RValue Abs(RValue x); class UShort8 : public LValue { public: UShort8() = default; UShort8(unsigned short c); UShort8(unsigned short c0, unsigned short c1, unsigned short c2, unsigned short c3, unsigned short c4, unsigned short c5, unsigned short c6, unsigned short c7); UShort8(RValue rhs); // UShort8(const UShort8 &rhs); UShort8(const Reference &rhs); UShort8(RValue lo, RValue hi); RValue operator=(RValue rhs); RValue operator=(const UShort8 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); // RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); // RValue operator|(RValue lhs, RValue rhs); // RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, unsigned char rhs); RValue operator>>(RValue lhs, unsigned char rhs); // RValue operator<<(RValue lhs, RValue rhs); // RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(UShort8 &lhs, RValue rhs); // RValue operator-=(UShort8 &lhs, RValue rhs); // RValue operator*=(UShort8 &lhs, RValue rhs); // RValue operator/=(UShort8 &lhs, RValue rhs); // RValue operator%=(UShort8 &lhs, RValue rhs); // RValue operator&=(UShort8 &lhs, RValue rhs); // RValue operator|=(UShort8 &lhs, RValue rhs); // RValue operator^=(UShort8 &lhs, RValue rhs); // RValue operator<<=(UShort8 &lhs, RValue rhs); // RValue operator>>=(UShort8 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(UShort8 &val, int); // Post-increment // const UShort8 &operator++(UShort8 &val); // Pre-increment // RValue operator--(UShort8 &val, int); // Post-decrement // const UShort8 &operator--(UShort8 &val); // Pre-decrement // RValue operator<(RValue lhs, RValue rhs); // RValue operator<=(RValue lhs, RValue rhs); // RValue operator>(RValue lhs, RValue rhs); // RValue operator>=(RValue lhs, RValue rhs); // RValue operator!=(RValue lhs, RValue rhs); // RValue operator==(RValue lhs, RValue rhs); RValue Swizzle(RValue x, uint32_t select); RValue MulHigh(RValue x, RValue y); class Int : public LValue { public: Int(Argument argument); explicit Int(RValue cast); explicit Int(RValue cast); explicit Int(RValue cast); explicit Int(RValue cast); explicit Int(RValue cast); explicit Int(RValue cast); explicit Int(RValue cast); Int() = default; Int(int x); Int(RValue rhs); Int(RValue rhs); Int(const Int &rhs); Int(const UInt &rhs); Int(const Reference &rhs); Int(const Reference &rhs); RValue operator=(int rhs); RValue operator=(RValue rhs); RValue operator=(RValue rhs); RValue operator=(const Int &rhs); RValue operator=(const UInt &rhs); RValue operator=(const Reference &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(Int &lhs, RValue rhs); RValue operator-=(Int &lhs, RValue rhs); RValue operator*=(Int &lhs, RValue rhs); RValue operator/=(Int &lhs, RValue rhs); RValue operator%=(Int &lhs, RValue rhs); RValue operator&=(Int &lhs, RValue rhs); RValue operator|=(Int &lhs, RValue rhs); RValue operator^=(Int &lhs, RValue rhs); RValue operator<<=(Int &lhs, RValue rhs); RValue operator>>=(Int &lhs, RValue rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); RValue operator++(Int &val, int); // Post-increment const Int &operator++(Int &val); // Pre-increment RValue operator--(Int &val, int); // Post-decrement const Int &operator--(Int &val); // Pre-decrement RValue operator<(RValue lhs, RValue rhs); RValue operator<=(RValue lhs, RValue rhs); RValue operator>(RValue lhs, RValue rhs); RValue operator>=(RValue lhs, RValue rhs); RValue operator!=(RValue lhs, RValue rhs); RValue operator==(RValue lhs, RValue rhs); RValue Max(RValue x, RValue y); RValue Min(RValue x, RValue y); RValue Clamp(RValue x, RValue min, RValue max); RValue RoundInt(RValue cast); class Long : public LValue { public: // Long(Argument argument); // explicit Long(RValue cast); // explicit Long(RValue cast); explicit Long(RValue cast); explicit Long(RValue cast); // explicit Long(RValue cast); Long() = default; // Long(qword x); Long(RValue rhs); // Long(RValue rhs); // Long(const Long &rhs); // Long(const Reference &rhs); // Long(const ULong &rhs); // Long(const Reference &rhs); RValue operator=(int64_t rhs); RValue operator=(RValue rhs); // RValue operator=(RValue rhs); RValue operator=(const Long &rhs); RValue operator=(const Reference &rhs); // RValue operator=(const ULong &rhs); // RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); // RValue operator&(RValue lhs, RValue rhs); // RValue operator|(RValue lhs, RValue rhs); // RValue operator^(RValue lhs, RValue rhs); // RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(Long &lhs, RValue rhs); RValue operator-=(Long &lhs, RValue rhs); // RValue operator*=(Long &lhs, RValue rhs); // RValue operator/=(Long &lhs, RValue rhs); // RValue operator%=(Long &lhs, RValue rhs); // RValue operator&=(Long &lhs, RValue rhs); // RValue operator|=(Long &lhs, RValue rhs); // RValue operator^=(Long &lhs, RValue rhs); // RValue operator<<=(Long &lhs, RValue rhs); // RValue operator>>=(Long &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); // RValue operator~(RValue val); // RValue operator++(Long &val, int); // Post-increment // const Long &operator++(Long &val); // Pre-increment // RValue operator--(Long &val, int); // Post-decrement // const Long &operator--(Long &val); // Pre-decrement // RValue operator<(RValue lhs, RValue rhs); // RValue operator<=(RValue lhs, RValue rhs); // RValue operator>(RValue lhs, RValue rhs); // RValue operator>=(RValue lhs, RValue rhs); // RValue operator!=(RValue lhs, RValue rhs); // RValue operator==(RValue lhs, RValue rhs); // RValue RoundLong(RValue cast); RValue AddAtomic(RValue> x, RValue y); class UInt : public LValue { public: UInt(Argument argument); explicit UInt(RValue cast); explicit UInt(RValue cast); explicit UInt(RValue cast); UInt() = default; UInt(int x); UInt(unsigned int x); UInt(RValue rhs); UInt(RValue rhs); UInt(const UInt &rhs); UInt(const Int &rhs); UInt(const Reference &rhs); UInt(const Reference &rhs); RValue operator=(unsigned int rhs); RValue operator=(RValue rhs); RValue operator=(RValue rhs); RValue operator=(const UInt &rhs); RValue operator=(const Int &rhs); RValue operator=(const Reference &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(UInt &lhs, RValue rhs); RValue operator-=(UInt &lhs, RValue rhs); RValue operator*=(UInt &lhs, RValue rhs); RValue operator/=(UInt &lhs, RValue rhs); RValue operator%=(UInt &lhs, RValue rhs); RValue operator&=(UInt &lhs, RValue rhs); RValue operator|=(UInt &lhs, RValue rhs); RValue operator^=(UInt &lhs, RValue rhs); RValue operator<<=(UInt &lhs, RValue rhs); RValue operator>>=(UInt &lhs, RValue rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); RValue operator++(UInt &val, int); // Post-increment const UInt &operator++(UInt &val); // Pre-increment RValue operator--(UInt &val, int); // Post-decrement const UInt &operator--(UInt &val); // Pre-decrement RValue operator<(RValue lhs, RValue rhs); RValue operator<=(RValue lhs, RValue rhs); RValue operator>(RValue lhs, RValue rhs); RValue operator>=(RValue lhs, RValue rhs); RValue operator!=(RValue lhs, RValue rhs); RValue operator==(RValue lhs, RValue rhs); RValue Max(RValue x, RValue y); RValue Min(RValue x, RValue y); RValue Clamp(RValue x, RValue min, RValue max); RValue AddAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue SubAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue AndAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue OrAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue XorAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue MinAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue MaxAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue MinAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue MaxAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue ExchangeAtomic(RValue> x, RValue y, std::memory_order memoryOrder); RValue CompareExchangeAtomic(RValue> x, RValue y, RValue compare, std::memory_order memoryOrderEqual, std::memory_order memoryOrderUnequal); // RValue RoundUInt(RValue cast); class Int2 : public LValue { public: // explicit Int2(RValue cast); explicit Int2(RValue cast); Int2() = default; Int2(int x, int y); Int2(RValue rhs); Int2(const Int2 &rhs); Int2(const Reference &rhs); Int2(RValue lo, RValue hi); RValue operator=(RValue rhs); RValue operator=(const Int2 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, unsigned char rhs); RValue operator>>(RValue lhs, unsigned char rhs); RValue operator+=(Int2 &lhs, RValue rhs); RValue operator-=(Int2 &lhs, RValue rhs); // RValue operator*=(Int2 &lhs, RValue rhs); // RValue operator/=(Int2 &lhs, RValue rhs); // RValue operator%=(Int2 &lhs, RValue rhs); RValue operator&=(Int2 &lhs, RValue rhs); RValue operator|=(Int2 &lhs, RValue rhs); RValue operator^=(Int2 &lhs, RValue rhs); RValue operator<<=(Int2 &lhs, unsigned char rhs); RValue operator>>=(Int2 &lhs, unsigned char rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(Int2 &val, int); // Post-increment // const Int2 &operator++(Int2 &val); // Pre-increment // RValue operator--(Int2 &val, int); // Post-decrement // const Int2 &operator--(Int2 &val); // Pre-decrement // RValue operator<(RValue lhs, RValue rhs); // RValue operator<=(RValue lhs, RValue rhs); // RValue operator>(RValue lhs, RValue rhs); // RValue operator>=(RValue lhs, RValue rhs); // RValue operator!=(RValue lhs, RValue rhs); // RValue operator==(RValue lhs, RValue rhs); // RValue RoundInt(RValue cast); RValue UnpackLow(RValue x, RValue y); RValue UnpackHigh(RValue x, RValue y); RValue Extract(RValue val, int i); RValue Insert(RValue val, RValue element, int i); class UInt2 : public LValue { public: UInt2() = default; UInt2(unsigned int x, unsigned int y); UInt2(RValue rhs); UInt2(const UInt2 &rhs); UInt2(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const UInt2 &rhs); RValue operator=(const Reference &rhs); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, unsigned char rhs); RValue operator>>(RValue lhs, unsigned char rhs); RValue operator+=(UInt2 &lhs, RValue rhs); RValue operator-=(UInt2 &lhs, RValue rhs); // RValue operator*=(UInt2 &lhs, RValue rhs); // RValue operator/=(UInt2 &lhs, RValue rhs); // RValue operator%=(UInt2 &lhs, RValue rhs); RValue operator&=(UInt2 &lhs, RValue rhs); RValue operator|=(UInt2 &lhs, RValue rhs); RValue operator^=(UInt2 &lhs, RValue rhs); RValue operator<<=(UInt2 &lhs, unsigned char rhs); RValue operator>>=(UInt2 &lhs, unsigned char rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(UInt2 &val, int); // Post-increment // const UInt2 &operator++(UInt2 &val); // Pre-increment // RValue operator--(UInt2 &val, int); // Post-decrement // const UInt2 &operator--(UInt2 &val); // Pre-decrement // RValue operator<(RValue lhs, RValue rhs); // RValue operator<=(RValue lhs, RValue rhs); // RValue operator>(RValue lhs, RValue rhs); // RValue operator>=(RValue lhs, RValue rhs); // RValue operator!=(RValue lhs, RValue rhs); // RValue operator==(RValue lhs, RValue rhs); // RValue RoundInt(RValue cast); RValue Extract(RValue val, int i); RValue Insert(RValue val, RValue element, int i); template struct Scalar; template struct XYZW; template class Swizzle2 { friend Vector4; public: operator RValue() const; private: Vector4 *parent; }; template class Swizzle4 { public: operator RValue() const; private: Vector4 *parent; }; template class SwizzleMask4 { friend XYZW; public: operator RValue() const; RValue operator=(RValue rhs); RValue operator=(RValue::Type> rhs); private: Vector4 *parent; }; template<> struct Scalar { using Type = Float; }; template<> struct Scalar { using Type = Int; }; template<> struct Scalar { using Type = UInt; }; template class SwizzleMask1 { public: operator RValue::Type>() const; operator RValue() const; RValue operator=(float x); RValue operator=(RValue rhs); RValue operator=(RValue::Type> rhs); private: Vector4 *parent; }; template class SwizzleMask2 { friend class Float4; public: operator RValue() const; RValue operator=(RValue rhs); private: Float4 *parent; }; template struct XYZW { friend Vector4; private: XYZW(Vector4 *parent) { xyzw.parent = parent; } public: union { SwizzleMask1 x; SwizzleMask1 y; SwizzleMask1 z; SwizzleMask1 w; Swizzle2 xx; Swizzle2 yx; Swizzle2 zx; Swizzle2 wx; SwizzleMask2 xy; Swizzle2 yy; Swizzle2 zy; Swizzle2 wy; SwizzleMask2 xz; SwizzleMask2 yz; Swizzle2 zz; Swizzle2 wz; SwizzleMask2 xw; SwizzleMask2 yw; SwizzleMask2 zw; Swizzle2 ww; Swizzle4 xxx; Swizzle4 yxx; Swizzle4 zxx; Swizzle4 wxx; Swizzle4 xyx; Swizzle4 yyx; Swizzle4 zyx; Swizzle4 wyx; Swizzle4 xzx; Swizzle4 yzx; Swizzle4 zzx; Swizzle4 wzx; Swizzle4 xwx; Swizzle4 ywx; Swizzle4 zwx; Swizzle4 wwx; Swizzle4 xxy; Swizzle4 yxy; Swizzle4 zxy; Swizzle4 wxy; Swizzle4 xyy; Swizzle4 yyy; Swizzle4 zyy; Swizzle4 wyy; Swizzle4 xzy; Swizzle4 yzy; Swizzle4 zzy; Swizzle4 wzy; Swizzle4 xwy; Swizzle4 ywy; Swizzle4 zwy; Swizzle4 wwy; Swizzle4 xxz; Swizzle4 yxz; Swizzle4 zxz; Swizzle4 wxz; SwizzleMask4 xyz; Swizzle4 yyz; Swizzle4 zyz; Swizzle4 wyz; Swizzle4 xzz; Swizzle4 yzz; Swizzle4 zzz; Swizzle4 wzz; Swizzle4 xwz; Swizzle4 ywz; Swizzle4 zwz; Swizzle4 wwz; Swizzle4 xxw; Swizzle4 yxw; Swizzle4 zxw; Swizzle4 wxw; SwizzleMask4 xyw; Swizzle4 yyw; Swizzle4 zyw; Swizzle4 wyw; SwizzleMask4 xzw; SwizzleMask4 yzw; Swizzle4 zzw; Swizzle4 wzw; Swizzle4 xww; Swizzle4 yww; Swizzle4 zww; Swizzle4 www; Swizzle4 xxxx; Swizzle4 yxxx; Swizzle4 zxxx; Swizzle4 wxxx; Swizzle4 xyxx; Swizzle4 yyxx; Swizzle4 zyxx; Swizzle4 wyxx; Swizzle4 xzxx; Swizzle4 yzxx; Swizzle4 zzxx; Swizzle4 wzxx; Swizzle4 xwxx; Swizzle4 ywxx; Swizzle4 zwxx; Swizzle4 wwxx; Swizzle4 xxyx; Swizzle4 yxyx; Swizzle4 zxyx; Swizzle4 wxyx; Swizzle4 xyyx; Swizzle4 yyyx; Swizzle4 zyyx; Swizzle4 wyyx; Swizzle4 xzyx; Swizzle4 yzyx; Swizzle4 zzyx; Swizzle4 wzyx; Swizzle4 xwyx; Swizzle4 ywyx; Swizzle4 zwyx; Swizzle4 wwyx; Swizzle4 xxzx; Swizzle4 yxzx; Swizzle4 zxzx; Swizzle4 wxzx; Swizzle4 xyzx; Swizzle4 yyzx; Swizzle4 zyzx; Swizzle4 wyzx; Swizzle4 xzzx; Swizzle4 yzzx; Swizzle4 zzzx; Swizzle4 wzzx; Swizzle4 xwzx; Swizzle4 ywzx; Swizzle4 zwzx; Swizzle4 wwzx; Swizzle4 xxwx; Swizzle4 yxwx; Swizzle4 zxwx; Swizzle4 wxwx; Swizzle4 xywx; Swizzle4 yywx; Swizzle4 zywx; Swizzle4 wywx; Swizzle4 xzwx; Swizzle4 yzwx; Swizzle4 zzwx; Swizzle4 wzwx; Swizzle4 xwwx; Swizzle4 ywwx; Swizzle4 zwwx; Swizzle4 wwwx; Swizzle4 xxxy; Swizzle4 yxxy; Swizzle4 zxxy; Swizzle4 wxxy; Swizzle4 xyxy; Swizzle4 yyxy; Swizzle4 zyxy; Swizzle4 wyxy; Swizzle4 xzxy; Swizzle4 yzxy; Swizzle4 zzxy; Swizzle4 wzxy; Swizzle4 xwxy; Swizzle4 ywxy; Swizzle4 zwxy; Swizzle4 wwxy; Swizzle4 xxyy; Swizzle4 yxyy; Swizzle4 zxyy; Swizzle4 wxyy; Swizzle4 xyyy; Swizzle4 yyyy; Swizzle4 zyyy; Swizzle4 wyyy; Swizzle4 xzyy; Swizzle4 yzyy; Swizzle4 zzyy; Swizzle4 wzyy; Swizzle4 xwyy; Swizzle4 ywyy; Swizzle4 zwyy; Swizzle4 wwyy; Swizzle4 xxzy; Swizzle4 yxzy; Swizzle4 zxzy; Swizzle4 wxzy; Swizzle4 xyzy; Swizzle4 yyzy; Swizzle4 zyzy; Swizzle4 wyzy; Swizzle4 xzzy; Swizzle4 yzzy; Swizzle4 zzzy; Swizzle4 wzzy; Swizzle4 xwzy; Swizzle4 ywzy; Swizzle4 zwzy; Swizzle4 wwzy; Swizzle4 xxwy; Swizzle4 yxwy; Swizzle4 zxwy; Swizzle4 wxwy; Swizzle4 xywy; Swizzle4 yywy; Swizzle4 zywy; Swizzle4 wywy; Swizzle4 xzwy; Swizzle4 yzwy; Swizzle4 zzwy; Swizzle4 wzwy; Swizzle4 xwwy; Swizzle4 ywwy; Swizzle4 zwwy; Swizzle4 wwwy; Swizzle4 xxxz; Swizzle4 yxxz; Swizzle4 zxxz; Swizzle4 wxxz; Swizzle4 xyxz; Swizzle4 yyxz; Swizzle4 zyxz; Swizzle4 wyxz; Swizzle4 xzxz; Swizzle4 yzxz; Swizzle4 zzxz; Swizzle4 wzxz; Swizzle4 xwxz; Swizzle4 ywxz; Swizzle4 zwxz; Swizzle4 wwxz; Swizzle4 xxyz; Swizzle4 yxyz; Swizzle4 zxyz; Swizzle4 wxyz; Swizzle4 xyyz; Swizzle4 yyyz; Swizzle4 zyyz; Swizzle4 wyyz; Swizzle4 xzyz; Swizzle4 yzyz; Swizzle4 zzyz; Swizzle4 wzyz; Swizzle4 xwyz; Swizzle4 ywyz; Swizzle4 zwyz; Swizzle4 wwyz; Swizzle4 xxzz; Swizzle4 yxzz; Swizzle4 zxzz; Swizzle4 wxzz; Swizzle4 xyzz; Swizzle4 yyzz; Swizzle4 zyzz; Swizzle4 wyzz; Swizzle4 xzzz; Swizzle4 yzzz; Swizzle4 zzzz; Swizzle4 wzzz; Swizzle4 xwzz; Swizzle4 ywzz; Swizzle4 zwzz; Swizzle4 wwzz; Swizzle4 xxwz; Swizzle4 yxwz; Swizzle4 zxwz; Swizzle4 wxwz; Swizzle4 xywz; Swizzle4 yywz; Swizzle4 zywz; Swizzle4 wywz; Swizzle4 xzwz; Swizzle4 yzwz; Swizzle4 zzwz; Swizzle4 wzwz; Swizzle4 xwwz; Swizzle4 ywwz; Swizzle4 zwwz; Swizzle4 wwwz; Swizzle4 xxxw; Swizzle4 yxxw; Swizzle4 zxxw; Swizzle4 wxxw; Swizzle4 xyxw; Swizzle4 yyxw; Swizzle4 zyxw; Swizzle4 wyxw; Swizzle4 xzxw; Swizzle4 yzxw; Swizzle4 zzxw; Swizzle4 wzxw; Swizzle4 xwxw; Swizzle4 ywxw; Swizzle4 zwxw; Swizzle4 wwxw; Swizzle4 xxyw; Swizzle4 yxyw; Swizzle4 zxyw; Swizzle4 wxyw; Swizzle4 xyyw; Swizzle4 yyyw; Swizzle4 zyyw; Swizzle4 wyyw; Swizzle4 xzyw; Swizzle4 yzyw; Swizzle4 zzyw; Swizzle4 wzyw; Swizzle4 xwyw; Swizzle4 ywyw; Swizzle4 zwyw; Swizzle4 wwyw; Swizzle4 xxzw; Swizzle4 yxzw; Swizzle4 zxzw; Swizzle4 wxzw; SwizzleMask4 xyzw; Swizzle4 yyzw; Swizzle4 zyzw; Swizzle4 wyzw; Swizzle4 xzzw; Swizzle4 yzzw; Swizzle4 zzzw; Swizzle4 wzzw; Swizzle4 xwzw; Swizzle4 ywzw; Swizzle4 zwzw; Swizzle4 wwzw; Swizzle4 xxww; Swizzle4 yxww; Swizzle4 zxww; Swizzle4 wxww; Swizzle4 xyww; Swizzle4 yyww; Swizzle4 zyww; Swizzle4 wyww; Swizzle4 xzww; Swizzle4 yzww; Swizzle4 zzww; Swizzle4 wzww; Swizzle4 xwww; Swizzle4 ywww; Swizzle4 zwww; Swizzle4 wwww; }; }; class Int4 : public LValue, public XYZW { public: explicit Int4(RValue cast); explicit Int4(RValue cast); explicit Int4(RValue cast); explicit Int4(RValue cast); explicit Int4(RValue cast); Int4(); Int4(int xyzw); Int4(int x, int yzw); Int4(int x, int y, int zw); Int4(int x, int y, int z, int w); Int4(RValue rhs); Int4(const Int4 &rhs); Int4(const Reference &rhs); Int4(RValue rhs); Int4(const UInt4 &rhs); Int4(const Reference &rhs); Int4(RValue lo, RValue hi); Int4(RValue rhs); Int4(const Int &rhs); Int4(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const Int4 &rhs); RValue operator=(const Reference &rhs); static Type *type(); private: void constant(int x, int y, int z, int w); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, unsigned char rhs); RValue operator>>(RValue lhs, unsigned char rhs); RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(Int4 &lhs, RValue rhs); RValue operator-=(Int4 &lhs, RValue rhs); RValue operator*=(Int4 &lhs, RValue rhs); // RValue operator/=(Int4 &lhs, RValue rhs); // RValue operator%=(Int4 &lhs, RValue rhs); RValue operator&=(Int4 &lhs, RValue rhs); RValue operator|=(Int4 &lhs, RValue rhs); RValue operator^=(Int4 &lhs, RValue rhs); RValue operator<<=(Int4 &lhs, unsigned char rhs); RValue operator>>=(Int4 &lhs, unsigned char rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(Int4 &val, int); // Post-increment // const Int4 &operator++(Int4 &val); // Pre-increment // RValue operator--(Int4 &val, int); // Post-decrement // const Int4 &operator--(Int4 &val); // Pre-decrement // RValue operator<(RValue lhs, RValue rhs); // RValue operator<=(RValue lhs, RValue rhs); // RValue operator>(RValue lhs, RValue rhs); // RValue operator>=(RValue lhs, RValue rhs); // RValue operator!=(RValue lhs, RValue rhs); // RValue operator==(RValue lhs, RValue rhs); inline RValue operator+(RValue lhs, RValue rhs) { return Int4(lhs) + rhs; } inline RValue operator+(RValue lhs, RValue rhs) { return lhs + Int4(rhs); } RValue CmpEQ(RValue x, RValue y); RValue CmpLT(RValue x, RValue y); RValue CmpLE(RValue x, RValue y); RValue CmpNEQ(RValue x, RValue y); RValue CmpNLT(RValue x, RValue y); RValue CmpNLE(RValue x, RValue y); inline RValue CmpGT(RValue x, RValue y) { return CmpNLE(x, y); } inline RValue CmpGE(RValue x, RValue y) { return CmpNLT(x, y); } RValue Max(RValue x, RValue y); RValue Min(RValue x, RValue y); // Convert to nearest integer. If a converted value is outside of the integer // range, the returned result is undefined. RValue RoundInt(RValue cast); // Rounds to the nearest integer, but clamps very large values to an // implementation-dependent range. // Specifically, on x86, values larger than 2147483583.0 are converted to // 2147483583 (0x7FFFFFBF) instead of producing 0x80000000. RValue RoundIntClamped(RValue cast); RValue PackSigned(RValue x, RValue y); RValue PackUnsigned(RValue x, RValue y); RValue Extract(RValue val, int i); RValue Insert(RValue val, RValue element, int i); RValue SignMask(RValue x); RValue Swizzle(RValue x, uint16_t select); RValue Shuffle(RValue x, RValue y, uint16_t select); RValue MulHigh(RValue x, RValue y); class UInt4 : public LValue, public XYZW { public: explicit UInt4(RValue cast); UInt4(); UInt4(int xyzw); UInt4(int x, int yzw); UInt4(int x, int y, int zw); UInt4(int x, int y, int z, int w); UInt4(RValue rhs); UInt4(const UInt4 &rhs); UInt4(const Reference &rhs); UInt4(RValue rhs); UInt4(const Int4 &rhs); UInt4(const Reference &rhs); UInt4(RValue lo, RValue hi); UInt4(RValue rhs); UInt4(const UInt &rhs); UInt4(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const UInt4 &rhs); RValue operator=(const Reference &rhs); static Type *type(); private: void constant(int x, int y, int z, int w); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator&(RValue lhs, RValue rhs); RValue operator|(RValue lhs, RValue rhs); RValue operator^(RValue lhs, RValue rhs); RValue operator<<(RValue lhs, unsigned char rhs); RValue operator>>(RValue lhs, unsigned char rhs); RValue operator<<(RValue lhs, RValue rhs); RValue operator>>(RValue lhs, RValue rhs); RValue operator+=(UInt4 &lhs, RValue rhs); RValue operator-=(UInt4 &lhs, RValue rhs); RValue operator*=(UInt4 &lhs, RValue rhs); // RValue operator/=(UInt4 &lhs, RValue rhs); // RValue operator%=(UInt4 &lhs, RValue rhs); RValue operator&=(UInt4 &lhs, RValue rhs); RValue operator|=(UInt4 &lhs, RValue rhs); RValue operator^=(UInt4 &lhs, RValue rhs); RValue operator<<=(UInt4 &lhs, unsigned char rhs); RValue operator>>=(UInt4 &lhs, unsigned char rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator~(RValue val); // RValue operator++(UInt4 &val, int); // Post-increment // const UInt4 &operator++(UInt4 &val); // Pre-increment // RValue operator--(UInt4 &val, int); // Post-decrement // const UInt4 &operator--(UInt4 &val); // Pre-decrement // RValue operator<(RValue lhs, RValue rhs); // RValue operator<=(RValue lhs, RValue rhs); // RValue operator>(RValue lhs, RValue rhs); // RValue operator>=(RValue lhs, RValue rhs); // RValue operator!=(RValue lhs, RValue rhs); // RValue operator==(RValue lhs, RValue rhs); RValue CmpEQ(RValue x, RValue y); RValue CmpLT(RValue x, RValue y); RValue CmpLE(RValue x, RValue y); RValue CmpNEQ(RValue x, RValue y); RValue CmpNLT(RValue x, RValue y); RValue CmpNLE(RValue x, RValue y); inline RValue CmpGT(RValue x, RValue y) { return CmpNLE(x, y); } inline RValue CmpGE(RValue x, RValue y) { return CmpNLT(x, y); } RValue Max(RValue x, RValue y); RValue Min(RValue x, RValue y); RValue MulHigh(RValue x, RValue y); RValue Extract(RValue val, int i); RValue Insert(RValue val, RValue element, int i); // RValue RoundInt(RValue cast); RValue Swizzle(RValue x, uint16_t select); RValue Shuffle(RValue x, RValue y, uint16_t select); class Half : public LValue { public: explicit Half(RValue cast); static Type *type(); }; class Float : public LValue { public: explicit Float(RValue cast); explicit Float(RValue cast); explicit Float(RValue cast); Float() = default; Float(float x); Float(RValue rhs); Float(const Float &rhs); Float(const Reference &rhs); Float(Argument argument); template Float(const SwizzleMask1 &rhs); RValue operator=(float rhs); RValue operator=(RValue rhs); RValue operator=(const Float &rhs); RValue operator=(const Reference &rhs); template RValue operator=(const SwizzleMask1 &rhs); static Float infinity(); static Type *type(); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator+=(Float &lhs, RValue rhs); RValue operator-=(Float &lhs, RValue rhs); RValue operator*=(Float &lhs, RValue rhs); RValue operator/=(Float &lhs, RValue rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue operator<(RValue lhs, RValue rhs); RValue operator<=(RValue lhs, RValue rhs); RValue operator>(RValue lhs, RValue rhs); RValue operator>=(RValue lhs, RValue rhs); RValue operator!=(RValue lhs, RValue rhs); RValue operator==(RValue lhs, RValue rhs); RValue Abs(RValue x); RValue Max(RValue x, RValue y); RValue Min(RValue x, RValue y); // Deprecated: use Rcp // TODO(b/147516027): Remove when GLES frontend is removed RValue Rcp_pp(RValue val, bool exactAtPow2 = false); // Deprecated: use RcpSqrt // TODO(b/147516027): Remove when GLES frontend is removed RValue RcpSqrt_pp(RValue val); RValue Rcp(RValue x, Precision p = Precision::Full, bool finite = false, bool exactAtPow2 = false); RValue RcpSqrt(RValue x, Precision p = Precision::Full); RValue Sqrt(RValue x); // RValue IsInf(RValue x); // RValue IsNan(RValue x); RValue Round(RValue x); RValue Trunc(RValue x); RValue Frac(RValue x); RValue Floor(RValue x); RValue Ceil(RValue x); // Trigonometric functions // TODO: Currently unimplemented for Subzero. // RValue Sin(RValue x); // RValue Cos(RValue x); // RValue Tan(RValue x); // RValue Asin(RValue x); // RValue Acos(RValue x); // RValue Atan(RValue x); // RValue Sinh(RValue x); // RValue Cosh(RValue x); // RValue Tanh(RValue x); // RValue Asinh(RValue x); // RValue Acosh(RValue x); // RValue Atanh(RValue x); // RValue Atan2(RValue x, RValue y); // Exponential functions // TODO: Currently unimplemented for Subzero. // RValue Pow(RValue x, RValue y); // RValue Exp(RValue x); // RValue Log(RValue x); RValue Exp2(RValue x); RValue Log2(RValue x); class Float2 : public LValue { public: // explicit Float2(RValue cast); // explicit Float2(RValue cast); // explicit Float2(RValue cast); // explicit Float2(RValue cast); // explicit Float2(RValue cast); explicit Float2(RValue cast); Float2() = default; // Float2(float x, float y); // Float2(RValue rhs); // Float2(const Float2 &rhs); // Float2(const Reference &rhs); // Float2(RValue rhs); // Float2(const Float &rhs); // Float2(const Reference &rhs); // template // Float2(const SwizzleMask1 &rhs); // RValue operator=(float replicate); // RValue operator=(RValue rhs); // RValue operator=(const Float2 &rhs); // RValue operator=(const Reference &rhs); // RValue operator=(RValue rhs); // RValue operator=(const Float &rhs); // RValue operator=(const Reference &rhs); // template // RValue operator=(const SwizzleMask1 &rhs); static Type *type(); }; // RValue operator+(RValue lhs, RValue rhs); // RValue operator-(RValue lhs, RValue rhs); // RValue operator*(RValue lhs, RValue rhs); // RValue operator/(RValue lhs, RValue rhs); // RValue operator%(RValue lhs, RValue rhs); // RValue operator+=(Float2 &lhs, RValue rhs); // RValue operator-=(Float2 &lhs, RValue rhs); // RValue operator*=(Float2 &lhs, RValue rhs); // RValue operator/=(Float2 &lhs, RValue rhs); // RValue operator%=(Float2 &lhs, RValue rhs); // RValue operator+(RValue val); // RValue operator-(RValue val); // RValue Abs(RValue x); // RValue Max(RValue x, RValue y); // RValue Min(RValue x, RValue y); // RValue Swizzle(RValue x, uint16_t select); // RValue Mask(Float2 &lhs, RValue rhs, uint16_t select); class Float4 : public LValue, public XYZW { public: explicit Float4(RValue cast); explicit Float4(RValue cast); explicit Float4(RValue cast); explicit Float4(RValue cast); explicit Float4(RValue cast); explicit Float4(RValue cast); Float4(); Float4(float xyzw); Float4(float x, float yzw); Float4(float x, float y, float zw); Float4(float x, float y, float z, float w); Float4(RValue rhs); Float4(const Float4 &rhs); Float4(const Reference &rhs); Float4(RValue rhs); Float4(const Float &rhs); Float4(const Reference &rhs); template Float4(const SwizzleMask1 &rhs); template Float4(const Swizzle4 &rhs); template Float4(const Swizzle2 &x, const Swizzle2 &y); template Float4(const SwizzleMask2 &x, const Swizzle2 &y); template Float4(const Swizzle2 &x, const SwizzleMask2 &y); template Float4(const SwizzleMask2 &x, const SwizzleMask2 &y); Float4(RValue lo, RValue hi); RValue operator=(float replicate); RValue operator=(RValue rhs); RValue operator=(const Float4 &rhs); RValue operator=(const Reference &rhs); RValue operator=(RValue rhs); RValue operator=(const Float &rhs); RValue operator=(const Reference &rhs); template RValue operator=(const SwizzleMask1 &rhs); template RValue operator=(const Swizzle4 &rhs); static Float4 infinity(); static Type *type(); private: void constant(float x, float y, float z, float w); }; RValue operator+(RValue lhs, RValue rhs); RValue operator-(RValue lhs, RValue rhs); RValue operator*(RValue lhs, RValue rhs); RValue operator/(RValue lhs, RValue rhs); RValue operator%(RValue lhs, RValue rhs); RValue operator+=(Float4 &lhs, RValue rhs); RValue operator-=(Float4 &lhs, RValue rhs); RValue operator*=(Float4 &lhs, RValue rhs); RValue operator/=(Float4 &lhs, RValue rhs); RValue operator%=(Float4 &lhs, RValue rhs); RValue operator+(RValue val); RValue operator-(RValue val); RValue Abs(RValue x); RValue Max(RValue x, RValue y); RValue Min(RValue x, RValue y); // Deprecated: use Rcp // TODO(b/147516027): Remove when GLES frontend is removed RValue Rcp_pp(RValue val, bool exactAtPow2 = false); // Deprecated: use RcpSqrt // TODO(b/147516027): Remove when GLES frontend is removed RValue RcpSqrt_pp(RValue val); RValue Rcp(RValue x, Precision p = Precision::Full, bool finite = false, bool exactAtPow2 = false); RValue RcpSqrt(RValue x, Precision p = Precision::Full); RValue Sqrt(RValue x); RValue Insert(RValue val, RValue element, int i); RValue Extract(RValue x, int i); RValue Swizzle(RValue x, uint16_t select); RValue Shuffle(RValue x, RValue y, uint16_t select); RValue ShuffleLowHigh(RValue x, RValue y, uint16_t imm); RValue UnpackLow(RValue x, RValue y); RValue UnpackHigh(RValue x, RValue y); RValue Mask(Float4 &lhs, RValue rhs, uint16_t select); RValue SignMask(RValue x); // Ordered comparison functions RValue CmpEQ(RValue x, RValue y); RValue CmpLT(RValue x, RValue y); RValue CmpLE(RValue x, RValue y); RValue CmpNEQ(RValue x, RValue y); RValue CmpNLT(RValue x, RValue y); RValue CmpNLE(RValue x, RValue y); inline RValue CmpGT(RValue x, RValue y) { return CmpNLE(x, y); } inline RValue CmpGE(RValue x, RValue y) { return CmpNLT(x, y); } // Unordered comparison functions RValue CmpUEQ(RValue x, RValue y); RValue CmpULT(RValue x, RValue y); RValue CmpULE(RValue x, RValue y); RValue CmpUNEQ(RValue x, RValue y); RValue CmpUNLT(RValue x, RValue y); RValue CmpUNLE(RValue x, RValue y); inline RValue CmpUGT(RValue x, RValue y) { return CmpUNLE(x, y); } inline RValue CmpUGE(RValue x, RValue y) { return CmpUNLT(x, y); } RValue IsInf(RValue x); RValue IsNan(RValue x); RValue Round(RValue x); RValue Trunc(RValue x); RValue Frac(RValue x); RValue Floor(RValue x); RValue Ceil(RValue x); // Trigonometric functions // TODO: Currently unimplemented for Subzero. RValue Sin(RValue x); RValue Cos(RValue x); RValue Tan(RValue x); RValue Asin(RValue x, Precision p); RValue Acos(RValue x, Precision p); RValue Atan(RValue x); RValue Sinh(RValue x); RValue Cosh(RValue x); RValue Tanh(RValue x); RValue Asinh(RValue x); RValue Acosh(RValue x); RValue Atanh(RValue x); RValue Atan2(RValue x, RValue y); // Exponential functions // TODO: Currently unimplemented for Subzero. RValue Pow(RValue x, RValue y); RValue Exp(RValue x); RValue Log(RValue x); RValue Exp2(RValue x); RValue Log2(RValue x); // Bit Manipulation functions. // TODO: Currently unimplemented for Subzero. // Count leading zeros. // Returns 32 when: !isZeroUndef && x == 0. // Returns an undefined value when: isZeroUndef && x == 0. RValue Ctlz(RValue x, bool isZeroUndef); RValue Ctlz(RValue x, bool isZeroUndef); // Count trailing zeros. // Returns 32 when: !isZeroUndef && x == 0. // Returns an undefined value when: isZeroUndef && x == 0. RValue Cttz(RValue x, bool isZeroUndef); RValue Cttz(RValue x, bool isZeroUndef); template class Pointer : public LValue> { public: template Pointer(RValue> pointerS, int alignment = 1) : alignment(alignment) { Value *pointerT = Nucleus::createBitCast(pointerS.value(), Nucleus::getPointerType(T::type())); this->storeValue(pointerT); } template Pointer(const Pointer &pointer, int alignment = 1) : alignment(alignment) { Value *pointerS = pointer.loadValue(); Value *pointerT = Nucleus::createBitCast(pointerS, Nucleus::getPointerType(T::type())); this->storeValue(pointerT); } Pointer(Argument> argument); Pointer(); Pointer(RValue> rhs); Pointer(const Pointer &rhs); Pointer(const Reference> &rhs); Pointer(std::nullptr_t); RValue> operator=(RValue> rhs); RValue> operator=(const Pointer &rhs); RValue> operator=(const Reference> &rhs); RValue> operator=(std::nullptr_t); Reference operator*() const; Reference operator[](int index) const; Reference operator[](unsigned int index) const; Reference operator[](RValue index) const; Reference operator[](RValue index) const; static Type *type(); private: const int alignment; }; RValue> operator+(RValue> lhs, int offset); RValue> operator+(RValue> lhs, RValue offset); RValue> operator+(RValue> lhs, RValue offset); RValue> operator+=(Pointer &lhs, int offset); RValue> operator+=(Pointer &lhs, RValue offset); RValue> operator+=(Pointer &lhs, RValue offset); RValue> operator-(RValue> lhs, int offset); RValue> operator-(RValue> lhs, RValue offset); RValue> operator-(RValue> lhs, RValue offset); RValue> operator-=(Pointer &lhs, int offset); RValue> operator-=(Pointer &lhs, RValue offset); RValue> operator-=(Pointer &lhs, RValue offset); template RValue operator==(const Pointer &lhs, const Pointer &rhs) { return RValue(Nucleus::createICmpEQ(lhs.loadValue(), rhs.loadValue())); } template RValue operator!=(const Pointer &lhs, const Pointer &rhs) { return RValue(Nucleus::createICmpNE(lhs.loadValue(), rhs.loadValue())); } template RValue Load(RValue> pointer, unsigned int alignment, bool atomic, std::memory_order memoryOrder) { return RValue(Nucleus::createLoad(pointer.value(), T::type(), false, alignment, atomic, memoryOrder)); } template RValue Load(Pointer pointer, unsigned int alignment, bool atomic, std::memory_order memoryOrder) { return Load(RValue>(pointer), alignment, atomic, memoryOrder); } // TODO: Use SIMD to template these. // TODO(b/155867273): These can be undeprecated if implemented for Subzero. [[deprecated]] RValue MaskedLoad(RValue> base, RValue mask, unsigned int alignment, bool zeroMaskedLanes = false); [[deprecated]] RValue MaskedLoad(RValue> base, RValue mask, unsigned int alignment, bool zeroMaskedLanes = false); [[deprecated]] void MaskedStore(RValue> base, RValue val, RValue mask, unsigned int alignment); [[deprecated]] void MaskedStore(RValue> base, RValue val, RValue mask, unsigned int alignment); RValue Gather(RValue> base, RValue offsets, RValue mask, unsigned int alignment, bool zeroMaskedLanes = false); RValue Gather(RValue> base, RValue offsets, RValue mask, unsigned int alignment, bool zeroMaskedLanes = false); void Scatter(RValue> base, RValue val, RValue offsets, RValue mask, unsigned int alignment); void Scatter(RValue> base, RValue val, RValue offsets, RValue mask, unsigned int alignment); template void Store(RValue value, RValue> pointer, unsigned int alignment, bool atomic, std::memory_order memoryOrder) { Nucleus::createStore(value.value(), pointer.value(), T::type(), false, alignment, atomic, memoryOrder); } template void Store(RValue value, Pointer pointer, unsigned int alignment, bool atomic, std::memory_order memoryOrder) { Store(value, RValue>(pointer), alignment, atomic, memoryOrder); } template void Store(T value, Pointer pointer, unsigned int alignment, bool atomic, std::memory_order memoryOrder) { Store(RValue(value), RValue>(pointer), alignment, atomic, memoryOrder); } // Fence adds a memory barrier that enforces ordering constraints on memory // operations. memoryOrder can only be one of: // std::memory_order_acquire, std::memory_order_release, // std::memory_order_acq_rel, or std::memory_order_seq_cst. void Fence(std::memory_order memoryOrder); template class Array : public LValue { public: Array(int size = S); Reference operator[](int index); Reference operator[](unsigned int index); Reference operator[](RValue index); Reference operator[](RValue index); // self() returns the this pointer to this Array object. // This function exists because operator&() is overloaded by LValue. inline Array *self() { return this; } }; // RValue> operator++(Array &val, int); // Post-increment // const Array &operator++(Array &val); // Pre-increment // RValue> operator--(Array &val, int); // Post-decrement // const Array &operator--(Array &val); // Pre-decrement void branch(RValue cmp, BasicBlock *bodyBB, BasicBlock *endBB); // ValueOf returns a rr::Value* for the given C-type, RValue, LValue // or Reference. template inline Value *ValueOf(const T &v) { return ReactorType::cast(v).loadValue(); } void Return(); template void Return(const T &ret) { static_assert(CanBeUsedAsReturn>::value, "Unsupported type for Return()"); Nucleus::createRet(ValueOf(ret)); // Place any unreachable instructions in an unreferenced block. Nucleus::setInsertBlock(Nucleus::createBasicBlock()); } // Generic template, leave undefined! template class Function; // Specialized for function types template class Function { // Static assert that the function signature is valid. static_assert(sizeof(AssertFunctionSignatureIsValid) >= 0, "Invalid function signature"); public: Function(); template Argument>::type> Arg() const { Value *arg = Nucleus::getArgument(index); return Argument>::type>(arg); } std::shared_ptr operator()(const char *name, ...); std::shared_ptr operator()(const Config::Edit &cfg, const char *name, ...); protected: std::unique_ptr core; std::vector arguments; }; template class Function : public Function { }; // FunctionT accepts a C-style function type template argument, allowing it to return a type-safe RoutineT wrapper template class FunctionT; template class FunctionT : public Function(CToReactorT...)> { public: // Type of base class using BaseType = Function(CToReactorT...)>; // Function type, e.g. void(int,float) using CFunctionType = Return(Arguments...); // Reactor function type, e.g. Void(Int, Float) using ReactorFunctionType = CToReactorT(CToReactorT...); // Returned RoutineT type using RoutineType = RoutineT; // Hide base implementations of operator() template RoutineType operator()(const char *name, VarArgs... varArgs) { return RoutineType(BaseType::operator()(name, std::forward(varArgs)...)); } template RoutineType operator()(const Config::Edit &cfg, const char *name, VarArgs... varArgs) { return RoutineType(BaseType::operator()(cfg, name, std::forward(varArgs)...)); } }; RValue Ticks(); } // namespace rr /* Inline implementations */ namespace rr { template LValue::LValue(int arraySize) : Variable(T::type(), arraySize) { #ifdef ENABLE_RR_DEBUG_INFO materialize(); #endif // ENABLE_RR_DEBUG_INFO } template RValue> LValue::operator&() { return RValue>(this->getBaseAddress()); } template Reference::Reference(Value *pointer, int alignment) : address(pointer) , alignment(alignment) { } template RValue Reference::operator=(RValue rhs) const { Nucleus::createStore(rhs.value(), address, T::type(), false, alignment); return rhs; } template RValue Reference::operator=(const Reference &ref) const { Value *tmp = Nucleus::createLoad(ref.address, T::type(), false, ref.alignment); Nucleus::createStore(tmp, address, T::type(), false, alignment); return RValue(tmp); } template RValue Reference::operator+=(RValue rhs) const { return *this = *this + rhs; } template Value *Reference::loadValue() const { return Nucleus::createLoad(address, T::type(), false, alignment); } template RValue Reference::load() const { return RValue(loadValue()); } template int Reference::getAlignment() const { return alignment; } template RValue::RValue(const RValue &rvalue) : val(rvalue.val) { RR_DEBUG_INFO_EMIT_VAR(val); } template RValue::RValue(Value *value) : val(value) { assert(Nucleus::createBitCast(value, T::type()) == value); // Run-time type should match T, so bitcast is no-op. RR_DEBUG_INFO_EMIT_VAR(val); } template RValue::RValue(const T &lvalue) : val(lvalue.loadValue()) { RR_DEBUG_INFO_EMIT_VAR(val); } template RValue::RValue(typename BoolLiteral::type i) : val(Nucleus::createConstantBool(i)) { RR_DEBUG_INFO_EMIT_VAR(val); } template RValue::RValue(typename IntLiteral::type i) : val(Nucleus::createConstantInt(i)) { RR_DEBUG_INFO_EMIT_VAR(val); } template RValue::RValue(typename FloatLiteral::type f) : val(Nucleus::createConstantFloat(f)) { RR_DEBUG_INFO_EMIT_VAR(val); } template RValue::RValue(const Reference &ref) : val(ref.loadValue()) { RR_DEBUG_INFO_EMIT_VAR(val); } template Swizzle2::operator RValue() const { RR_DEBUG_INFO_UPDATE_LOC(); Value *vector = parent->loadValue(); return Swizzle(RValue(vector), T); } template Swizzle4::operator RValue() const { RR_DEBUG_INFO_UPDATE_LOC(); Value *vector = parent->loadValue(); return Swizzle(RValue(vector), T); } template SwizzleMask4::operator RValue() const { RR_DEBUG_INFO_UPDATE_LOC(); Value *vector = parent->loadValue(); return Swizzle(RValue(vector), T); } template RValue SwizzleMask4::operator=(RValue rhs) { RR_DEBUG_INFO_UPDATE_LOC(); return Mask(*parent, rhs, T); } template RValue SwizzleMask4::operator=(RValue::Type> rhs) { RR_DEBUG_INFO_UPDATE_LOC(); return Mask(*parent, Vector4(rhs), T); } template SwizzleMask1::operator RValue::Type>() const // FIXME: Call a non-template function { RR_DEBUG_INFO_UPDATE_LOC(); return Extract(*parent, T & 0x3); } template SwizzleMask1::operator RValue() const { RR_DEBUG_INFO_UPDATE_LOC(); Value *vector = parent->loadValue(); return Swizzle(RValue(vector), T); } template RValue SwizzleMask1::operator=(float x) { RR_DEBUG_INFO_UPDATE_LOC(); return *parent = Insert(*parent, Float(x), T & 0x3); } template RValue SwizzleMask1::operator=(RValue rhs) { RR_DEBUG_INFO_UPDATE_LOC(); return Mask(*parent, Float4(rhs), T); } template RValue SwizzleMask1::operator=(RValue::Type> rhs) // FIXME: Call a non-template function { RR_DEBUG_INFO_UPDATE_LOC(); return *parent = Insert(*parent, rhs, T & 0x3); } template SwizzleMask2::operator RValue() const { RR_DEBUG_INFO_UPDATE_LOC(); Value *vector = parent->loadValue(); return Swizzle(RValue(vector), T); } template RValue SwizzleMask2::operator=(RValue rhs) { RR_DEBUG_INFO_UPDATE_LOC(); return Mask(*parent, Float4(rhs), T); } template Float::Float(const SwizzleMask1 &rhs) { *this = rhs.operator RValue(); } template RValue Float::operator=(const SwizzleMask1 &rhs) { return *this = rhs.operator RValue(); } template Float4::Float4(const SwizzleMask1 &rhs) : XYZW(this) { *this = rhs.operator RValue(); } template Float4::Float4(const Swizzle4 &rhs) : XYZW(this) { *this = rhs.operator RValue(); } template Float4::Float4(const Swizzle2 &x, const Swizzle2 &y) : XYZW(this) { RR_DEBUG_INFO_UPDATE_LOC(); *this = ShuffleLowHigh(*x.parent, *y.parent, (uint16_t(X) & 0xFF00u) | (uint16_t(Y >> 8) & 0x00FFu)); } template Float4::Float4(const SwizzleMask2 &x, const Swizzle2 &y) : XYZW(this) { RR_DEBUG_INFO_UPDATE_LOC(); *this = ShuffleLowHigh(*x.parent, *y.parent, (uint16_t(X) & 0xFF00u) | (uint16_t(Y >> 8) & 0x00FFu)); } template Float4::Float4(const Swizzle2 &x, const SwizzleMask2 &y) : XYZW(this) { RR_DEBUG_INFO_UPDATE_LOC(); *this = ShuffleLowHigh(*x.parent, *y.parent, (uint16_t(X) & 0xFF00u) | (uint16_t(Y >> 8) & 0x00FFu)); } template Float4::Float4(const SwizzleMask2 &x, const SwizzleMask2 &y) : XYZW(this) { RR_DEBUG_INFO_UPDATE_LOC(); *this = ShuffleLowHigh(*x.parent, *y.parent, (uint16_t(X) & 0xFF00u) | (uint16_t(Y >> 8) & 0x00FFu)); } template RValue Float4::operator=(const SwizzleMask1 &rhs) { return *this = rhs.operator RValue(); } template RValue Float4::operator=(const Swizzle4 &rhs) { return *this = rhs.operator RValue(); } // Returns a reactor pointer to the fixed-address ptr. RValue> ConstantPointer(void const *ptr); // Returns a reactor pointer to an immutable copy of the data of size bytes. RValue> ConstantData(void const *data, size_t size); template Pointer::Pointer(Argument> argument) : alignment(1) { this->store(argument.rvalue()); } template Pointer::Pointer() : alignment(1) {} template Pointer::Pointer(RValue> rhs) : alignment(1) { this->store(rhs); } template Pointer::Pointer(const Pointer &rhs) : alignment(rhs.alignment) { this->store(rhs.load()); } template Pointer::Pointer(const Reference> &rhs) : alignment(rhs.getAlignment()) { this->store(rhs.load()); } template Pointer::Pointer(std::nullptr_t) : alignment(1) { Value *value = Nucleus::createNullPointer(T::type()); this->storeValue(value); } template RValue> Pointer::operator=(RValue> rhs) { return this->store(rhs); } template RValue> Pointer::operator=(const Pointer &rhs) { return this->store(rhs.load()); } template RValue> Pointer::operator=(const Reference> &rhs) { return this->store(rhs.load()); } template RValue> Pointer::operator=(std::nullptr_t) { Value *value = Nucleus::createNullPointer(T::type()); this->storeValue(value); return RValue>(this); } template Reference Pointer::operator*() const { return Reference(this->loadValue(), alignment); } template Reference Pointer::operator[](int index) const { RR_DEBUG_INFO_UPDATE_LOC(); Value *element = Nucleus::createGEP(this->loadValue(), T::type(), Nucleus::createConstantInt(index), false); return Reference(element, alignment); } template Reference Pointer::operator[](unsigned int index) const { RR_DEBUG_INFO_UPDATE_LOC(); Value *element = Nucleus::createGEP(this->loadValue(), T::type(), Nucleus::createConstantInt(index), true); return Reference(element, alignment); } template Reference Pointer::operator[](RValue index) const { RR_DEBUG_INFO_UPDATE_LOC(); Value *element = Nucleus::createGEP(this->loadValue(), T::type(), index.value(), false); return Reference(element, alignment); } template Reference Pointer::operator[](RValue index) const { RR_DEBUG_INFO_UPDATE_LOC(); Value *element = Nucleus::createGEP(this->loadValue(), T::type(), index.value(), true); return Reference(element, alignment); } template Type *Pointer::type() { return Nucleus::getPointerType(T::type()); } template Array::Array(int size) : LValue(size) { } template Reference Array::operator[](int index) { assert(index < Variable::getArraySize()); Value *element = this->getElementPointer(Nucleus::createConstantInt(index), false); return Reference(element); } template Reference Array::operator[](unsigned int index) { assert(index < static_cast(Variable::getArraySize())); Value *element = this->getElementPointer(Nucleus::createConstantInt(index), true); return Reference(element); } template Reference Array::operator[](RValue index) { Value *element = this->getElementPointer(index.value(), false); return Reference(element); } template Reference Array::operator[](RValue index) { Value *element = this->getElementPointer(index.value(), true); return Reference(element); } // template // RValue> operator++(Array &val, int) // { // // FIXME: Requires storing the address of the array // } // template // const Array &operator++(Array &val) // { // // FIXME: Requires storing the address of the array // } // template // RValue> operator--(Array &val, int) // { // // FIXME: Requires storing the address of the array // } // template // const Array &operator--(Array &val) // { // // FIXME: Requires storing the address of the array // } template RValue IfThenElse(RValue condition, RValue ifTrue, RValue ifFalse) { RR_DEBUG_INFO_UPDATE_LOC(); return RValue(Nucleus::createSelect(condition.value(), ifTrue.value(), ifFalse.value())); } template RValue IfThenElse(RValue condition, const T &ifTrue, RValue ifFalse) { RR_DEBUG_INFO_UPDATE_LOC(); Value *trueValue = ifTrue.loadValue(); return RValue(Nucleus::createSelect(condition.value(), trueValue, ifFalse.value())); } template RValue IfThenElse(RValue condition, RValue ifTrue, const T &ifFalse) { RR_DEBUG_INFO_UPDATE_LOC(); Value *falseValue = ifFalse.loadValue(); return RValue(Nucleus::createSelect(condition.value(), ifTrue.value(), falseValue)); } template RValue IfThenElse(RValue condition, const T &ifTrue, const T &ifFalse) { RR_DEBUG_INFO_UPDATE_LOC(); Value *trueValue = ifTrue.loadValue(); Value *falseValue = ifFalse.loadValue(); return RValue(Nucleus::createSelect(condition.value(), trueValue, falseValue)); } template Function::Function() : core(new Nucleus()) { Type *types[] = { Arguments::type()... }; for(Type *type : types) { if(type != Void::type()) { arguments.push_back(type); } } Nucleus::createFunction(Return::type(), arguments); } template std::shared_ptr Function::operator()(const char *name, ...) { char fullName[1024 + 1]; va_list vararg; va_start(vararg, name); vsnprintf(fullName, 1024, name, vararg); va_end(vararg); auto routine = core->acquireRoutine(fullName, nullptr); core.reset(nullptr); return routine; } template std::shared_ptr Function::operator()(const Config::Edit &cfg, const char *name, ...) { char fullName[1024 + 1]; va_list vararg; va_start(vararg, name); vsnprintf(fullName, 1024, name, vararg); va_end(vararg); auto routine = core->acquireRoutine(fullName, &cfg); core.reset(nullptr); return routine; } template RValue ReinterpretCast(RValue val) { RR_DEBUG_INFO_UPDATE_LOC(); return RValue(Nucleus::createBitCast(val.value(), T::type())); } template RValue ReinterpretCast(const LValue &var) { RR_DEBUG_INFO_UPDATE_LOC(); Value *val = var.loadValue(); return RValue(Nucleus::createBitCast(val, T::type())); } template RValue ReinterpretCast(const Reference &var) { return ReinterpretCast(RValue(var)); } template RValue As(Value *val) { RR_DEBUG_INFO_UPDATE_LOC(); return RValue(Nucleus::createBitCast(val, T::type())); } template RValue As(RValue val) { return ReinterpretCast(val); } template RValue As(const LValue &var) { return ReinterpretCast(var); } template RValue As(const Reference &val) { return ReinterpretCast(val); } // Calls the function pointer fptr with the given arguments, return type // and parameter types. Returns the call's return value if the function has // a non-void return type. Value *Call(RValue> fptr, Type *retTy, std::initializer_list args, std::initializer_list paramTys); template class CallHelper {}; template class CallHelper { public: using RReturn = CToReactorT; static inline RReturn Call(Return(fptr)(Arguments...), CToReactorT... args) { return RValue(rr::Call( ConstantPointer(reinterpret_cast(fptr)), RReturn::type(), { ValueOf(args)... }, { CToReactorT::type()... })); } static inline RReturn Call(Pointer fptr, CToReactorT... args) { return RValue(rr::Call( fptr, RReturn::type(), { ValueOf(args)... }, { CToReactorT::type()... })); } }; template class CallHelper { public: static inline void Call(void(fptr)(Arguments...), CToReactorT... args) { rr::Call(ConstantPointer(reinterpret_cast(fptr)), Void::type(), { ValueOf(args)... }, { CToReactorT::type()... }); } static inline void Call(Pointer fptr, CToReactorT... args) { rr::Call(fptr, Void::type(), { ValueOf(args)... }, { CToReactorT::type()... }); } }; template inline ReactorTypeT CastToReactor(const T &v) { return ReactorType::cast(v); } // Calls the static function pointer fptr with the given arguments args. template inline CToReactorT Call(Return(fptr)(CArgs...), RArgs &&...args) { return CallHelper::Call(fptr, CastToReactor(std::forward(args))...); } // Calls the static function pointer fptr with the given arguments args. // Overload for calling functions with void return type. template inline void Call(void(fptr)(CArgs...), RArgs &&...args) { CallHelper::Call(fptr, CastToReactor(std::forward(args))...); } // Calls the member function pointer fptr with the given arguments args. // object can be a Class*, or a Pointer. template inline CToReactorT Call(Return (Class::*fptr)(CArgs...), C &&object, RArgs &&...args) { using Helper = CallHelper; using fptrTy = decltype(fptr); struct Static { static inline Return Call(Class *object, void *fptrptr, CArgs... args) { auto fptr = *reinterpret_cast(fptrptr); return (object->*fptr)(std::forward(args)...); } }; return Helper::Call(&Static::Call, CastToReactor(object), ConstantData(&fptr, sizeof(fptr)), CastToReactor(std::forward(args))...); } // Calls the member function pointer fptr with the given arguments args. // Overload for calling functions with void return type. // object can be a Class*, or a Pointer. template inline void Call(void (Class::*fptr)(CArgs...), C &&object, RArgs &&...args) { using Helper = CallHelper; using fptrTy = decltype(fptr); struct Static { static inline void Call(Class *object, void *fptrptr, CArgs... args) { auto fptr = *reinterpret_cast(fptrptr); (object->*fptr)(std::forward(args)...); } }; Helper::Call(&Static::Call, CastToReactor(object), ConstantData(&fptr, sizeof(fptr)), CastToReactor(std::forward(args))...); } // NonVoidFunction and VoidFunction are helper classes which define ReturnType // when F matches a non-void fuction signature or void function signature, respectively, // as the function's return type. template struct NonVoidFunction {}; template struct NonVoidFunction { using ReturnType = Return; }; template struct NonVoidFunction { }; template using NonVoidFunctionReturnType = typename NonVoidFunction::ReturnType; template struct VoidFunction {}; template struct VoidFunction { using ReturnType = void; }; template using VoidFunctionReturnType = typename VoidFunction::ReturnType; // Calls the Reactor function pointer fptr with the signature FUNCTION_SIGNATURE and arguments. // Overload for calling functions with non-void return type. template inline CToReactorT> Call(Pointer fptr, RArgs &&...args) { return CallHelper::Call(fptr, CastToReactor(std::forward(args))...); } // Calls the Reactor function pointer fptr with the signature FUNCTION_SIGNATURE and arguments. // Overload for calling functions with void return type. template inline VoidFunctionReturnType Call(Pointer fptr, RArgs &&...args) { CallHelper::Call(fptr, CastToReactor(std::forward(args))...); } // Breakpoint emits an instruction that will cause the application to trap. // This can be used to stop an attached debugger at the given call. void Breakpoint(); class ForData { public: ForData(bool init) : loopOnce(init) { } operator bool() { return loopOnce; } bool operator=(bool value) { return loopOnce = value; } bool setup() { RR_DEBUG_INFO_FLUSH(); if(Nucleus::getInsertBlock() != endBB) { testBB = Nucleus::createBasicBlock(); Nucleus::createBr(testBB); Nucleus::setInsertBlock(testBB); return true; } return false; } bool test(RValue cmp) { BasicBlock *bodyBB = Nucleus::createBasicBlock(); endBB = Nucleus::createBasicBlock(); Nucleus::createCondBr(cmp.value(), bodyBB, endBB); Nucleus::setInsertBlock(bodyBB); return true; } void end() { Nucleus::createBr(testBB); Nucleus::setInsertBlock(endBB); } private: BasicBlock *testBB = nullptr; BasicBlock *endBB = nullptr; bool loopOnce = true; }; class IfElseData { public: IfElseData(RValue cmp) { trueBB = Nucleus::createBasicBlock(); falseBB = Nucleus::createBasicBlock(); endBB = falseBB; // Until we encounter an Else statement, these are the same. Nucleus::createCondBr(cmp.value(), trueBB, falseBB); Nucleus::setInsertBlock(trueBB); } ~IfElseData() { Nucleus::createBr(endBB); Nucleus::setInsertBlock(endBB); } operator int() { return iteration; } IfElseData &operator++() { ++iteration; return *this; } void elseClause() { endBB = Nucleus::createBasicBlock(); Nucleus::createBr(endBB); Nucleus::setInsertBlock(falseBB); } private: BasicBlock *trueBB = nullptr; BasicBlock *falseBB = nullptr; BasicBlock *endBB = nullptr; int iteration = 0; }; #define For(init, cond, inc) \ for(ForData for__ = true; for__; for__ = false) \ for(init; for__.setup() && for__.test(cond); inc, for__.end()) #define While(cond) For((void)0, cond, (void)0) #define Do \ { \ BasicBlock *body__ = Nucleus::createBasicBlock(); \ Nucleus::createBr(body__); \ Nucleus::setInsertBlock(body__); #define Until(cond) \ BasicBlock *end__ = Nucleus::createBasicBlock(); \ Nucleus::createCondBr((cond).value(), end__, body__); \ Nucleus::setInsertBlock(end__); \ } \ do \ { \ } while(false) // Require a semi-colon at the end of the Until() enum { IF_BLOCK__, ELSE_CLAUSE__, ELSE_BLOCK__, IFELSE_NUM__ }; #define If(cond) \ for(IfElseData ifElse__{ cond }; ifElse__ < IFELSE_NUM__; ++ifElse__) \ if(ifElse__ == IF_BLOCK__) #define Else \ else if(ifElse__ == ELSE_CLAUSE__) \ { \ ifElse__.elseClause(); \ } \ else // ELSE_BLOCK__ // The OFFSET macro is a generalization of the offsetof() macro defined in . // It allows e.g. getting the offset of array elements, even when indexed dynamically. // We cast the address '32' and subtract it again, because null-dereference is undefined behavior. #define OFFSET(s, m) ((int)(size_t) & reinterpret_cast((((s *)32)->m)) - 32) } // namespace rr #include "Traits.inl" #endif // rr_Reactor_hpp