summaryrefslogtreecommitdiffstats
path: root/source/slang/slang.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang.cpp')
-rw-r--r--source/slang/slang.cpp464
1 files changed, 399 insertions, 65 deletions
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index a3875ef62..b18e4d4d9 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -33,6 +33,12 @@
namespace Slang {
+// Allocate static const storage for the various interface IDs that the Slang API needs to expose
+static const Guid IID_ISlangUnknown = SLANG_UUID_ISlangUnknown;
+static const Guid IID_ISlangBlob = SLANG_UUID_ISlangBlob;
+static const Guid IID_ISession = SLANG_UUID_ISession;
+static const Guid IID_IGlobalSession = SLANG_UUID_IGlobalSession;
+static const Guid IID_IModule = SLANG_UUID_IModule;
Session::Session()
{
@@ -91,6 +97,55 @@ Session::Session()
addBuiltinSource(hlslLanguageScope, "hlsl", getHLSLLibraryCode());
}
+ISlangUnknown* Session::getInterface(const Guid& guid)
+{
+ if(guid == IID_ISlangUnknown || guid == IID_IGlobalSession)
+ return asExternal(this);
+ return nullptr;
+}
+
+SLANG_NO_THROW SlangResult SLANG_MCALL Session::createSession(
+ slang::SessionDesc const& desc,
+ slang::ISession** outSession)
+{
+ RefPtr<Linkage> linkage = new Linkage(this);
+
+ Int targetCount = desc.targetCount;
+ for(Int ii = 0; ii < targetCount; ++ii)
+ {
+ linkage->addTarget(desc.targets[ii]);
+ }
+
+ if(desc.flags & slang::kSessionFlag_FalcorCustomSharedKeywordSemantics)
+ {
+ linkage->m_useFalcorCustomSharedKeywordSemantics = true;
+ }
+
+ linkage->setMatrixLayoutMode(desc.defaultMatrixLayoutMode);
+
+ Int searchPathCount = desc.searchPathCount;
+ for(Int ii = 0; ii < searchPathCount; ++ii)
+ {
+ linkage->addSearchPath(desc.searchPaths[ii]);
+ }
+
+ Int macroCount = desc.preprocessorMacroCount;
+ for(Int ii = 0; ii < macroCount; ++ii)
+ {
+ auto& macro = desc.preprocessorMacros[ii];
+ linkage->addPreprocessorDefine(macro.name, macro.value);
+ }
+
+ *outSession = asExternal(linkage.detach());
+ return SLANG_OK;
+}
+
+SLANG_NO_THROW SlangProfileID SLANG_MCALL Session::findProfile(
+ char const* name)
+{
+ return Slang::Profile::LookUp(name).raw;
+}
+
struct IncludeHandlerImpl : IncludeHandler
{
Linkage* linkage;
@@ -330,9 +385,183 @@ Linkage::Linkage(Session* session)
setFileSystem(nullptr);
}
-// Allocate static const storage for the various interface IDs that the Slang API needs to expose
-static const Guid IID_ISlangUnknown = SLANG_UUID_ISlangUnknown;
-static const Guid IID_ISlangBlob = SLANG_UUID_ISlangBlob;
+ISlangUnknown* Linkage::getInterface(const Guid& guid)
+{
+ if(guid == IID_ISlangUnknown || guid == IID_ISession)
+ return asExternal(this);
+
+ return nullptr;
+}
+
+SLANG_NO_THROW slang::IGlobalSession* SLANG_MCALL Linkage::getGlobalSession()
+{
+ return asExternal(getSessionImpl());
+}
+
+void Linkage::addTarget(
+ slang::TargetDesc const& desc)
+{
+ auto targetIndex = addTarget(CodeGenTarget(desc.format));
+ auto target = targets[targetIndex];
+
+ target->floatingPointMode = FloatingPointMode(desc.floatingPointMode);
+ target->targetFlags = desc.flags;
+ target->targetProfile = Profile(desc.profile);
+}
+
+#if 0
+SLANG_NO_THROW SlangInt SLANG_MCALL Linkage::getTargetCount()
+{
+ return targets.getCount();
+}
+
+SLANG_NO_THROW slang::ITarget* SLANG_MCALL Linkage::getTargetByIndex(SlangInt index)
+{
+ if(index < 0) return nullptr;
+ if(index >= targets.getCount()) return nullptr;
+ return asExternal(targets[index]);
+}
+#endif
+
+SLANG_NO_THROW slang::IModule* SLANG_MCALL Linkage::loadModule(
+ const char* moduleName,
+ slang::IBlob** outDiagnostics)
+{
+ auto name = getNamePool()->getName(moduleName);
+
+ DiagnosticSink sink(getSourceManager());
+ auto module = findOrImportModule(name, SourceLoc(), &sink);
+ sink.getBlobIfNeeded(outDiagnostics);
+
+ return asExternal(module);
+}
+
+SLANG_NO_THROW SlangResult SLANG_MCALL Linkage::createProgram(
+ slang::ProgramDesc const& desc,
+ slang::IProgram** outProgram)
+{
+ RefPtr<Program> program = new Program(this);
+
+ auto itemCount = desc.itemCount;
+ for(SlangInt ii = 0; ii < itemCount; ++ii)
+ {
+ auto& item = desc.items[ii];
+ switch(item.kind)
+ {
+ case slang::ProgramDesc::Item::Kind::Program:
+ {
+ Program* existingProgram = asInternal(item.program);
+ for(auto referencedModule : existingProgram->getModuleDependencies())
+ {
+ program->addReferencedLeafModule(referencedModule);
+ }
+
+ // TODO: Need to decide whether to include the entry points as well...
+ }
+ break;
+
+ case slang::ProgramDesc::Item::Kind::Module:
+ {
+ Module* module = asInternal(item.module);
+ program->addReferencedModule(module);
+ }
+ break;
+
+ default:
+ return SLANG_E_INVALID_ARG;
+ }
+ }
+
+ *outProgram = asExternal(program.detach());
+ return SLANG_OK;
+}
+
+SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL Linkage::specializeType(
+ slang::TypeReflection* inUnspecializedType,
+ slang::SpecializationArg const* specializationArgs,
+ SlangInt specializationArgCount,
+ ISlangBlob** outDiagnostics)
+{
+ auto unspecializedType = asInternal(inUnspecializedType);
+
+ List<Type*> typeArgs;
+
+ for(Int ii = 0; ii < specializationArgCount; ++ii)
+ {
+ auto& arg = specializationArgs[ii];
+ if(arg.kind != slang::SpecializationArg::Kind::Type)
+ return nullptr;
+
+ typeArgs.add(asInternal(arg.type));
+ }
+
+ DiagnosticSink sink(getSourceManager());
+ auto specializedType = specializeType(unspecializedType, typeArgs.getCount(), typeArgs.getBuffer(), &sink);
+ sink.getBlobIfNeeded(outDiagnostics);
+
+ return asExternal(specializedType);
+}
+
+SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL Linkage::getTypeLayout(
+ slang::TypeReflection* inType,
+ SlangInt targetIndex,
+ slang::LayoutRules rules,
+ ISlangBlob** outDiagnostics)
+{
+ auto type = asInternal(inType);
+
+ if(targetIndex < 0 || targetIndex >= targets.getCount())
+ return nullptr;
+
+ auto target = targets[targetIndex];
+
+ // TODO: We need a way to pass through the layout rules
+ // that the user requested (e.g., constant buffers vs.
+ // structured buffer rules). Right now the API only
+ // exposes a single case, so this isn't a big deal.
+ //
+ SLANG_UNUSED(rules);
+
+ auto typeLayout = target->getTypeLayout(type);
+
+ // TODO: We currently don't have a path for capturing
+ // errors that occur during layout (e.g., types that
+ // are invalid because of target-specific layout constraints).
+ //
+ SLANG_UNUSED(outDiagnostics);
+
+ return asExternal(typeLayout);
+}
+
+SLANG_NO_THROW SlangResult SLANG_MCALL Linkage::createCompileRequest(
+ SlangCompileRequest** outCompileRequest)
+{
+ auto compileRequest = new EndToEndCompileRequest(this);
+ *outCompileRequest = asExternal(compileRequest);
+ return SLANG_OK;
+}
+
+SlangResult Linkage::addSearchPath(
+ char const* path)
+{
+ searchDirectories.searchDirectories.add(Slang::SearchDirectory(path));
+ return SLANG_OK;
+}
+
+SlangResult Linkage::addPreprocessorDefine(
+ char const* name,
+ char const* value)
+{
+ preprocessorDefinitions[name] = value;
+ return SLANG_OK;
+}
+
+SlangResult Linkage::setMatrixLayoutMode(
+ SlangMatrixLayoutMode mode)
+{
+ defaultMatrixLayoutMode = MatrixLayoutMode(mode);
+ return SLANG_OK;
+}
/** Base class for simple blobs.
*/
@@ -386,7 +615,7 @@ ComPtr<ISlangBlob> createRawBlob(void const* inData, size_t size)
Session* TargetRequest::getSession()
{
- return linkage->getSession();
+ return linkage->getSessionImpl();
}
MatrixLayoutMode TargetRequest::getDefaultMatrixLayoutMode()
@@ -394,6 +623,29 @@ MatrixLayoutMode TargetRequest::getDefaultMatrixLayoutMode()
return linkage->getDefaultMatrixLayoutMode();
}
+TypeLayout* TargetRequest::getTypeLayout(Type* type)
+{
+ // TODO: We are not passing in a `ProgramLayout` here, although one
+ // is nominally required to establish the global ordering of
+ // generic type parameters, which might be referenced from field types.
+ //
+ // The solution here is to make sure that the reflection data for
+ // uses of global generic/existential types does *not* include any
+ // kind of index in that global ordering, and just refers to the
+ // parameter instead (leaving the user to figure out how that
+ // maps to the ordering via some API on the program layout).
+ //
+ auto layoutContext = getInitialLayoutContextForTarget(this, nullptr);
+
+ RefPtr<TypeLayout> result;
+ if (getTypeLayouts().TryGetValue(type, result))
+ return result.Ptr();
+ result = createTypeLayout(layoutContext, type);
+ getTypeLayouts()[type] = result;
+ return result.Ptr();
+}
+
+
//
// TranslationUnitRequest
//
@@ -485,8 +737,7 @@ RefPtr<Expr> Linkage::parseTypeString(String typeStr, RefPtr<Scope> scope)
Slang::SourceFile* srcFile = localSourceManager.createSourceFileWithString(PathInfo::makeTypeParse(), typeStr);
// We'll use a temporary diagnostic sink
- DiagnosticSink sink;
- sink.sourceManager = &localSourceManager;
+ DiagnosticSink sink(&localSourceManager);
// RAII type to make make sure current SourceManager is restored after parse.
// Use RAII - to make sure everything is reset even if an exception is thrown.
@@ -521,7 +772,7 @@ RefPtr<Expr> Linkage::parseTypeString(String typeStr, RefPtr<Scope> scope)
nullptr);
return parseTypeFromSourceFile(
- getSession(),
+ getSessionImpl(),
tokens, &sink, scope, getNamePool(), SourceLanguage::Slang);
}
@@ -552,7 +803,7 @@ Type* Program::getTypeFromString(String typeStr, DiagnosticSink* sink)
for(auto module : getModuleDependencies())
scopesToTry.add(module->getModuleDecl()->scope);
- auto linkage = getLinkage();
+ auto linkage = getLinkageImpl();
for(auto& s : scopesToTry)
{
RefPtr<Expr> typeExpr = linkage->parseTypeString(
@@ -785,13 +1036,15 @@ SlangResult FrontEndCompileRequest::executeActionsInner()
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();
- }
-
+ // We always generate IR for all the translation units.
+ //
+ // TODO: We may eventually have a mode where we skip
+ // IR codegen and only produce an AST (e.g., for use when
+ // debugging problems in the parser or semantic checking),
+ // but for now there are no cases where not having IR
+ // makes sense.
+ //
+ generateIR();
if (getSink()->GetErrorCount() != 0)
return SLANG_FAIL;
@@ -819,9 +1072,23 @@ BackEndCompileRequest::BackEndCompileRequest(
EndToEndCompileRequest::EndToEndCompileRequest(
Session* session)
: m_session(session)
+ , m_sink(nullptr)
{
m_linkage = new Linkage(session);
+ init();
+}
+EndToEndCompileRequest::EndToEndCompileRequest(
+ Linkage* linkage)
+ : m_session(linkage->getSessionImpl())
+ , m_linkage(linkage)
+ , m_sink(nullptr)
+{
+ init();
+}
+
+void EndToEndCompileRequest::init()
+{
m_sink.sourceManager = m_linkage->getSourceManager();
// Set all the default writers
@@ -919,7 +1186,7 @@ SlangResult EndToEndCompileRequest::executeActionsInner()
entryPointReq->getName(),
entryPointReq->getProfile());
- specializedProgram->addEntryPoint(entryPoint);
+ specializedProgram->addEntryPoint(entryPoint, getSink());
}
}
@@ -1353,6 +1620,12 @@ Module::Module(Linkage* linkage)
: m_linkage(linkage)
{}
+ISlangUnknown* Module::getInterface(const Guid& guid)
+{
+ if(guid == IID_ISlangUnknown || guid == IID_IModule)
+ return asExternal(this);
+ return nullptr;
+}
void Module::addModuleDependency(Module* module)
{
@@ -1367,10 +1640,69 @@ void Module::addFilePathDependency(String const& path)
// Program
+static const Guid IID_IProgram = SLANG_UUID_IProgram;
+
Program::Program(Linkage* linkage)
: m_linkage(linkage)
{}
+ISlangUnknown* Program::getInterface(Guid const& guid)
+{
+ if(guid == IID_ISlangUnknown
+ || guid == IID_IProgram)
+ {
+ return static_cast<slang::IProgram*>(this);
+ }
+
+ return nullptr;
+}
+
+SLANG_NO_THROW slang::ISession* SLANG_MCALL Program::getSession()
+{
+ return m_linkage;
+}
+
+SLANG_NO_THROW slang::ProgramLayout* SLANG_MCALL Program::getLayout(
+ Int targetIndex,
+ slang::IBlob** outDiagnostics)
+{
+ auto linkage = getLinkageImpl();
+ if(targetIndex < 0 || targetIndex >= linkage->targets.getCount())
+ return nullptr;
+ auto target = linkage->targets[targetIndex];
+
+ DiagnosticSink sink(linkage->getSourceManager());
+ auto programLayout = getTargetProgram(target)->getOrCreateLayout(&sink);
+ sink.getBlobIfNeeded(outDiagnostics);
+
+ return asExternal(programLayout);
+}
+
+SLANG_NO_THROW SlangResult SLANG_MCALL Program::getEntryPointCode(
+ SlangInt entryPointIndex,
+ Int targetIndex,
+ slang::IBlob** outCode,
+ slang::IBlob** outDiagnostics)
+{
+ auto linkage = getLinkageImpl();
+ if(targetIndex < 0 || targetIndex >= linkage->targets.getCount())
+ return SLANG_E_INVALID_ARG;
+ auto target = linkage->targets[targetIndex];
+
+ auto targetProgram = getTargetProgram(target);
+
+ DiagnosticSink sink(linkage->getSourceManager());
+ auto& entryPointResult = targetProgram->getOrCreateEntryPointResult(entryPointIndex, &sink);
+ sink.getBlobIfNeeded(outDiagnostics);
+
+ if(entryPointResult.format == ResultFormat::None )
+ return SLANG_FAIL;
+
+ *outCode = entryPointResult.getBlob().detach();
+ return SLANG_OK;
+}
+
+
void Program::addReferencedModule(Module* module)
{
m_moduleDependencyList.addDependency(module);
@@ -1383,13 +1715,27 @@ void Program::addReferencedLeafModule(Module* module)
m_filePathDependencyList.addDependency(module);
}
-void Program::addEntryPoint(EntryPoint* entryPoint)
+void Program::addEntryPoint(EntryPoint* entryPoint, DiagnosticSink* sink)
+{
+ List<RefPtr<EntryPoint>> entryPoints;
+ entryPoints.add(entryPoint);
+
+ RefPtr<EntryPointGroup> entryPointGroup = EntryPointGroup::create(getLinkageImpl(), entryPoints, sink);
+
+ addEntryPointGroup(entryPointGroup);
+}
+
+void Program::addEntryPointGroup(EntryPointGroup* entryPointGroup)
{
- m_entryPoints.add(entryPoint);
+ m_entryPointGroups.add(entryPointGroup);
- for(auto module : entryPoint->getModuleDependencies())
+ for(auto entryPoint : entryPointGroup->getEntryPoints())
{
- addReferencedModule(module);
+ m_entryPoints.add(entryPoint);
+ for(auto module : entryPoint->getModuleDependencies())
+ {
+ addReferencedModule(module);
+ }
}
}
@@ -1398,7 +1744,7 @@ RefPtr<IRModule> Program::getOrCreateIRModule(DiagnosticSink* sink)
if(!m_irModule)
{
m_irModule = generateIRForProgram(
- m_linkage->getSession(),
+ m_linkage->getSessionImpl(),
this,
sink);
}
@@ -1466,7 +1812,7 @@ SlangResult DiagnosticSink::getBlobIfNeeded(ISlangBlob** outBlob)
Session* CompileRequestBase::getSession()
{
- return getLinkage()->getSession();
+ return getLinkage()->getSessionImpl();
}
static const Slang::Guid IID_ISlangFileSystemExt = SLANG_UUID_ISlangFileSystemExt;
@@ -1512,12 +1858,13 @@ void Session::addBuiltinSource(
String const& path,
String const& source)
{
- DiagnosticSink sink;
+ SourceManager* sourceManager = getBuiltinSourceManager();
+
+ DiagnosticSink sink(sourceManager);
RefPtr<FrontEndCompileRequest> compileRequest = new FrontEndCompileRequest(
m_builtinLinkage,
&sink);
- SourceManager* sourceManager = getBuiltinSourceManager();
// Set the source manager on the sink
sink.sourceManager = sourceManager;
@@ -1611,20 +1958,24 @@ static SlangCompileRequest* convert(Slang::EndToEndCompileRequest* 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 convert(new Slang::Session());
}
+SLANG_API SlangResult slang_createGlobalSession(
+ SlangInt apiVersion,
+ slang::IGlobalSession** outGlobalSession)
+{
+ if(apiVersion != 0)
+ return SLANG_E_NOT_IMPLEMENTED;
+
+ Slang::Session* globalSession = new Slang::Session();
+ Slang::ComPtr<slang::IGlobalSession> result(Slang::asExternal(globalSession));
+ *outGlobalSession = result.detach();
+ return SLANG_OK;
+}
+
SLANG_API void spDestroySession(
SlangSession* session)
{
@@ -1698,35 +2049,6 @@ SLANG_API SlangResult spSessionCheckPassThroughSupport(
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)
{
@@ -1839,7 +2161,7 @@ SLANG_API void spSetMatrixLayoutMode(
{
auto req = convert(request);
auto linkage = req->getLinkage();
- linkage->defaultMatrixLayoutMode = Slang::MatrixLayoutMode(mode);
+ linkage->setMatrixLayoutMode(mode);
}
SLANG_API void spSetTargetMatrixLayoutMode(
@@ -1932,7 +2254,7 @@ SLANG_API void spAddSearchPath(
{
auto req = convert(request);
auto linkage = req->getLinkage();
- linkage->searchDirectories.searchDirectories.add(Slang::SearchDirectory(path));
+ linkage->addSearchPath(path);
}
SLANG_API void spAddPreprocessorDefine(
@@ -1942,7 +2264,7 @@ SLANG_API void spAddPreprocessorDefine(
{
auto req = convert(request);
auto linkage = req->getLinkage();
- linkage->preprocessorDefinitions[key] = value;
+ linkage->addPreprocessorDefine(key, value);
}
SLANG_API char const* spGetDiagnosticOutput(
@@ -2391,6 +2713,18 @@ SLANG_API void const* spGetCompileRequestCode(
// Reflection API
+SLANG_API SlangResult spCompileRequest_getProgram(
+ SlangCompileRequest* request,
+ slang::IProgram** outProgram)
+{
+ if( !request ) return SLANG_ERROR_INVALID_PARAMETER;
+ auto req = convert(request);
+ auto program = req->getSpecializedProgram();
+
+ *outProgram = Slang::ComPtr<slang::IProgram>(program).detach();
+ return SLANG_OK;
+}
+
SLANG_API SlangReflection* spGetReflection(
SlangCompileRequest* request)
{