summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/compiler-core/slang-artifact-desc-util.h2
-rw-r--r--source/slang/slang-diagnostic-defs.h1
-rw-r--r--source/slang/slang-emit-c-like.cpp18
-rw-r--r--source/slang/slang-emit-glsl.cpp7
-rw-r--r--source/slang/slang-emit-hlsl.cpp7
-rw-r--r--source/slang/slang-emit.cpp18
-rw-r--r--source/slang/slang-ir-inline.cpp92
-rw-r--r--source/slang/slang-ir-inline.h7
-rw-r--r--source/slang/slang-ir-string-hash.cpp28
-rw-r--r--source/slang/slang-ir-string-hash.h8
10 files changed, 172 insertions, 16 deletions
diff --git a/source/compiler-core/slang-artifact-desc-util.h b/source/compiler-core/slang-artifact-desc-util.h
index 6aa5c321e..1e8b853e6 100644
--- a/source/compiler-core/slang-artifact-desc-util.h
+++ b/source/compiler-core/slang-artifact-desc-util.h
@@ -44,7 +44,7 @@ struct ArtifactDescUtil
/// True if is a CPU binary
static bool isCpuBinary(const ArtifactDesc& desc);
- /// True if is a GPU usable (can be passed to a driver/API and be used
+ /// True if is a GPU usable (can be passed to a driver/API and be used)
static bool isGpuUsable(const ArtifactDesc& desc);
/// True if the desc holds textual information
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index fc92241e1..db97f4865 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -576,6 +576,7 @@ DIAGNOSTIC(41012, Error, typeCannotBePackedIntoAnyValue, "type '$0' contains fie
DIAGNOSTIC(41020, Error, lossOfDerivativeDueToCallOfNonDifferentiableFunction, "derivative cannot be propagated through call to non-differentiable function `$0`, use 'no_diff' to clarify intention.")
DIAGNOSTIC(41021, Error, differentiableFuncMustHaveOutput, "a differentiable function must have at least one differentiable output.")
DIAGNOSTIC(41022, Error, differentiableFuncMustHaveInput, "a differentiable function must have at least one differentiable input.")
+DIAGNOSTIC(41023, Error, getStringHashMustBeOnStringLiteral, "getStringHash can only be called when argument is statically resolvable to a string literal")
//
// 5xxxx - Target code generation.
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 5b2370665..1ac50b8a7 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -2261,6 +2261,24 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
m_writer->emit(")");
break;
}
+ case kIROp_GetStringHash:
+ {
+ auto getStringHashInst = as<IRGetStringHash>(inst);
+ auto stringLit = getStringHashInst->getStringLit();
+
+ if (stringLit)
+ {
+ auto slice = stringLit->getStringSlice();
+ m_writer->emit(static_cast<int32_t>(getStableHashCode32(slice.begin(), slice.getLength())));
+ }
+ else
+ {
+ // Couldn't handle
+ diagnoseUnhandledInst(inst);
+ }
+ break;
+ }
+
default:
diagnoseUnhandledInst(inst);
break;
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index 8a074d057..02e633f98 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -1757,13 +1757,6 @@ bool GLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
return true;
}
- case kIROp_GetStringHash:
- {
- const UnownedStringSlice slice = as<IRStringLit>(inst->getOperand(0))->getStringSlice();
- m_writer->emit(static_cast<int32_t>(getStableHashCode32(slice.begin(), slice.getLength())));
-
- return true;
- }
case kIROp_ImageLoad:
{
m_writer->emit("imageLoad(");
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 8891f06a6..b4db75616 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -566,13 +566,6 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
return true;
}
- case kIROp_GetStringHash:
- {
- const UnownedStringSlice slice = as<IRStringLit>(inst->getOperand(0))->getStringSlice();
- m_writer->emit(static_cast<int32_t>(getStableHashCode32(slice.begin(), slice.getLength())));
-
- return true;
- }
case kIROp_ByteAddressBufferLoad:
{
// HLSL byte-address buffers have two kinds of `Load` operations.
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 2476f79e5..065a30672 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -53,6 +53,8 @@
#include "slang-ir-wrap-structured-buffers.h"
#include "slang-ir-liveness.h"
#include "slang-ir-glsl-liveness.h"
+#include "slang-ir-string-hash.h"
+
#include "slang-legalize-types.h"
#include "slang-lower-to-ir.h"
#include "slang-mangle.h"
@@ -383,6 +385,16 @@ Result linkAndOptimizeIR(
break;
}
+ // If we have a target that is GPU like we use the string hashing mechanism
+ // but for that to work we need to inline such that calls (or returns) of strings
+ // boil down into getStringHash(stringLiteral)
+ if (!ArtifactDescUtil::isCpuLikeTarget(artifactDesc))
+ {
+ // We could fail because
+ // 1) It's not inlinable for some reason (for example if it's recursive)
+ SLANG_RETURN_ON_FAIL(performStringInlining(irModule, sink));
+ }
+
finalizeAutoDiffPass(irModule);
lowerReinterpret(targetRequest, irModule, sink);
@@ -391,6 +403,12 @@ Result linkAndOptimizeIR(
simplifyIR(irModule);
+ if (!ArtifactDescUtil::isCpuLikeTarget(artifactDesc))
+ {
+ // We could fail because (perhaps, somehow) end up with getStringHash that the operand is not a string literal
+ SLANG_RETURN_ON_FAIL(checkGetStringHashInsts(irModule, sink));
+ }
+
// For targets that supports dynamic dispatch, we need to lower the
// generics / interface types to ordinary functions and types using
// function pointers.
diff --git a/source/slang/slang-ir-inline.cpp b/source/slang/slang-ir-inline.cpp
index 13221ee8c..f49b52975 100644
--- a/source/slang/slang-ir-inline.cpp
+++ b/source/slang/slang-ir-inline.cpp
@@ -34,7 +34,7 @@ struct InliningPassBase
{
}
- /// Consider all the call sites in the module for inliing
+ /// Consider all the call sites in the module for inlining
bool considerAllCallSites()
{
return considerAllCallSitesRec(m_module->getModuleInst());
@@ -517,6 +517,96 @@ void performMandatoryEarlyInlining(IRModule* module)
pass.considerAllCallSites();
}
+namespace { // anonymous
+
+// Inlines calls that involve String types
+struct StringInliningPass : InliningPassBase
+{
+ typedef InliningPassBase Super;
+
+ StringInliningPass(IRModule* module)
+ : Super(module)
+ {}
+
+ bool doesTypeRequireInline(IRType* type)
+ {
+ // TODO(JS):
+ // I guess there is a question here about what type around string requires
+ // inlining.
+ // For example if we had an array of strings etc.
+ // For now we just consider just basic string types.
+ const auto op = type->getOp();
+ switch (op)
+ {
+ case kIROp_StringType:
+ case kIROp_NativeStringType:
+ {
+ return true;
+ }
+ default: break;
+ }
+
+ return false;
+ }
+
+ bool shouldInline(CallSiteInfo const& info)
+ {
+ auto callee = info.callee;
+
+ if (doesTypeRequireInline(callee->getResultType()))
+ {
+ return true;
+ }
+
+ const auto count = Count(callee->getParamCount());
+ for (Index i = 0; i < count; ++i)
+ {
+ if (doesTypeRequireInline(callee->getParamType(UInt(i))))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+
+} // anonymous
+
+Result performStringInlining(IRModule* module, DiagnosticSink* sink)
+{
+ SLANG_UNUSED(sink);
+
+ // TODO(JS):
+ // This is perhaps not as efficient as might be desirable.
+ // A more optimized version might not need to pass over all of the module
+ // to find new call sites.
+ //
+ // Another problem here is recursion. Right now Slang compiler doesn't accept recursive input,
+ // but the Slang language is supposed to support recursion on targets that support it.
+ // There are GPU targets that allow recursion such as CUDA.
+ //
+ // Another approach would be (when enabled) when inlining occurs, would be instead of continuing
+ // *after*, to start the checks/inlining from where the inline took place.
+ //
+ while(true)
+ {
+ StringInliningPass pass(module);
+ if (pass.considerAllCallSites())
+ {
+ // If there was a change try inlining again
+ continue;
+ }
+
+ // Done.
+ break;
+ }
+
+
+
+ return SLANG_OK;
+}
+
struct ForceInliningPass : InliningPassBase
{
typedef InliningPassBase Super;
diff --git a/source/slang/slang-ir-inline.h b/source/slang/slang-ir-inline.h
index 70c7c3321..2f3a7a965 100644
--- a/source/slang/slang-ir-inline.h
+++ b/source/slang/slang-ir-inline.h
@@ -1,11 +1,18 @@
// slang-ir-inline.h
#pragma once
+#include "../../slang-com-helper.h"
+
namespace Slang
{
struct IRModule;
struct IRCall;
+ class DiagnosticSink;
+
+ /// Any call to a function that takes or returns a string parameter is inlined
+ Result performStringInlining(IRModule* module, DiagnosticSink* sink);
+
/// Inline any call sites to functions marked `[unsafeForceInlineEarly]`
void performMandatoryEarlyInlining(IRModule* module);
diff --git a/source/slang/slang-ir-string-hash.cpp b/source/slang/slang-ir-string-hash.cpp
index 8ff0ec756..8bccb97db 100644
--- a/source/slang/slang-ir-string-hash.cpp
+++ b/source/slang/slang-ir-string-hash.cpp
@@ -18,6 +18,11 @@ static void _findGetStringHashRec(IRInst* inst, List<IRGetStringHash*>& outInsts
}
}
+void findGetStringHashInsts(IRModule* module, List<IRGetStringHash*>& outInsts)
+{
+ _findGetStringHashRec(module->getModuleInst(), outInsts);
+}
+
void findGlobalHashedStringLiterals(IRModule* module, StringSlicePool& pool)
{
IRModuleInst* moduleInst = module->getModuleInst();
@@ -78,4 +83,27 @@ void addGlobalHashedStringLiterals(const StringSlicePool& pool, SharedIRBuilder&
builder.addKeepAliveDecoration(globalHashedInst);
}
+Result checkGetStringHashInsts(IRModule* module, DiagnosticSink* sink)
+{
+ // Check all getStringHash are all on string literals
+ List<IRGetStringHash*> insts;
+ findGetStringHashInsts(module, insts);
+
+ for (auto inst : insts)
+ {
+ if (inst->getStringLit() == nullptr)
+ {
+ if (sink)
+ {
+ sink->diagnose(inst, Diagnostics::getStringHashMustBeOnStringLiteral);
+ }
+
+ // Doesn't access a string literal
+ return SLANG_FAIL;
+ }
+ }
+
+ return SLANG_OK;
+}
+
}
diff --git a/source/slang/slang-ir-string-hash.h b/source/slang/slang-ir-string-hash.h
index ccbbf4049..aa724fa5c 100644
--- a/source/slang/slang-ir-string-hash.h
+++ b/source/slang/slang-ir-string-hash.h
@@ -11,6 +11,8 @@ namespace Slang
struct IRModule;
struct SharedIRBuilder;
+class DiagnosticSink;
+
// Finds the global GlobalHashedStringLiterals instruction for the module if there is one, and then
// adds all of it's strings to ioPool.
void findGlobalHashedStringLiterals(IRModule* module, StringSlicePool& ioPool);
@@ -18,5 +20,11 @@ void findGlobalHashedStringLiterals(IRModule* module, StringSlicePool& ioPool);
// Given a pool, with > 0 strings adds a GlobalHashedStringLiterals to the module.
void addGlobalHashedStringLiterals(const StringSlicePool& pool, SharedIRBuilder& sharedBuilder);
+// Find all of the IRGetStringHash instructions within the module
+void findGetStringHashInsts(IRModule* module, List<IRGetStringHash*>& outInsts);
+
+// Looks at all getStringHash instructions to make sure they access something valid (like a string literal)
+// sink is optional and can be passed as nullptr
+Result checkGetStringHashInsts(IRModule* module, DiagnosticSink* sink);
} // namespace Slang