diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2020-08-04 10:43:05 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-04 10:43:05 -0700 |
| commit | 00b1fe044840e7818c6c9bcd4c42d4baafd5b78a (patch) | |
| tree | c7c3f6b4ae1805cf16ebe47db270166a8978a318 /source | |
| parent | 79ba9279becf480c9d92bb2faaede0e241f0b029 (diff) | |
Fix stdlib declarations of bit-shift ops (#1471)
The declarations of the left- and right-shift operations in the Slang standard library were set up identically to the declarations of operator binary (and compound binary) operations. A consequence of this choice was that both operands to a shift were expected to have the same type, which can lead to a confusing result.
If the user wrote a shift of the form `int >> uint`, then the ordinary promotion rules for Slang would decide to perform the operation on `uint` value, so it would change to `uint(int) >> uint` and perform an unsigned shift, which isn't what the user would expect.
The fix implemented here is to make the shift operations be declared separately from the other binary operations, with *two* generic type parameters instead of one: distinct parameters for the left-hand-side and right-hand side types. Each parameter is only constrained to be a built-in integer type.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/core.meta.slang | 88 | ||||
| -rw-r--r-- | source/slang/slang-stdlib.cpp | 2 |
2 files changed, 86 insertions, 4 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 716a93328..65da2af92 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -1727,6 +1727,92 @@ for (auto op : intrinsicBinaryOps) } } +// We will declare the shift operations entirely as generics +// rather than try to handle all the pairings of left-hand +// and right-hand side types. +// +static const struct ShiftOpInfo +{ + char const* name; + int op; +} kShiftOps[] = +{ + { "<<", kIROp_Lsh }, + { ">>", kIROp_Rsh }, +}; +for(auto info : kShiftOps) { +}}}} + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType> +__intrinsic_op($(info.op)) +L operator$(info.name)(L left, R right); + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType> +[__unsafeForceInlineEarly] +L operator$(info.name)=(in out L left, R right) +{ + left = left $(info.name) right; + return left; +} + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int> +__intrinsic_op($(info.op)) +vector<L,N> operator$(info.name)(vector<L,N> left, vector<R,N> right); + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int> +[__unsafeForceInlineEarly] +vector<L,N> operator$(info.name)=(in out vector<L,N> left, vector<R,N> right) +{ + left = left $(info.name) right; + return left; +} + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int, let M : int> +__intrinsic_op($(info.op)) +matrix<L,N,M> operator$(info.name)(matrix<L,N,M> left, matrix<R,N,M> right); + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int, let M : int> +[__unsafeForceInlineEarly] +matrix<L, N, M> operator$(info.name)=(in out matrix<L, N, M> left, matrix<R, N, M> right) +{ + left = left $(info.name) right; + return left; +} + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int> +__intrinsic_op($(info.op)) +vector<L,N> operator$(info.name)(L left, vector<R,N> right); + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int, let M : int> +__intrinsic_op($(info.op)) +matrix<L,N,M> operator$(info.name)(L left, matrix<R,N,M> right); + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int> +__intrinsic_op($(info.op)) +vector<L,N> operator$(info.name)(vector<L,N> left, R right); + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int> +[__unsafeForceInlineEarly] +vector<L, N> operator$(info.name)=(in out vector<L, N> left, R right) +{ + left = left $(info.name) right; + return left; +} + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int, let M : int> +__intrinsic_op($(info.op)) +matrix<L,N,M> operator$(info.name)(matrix<L,N,M> left, R right); + +__generic<L: __BuiltinIntegerType, R: __BuiltinIntegerType, let N : int, let M : int> +[__unsafeForceInlineEarly] +matrix<L,N,M> operator$(info.name)=(in out matrix<L,N,M> left, R right) +{ + left = left $(info.name) right; + return left; +} + +${{{{ +} static const struct CompoundBinaryOpInfo { @@ -1743,8 +1829,6 @@ for (auto op : intrinsicBinaryOps) { "&", "__BuiltinLogicalType" }, { "|", "__BuiltinLogicalType" }, { "^", "__BuiltinLogicalType" }, - { "<<", "__BuiltinIntegerType" }, - { ">>", "__BuiltinIntegerType" }, }; for( auto op : kCompoundBinaryOps ) { diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index a310ba748..e0727f19a 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -208,8 +208,6 @@ namespace Slang { kIROp_BitAnd, "&", "__BuiltinLogicalType", LOGICAL_MASK }, { kIROp_BitOr, "|", "__BuiltinLogicalType", LOGICAL_MASK }, { kIROp_BitXor, "^", "__BuiltinLogicalType", LOGICAL_MASK }, - { kIROp_Lsh, "<<", "__BuiltinIntegerType", INT_MASK }, - { kIROp_Rsh, ">>", "__BuiltinIntegerType", INT_MASK }, { kIROp_Eql, "==", "__BuiltinType", ANY_MASK | BOOL_RESULT }, { kIROp_Neq, "!=", "__BuiltinType", ANY_MASK | BOOL_RESULT }, { kIROp_Greater, ">", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT }, |
