summaryrefslogtreecommitdiffstats
path: root/source/slang/slang.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2019-02-15 09:08:19 -0800
committerGitHub <noreply@github.com>2019-02-15 09:08:19 -0800
commita3fd4e2bc40cfc77db953b14744c30e7a18e7c1d (patch)
tree5c226a6a4304086412c051f642a5f45fb043083c /source/slang/slang.cpp
parent4cd317bcae0a13dc2bbb78448c8d60cd1dcc76bd (diff)
Split front- and back-ends (#846)
* Split front- and back-ends This change is a major refactor of several of the types that provide the behind-the-scenes implementation of the public C API. The goal of this refactor is primarily to allow for future API services that let the user operate both the front- and back-ends of the compiler in a more complex fashion. For example, as user should be able to compile a bunch of source code into modules, look up types, functions, etc. in those modules, specialize generic types/functions to the types they've looked up, and then finally request target code to be gernerated for specialized entry points. The back-end code generation they trigger should re-use the front-end compilation work (parsing, semantic checking, IR generation) that was already performed. The most visible change is that `CompileRequest` has been split up into several smaller types that take responsibility for parts of what it did: * The `Linkage` type owns the storage for `import`ed modules, and well as the `TargetRequest`s that represent code-generation targets. The intention is that an application could use a single `Linkage` for the duration of its runtime (so long as it was okay with the memory usage), so that each `import`ed module only gets loaded once. For now, this type needs to manage the search paths, file system, and source manager, because of its responsibility for loading files. * A `FrontEndCompileRequest` owns the stuff related to parsing, semantic checking, and initial IR generation. This most notably includes the `TranslationUnitRequest`s and the `FrontEndEntryPointRequest`s (which used to be just `EntryPointRequest`s). It's main job is to produce AST and IR modules for each translation unit, and to find and validate the entry points. The front-end request does *not* interact with generic arguments for global or entry-point generic parameters. * The main output of both `import` operations and front-end translation units is the `Module` type, which is just a simple container for both the AST module (to service the reflection/layout APIs, and also for semantic checking of code that `import`s the module) and the IR module (for linking and code generation). This type captures the commonalities between the old `LoadedModule` (which is now just an alias for `Module`) and `TranslationUnitRequest` (which now owns a `Module`). * The secondary output of front-end compilation is a `Program`, which comprises a list of referenced `Module`s and validated `EntryPoint`s that will be used together. Layout and code generation both need a `Program` to tell them what modules and entry points will be used together (we don't want to just code-gen everythin that has ever been loaded into the linakge). The `Program`s created by the front-end do not include generic arguments, so they may provide incomplete layout information and/or be unsuitable for code generation. * A `BackEndCompileRequest` owns stuff related to turning a `Program` into output kernels for the targets of a `Linkage`. Most of the data it owns beyond the `Program` to be compiled is minor, so this is a good candidate for demotion from a heap-allocated object to just a `struct` of options that gets passed around. * The `CompileRequestBase` type is an attempt to wrap up the common functionality of both front-end and back-end compile requests. Most of it is just exposing the availability of a linkage and `DiagnosticSink`, so this type is a good candidate for subsequent removal. The main interesting thing it has is the flags related to dumping and validation of IR, so there is probably a good refactoring still to be made around deciding how options should be handled going forward. * Behind the scenes, the `Program` type is set up to handle some level of on-line compilation and layout work. The `Program` knows the `Linkage` it belongs to, and allows for a `TargetProgram` to be looked up based on a specific `TargetRequest`. A `TargetProgram` then allows layout information and compiled kernel code to be asked for on-demand, in order to support eventual "live" compilation scenarios. * The `EndToEndCompileRequest` type is a composition/coordination type that replaces the old `CompileRequest` in a way that uses the services of the various other types. It owns a few pieces of state that only make sense in the context of an end-to-end compile (e.g., there is really no way to "pass through" code when the front- and back-ends are run separately) or a command-line compile (everything to do with specifying output paths for files is really just for the benefit of `slangc`, and might even be moved there over time). * One important detail is that the `EndToEndCompilRequest` owns all of the string-based generic arguments for both global and entry-point generic parameters. The logic in `check.cpp` for dealing with those arguments has been heavily refactored to separate out the parsings steps that are specific to end-to-end compilation with string-based type arguments, and the semantic checking steps that result in a specialized `Program` (which can be exposed through new APIs that aren't tied to end-to-end compilation). It is perhaps not surprising that this change had a lot of consequences, so I'll briefly run over some of the main categories of changes required: * I changed the way that global generic arguments are passed via API (use `spSetGlobalGenericArgs` instead of the generic arguments for `spAddEntryPointEx`, which are not just for entry-point generics), which has been a change that we've needed for a long time. This is technically a breaking API change, although we should have very few client applications that care about it. * A bunch of places that used to take "big" objects like `CompileRequest` now just take the sub-pieces they care about (e.g., a function might have only needed a `Linkage` and a `DiagnosticSink`). This makes many subroutines or "context" struct types more generally useful, at the cost of taking more parameters. * In a few cases the conceptually clean separation of the layers breaks down (often for edge-case or compatibility features), and so we may pass along additional objects that are allowed to be null, but are used when present. A big example of this is how the back-end code generation routines accept an `EndToEndCompileRequest` that is optional, and only used to check whether "pass through" compilation is needed. We should probably look into cleaning this kind of logic up over time so that we don't need to violate the apparent separation of phases of compilation. * In cases where separation of layers was being broken for the sake of GLSL features, I went ahead and ripped them out, since all of that should be dead code anyway. * In many cases I increased the encapsulation of data in the core types to help track down use sites and make sure they are following invariants better. * In cases where code was doing, e.g., `context->shared->compileRequest->session->getThing()` I have tried to introduce convenience routines so that the usage site is just `context->getThing()` to improve encapsulation and allow changes to be made more easily going forward. * The `noteInternalErrorLoc` functionality was moved off of the compile request and into `DiagnosticSink`, since that is the one type you can rely on having around when you want to note an internal error. We may consider going forward if (and how) it should reset the counter used for noting locations on internal errors. * A few APIs now take `DiagnosticSink*` arguments where they didn't before, and as a result some public APIs need to create `DiagnosticSink`s to pass in, before going ahead and ignoring the messages. In the future there should be variations of these APIs that accept an `ISlangBlob**` parameter for the output. * fixup: missing include for compilers with accurate template checking (non-VS) * fixup: review feedback
Diffstat (limited to 'source/slang/slang.cpp')
-rw-r--r--source/slang/slang.cpp1127
1 files changed, 807 insertions, 320 deletions
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 16dfe8618..7a5b58d07 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -60,6 +60,8 @@ Session::Session()
// Make sure our source manager is initialized
builtinSourceManager.initialize(nullptr, nullptr);
+ m_builtinLinkage = new Linkage(this);
+
// Initialize representations of some very basic types:
initializeTypes();
@@ -90,11 +92,12 @@ Session::Session()
struct IncludeHandlerImpl : IncludeHandler
{
- CompileRequest* request;
+ Linkage* linkage;
+ SearchDirectoryList* searchDirectories;
ISlangFileSystemExt* _getFileSystemExt()
{
- return request->fileSystemExt;
+ return linkage->getFileSystemExt();
}
SlangResult _findFile(SlangPathType fromPathType, const String& fromPath, const String& path, PathInfo& pathInfoOut)
@@ -153,18 +156,22 @@ struct IncludeHandlerImpl : IncludeHandler
}
// Search all the searchDirectories
- for (auto & dir : request->searchDirectories)
+ for(auto sd = searchDirectories; sd; sd = sd->parent)
{
- SlangResult res = _findFile(SLANG_PATH_TYPE_DIRECTORY, dir.path, pathToInclude, pathInfoOut);
- if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND)
+ for(auto& dir : sd->searchDirectories)
{
- return res;
+ SlangResult res = _findFile(SLANG_PATH_TYPE_DIRECTORY, dir.path, pathToInclude, pathInfoOut);
+ if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND)
+ {
+ return res;
+ }
}
}
return SLANG_E_NOT_FOUND;
}
+#if 0
virtual SlangResult readFile(const String& path,
ISlangBlob** blobOut) override
{
@@ -175,6 +182,7 @@ struct IncludeHandlerImpl : IncludeHandler
return SLANG_OK;
}
+#endif
virtual String simplifyPath(const String& path) override
{
@@ -192,9 +200,9 @@ struct IncludeHandlerImpl : IncludeHandler
//
-Profile getEffectiveProfile(EntryPointRequest* entryPoint, TargetRequest* target)
+Profile getEffectiveProfile(EntryPoint* entryPoint, TargetRequest* target)
{
- auto entryPointProfile = entryPoint->profile;
+ auto entryPointProfile = entryPoint->getProfile();
auto targetProfile = target->targetProfile;
// Depending on the target *format* we might have to restrict the
@@ -310,20 +318,13 @@ Profile getEffectiveProfile(EntryPointRequest* entryPoint, TargetRequest* target
//
-CompileRequest::CompileRequest(Session* session)
- : mSession(session)
+Linkage::Linkage(Session* session)
+ : m_session(session)
+ , m_sourceManager(&m_defaultSourceManager)
{
getNamePool()->setRootNamePool(session->getRootNamePool());
- setSourceManager(&sourceManagerStorage);
-
- sourceManager->initialize(session->getBuiltinSourceManager(), nullptr);
-
- // Set all the default writers
- for (int i = 0; i < int(WriterChannel::CountOf); ++i)
- {
- setWriter(WriterChannel(i), nullptr);
- }
+ m_defaultSourceManager.initialize(session->getBuiltinSourceManager(), nullptr);
setFileSystem(nullptr);
}
@@ -379,10 +380,61 @@ ComPtr<ISlangBlob> createRawBlob(void const* inData, size_t size)
}
//
+// TargetRequest
+//
+
+Session* TargetRequest::getSession()
+{
+ return linkage->getSession();
+}
MatrixLayoutMode TargetRequest::getDefaultMatrixLayoutMode()
{
- return compileRequest->getDefaultMatrixLayoutMode();
+ return linkage->getDefaultMatrixLayoutMode();
+}
+
+//
+// TranslationUnitRequest
+//
+
+TranslationUnitRequest::TranslationUnitRequest(
+ FrontEndCompileRequest* compileRequest)
+ : compileRequest(compileRequest)
+{
+ module = new Module(compileRequest->getLinkage());
+}
+
+
+Session* TranslationUnitRequest::getSession()
+{
+ return compileRequest->getSession();
+}
+
+NamePool* TranslationUnitRequest::getNamePool()
+{
+ return compileRequest->getNamePool();
+}
+
+SourceManager* TranslationUnitRequest::getSourceManager()
+{
+ return compileRequest->getSourceManager();
+}
+
+void TranslationUnitRequest::addSourceFile(SourceFile* sourceFile)
+{
+ m_sourceFiles.Add(sourceFile);
+
+ // We want to record that the compiled module has a dependency
+ // on the path of the source file, but we also need to account
+ // for cases where the user added a source string/blob without
+ // an associated path (so that the API passes along an empty
+ // string).
+ //
+ auto path = sourceFile->getPathInfo().foundPath;
+ if(path.Length())
+ {
+ getModule()->addFilePathDependency(path);
+ }
}
@@ -407,7 +459,7 @@ static ISlangWriter* _getDefaultWriter(WriterChannel chan)
}
}
-void CompileRequest::setWriter(WriterChannel chan, ISlangWriter* writer)
+void EndToEndCompileRequest::setWriter(WriterChannel chan, ISlangWriter* writer)
{
// If the user passed in null, we will use the default writer on that channel
m_writers[int(chan)] = writer ? writer : _getDefaultWriter(chan);
@@ -415,20 +467,20 @@ void CompileRequest::setWriter(WriterChannel chan, ISlangWriter* writer)
// For diagnostic output, if the user passes in nullptr, we set on mSink.writer as that enables buffering on DiagnosticSink
if (chan == WriterChannel::Diagnostic)
{
- mSink.writer = writer;
+ m_sink.writer = writer;
}
}
-SlangResult CompileRequest::loadFile(String const& path, ISlangBlob** outBlob)
+SlangResult Linkage::loadFile(String const& path, ISlangBlob** outBlob)
{
return fileSystemExt->loadFile(path.Buffer(), outBlob);
}
-RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translationUnit, String typeStr, RefPtr<Scope> scope)
+RefPtr<Expr> Linkage::parseTypeString(String typeStr, RefPtr<Scope> scope)
{
// Create a SourceManager on the stack, so any allocations for 'SourceFile'/'SourceView' etc will be cleaned up
SourceManager localSourceManager;
- localSourceManager.initialize(sourceManager, nullptr);
+ localSourceManager.initialize(getSourceManager(), nullptr);
Slang::SourceFile* srcFile = localSourceManager.createSourceFileWithString(PathInfo::makeTypeParse(), typeStr);
@@ -440,20 +492,20 @@ RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translatio
// Use RAII - to make sure everything is reset even if an exception is thrown.
struct ScopeReplaceSourceManager
{
- ScopeReplaceSourceManager(CompileRequest* request, SourceManager* replaceManager):
- m_request(request),
- m_originalSourceManager(request->getSourceManager())
+ ScopeReplaceSourceManager(Linkage* linkage, SourceManager* replaceManager):
+ m_linkage(linkage),
+ m_originalSourceManager(linkage->getSourceManager())
{
- request->setSourceManager(replaceManager);
+ linkage->setSourceManager(replaceManager);
}
~ScopeReplaceSourceManager()
{
- m_request->setSourceManager(m_originalSourceManager);
+ m_linkage->setSourceManager(m_originalSourceManager);
}
private:
- CompileRequest* m_request;
+ Linkage* m_linkage;
SourceManager* m_originalSourceManager;
};
@@ -465,87 +517,131 @@ RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translatio
&sink,
nullptr,
Dictionary<String,String>(),
- translationUnit);
+ this,
+ nullptr);
- return parseTypeFromSourceFile(translationUnit, tokens, &sink, scope);
+ return parseTypeFromSourceFile(
+ getSession(),
+ tokens, &sink, scope, getNamePool(), SourceLanguage::Slang);
}
-RefPtr<Type> checkProperType(TranslationUnitRequest * tu, TypeExp typeExp);
-Type* CompileRequest::getTypeFromString(String typeStr)
+RefPtr<Type> checkProperType(
+ Linkage* linkage,
+ TypeExp typeExp,
+ DiagnosticSink* sink);
+
+Type* Program::getTypeFromString(String typeStr, DiagnosticSink* sink)
{
+ // If we've looked up this type name before,
+ // then we can re-use it.
+ //
RefPtr<Type> type;
- if (types.TryGetValue(typeStr, type))
+ if(m_types.TryGetValue(typeStr, type))
return type;
- auto translationUnit = translationUnits.First();
+
+ // Otherwise, we need to start looking in
+ // the modules that were directly or
+ // indirectly referenced.
+ //
+ // TODO: This `scopesToTry` idiom appears
+ // all over the code, and isn't really
+ // how we should be handling this kind of
+ // lookup at all.
+ //
List<RefPtr<Scope>> scopesToTry;
- for (auto tu : translationUnits)
- scopesToTry.Add(tu->SyntaxNode->scope);
- for (auto & module : loadedModulesList)
- scopesToTry.Add(module->moduleDecl->scope);
- // parse type name
- for (auto & s : scopesToTry)
- {
- RefPtr<Expr> typeExpr = parseTypeString(translationUnit,
+ for(auto module : getModuleDependencies())
+ scopesToTry.Add(module->getModuleDecl()->scope);
+
+ auto linkage = getLinkage();
+ for(auto& s : scopesToTry)
+ {
+ RefPtr<Expr> typeExpr = linkage->parseTypeString(
typeStr, s);
- type = checkProperType(translationUnit, TypeExp(typeExpr));
- if (type)
+ type = checkProperType(linkage, TypeExp(typeExpr), sink);
+ if(type)
break;
}
- if (type)
+ if( type )
{
- types[typeStr] = type;
+ m_types[typeStr] = type;
}
- return type.Ptr();
+ return type;
}
-void CompileRequest::parseTranslationUnit(
+CompileRequestBase::CompileRequestBase(
+ Linkage* linkage,
+ DiagnosticSink* sink)
+ : m_linkage(linkage)
+ , m_sink(sink)
+{}
+
+
+FrontEndCompileRequest::FrontEndCompileRequest(
+ Linkage* linkage,
+ DiagnosticSink* sink)
+ : CompileRequestBase(linkage, sink)
+{
+}
+
+void FrontEndCompileRequest::parseTranslationUnit(
TranslationUnitRequest* translationUnit)
{
IncludeHandlerImpl includeHandler;
- includeHandler.request = this;
+ includeHandler.linkage = getLinkage();
+ includeHandler.searchDirectories = &searchDirectories;
RefPtr<Scope> languageScope;
switch (translationUnit->sourceLanguage)
{
case SourceLanguage::HLSL:
- languageScope = mSession->hlslLanguageScope;
+ languageScope = getSession()->hlslLanguageScope;
break;
case SourceLanguage::Slang:
default:
- languageScope = mSession->slangLanguageScope;
+ languageScope = getSession()->slangLanguageScope;
break;
}
Dictionary<String, String> combinedPreprocessorDefinitions;
+ for(auto& def : getLinkage()->preprocessorDefinitions)
+ combinedPreprocessorDefinitions.Add(def.Key, def.Value);
for(auto& def : preprocessorDefinitions)
combinedPreprocessorDefinitions.Add(def.Key, def.Value);
for(auto& def : translationUnit->preprocessorDefinitions)
combinedPreprocessorDefinitions.Add(def.Key, def.Value);
+ auto module = translationUnit->getModule();
RefPtr<ModuleDecl> translationUnitSyntax = new ModuleDecl();
- translationUnit->SyntaxNode = translationUnitSyntax;
+ translationUnitSyntax->nameAndLoc.name = translationUnit->moduleName;
+ translationUnitSyntax->module = module;
+ module->setModuleDecl(translationUnitSyntax);
- for (auto sourceFile : translationUnit->sourceFiles)
+ for (auto sourceFile : translationUnit->getSourceFiles())
{
auto tokens = preprocessSource(
sourceFile,
- &mSink,
+ getSink(),
&includeHandler,
combinedPreprocessorDefinitions,
- translationUnit);
+ getLinkage(),
+ module);
parseSourceFile(
translationUnit,
tokens,
- &mSink,
+ getSink(),
languageScope);
}
}
-void validateEntryPoints(CompileRequest*);
+RefPtr<Program> createUnspecializedProgram(
+ FrontEndCompileRequest* compileRequest);
-void CompileRequest::checkAllTranslationUnits()
+RefPtr<Program> createSpecializedProgram(
+ EndToEndCompileRequest* endToEndReq);
+
+void FrontEndCompileRequest::checkAllTranslationUnits()
{
// Iterate over all translation units and
// apply the semantic checking logic.
@@ -553,12 +649,9 @@ void CompileRequest::checkAllTranslationUnits()
{
checkTranslationUnit(translationUnit.Ptr());
}
-
- // Next, do follow-up validation on any entry points.
- validateEntryPoints(this);
}
-void CompileRequest::generateIR()
+void FrontEndCompileRequest::generateIR()
{
// Our task in this function is to generate IR code
// for all of the declarations in the translation
@@ -581,9 +674,9 @@ void CompileRequest::generateIR()
if (verifyDebugSerialization)
{
// Verify debug information
- if (SLANG_FAILED(IRSerialUtil::verifySerialize(irModule, mSession, sourceManager, IRSerialBinary::CompressionType::None, IRSerialWriter::OptionFlag::DebugInfo)))
+ if (SLANG_FAILED(IRSerialUtil::verifySerialize(irModule, getSession(), getSourceManager(), IRSerialBinary::CompressionType::None, IRSerialWriter::OptionFlag::DebugInfo)))
{
- mSink.diagnose(irModule->moduleInst->sourceLoc, Diagnostics::serialDebugVerificationFailed);
+ getSink()->diagnose(irModule->moduleInst->sourceLoc, Diagnostics::serialDebugVerificationFailed);
}
}
@@ -593,7 +686,7 @@ void CompileRequest::generateIR()
{
// Write IR out to serialData - copying over SourceLoc information directly
IRSerialWriter writer;
- writer.write(irModule, sourceManager, IRSerialWriter::OptionFlag::RawSourceLocation, &serialData);
+ writer.write(irModule, getSourceManager(), IRSerialWriter::OptionFlag::RawSourceLocation, &serialData);
// Destroy irModule such that memory can be used for newly constructed read irReadModule
irModule = nullptr;
@@ -602,7 +695,7 @@ void CompileRequest::generateIR()
{
// Read IR back from serialData
IRSerialReader reader;
- reader.read(serialData, mSession, nullptr, irReadModule);
+ reader.read(serialData, getSession(), nullptr, irReadModule);
}
// Set irModule to the read module
@@ -610,12 +703,12 @@ void CompileRequest::generateIR()
}
// Set the module on the translation unit
- translationUnit->irModule = irModule;
+ translationUnit->getModule()->setIRModule(irModule);
}
}
// Try to infer a single common source language for a request
-static SourceLanguage inferSourceLanguage(CompileRequest* request)
+static SourceLanguage inferSourceLanguage(FrontEndCompileRequest* request)
{
SourceLanguage language = SourceLanguage::Unknown;
for (auto& translationUnit : request->translationUnits)
@@ -639,29 +732,115 @@ static SourceLanguage inferSourceLanguage(CompileRequest* request)
return language;
}
-SlangResult CompileRequest::executeActionsInner()
+SlangResult FrontEndCompileRequest::executeActionsInner()
{
- // Do some cleanup on settings specified by user.
- // In particular, we want to propagate flags from the overall request down to
- // each translation unit.
+ // We currently allow GlSL files on the command line so that we can
+ // drive our "pass-through" mode, but we really want to issue an error
+ // message if the user is seriously asking us to compile them.
for (auto& translationUnit : translationUnits)
{
- translationUnit->compileFlags |= compileFlags;
+ switch(translationUnit->sourceLanguage)
+ {
+ default:
+ break;
+
+ case SourceLanguage::GLSL:
+ getSink()->diagnose(SourceLoc(), Diagnostics::glslIsNotSupported);
+ return SLANG_FAIL;
+ }
+ }
+
+
+ // Parse everything from the input files requested
+ for (auto& translationUnit : translationUnits)
+ {
+ parseTranslationUnit(translationUnit.Ptr());
}
+ if (getSink()->GetErrorCount() != 0)
+ return SLANG_FAIL;
+
+ // Perform semantic checking on the whole collection
+ checkAllTranslationUnits();
+ if (getSink()->GetErrorCount() != 0)
+ return SLANG_FAIL;
+
+ // Look up all the entry points that are expected,
+ // and use them to populate the `program` member.
+ //
+ m_program = createUnspecializedProgram(this);
+ if (getSink()->GetErrorCount() != 0)
+ return SLANG_FAIL;
+
+ if ((compileFlags & SLANG_COMPILE_FLAG_NO_CODEGEN) == 0)
+ {
+ // Generate initial IR for all the translation
+ // units, if we are in a mode where IR is called for.
+ generateIR();
+ }
+
+ if (getSink()->GetErrorCount() != 0)
+ return SLANG_FAIL;
+
+ // Do parameter binding generation, for each compilation target.
+ //
+ for(auto targetReq : getLinkage()->targets)
+ {
+ auto targetProgram = m_program->getTargetProgram(targetReq);
+ targetProgram->getOrCreateLayout(getSink());
+ }
+ if (getSink()->GetErrorCount() != 0)
+ return SLANG_FAIL;
+
+ return SLANG_OK;
+}
+
+BackEndCompileRequest::BackEndCompileRequest(
+ Linkage* linkage,
+ DiagnosticSink* sink,
+ Program* program)
+ : CompileRequestBase(linkage, sink)
+ , m_program(program)
+{}
+
+EndToEndCompileRequest::EndToEndCompileRequest(
+ Session* session)
+ : m_session(session)
+{
+ m_linkage = new Linkage(session);
+
+ m_sink.sourceManager = m_linkage->getSourceManager();
+
+ // Set all the default writers
+ for (int i = 0; i < int(WriterChannel::CountOf); ++i)
+ {
+ setWriter(WriterChannel(i), nullptr);
+ }
+
+ m_frontEndReq = new FrontEndCompileRequest(getLinkage(), getSink());
+
+ m_backEndReq = new BackEndCompileRequest(getLinkage(), getSink());
+}
+
+SlangResult EndToEndCompileRequest::executeActionsInner()
+{
// If no code-generation target was specified, then try to infer one from the source language,
// just to make sure we can do something reasonable when invoked from the command line.
- if (targets.Count() == 0)
+ //
+ // TODO: This logic should be moved into `options.cpp` or somewhere else
+ // specific to the command-line tool.
+ //
+ if (getLinkage()->targets.Count() == 0)
{
- auto language = inferSourceLanguage(this);
+ auto language = inferSourceLanguage(getFrontEndReq());
switch (language)
{
case SourceLanguage::HLSL:
- addTarget(CodeGenTarget::DXBytecode);
+ getLinkage()->addTarget(CodeGenTarget::DXBytecode);
break;
case SourceLanguage::GLSL:
- addTarget(CodeGenTarget::SPIRV);
+ getLinkage()->addTarget(CodeGenTarget::SPIRV);
break;
default:
@@ -672,105 +851,117 @@ SlangResult CompileRequest::executeActionsInner()
// We only do parsing and semantic checking if we *aren't* doing
// a pass-through compilation.
//
- // Note that we *do* perform output generation as normal in pass-through mode.
if (passThrough == PassThroughMode::None)
{
- // We currently allow GlSL files on the command line so that we can
- // drive our "pass-through" mode, but we really want to issue an error
- // message if the user is seriously asking us to compile them.
- for (auto& translationUnit : translationUnits)
- {
- switch(translationUnit->sourceLanguage)
- {
- default:
- break;
-
- case SourceLanguage::GLSL:
- mSink.diagnose(SourceLoc(), Diagnostics::glslIsNotSupported);
- return SLANG_FAIL;
- }
- }
+ SLANG_RETURN_ON_FAIL(getFrontEndReq()->executeActionsInner());
+ }
+ // If command line specifies to skip codegen, we exit here.
+ // Note: this is a debugging option.
+ //
+ if (shouldSkipCodegen ||
+ ((getFrontEndReq()->compileFlags & SLANG_COMPILE_FLAG_NO_CODEGEN) != 0))
+ {
+ // We will use the program (and matching layout information)
+ // that was computed in the front-end for all subsequent
+ // reflection queries, etc.
+ //
+ m_specializedProgram = getUnspecializedProgram();
- // Parse everything from the input files requested
- for (auto& translationUnit : translationUnits)
- {
- parseTranslationUnit(translationUnit.Ptr());
- }
- if (mSink.GetErrorCount() != 0)
- return SLANG_FAIL;
+ return SLANG_OK;
+ }
- // Perform semantic checking on the whole collection
- checkAllTranslationUnits();
- if (mSink.GetErrorCount() != 0)
+ // If codegen is enabled, we need to move along to
+ // apply any generic specialization that the user asked for.
+ //
+ if (passThrough == PassThroughMode::None)
+ {
+ m_specializedProgram = createSpecializedProgram(this);
+ if (getSink()->GetErrorCount() != 0)
return SLANG_FAIL;
- if ((compileFlags & SLANG_COMPILE_FLAG_NO_CODEGEN) == 0)
+ // For each code generation target, we will generate specialized
+ // parameter binding information (taking global generic
+ // arguments into account at this time).
+ //
+ for (auto targetReq : getLinkage()->targets)
{
- // Generate initial IR for all the translation
- // units, if we are in a mode where IR is called for.
- generateIR();
+ auto targetProgram = m_specializedProgram->getTargetProgram(targetReq);
+ targetProgram->getOrCreateLayout(getSink());
}
-
- if (mSink.GetErrorCount() != 0)
+ if (getSink()->GetErrorCount() != 0)
return SLANG_FAIL;
-
- // For each code generation target generate
- // parameter binding information.
- // This step is done globally, because all translation
- // units and entry points need to agree on where
- // parameters are allocated.
- for (auto targetReq : targets)
+ }
+ else
+ {
+ // We need to create dummy `EntryPoint` objects
+ // to make sure that the logic in `generateOutput`
+ // sees something worth processing.
+ //
+ auto specializedProgram = new Program(getLinkage());
+ m_specializedProgram = specializedProgram;
+ for(auto entryPointReq : getFrontEndReq()->getEntryPointReqs())
{
- generateParameterBindings(targetReq);
- if (mSink.GetErrorCount() != 0)
- return SLANG_FAIL;
+ RefPtr<EntryPoint> entryPoint = EntryPoint::createDummyForPassThrough(
+ entryPointReq->getName(),
+ entryPointReq->getProfile());
+
+ specializedProgram->addEntryPoint(entryPoint);
}
}
- // If command line specifies to skip codegen, we exit here.
- // Note: this is a debugging option.
- if (shouldSkipCodegen ||
- ((compileFlags & SLANG_COMPILE_FLAG_NO_CODEGEN) != 0))
- return SLANG_OK;
-
// Generate output code, in whatever format was requested
+ getBackEndReq()->setProgram(getSpecializedProgram());
generateOutput(this);
- if (mSink.GetErrorCount() != 0)
+ if (getSink()->GetErrorCount() != 0)
return SLANG_FAIL;
return SLANG_OK;
}
// Act as expected of the API-based compiler
-SlangResult CompileRequest::executeActions()
+SlangResult EndToEndCompileRequest::executeActions()
{
SlangResult res = executeActionsInner();
- mDiagnosticOutput = mSink.outputBuffer.ProduceString();
+ mDiagnosticOutput = getSink()->outputBuffer.ProduceString();
return res;
}
-int CompileRequest::addTranslationUnit(SourceLanguage language, String const&)
+int FrontEndCompileRequest::addTranslationUnit(SourceLanguage language, Name* moduleName)
{
UInt result = translationUnits.Count();
- RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest();
+ RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest(this);
translationUnit->compileRequest = this;
translationUnit->sourceLanguage = SourceLanguage(language);
+ translationUnit->moduleName = moduleName;
+
translationUnits.Add(translationUnit);
return (int) result;
}
-void CompileRequest::addTranslationUnitSourceFile(
+int FrontEndCompileRequest::addTranslationUnit(SourceLanguage language)
+{
+ // We want to ensure that symbols defined in different translation
+ // units get unique mangled names, so that we can, e.g., tell apart
+ // a `main()` function in `vertex.slang` and a `main()` in `fragment.slang`,
+ // even when they are being compiled together.
+ //
+ String generatedName = "tu";
+ generatedName.append(translationUnits.Count());
+ return addTranslationUnit(language, getNamePool()->getName(generatedName));
+}
+
+void FrontEndCompileRequest::addTranslationUnitSourceFile(
int translationUnitIndex,
SourceFile* sourceFile)
{
- translationUnits[translationUnitIndex]->sourceFiles.Add(sourceFile);
+ translationUnits[translationUnitIndex]->addSourceFile(sourceFile);
}
-void CompileRequest::addTranslationUnitSourceBlob(
+void FrontEndCompileRequest::addTranslationUnitSourceBlob(
int translationUnitIndex,
String const& path,
ISlangBlob* sourceBlob)
@@ -781,7 +972,7 @@ void CompileRequest::addTranslationUnitSourceBlob(
addTranslationUnitSourceFile(translationUnitIndex, sourceFile);
}
-void CompileRequest::addTranslationUnitSourceString(
+void FrontEndCompileRequest::addTranslationUnitSourceString(
int translationUnitIndex,
String const& path,
String const& source)
@@ -792,7 +983,7 @@ void CompileRequest::addTranslationUnitSourceString(
addTranslationUnitSourceFile(translationUnitIndex, sourceFile);
}
-void CompileRequest::addTranslationUnitSourceFile(
+void FrontEndCompileRequest::addTranslationUnitSourceFile(
int translationUnitIndex,
String const& path)
{
@@ -809,7 +1000,7 @@ void CompileRequest::addTranslationUnitSourceFile(
if(SLANG_FAILED(result))
{
// Emit a diagnostic!
- mSink.diagnose(
+ getSink()->diagnose(
SourceLoc(),
Diagnostics::cannotOpenFile,
path);
@@ -820,36 +1011,51 @@ void CompileRequest::addTranslationUnitSourceFile(
translationUnitIndex,
path,
sourceBlob);
+}
+
+int FrontEndCompileRequest::addEntryPoint(
+ int translationUnitIndex,
+ String const& name,
+ Profile entryPointProfile)
+{
+ auto translationUnitReq = translationUnits[translationUnitIndex];
+
+ UInt result = m_entryPointReqs.Count();
+
+ RefPtr<FrontEndEntryPointRequest> entryPointReq = new FrontEndEntryPointRequest(
+ this,
+ translationUnitIndex,
+ getNamePool()->getName(name),
+ entryPointProfile);
+
+ m_entryPointReqs.Add(entryPointReq);
+// translationUnitReq->entryPoints.Add(entryPointReq);
- mDependencyFilePaths.Add(path);
+ return int(result);
}
-int CompileRequest::addEntryPoint(
+int EndToEndCompileRequest::addEntryPoint(
int translationUnitIndex,
String const& name,
Profile entryPointProfile,
List<String> const & genericTypeNames)
{
- RefPtr<EntryPointRequest> entryPoint = new EntryPointRequest();
- entryPoint->compileRequest = this;
- entryPoint->name = getNamePool()->getName(name);
- entryPoint->profile = entryPointProfile;
- entryPoint->translationUnitIndex = translationUnitIndex;
+ getFrontEndReq()->addEntryPoint(translationUnitIndex, name, entryPointProfile);
+
+ EntryPointInfo entryPointInfo;
for (auto typeName : genericTypeNames)
- entryPoint->genericArgStrings.Add(typeName);
- auto translationUnit = translationUnits[translationUnitIndex].Ptr();
- translationUnit->entryPoints.Add(entryPoint);
+ entryPointInfo.genericArgStrings.Add(typeName);
UInt result = entryPoints.Count();
- entryPoints.Add(entryPoint);
+ entryPoints.Add(_Move(entryPointInfo));
return (int) result;
}
-UInt CompileRequest::addTarget(
+UInt Linkage::addTarget(
CodeGenTarget target)
{
RefPtr<TargetRequest> targetReq = new TargetRequest();
- targetReq->compileRequest = this;
+ targetReq->linkage = this;
targetReq->target = target;
UInt result = targets.Count();
@@ -857,15 +1063,16 @@ UInt CompileRequest::addTarget(
return (int) result;
}
-void CompileRequest::loadParsedModule(
- RefPtr<TranslationUnitRequest> const& translationUnit,
- Name* name,
- const PathInfo& pathInfo)
+void Linkage::loadParsedModule(
+ RefPtr<TranslationUnitRequest> translationUnit,
+ Name* name,
+ const PathInfo& pathInfo)
{
// Note: we add the loaded module to our name->module listing
// before doing semantic checking, so that if it tries to
// recursively `import` itself, we can detect it.
- RefPtr<LoadedModule> loadedModule = new LoadedModule();
+ //
+ RefPtr<Module> loadedModule = translationUnit->getModule();
// Get a path
String mostUniqueIdentity = pathInfo.getMostUniqueIdentity();
@@ -874,12 +1081,11 @@ void CompileRequest::loadParsedModule(
mapPathToLoadedModule.Add(mostUniqueIdentity, loadedModule);
mapNameToLoadedModules.Add(name, loadedModule);
- int errorCountBefore = mSink.GetErrorCount();
- checkTranslationUnit(translationUnit.Ptr());
- int errorCountAfter = mSink.GetErrorCount();
+ auto sink = translationUnit->compileRequest->getSink();
- RefPtr<ModuleDecl> moduleDecl = translationUnit->SyntaxNode;
- loadedModule->moduleDecl = moduleDecl;
+ int errorCountBefore = sink->GetErrorCount();
+ checkTranslationUnit(translationUnit.Ptr());
+ int errorCountAfter = sink->GetErrorCount();
if (errorCountAfter != errorCountBefore)
{
@@ -890,39 +1096,56 @@ void CompileRequest::loadParsedModule(
// If we didn't run into any errors, then try to generate
// IR code for the imported module.
SLANG_ASSERT(errorCountAfter == 0);
- loadedModule->irModule = generateIRForTranslationUnit(translationUnit);
+ loadedModule->setIRModule(generateIRForTranslationUnit(translationUnit));
}
loadedModulesList.Add(loadedModule);
}
-RefPtr<ModuleDecl> CompileRequest::loadModule(
+Module* Linkage::loadModule(String const& name)
+{
+ // TODO: We either need to have a diagnostics sink
+ // get passed into this operation, or associate
+ // one with the linkage.
+ //
+ DiagnosticSink* sink = nullptr;
+ return findOrImportModule(
+ getNamePool()->getName(name),
+ SourceLoc(),
+ sink);
+}
+
+
+RefPtr<Module> Linkage::loadModule(
Name* name,
const PathInfo& filePathInfo,
ISlangBlob* sourceBlob,
- SourceLoc const& srcLoc)
+ SourceLoc const& srcLoc,
+ DiagnosticSink* sink)
{
- RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest();
- translationUnit->compileRequest = this;
+ RefPtr<FrontEndCompileRequest> frontEndReq = new FrontEndCompileRequest(this, sink);
- // We don't want to use the same options that the user specified
- // for loading modules on-demand. In particular, we always want
- // semantic checking to be enabled.
- //
- // TODO: decide which options, if any, should be inherited.
- translationUnit->compileFlags = 0;
+ RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest(frontEndReq);
+ translationUnit->compileRequest = frontEndReq;
+ translationUnit->moduleName = name;
+
+ auto module = translationUnit->getModule();
+
+ ModuleBeingImportedRAII moduleBeingImported(
+ this,
+ module);
// Create with the 'friendly' name
SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(filePathInfo, sourceBlob);
- translationUnit->sourceFiles.Add(sourceFile);
+ translationUnit->addSourceFile(sourceFile);
- int errorCountBefore = mSink.GetErrorCount();
- parseTranslationUnit(translationUnit.Ptr());
- int errorCountAfter = mSink.GetErrorCount();
+ int errorCountBefore = sink->GetErrorCount();
+ frontEndReq->parseTranslationUnit(translationUnit);
+ int errorCountAfter = sink->GetErrorCount();
if( errorCountAfter != errorCountBefore )
{
- mSink.diagnose(srcLoc, Diagnostics::errorInImportedModule);
+ sink->diagnose(srcLoc, Diagnostics::errorInImportedModule);
}
if (errorCountAfter)
{
@@ -935,38 +1158,57 @@ RefPtr<ModuleDecl> CompileRequest::loadModule(
name,
filePathInfo);
- errorCountAfter = mSink.GetErrorCount();
+ errorCountAfter = sink->GetErrorCount();
if (errorCountAfter != errorCountBefore)
{
- mSink.diagnose(srcLoc, Diagnostics::errorInImportedModule);
+ sink->diagnose(srcLoc, Diagnostics::errorInImportedModule);
// Something went wrong during the parsing, so we should bail out.
return nullptr;
}
- return translationUnit->SyntaxNode;
+ return module;
+}
+
+bool Linkage::isBeingImported(Module* module)
+{
+ for(auto ii = m_modulesBeingImported; ii; ii = ii->next)
+ {
+ if(module == ii->module)
+ return true;
+ }
+ return false;
}
-RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
+RefPtr<Module> Linkage::findOrImportModule(
Name* name,
- SourceLoc const& loc)
+ SourceLoc const& loc,
+ DiagnosticSink* sink)
{
// Have we already loaded a module matching this name?
- // If so, return it.
+ //
RefPtr<LoadedModule> loadedModule;
if (mapNameToLoadedModules.TryGetValue(name, loadedModule))
{
+ // If the map shows a null module having been loaded,
+ // then that means there was a prior load attempt,
+ // but it failed, so we won't bother trying again.
+ //
if (!loadedModule)
return nullptr;
- if (!loadedModule->moduleDecl)
+ // If state shows us that the module is already being
+ // imported deeper on the call stack, then we've
+ // hit a recursive case, and that is an error.
+ //
+ if(isBeingImported(loadedModule))
{
// We seem to be in the middle of loading this module
- mSink.diagnose(loc, Diagnostics::recursiveModuleImport, name);
+ sink->diagnose(loc, Diagnostics::recursiveModuleImport, name);
return nullptr;
}
- return loadedModule->moduleDecl;
+ return loadedModule;
}
// Derive a file name for the module, by taking the given
@@ -991,7 +1233,8 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
// using our ordinary include-handling logic.
IncludeHandlerImpl includeHandler;
- includeHandler.request = this;
+ includeHandler.linkage = this;
+ includeHandler.searchDirectories = &searchDirectories;
// Get the original path info
PathInfo pathIncludedFromInfo = getSourceManager()->getPathInfo(loc, SourceLocType::Actual);
@@ -1000,20 +1243,20 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
// We have to load via the found path - as that is how file was originally loaded
if (SLANG_FAILED(includeHandler.findFile(fileName, pathIncludedFromInfo.foundPath, filePathInfo)))
{
- this->mSink.diagnose(loc, Diagnostics::cannotFindFile, fileName);
+ sink->diagnose(loc, Diagnostics::cannotFindFile, fileName);
mapNameToLoadedModules[name] = nullptr;
return nullptr;
}
// Maybe this was loaded previously at a different relative name?
if (mapPathToLoadedModule.TryGetValue(filePathInfo.getMostUniqueIdentity(), loadedModule))
- return loadedModule->moduleDecl;
+ return loadedModule;
// Try to load it
ComPtr<ISlangBlob> fileContents;
- if (SLANG_FAILED(includeHandler.readFile(filePathInfo.foundPath, fileContents.writeRef())))
+ if(SLANG_FAILED(getFileSystemExt()->loadFile(filePathInfo.foundPath.Buffer(), fileContents.writeRef())))
{
- this->mSink.diagnose(loc, Diagnostics::cannotOpenFile, fileName);
+ sink->diagnose(loc, Diagnostics::cannotOpenFile, fileName);
mapNameToLoadedModules[name] = nullptr;
return nullptr;
}
@@ -1024,26 +1267,159 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
name,
filePathInfo,
fileContents,
- loc);
+ loc,
+ sink);
}
-Decl * CompileRequest::lookupGlobalDecl(Name * name)
+//
+// ModuleDependencyList
+//
+
+void ModuleDependencyList::addDependency(Module* module)
{
- Decl* resultDecl = nullptr;
- for (auto module : loadedModulesList)
+ // If we depend on a module, then we depend on everything it depends on.
+ //
+ // Note: We are processing these sub-depenencies before adding the
+ // `module` itself, so that in the common case a module will always
+ // appear *after* everything it depends on.
+ //
+ // However, this rule is being violated in the compiler right now because
+ // the modules for hte top-level translation units of a compile request
+ // will be added to the list first (using `addLeafDependency`) to
+ // maintain compatibility with old behavior. This may be fixed later.
+ //
+ for(auto subDependency : module->getModuleDependencyList())
{
- if (module->moduleDecl->memberDictionary.TryGetValue(name, resultDecl))
- break;
+ _addDependency(subDependency);
+ }
+ _addDependency(module);
+}
+
+void ModuleDependencyList::addLeafDependency(Module* module)
+{
+ _addDependency(module);
+}
+
+void ModuleDependencyList::_addDependency(Module* module)
+{
+ if(m_moduleSet.Contains(module))
+ return;
+
+ m_moduleList.Add(module);
+ m_moduleSet.Add(module);
+}
+
+//
+// FilePathDependencyList
+//
+
+void FilePathDependencyList::addDependency(String const& path)
+{
+ if(m_filePathSet.Contains(path))
+ return;
+
+ m_filePathList.Add(path);
+ m_filePathSet.Add(path);
+}
+
+void FilePathDependencyList::addDependency(Module* module)
+{
+ for(auto& path : module->getFilePathDependencyList())
+ {
+ addDependency(path);
}
- for (auto transUnit : translationUnits)
+}
+
+
+
+//
+// Module
+//
+
+Module::Module(Linkage* linkage)
+ : m_linkage(linkage)
+{}
+
+
+void Module::addModuleDependency(Module* module)
+{
+ m_moduleDependencyList.addDependency(module);
+ m_filePathDependencyList.addDependency(module);
+}
+
+void Module::addFilePathDependency(String const& path)
+{
+ m_filePathDependencyList.addDependency(path);
+}
+
+// Program
+
+Program::Program(Linkage* linkage)
+ : m_linkage(linkage)
+{}
+
+void Program::addReferencedModule(Module* module)
+{
+ m_moduleDependencyList.addDependency(module);
+ m_filePathDependencyList.addDependency(module);
+}
+
+void Program::addReferencedLeafModule(Module* module)
+{
+ m_moduleDependencyList.addLeafDependency(module);
+ m_filePathDependencyList.addDependency(module);
+}
+
+void Program::addEntryPoint(EntryPoint* entryPoint)
+{
+ m_entryPoints.Add(entryPoint);
+
+ for(auto module : entryPoint->getModuleDependencies())
{
- if (transUnit->SyntaxNode->memberDictionary.TryGetValue(name, resultDecl))
- break;
+ addReferencedModule(module);
}
- return resultDecl;
}
-void CompileRequest::noteInternalErrorLoc(SourceLoc const& loc)
+RefPtr<IRModule> Program::getOrCreateIRModule(DiagnosticSink* sink)
+{
+ if(!m_irModule)
+ {
+ m_irModule = generateIRForProgram(
+ m_linkage->getSession(),
+ this,
+ sink);
+ }
+ return m_irModule;
+}
+
+
+TargetProgram* Program::getTargetProgram(TargetRequest* target)
+{
+ RefPtr<TargetProgram> targetProgram;
+ if(!m_targetPrograms.TryGetValue(target, targetProgram))
+ {
+ targetProgram = new TargetProgram(this, target);
+ m_targetPrograms[target] = targetProgram;
+ }
+ return targetProgram;
+}
+
+//
+// TargetProgram
+//
+
+TargetProgram::TargetProgram(
+ Program* program,
+ TargetRequest* targetReq)
+ : m_program(program)
+ , m_targetReq(targetReq)
+{
+ m_entryPointResults.SetSize(program->getEntryPoints().Count());
+}
+
+//
+
+void DiagnosticSink::noteInternalErrorLoc(SourceLoc const& loc)
{
// Don't consider invalid source locations.
if(!loc.isValid())
@@ -1054,14 +1430,19 @@ void CompileRequest::noteInternalErrorLoc(SourceLoc const& loc)
// code might have confused the compiler.
if(internalErrorLocsNoted == 0)
{
- mSink.diagnose(loc, Diagnostics::noteLocationOfInternalError);
+ diagnose(loc, Diagnostics::noteLocationOfInternalError);
}
internalErrorLocsNoted++;
}
+Session* CompileRequestBase::getSession()
+{
+ return getLinkage()->getSession();
+}
+
static const Slang::Guid IID_ISlangFileSystemExt = SLANG_UUID_ISlangFileSystemExt;
-void CompileRequest::setFileSystem(ISlangFileSystem* inFileSystem)
+void Linkage::setFileSystem(ISlangFileSystem* inFileSystem)
{
// Set the fileSystem
fileSystem = inFileSystem;
@@ -1085,15 +1466,16 @@ void CompileRequest::setFileSystem(ISlangFileSystem* inFileSystem)
}
// Set the file system used on the source manager
- sourceManager->setFileSystemExt(fileSystemExt);
+ getSourceManager()->setFileSystemExt(fileSystemExt);
}
-RefPtr<ModuleDecl> findOrImportModule(
- CompileRequest* request,
+RefPtr<Module> findOrImportModule(
+ Linkage* linkage,
Name* name,
- SourceLoc const& loc)
+ SourceLoc const& loc,
+ DiagnosticSink* sink)
{
- return request->findOrImportModule(name, loc);
+ return linkage->findOrImportModule(name, loc, sink);
}
void Session::addBuiltinSource(
@@ -1101,30 +1483,34 @@ void Session::addBuiltinSource(
String const& path,
String const& source)
{
- RefPtr<CompileRequest> compileRequest = new CompileRequest(this);
- compileRequest->setSourceManager(getBuiltinSourceManager());
+ DiagnosticSink sink;
+ RefPtr<FrontEndCompileRequest> compileRequest = new FrontEndCompileRequest(
+ m_builtinLinkage,
+ &sink);
- auto translationUnitIndex = compileRequest->addTranslationUnit(SourceLanguage::Slang, path);
+ Name* moduleName = getNamePool()->getName(path);
+ auto translationUnitIndex = compileRequest->addTranslationUnit(SourceLanguage::Slang, moduleName);
compileRequest->addTranslationUnitSourceString(
translationUnitIndex,
path,
source);
- SlangResult res = compileRequest->executeActions();
+ SlangResult res = compileRequest->executeActionsInner();
if (SLANG_FAILED(res))
{
- fprintf(stderr, "%s", compileRequest->mDiagnosticOutput.Buffer());
+ char const* diagnostics = sink.outputBuffer.Buffer();
+ fprintf(stderr, "%s", diagnostics);
#ifdef _WIN32
- OutputDebugStringA(compileRequest->mDiagnosticOutput.Buffer());
+ OutputDebugStringA(diagnostics);
#endif
SLANG_UNEXPECTED("error in Slang standard library");
}
// Extract the AST for the code we just parsed
- auto syntax = compileRequest->translationUnits[translationUnitIndex]->SyntaxNode;
+ auto syntax = compileRequest->translationUnits[translationUnitIndex]->getModuleDecl();
// HACK(tfoley): mark all declarations in the "stdlib" so
// that we can detect them later (e.g., so we don't emit them)
@@ -1176,19 +1562,37 @@ Session::~Session()
// implementation of C interface
-#define SESSION(x) reinterpret_cast<Slang::Session *>(x)
-#define REQ(x) reinterpret_cast<Slang::CompileRequest*>(x)
+static SlangSession* convert(Slang::Session* session)
+{ return reinterpret_cast<SlangSession*>(session); }
+
+static Slang::Session* convert(SlangSession* session)
+{ return reinterpret_cast<Slang::Session*>(session); }
+
+static SlangCompileRequest* convert(Slang::EndToEndCompileRequest* request)
+{ return reinterpret_cast<SlangCompileRequest*>(request); }
+
+static Slang::EndToEndCompileRequest* convert(SlangCompileRequest* request)
+{ return reinterpret_cast<Slang::EndToEndCompileRequest*>(request); }
+
+static SlangLinkage* convert(Slang::Linkage* linkage)
+{ return reinterpret_cast<SlangLinkage*>(linkage); }
+
+static Slang::Linkage* convert(SlangLinkage* linkage)
+{ return reinterpret_cast<Slang::Linkage*>(linkage); }
+
+static SlangModule* convert(Slang::Module* module)
+{ return reinterpret_cast<SlangModule*>(module); }
SLANG_API SlangSession* spCreateSession(const char*)
{
- return reinterpret_cast<SlangSession *>(new Slang::Session());
+ return convert(new Slang::Session());
}
SLANG_API void spDestroySession(
SlangSession* session)
{
if(!session) return;
- delete SESSION(session);
+ delete convert(session);
}
SLANG_API void spAddBuiltins(
@@ -1196,7 +1600,7 @@ SLANG_API void spAddBuiltins(
char const* sourcePath,
char const* sourceString)
{
- auto s = SESSION(session);
+ auto s = convert(session);
s->addBuiltinSource(
// TODO(tfoley): Add ability to directly new builtins to the approriate scope
@@ -1210,7 +1614,7 @@ SLANG_API void spSessionSetSharedLibraryLoader(
SlangSession* session,
ISlangSharedLibraryLoader* loader)
{
- auto s = SESSION(session);
+ auto s = convert(session);
if (!loader)
{
@@ -1237,7 +1641,7 @@ SLANG_API void spSessionSetSharedLibraryLoader(
SLANG_API ISlangSharedLibraryLoader* spSessionGetSharedLibraryLoader(
SlangSession* session)
{
- auto s = SESSION(session);
+ auto s = convert(session);
return (s->sharedLibraryLoader == Slang::DefaultSharedLibraryLoader::getSingleton()) ? nullptr : s->sharedLibraryLoader.get();
}
@@ -1245,7 +1649,7 @@ SLANG_API SlangResult spSessionCheckCompileTargetSupport(
SlangSession* session,
SlangCompileTarget target)
{
- auto s = SESSION(session);
+ auto s = convert(session);
return Slang::checkCompileTargetSupport(s, Slang::CodeGenTarget(target));
}
@@ -1253,16 +1657,45 @@ SLANG_API SlangResult spSessionCheckPassThroughSupport(
SlangSession* session,
SlangPassThrough passThrough)
{
- auto s = SESSION(session);
+ auto s = convert(session);
return Slang::checkExternalCompilerSupport(s, Slang::PassThroughMode(passThrough));
}
+
+SLANG_API SlangLinkage* spCreateLinkage(
+ SlangSession* session)
+{
+ auto s = convert(session);
+ auto linkage = new Slang::Linkage(s);
+ return convert(linkage);
+}
+
+SLANG_API void spDestroyLinkage(
+ SlangLinkage* linkage)
+{
+ if(!linkage) return;
+ auto lnk = convert(linkage);
+ delete lnk;
+}
+
+SLANG_API SlangModule* spLoadModule(
+ SlangLinkage* linkage,
+ char const* moduleName)
+{
+ if(!linkage) return nullptr;
+ auto lnk = convert(linkage);
+
+ auto mod = lnk->loadModule(moduleName);
+ return convert(mod);
+}
+
+
SLANG_API SlangCompileRequest* spCreateCompileRequest(
SlangSession* session)
{
- auto s = SESSION(session);
- auto req = new Slang::CompileRequest(s);
- return reinterpret_cast<SlangCompileRequest*>(req);
+ auto s = convert(session);
+ auto req = new Slang::EndToEndCompileRequest(s);
+ return convert(req);
}
/*!
@@ -1272,7 +1705,7 @@ SLANG_API void spDestroyCompileRequest(
SlangCompileRequest* request)
{
if(!request) return;
- auto req = REQ(request);
+ auto req = convert(request);
delete req;
}
@@ -1281,21 +1714,21 @@ SLANG_API void spSetFileSystem(
ISlangFileSystem* fileSystem)
{
if(!request) return;
- REQ(request)->setFileSystem(fileSystem);
+ convert(request)->getLinkage()->setFileSystem(fileSystem);
}
SLANG_API void spSetCompileFlags(
SlangCompileRequest* request,
SlangCompileFlags flags)
{
- REQ(request)->compileFlags = flags;
+ convert(request)->getFrontEndReq()->compileFlags = flags;
}
SLANG_API void spSetDumpIntermediates(
SlangCompileRequest* request,
int enable)
{
- REQ(request)->shouldDumpIntermediates = enable != 0;
+ convert(request)->getBackEndReq()->shouldDumpIntermediates = enable != 0;
}
SLANG_API void spSetLineDirectiveMode(
@@ -1304,13 +1737,13 @@ SLANG_API void spSetLineDirectiveMode(
{
// TODO: validation
- REQ(request)->lineDirectiveMode = Slang::LineDirectiveMode(mode);
+ convert(request)->getBackEndReq()->lineDirectiveMode = Slang::LineDirectiveMode(mode);
}
SLANG_API void spSetCommandLineCompilerMode(
SlangCompileRequest* request)
{
- REQ(request)->isCommandLineCompile = true;
+ convert(request)->isCommandLineCompile = true;
}
@@ -1318,17 +1751,19 @@ SLANG_API void spSetCodeGenTarget(
SlangCompileRequest* request,
SlangCompileTarget target)
{
- auto req = REQ(request);
- req->targets.Clear();
- req->addTarget(Slang::CodeGenTarget(target));
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ linkage->targets.Clear();
+ linkage->addTarget(Slang::CodeGenTarget(target));
}
SLANG_API int spAddCodeGenTarget(
SlangCompileRequest* request,
SlangCompileTarget target)
{
- auto req = REQ(request);
- return (int) req->addTarget(Slang::CodeGenTarget(target));
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ return (int) linkage->addTarget(Slang::CodeGenTarget(target));
}
SLANG_API void spSetTargetProfile(
@@ -1336,8 +1771,9 @@ SLANG_API void spSetTargetProfile(
int targetIndex,
SlangProfileID profile)
{
- auto req = REQ(request);
- req->targets[targetIndex]->targetProfile = Slang::Profile(profile);
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ linkage->targets[targetIndex]->targetProfile = Slang::Profile(profile);
}
SLANG_API void spSetTargetFlags(
@@ -1345,8 +1781,9 @@ SLANG_API void spSetTargetFlags(
int targetIndex,
SlangTargetFlags flags)
{
- auto req = REQ(request);
- req->targets[targetIndex]->targetFlags = flags;
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ linkage->targets[targetIndex]->targetFlags = flags;
}
SLANG_API void spSetTargetFloatingPointMode(
@@ -1354,16 +1791,18 @@ SLANG_API void spSetTargetFloatingPointMode(
int targetIndex,
SlangFloatingPointMode mode)
{
- auto req = REQ(request);
- req->targets[targetIndex]->floatingPointMode = Slang::FloatingPointMode(mode);
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ linkage->targets[targetIndex]->floatingPointMode = Slang::FloatingPointMode(mode);
}
SLANG_API void spSetMatrixLayoutMode(
SlangCompileRequest* request,
SlangMatrixLayoutMode mode)
{
- auto req = REQ(request);
- req->defaultMatrixLayoutMode = Slang::MatrixLayoutMode(mode);
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ linkage->defaultMatrixLayoutMode = Slang::MatrixLayoutMode(mode);
}
SLANG_API void spSetTargetMatrixLayoutMode(
@@ -1380,7 +1819,7 @@ SLANG_API void spSetOutputContainerFormat(
SlangCompileRequest* request,
SlangContainerFormat format)
{
- auto req = REQ(request);
+ auto req = convert(request);
req->containerFormat = Slang::ContainerFormat(format);
}
@@ -1389,7 +1828,7 @@ SLANG_API void spSetPassThrough(
SlangCompileRequest* request,
SlangPassThrough passThrough)
{
- REQ(request)->passThrough = Slang::PassThroughMode(passThrough);
+ convert(request)->passThrough = Slang::PassThroughMode(passThrough);
}
SLANG_API void spSetDiagnosticCallback(
@@ -1400,7 +1839,7 @@ SLANG_API void spSetDiagnosticCallback(
using namespace Slang;
if(!request) return;
- auto req = REQ(request);
+ auto req = convert(request);
ComPtr<ISlangWriter> writer(new CallbackWriter(callback, userData, WriterFlag::IsConsole));
req->setWriter(WriterChannel::Diagnostic, writer);
@@ -1412,7 +1851,7 @@ SLANG_API void spSetWriter(
ISlangWriter* writer)
{
if (!request) return;
- auto req = REQ(request);
+ auto req = convert(request);
req->setWriter(Slang::WriterChannel(chan), writer);
}
@@ -1422,15 +1861,17 @@ SLANG_API ISlangWriter* spGetWriter(
SlangWriterChannel chan)
{
if (!request) return nullptr;
- auto req = REQ(request);
+ auto req = convert(request);
return req->getWriter(Slang::WriterChannel(chan));
}
SLANG_API void spAddSearchPath(
- SlangCompileRequest* request,
- const char* path)
+ SlangCompileRequest* request,
+ const char* path)
{
- REQ(request)->searchDirectories.Add(Slang::SearchDirectory(path));
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ linkage->searchDirectories.searchDirectories.Add(Slang::SearchDirectory(path));
}
SLANG_API void spAddPreprocessorDefine(
@@ -1438,25 +1879,27 @@ SLANG_API void spAddPreprocessorDefine(
const char* key,
const char* value)
{
- REQ(request)->preprocessorDefinitions[key] = value;
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ linkage->preprocessorDefinitions[key] = value;
}
SLANG_API char const* spGetDiagnosticOutput(
SlangCompileRequest* request)
{
if(!request) return 0;
- auto req = REQ(request);
+ auto req = convert(request);
return req->mDiagnosticOutput.begin();
}
SLANG_API SlangResult spGetDiagnosticOutputBlob(
- SlangCompileRequest* request,
- ISlangBlob** outBlob)
+ SlangCompileRequest* request,
+ ISlangBlob** outBlob)
{
if(!request) return SLANG_ERROR_INVALID_PARAMETER;
if(!outBlob) return SLANG_ERROR_INVALID_PARAMETER;
- auto req = REQ(request);
+ auto req = convert(request);
if(!req->diagnosticOutputBlob)
{
@@ -1475,11 +1918,13 @@ SLANG_API int spAddTranslationUnit(
SlangSourceLanguage language,
char const* name)
{
- auto req = REQ(request);
+ SLANG_UNUSED(name);
+
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
- return req->addTranslationUnit(
- Slang::SourceLanguage(language),
- name ? name : "");
+ return frontEndReq->addTranslationUnit(
+ Slang::SourceLanguage(language));
}
SLANG_API void spTranslationUnit_addPreprocessorDefine(
@@ -1488,10 +1933,10 @@ SLANG_API void spTranslationUnit_addPreprocessorDefine(
const char* key,
const char* value)
{
- auto req = REQ(request);
-
- req->translationUnits[translationUnitIndex]->preprocessorDefinitions[key] = value;
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
+ frontEndReq->translationUnits[translationUnitIndex]->preprocessorDefinitions[key] = value;
}
SLANG_API void spAddTranslationUnitSourceFile(
@@ -1500,12 +1945,13 @@ SLANG_API void spAddTranslationUnitSourceFile(
char const* path)
{
if(!request) return;
- auto req = REQ(request);
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
if(!path) return;
if(translationUnitIndex < 0) return;
- if(Slang::UInt(translationUnitIndex) >= req->translationUnits.Count()) return;
+ if(Slang::UInt(translationUnitIndex) >= frontEndReq->translationUnits.Count()) return;
- req->addTranslationUnitSourceFile(
+ frontEndReq->addTranslationUnitSourceFile(
translationUnitIndex,
path);
}
@@ -1533,14 +1979,15 @@ SLANG_API void spAddTranslationUnitSourceStringSpan(
char const* sourceEnd)
{
if(!request) return;
- auto req = REQ(request);
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
if(!sourceBegin) return;
if(translationUnitIndex < 0) return;
- if(Slang::UInt(translationUnitIndex) >= req->translationUnits.Count()) return;
+ if(Slang::UInt(translationUnitIndex) >= frontEndReq->translationUnits.Count()) return;
if(!path) path = "";
- req->addTranslationUnitSourceString(
+ frontEndReq->addTranslationUnitSourceString(
translationUnitIndex,
path,
Slang::UnownedStringSlice(sourceBegin, sourceEnd));
@@ -1553,14 +2000,15 @@ SLANG_API void spAddTranslationUnitSourceBlob(
ISlangBlob* sourceBlob)
{
if(!request) return;
- auto req = REQ(request);
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
if(!sourceBlob) return;
if(translationUnitIndex < 0) return;
- if(Slang::UInt(translationUnitIndex) >= req->translationUnits.Count()) return;
+ if(Slang::UInt(translationUnitIndex) >= frontEndReq->translationUnits.Count()) return;
if(!path) path = "";
- req->addTranslationUnitSourceBlob(
+ frontEndReq->addTranslationUnitSourceBlob(
translationUnitIndex,
path,
sourceBlob);
@@ -1584,17 +2032,13 @@ SLANG_API int spAddEntryPoint(
char const* name,
SlangStage stage)
{
- if(!request) return -1;
- auto req = REQ(request);
- if(!name) return -1;
- if(translationUnitIndex < 0) return -1;
- if(Slang::UInt(translationUnitIndex) >= req->translationUnits.Count()) return -1;
-
- return req->addEntryPoint(
+ return spAddEntryPointEx(
+ request,
translationUnitIndex,
name,
- Slang::Profile(Slang::Stage(stage)),
- Slang::List<Slang::String>());
+ stage,
+ 0,
+ nullptr);
}
SLANG_API int spAddEntryPointEx(
@@ -1606,10 +2050,11 @@ SLANG_API int spAddEntryPointEx(
char const ** genericParamTypeNames)
{
if (!request) return -1;
- auto req = REQ(request);
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
if (!name) return -1;
if (translationUnitIndex < 0) return -1;
- if (Slang::UInt(translationUnitIndex) >= req->translationUnits.Count()) return -1;
+ if (Slang::UInt(translationUnitIndex) >= frontEndReq->translationUnits.Count()) return -1;
Slang::List<Slang::String> typeNames;
for (int i = 0; i < genericParamTypeNameCount; i++)
typeNames.Add(genericParamTypeNames[i]);
@@ -1620,12 +2065,28 @@ SLANG_API int spAddEntryPointEx(
typeNames);
}
+SLANG_API SlangResult spSetGlobalGenericArgs(
+ SlangCompileRequest* request,
+ int genericArgCount,
+ char const** genericArgs)
+{
+ if (!request) return SLANG_FAIL;
+ auto req = convert(request);
+
+ auto& genericArgStrings = req->globalGenericArgStrings;
+ genericArgStrings.Clear();
+ for (int i = 0; i < genericArgCount; i++)
+ genericArgStrings.Add(genericArgs[i]);
+
+ return SLANG_OK;
+}
+
// Compile in a context that already has its translation units specified
SLANG_API SlangResult spCompile(
SlangCompileRequest* request)
{
- auto req = REQ(request);
+ auto req = convert(request);
#if !defined(SLANG_DEBUG_INTERNAL_ERROR)
// By default we'd like to catch as many internal errors as possible,
@@ -1654,7 +2115,7 @@ SLANG_API SlangResult spCompile(
// We will print out information on the exception to help out the user
// in either filing a bug, or locating what in their code created
// a problem.
- req->mSink.diagnose(Slang::SourceLoc(), Slang::Diagnostics::compilationAbortedDueToException, typeid(e).name(), e.Message);
+ req->getSink()->diagnose(Slang::SourceLoc(), Slang::Diagnostics::compilationAbortedDueToException, typeid(e).name(), e.Message);
}
catch (...)
{
@@ -1662,9 +2123,9 @@ SLANG_API SlangResult spCompile(
// `Exception`, so something really fishy is going on. We want to
// let the user know that we messed up, so they know to blame Slang
// and not some other component in their system.
- req->mSink.diagnose(Slang::SourceLoc(), Slang::Diagnostics::compilationAborted);
+ req->getSink()->diagnose(Slang::SourceLoc(), Slang::Diagnostics::compilationAborted);
}
- req->mDiagnosticOutput = req->mSink.outputBuffer.ProduceString();
+ req->mDiagnosticOutput = req->getSink()->outputBuffer.ProduceString();
return res;
#else
// When debugging, we probably don't want to filter out any errors, since
@@ -1680,8 +2141,10 @@ spGetDependencyFileCount(
SlangCompileRequest* request)
{
if(!request) return 0;
- auto req = REQ(request);
- return (int) req->mDependencyFilePaths.Count();
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
+ auto program = frontEndReq->getProgram();
+ return (int) program->getFilePathDependencies().Count();
}
/** Get the path to a file this compilation dependend on.
@@ -1692,16 +2155,19 @@ spGetDependencyFilePath(
int index)
{
if(!request) return 0;
- auto req = REQ(request);
- return req->mDependencyFilePaths[index].begin();
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
+ auto program = frontEndReq->getProgram();
+ return program->getFilePathDependencies()[index].begin();
}
SLANG_API int
spGetTranslationUnitCount(
SlangCompileRequest* request)
{
- auto req = REQ(request);
- return (int) req->translationUnits.Count();
+ auto req = convert(request);
+ auto frontEndReq = req->getFrontEndReq();
+ return (int) frontEndReq->translationUnits.Count();
}
// Get the output code associated with a specific translation unit
@@ -1718,15 +2184,26 @@ SLANG_API void const* spGetEntryPointCode(
int entryPointIndex,
size_t* outSize)
{
- auto req = REQ(request);
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ auto program = req->getSpecializedProgram();
// TODO: We should really accept a target index in this API
- auto targetCount = req->targets.Count();
- if (targetCount == 0)
+ Slang::UInt targetIndex = 0;
+ auto targetCount = linkage->targets.Count();
+ if (targetIndex >= targetCount)
return nullptr;
- auto targetReq = req->targets[0];
+ auto targetReq = linkage->targets[targetIndex];
- Slang::CompileResult& result = targetReq->entryPointResults[entryPointIndex];
+
+ if(entryPointIndex < 0) return nullptr;
+ if(Slang::UInt(entryPointIndex) >= req->entryPoints.Count()) return nullptr;
+ auto entryPoint = program->getEntryPoint(entryPointIndex);
+
+ auto targetProgram = program->getTargetProgram(targetReq);
+ if(!targetProgram)
+ return nullptr;
+ Slang::CompileResult& result = targetProgram->getExistingEntryPointResult(entryPointIndex);
void const* data = nullptr;
size_t size = 0;
@@ -1761,21 +2238,29 @@ SLANG_API SlangResult spGetEntryPointCodeBlob(
if(!request) return SLANG_ERROR_INVALID_PARAMETER;
if(!outBlob) return SLANG_ERROR_INVALID_PARAMETER;
- auto req = REQ(request);
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ auto program = req->getSpecializedProgram();
- int targetCount = (int) req->targets.Count();
+ int targetCount = (int) linkage->targets.Count();
if((targetIndex < 0) || (targetIndex >= targetCount))
{
return SLANG_ERROR_INVALID_PARAMETER;
}
- auto targetReq = req->targets[targetIndex];
+ auto targetReq = linkage->targets[targetIndex];
int entryPointCount = (int) req->entryPoints.Count();
if((entryPointIndex < 0) || (entryPointIndex >= entryPointCount))
{
return SLANG_ERROR_INVALID_PARAMETER;
}
- Slang::CompileResult& result = targetReq->entryPointResults[entryPointIndex];
+ auto entryPointReq = program->getEntryPoint(entryPointIndex);
+
+
+ auto targetProgram = program->getTargetProgram(targetReq);
+ if(!targetProgram)
+ return SLANG_FAIL;
+ Slang::CompileResult& result = targetProgram->getExistingEntryPointResult(entryPointIndex);
auto blob = result.getBlob();
*outBlob = blob.detach();
@@ -1793,13 +2278,9 @@ SLANG_API void const* spGetCompileRequestCode(
SlangCompileRequest* request,
size_t* outSize)
{
- auto req = REQ(request);
-
- void const* data = req->generatedBytecode.Buffer();
- size_t size = req->generatedBytecode.Count();
-
- if(outSize) *outSize = size;
- return data;
+ SLANG_UNUSED(request);
+ SLANG_UNUSED(outSize);
+ return nullptr;
}
// Reflection API
@@ -1808,7 +2289,9 @@ SLANG_API SlangReflection* spGetReflection(
SlangCompileRequest* request)
{
if( !request ) return 0;
- auto req = REQ(request);
+ auto req = convert(request);
+ auto linkage = req->getLinkage();
+ auto program = req->getSpecializedProgram();
// Note(tfoley): The API signature doesn't let the client
// specify which target they want to access reflection
@@ -1818,12 +2301,16 @@ SLANG_API SlangReflection* spGetReflection(
// so that we can do this better, and make it clear that
// `spGetReflection()` is shorthand for `targetIndex == 0`.
//
- auto targetCount = req->targets.Count();
- if (targetCount == 0)
- return 0;
- auto targetReq = req->targets[0];
+ Slang::UInt targetIndex = 0;
+ auto targetCount = linkage->targets.Count();
+ if (targetIndex >= targetCount)
+ return nullptr;
+
+ auto targetReq = linkage->targets[targetIndex];
+ auto targetProgram = program->getTargetProgram(targetReq);
+ auto programLayout = targetProgram->getExistingLayout();
- return (SlangReflection*) targetReq->layout.Ptr();
+ return (SlangReflection*) programLayout;
}
// ... rest of reflection API implementation is in `Reflection.cpp`