summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2020-08-04 10:43:05 -0700
committerGitHub <noreply@github.com>2020-08-04 10:43:05 -0700
commit00b1fe044840e7818c6c9bcd4c42d4baafd5b78a (patch)
treec7c3f6b4ae1805cf16ebe47db270166a8978a318 /source
parent79ba9279becf480c9d92bb2faaede0e241f0b029 (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.slang88
-rw-r--r--source/slang/slang-stdlib.cpp2
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 },