Repository: shader-slang/slang (C++)

Issue:
Allow `IModule::findEntryPointByName` to work with entrypoints without `[shader]` attribute.
If the user writes something like:
```
float4 vsMain() { return 0; }
```

And calls `module->findEntryPointByName("vsMain")`,
we will return `nullptr` because there is nothing in the module defined with `shader` attribute.

We should allow this function to proceed to find other functions with the name and just return that.

This will enable our users to get rid of the dependence on `ICompileRequest` API, which has this feature to compile entrypoints not marked as `[shader("...")]`.

Once we have this we can deprecate all the legacy APIs, including `ICompileRequest` interface.



Fix (patch):
diff --git a/slang.h b/slang.h
index 4014be4010..4ed37d88ce 100644
--- a/slang.h
+++ b/slang.h
@@ -4949,6 +4949,13 @@ namespace slang
         /// Get the unique identity of the module.
         virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() = 0;
 
+        /// Find and validate an entry point by name, even if the function is
+        /// not marked with the `[shader("...")]` attribute.
+        virtual SLANG_NO_THROW SlangResult SLANG_MCALL findAndCheckEntryPoint(
+            char const* name,
+            SlangStage stage,
+            IEntryPoint** outEntryPoint,
+            ISlangBlob** outDiagnostics) = 0;
     };
     
     #define SLANG_UUID_IModule IModule::getTypeGuid()
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index 55edba6b9b..e6e980fe8c 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -2773,4 +2773,7 @@ namespace Slang
         SemanticsDeclVisitorBase* visitor,
         Decl* decl,
         DeclCheckState              state);
+
+    RefPtr<EntryPoint> findAndValidateEntryPoint(
+        FrontEndEntryPointRequest* entryPointReq);
 }
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 14d4054c43..014b678f5c 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -1338,6 +1338,20 @@ namespace Slang
             return SLANG_OK;
         }
 
+        virtual SLANG_NO_THROW SlangResult SLANG_MCALL findAndCheckEntryPoint(
+            char const* name,
+            SlangStage stage,
+            slang::IEntryPoint** outEntryPoint,
+            ISlangBlob** outDiagnostics)
+        {
+            ComPtr<slang::IEntryPoint> entryPoint(findAndCheckEntryPoint(UnownedStringSlice(name), stage, outDiagnostics));
+            if ((!entryPoint))
+                return SLANG_FAIL;
+
+            *outEntryPoint = entryPoint.detach();
+            return SLANG_OK;
+        }
+
         virtual SlangInt32 SLANG_MCALL getDefinedEntryPointCount() override
         {
             return (SlangInt32)m_entryPoints.getCount();
@@ -1481,6 +1495,7 @@ namespace Slang
         };
 
         RefPtr<EntryPoint> findEntryPointByName(UnownedStringSlice const& name);
+        RefPtr<EntryPoint> findAndCheckEntryPoint(UnownedStringSlice const& name, SlangStage stage, ISlangBlob** outDiagnostics);
 
         List<RefPtr<EntryPoint>>& getEntryPoints() { return m_entryPoints; }
         void _addEntryPoint(EntryPoint* entryPoint);
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 6d40b46a2f..0db833c7a3 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -3987,13 +3987,6 @@ void Module::setName(String name)
 
 RefPtr<EntryPoint> Module::findEntryPointByName(UnownedStringSlice const& name)
 {
-    // TODO: We should consider having this function be expanded to be able
-    // to look up and validate possible entry-point functions in teh module
-    // even if they were not marked with `[shader(...)]` in the source code.
-    //
-    // With such a change the function would probably need to accept a stage
-    // to use and a sink to write validation errors to.
-
     for(auto entryPoint : m_entryPoints)
     {
         if(entryPoint->getName()->text.getUnownedSlice() == name)
@@ -4003,6 +3996,41 @@ RefPtr<EntryPoint> Module::findEntryPointByName(UnownedStringSlice const& name)
     return nullptr;
 }
 
+
+RefPtr<EntryPoint> Module::findAndCheckEntryPoint(
+    UnownedStringSlice const& name,
+    SlangStage stage,
+    ISlangBlob** outDiagnostics)
+{
+    // If there is already an entrypoint marked with the [shader] attribute,
+    // we should just return that.
+    //
+    if (auto existingEntryPoint = findEntryPointByName(name))
+        return existingEntryPoint;
+
+    // If the function hasn't been marked as [shader], then it won't be discovered
+    // by findEntryPointByName. We need to route this to the `findAndValidateEntryPoint`
+    // function. To do that we need to setup a FrontEndCompileRequest and a FrontEndEntryPointRequest.
+    //
+    DiagnosticSink sink(getLinkage()->getSourceManager(), DiagnosticSink::SourceLocationLexer());
+    FrontEndCompileRequest frontEndRequest(getLinkage(), StdWriters::getSingleton(), &sink);
+    RefPtr<TranslationUnitRequest> tuRequest = new TranslationUnitRequest(&frontEndRequest);
+    tuRequest->module = this;
+    tuRequest->moduleName = m_name;
+    frontEndRequest.translationUnits.add(tuRequest);
+    FrontEndEntryPointRequest entryPointRequest(
+        &frontEndRequest,
+        0,
+        getLinkage()->getNamePool()->getName(name),
+        Profile((Stage)stage));
+    auto result = findAndValidateEntryPoint(&entryPointRequest);
+    if (outDiagnostics)
+    {
+        sink.getBlobIfNeeded(outDiagnostics);
+    }
+    return result;
+}
+
 void Module::_addEntryPoint(EntryPoint* entryPoint)
 {
     m_entryPoints.add(entryPoint);