summaryrefslogtreecommitdiff
path: root/source/slang/slang-compiler-tu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-compiler-tu.cpp')
-rw-r--r--source/slang/slang-compiler-tu.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/source/slang/slang-compiler-tu.cpp b/source/slang/slang-compiler-tu.cpp
new file mode 100644
index 000000000..b007e7b71
--- /dev/null
+++ b/source/slang/slang-compiler-tu.cpp
@@ -0,0 +1,115 @@
+// slang-compiler-tu.cpp: Compiles translation units to target language
+// and emit precompiled blobs into IR
+
+#include "../core/slang-basic.h"
+#include "slang-compiler.h"
+#include "slang-ir-insts.h"
+#include "slang-capability.h"
+
+namespace Slang
+{
+ SLANG_NO_THROW SlangResult SLANG_MCALL Module::precompileForTargets(
+ DiagnosticSink* sink,
+ EndToEndCompileRequest* endToEndReq,
+ TargetRequest* targetReq)
+ {
+ auto module = getIRModule();
+ Slang::Session* session = endToEndReq->getSession();
+ Slang::ASTBuilder* astBuilder = session->getGlobalASTBuilder();
+ Slang::Linkage* builtinLinkage = session->getBuiltinLinkage();
+ Slang::Linkage linkage(session, astBuilder, builtinLinkage);
+
+ CapabilityName precompileRequirement = CapabilityName::Invalid;
+ switch (targetReq->getTarget())
+ {
+ case CodeGenTarget::DXIL:
+ linkage.addTarget(Slang::CodeGenTarget::DXIL);
+ precompileRequirement = CapabilityName::dxil_lib;
+ break;
+ default:
+ assert(!"Unhandled target");
+ break;
+ }
+ SLANG_ASSERT(precompileRequirement != CapabilityName::Invalid);
+
+ // Ensure precompilation capability requirements are met.
+ auto targetCaps = targetReq->getTargetCaps();
+ auto precompileRequirementsCapabilitySet = CapabilitySet(precompileRequirement);
+ if (targetCaps.atLeastOneSetImpliedInOther(precompileRequirementsCapabilitySet) == CapabilitySet::ImpliesReturnFlags::NotImplied)
+ {
+ // If `RestrictiveCapabilityCheck` is true we will error, else we will warn.
+ // error ...: dxil libraries require $0, entry point compiled with $1.
+ // warn ...: dxil libraries require $0, entry point compiled with $1, implicitly upgrading capabilities.
+ maybeDiagnoseWarningOrError(
+ sink,
+ targetReq->getOptionSet(),
+ DiagnosticCategory::Capability,
+ SourceLoc(),
+ Diagnostics::incompatibleWithPrecompileLib,
+ Diagnostics::incompatibleWithPrecompileLibRestrictive,
+ precompileRequirementsCapabilitySet,
+ targetCaps);
+
+ // add precompile requirements to the cooked targetCaps
+ targetCaps.join(precompileRequirementsCapabilitySet);
+ if (targetCaps.isInvalid())
+ {
+ sink->diagnose(SourceLoc(), Diagnostics::unknownCapability, targetCaps);
+ return SLANG_FAIL;
+ }
+ else
+ {
+ targetReq->setTargetCaps(targetCaps);
+ }
+ }
+
+ List<RefPtr<ComponentType>> allComponentTypes;
+ allComponentTypes.add(this); // Add Module as a component type
+
+ for (auto entryPoint : this->getEntryPoints())
+ {
+ allComponentTypes.add(entryPoint); // Add the entry point as a component type
+ }
+
+ auto composite = CompositeComponentType::create(
+ &linkage,
+ allComponentTypes);
+
+ TargetProgram tp(composite, targetReq);
+ tp.getOrCreateLayout(sink);
+ Slang::Index const entryPointCount = m_entryPoints.getCount();
+
+ CodeGenContext::EntryPointIndices entryPointIndices;
+
+ entryPointIndices.setCount(entryPointCount);
+ for (Index i = 0; i < entryPointCount; i++)
+ entryPointIndices[i] = i;
+ CodeGenContext::Shared sharedCodeGenContext(&tp, entryPointIndices, sink, endToEndReq);
+ CodeGenContext codeGenContext(&sharedCodeGenContext);
+
+ ComPtr<IArtifact> outArtifact;
+ SlangResult res = codeGenContext.emitTranslationUnit(outArtifact);
+ if (res != SLANG_OK)
+ {
+ return res;
+ }
+
+ ISlangBlob* blob;
+ outArtifact->loadBlob(ArtifactKeep::Yes, &blob);
+
+ auto builder = IRBuilder(module);
+ builder.setInsertInto(module);
+
+ switch (targetReq->getTarget())
+ {
+ case CodeGenTarget::DXIL:
+ builder.emitEmbeddedDXIL(blob);
+ break;
+ default:
+ assert(!"Unhandled target");
+ break;
+ }
+
+ return SLANG_OK;
+ }
+}