summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-emit-c-like.cpp72
-rw-r--r--source/slang/slang-ir-sccp.cpp22
-rw-r--r--source/slang/slang-ir.cpp42
-rw-r--r--tests/ir/scalar-truncate.slang16
-rw-r--r--tests/ir/scalar-truncate.slang.expected.txt4
5 files changed, 90 insertions, 66 deletions
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 6b77cba6a..d3dd0e5b8 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -850,60 +850,40 @@ void CLikeSourceEmitter::emitSimpleValueImpl(IRInst* inst)
switch (type->getBaseType())
{
default:
- case BaseType::Int8:
- case BaseType::Int16:
+
case BaseType::Int:
{
- // NOTE! This hack is required, otherwise we get different results across targets.
- // You'd hope that outputting L suffix would be enough to make this work, and not require a cast, but testing shows L suffix
- // does not have the same meaning across targets.
- //
- // For example
- //
- // uint64_t v = 0x80000000;
- //
- // When output this becomes...
- // v_0 = uint64_t(-2147483648L);
- //
- // On MSVC/Gcc/Clang this is equal to 0x80000000, elsewhere it's 0xffffffff80000000 elsewhere.
- // Note that '-' isn't the issue because v0 = uint64_t(0x80000000L); produces the same issue
- //
- // If we use a cast, we get the same result across targets (which is why the hack is here).
- //
- // Why? It's not clear - it seems likely that it's related to the order of how the promotion takes place.
- //
- // If we convert from int32_t -> uint64_t, there are two possible scenarios
- // 1) int32_t -> int64_t -> uint64_t (ie widen first then do sign type change)
- // 2) int32_t -> uint32_t -> uint64_t (ie do sign type change then widen)
- //
- // 2 would produce what we see on C++, 1 what we see everywhere else.
- //
- // Why having a cast or having a suffix would make a difference though is not clear. It is also possible that the
- // L suffix is just ignored, and the literal is really a 'non typed' int literal in C++.
-
- // This little hack is needed for gcc that if we have the expression
- // int(-0x80000000) we get the warning: warning : integer overflow in expression [-Woverflow]
- // 0x80000000 and -0x80000000 mean the same thing when casted to 32 bit int, so we just flip the value here.
- IRIntegerValue value = litInst->value.intVal;
- value = (value == -0x80000000ll) ? -value : value;
-
m_writer->emit("int(");
- m_writer->emit(value);
+ m_writer->emit(int32_t(litInst->value.intVal));
+ m_writer->emit(")");
+ return;
+ }
+ case BaseType::Int8:
+ {
+ m_writer->emit("int8_t(");
+ m_writer->emit(int8_t(litInst->value.intVal));
+ m_writer->emit(")");
+ return;
+ }
+ case BaseType::Int16:
+ {
+ m_writer->emit("int16_t(");
+ m_writer->emit(int16_t(litInst->value.intVal));
m_writer->emit(")");
return;
}
case BaseType::UInt8:
- {
- m_writer->emit(UInt(uint8_t(litInst->value.intVal)));
- m_writer->emit("U");
- break;
- }
+ {
+ m_writer->emit(UInt(uint8_t(litInst->value.intVal)));
+ m_writer->emit("U");
+ break;
+ }
case BaseType::UInt16:
- {
- m_writer->emit(UInt(uint16_t(litInst->value.intVal)));
- m_writer->emit("U");
- break;
- }
+ {
+ m_writer->emit(UInt(uint16_t(litInst->value.intVal)));
+ m_writer->emit("U");
+ break;
+ }
case BaseType::UInt:
{
m_writer->emit(UInt(uint32_t(litInst->value.intVal)));
diff --git a/source/slang/slang-ir-sccp.cpp b/source/slang/slang-ir-sccp.cpp
index 28f262c1a..e724d0d88 100644
--- a/source/slang/slang-ir-sccp.cpp
+++ b/source/slang/slang-ir-sccp.cpp
@@ -288,7 +288,11 @@ struct SCCPContext
{
SLANG_SCCP_RETURN_IF_NONE_OR_ANY(v0)
auto irConstant = as<IRConstant>(v0.value);
+
IRInst* resultVal = nullptr;
+ if (type->getOp() == irConstant->getOp())
+ return LatticeVal::getConstant(irConstant);
+
switch (type->getOp())
{
case kIROp_Int8Type:
@@ -309,24 +313,6 @@ struct SCCPContext
case kIROp_BoolLit:
{
IRIntegerValue intVal = irConstant->value.intVal;
- switch (type->getOp())
- {
- case kIROp_Int8Type:
- case kIROp_UInt8Type:
- intVal = intVal & 0xFF;
- break;
- case kIROp_Int16Type:
- case kIROp_UInt16Type:
- intVal = intVal & 0xFFFF;
- break;
- case kIROp_IntType:
- case kIROp_UIntType:
- case kIROp_BoolType:
- intVal = intVal & 0xFFFFFFFF;
- break;
- default:
- break;
- }
resultVal = getBuilder()->getIntValue(type, (IRIntegerValue)intVal);
}
break;
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 721488f82..bb1b0a9d2 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -2081,7 +2081,32 @@ namespace Slang
memset(&keyInst, 0, sizeof(keyInst));
keyInst.m_op = kIROp_IntLit;
keyInst.typeUse.usedValue = type;
- keyInst.value.intVal = inValue;
+ // Truncate the input value based on `type`.
+ switch (type->getOp())
+ {
+ case kIROp_Int8Type:
+ keyInst.value.intVal = static_cast<int8_t>(inValue);
+ break;
+ case kIROp_Int16Type:
+ keyInst.value.intVal = static_cast<int16_t>(inValue);
+ break;
+ case kIROp_IntType:
+ keyInst.value.intVal = static_cast<int32_t>(inValue);
+ break;
+ case kIROp_UInt8Type:
+ keyInst.value.intVal = static_cast<uint8_t>(inValue);
+ break;
+ case kIROp_UInt16Type:
+ keyInst.value.intVal = static_cast<uint16_t>(inValue);
+ break;
+ case kIROp_BoolType:
+ case kIROp_UIntType:
+ keyInst.value.intVal = static_cast<uint32_t>(inValue);
+ break;
+ default:
+ keyInst.value.intVal = inValue;
+ break;
+ }
return _findOrEmitConstant(keyInst);
}
@@ -2091,7 +2116,20 @@ namespace Slang
memset(&keyInst, 0, sizeof(keyInst));
keyInst.m_op = kIROp_FloatLit;
keyInst.typeUse.usedValue = type;
- keyInst.value.floatVal = inValue;
+ // Truncate the input value based on `type`.
+ switch (type->getOp())
+ {
+ case kIROp_FloatType:
+ keyInst.value.floatVal = static_cast<float>(inValue);
+ break;
+ case kIROp_HalfType:
+ keyInst.value.floatVal = HalfToFloat(FloatToHalf((float)inValue));
+ break;
+ default:
+ keyInst.value.floatVal = inValue;
+ break;
+ }
+
return _findOrEmitConstant(keyInst);
}
diff --git a/tests/ir/scalar-truncate.slang b/tests/ir/scalar-truncate.slang
new file mode 100644
index 000000000..9d9d33261
--- /dev/null
+++ b/tests/ir/scalar-truncate.slang
@@ -0,0 +1,16 @@
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
+//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+[numthreads(1, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ {
+ int16_t a = 30000; // 0x00007530 -> 0x7530 (30000) in 16-bit.
+ int16_t b = -200000; // 0xfffcf2c0 -> Truncated to 0xf2c0 (-3392) in 16-bit.
+ outputBuffer[0] = asuint((int)a);
+ outputBuffer[1] = asuint((int)b);
+ }
+}
diff --git a/tests/ir/scalar-truncate.slang.expected.txt b/tests/ir/scalar-truncate.slang.expected.txt
new file mode 100644
index 000000000..edaa32088
--- /dev/null
+++ b/tests/ir/scalar-truncate.slang.expected.txt
@@ -0,0 +1,4 @@
+7530
+FFFFF2C0
+0
+0