diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2024-10-29 14:49:26 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-29 14:49:26 +0800 |
| commit | f65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch) | |
| tree | ea1d61342cd29368e19135000ec2948813096205 /source/slang/slang-compiler-tu.cpp | |
| parent | a729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff) | |
format
* format
* Minor test fixes
* enable checking cpp format in ci
Diffstat (limited to 'source/slang/slang-compiler-tu.cpp')
| -rw-r--r-- | source/slang/slang-compiler-tu.cpp | 474 |
1 files changed, 235 insertions, 239 deletions
diff --git a/source/slang/slang-compiler-tu.cpp b/source/slang/slang-compiler-tu.cpp index 5f88e871d..4a74ca64c 100644 --- a/source/slang/slang-compiler-tu.cpp +++ b/source/slang/slang-compiler-tu.cpp @@ -2,298 +2,294 @@ // and emit precompiled blobs into IR #include "../core/slang-basic.h" +#include "slang-capability.h" +#include "slang-check-impl.h" #include "slang-compiler.h" #include "slang-ir-insts.h" #include "slang-ir-util.h" -#include "slang-capability.h" -#include "slang-check-impl.h" namespace Slang { - // Only attempt to precompile functions: - // 1) With function bodies (not just empty decls) - // 2) Not marked with unsafeForceInlineDecoration - // 3) Have a simple HLSL data type as the return or parameter type - static bool attemptPrecompiledExport(IRInst* inst) +// Only attempt to precompile functions: +// 1) With function bodies (not just empty decls) +// 2) Not marked with unsafeForceInlineDecoration +// 3) Have a simple HLSL data type as the return or parameter type +static bool attemptPrecompiledExport(IRInst* inst) +{ + if (inst->getOp() != kIROp_Func) { - if (inst->getOp() != kIROp_Func) - { - return false; - } - - // Skip functions with no body - bool hasBody = false; - for (auto child : inst->getChildren()) - { - if (child->getOp() == kIROp_Block) - { - hasBody = true; - break; - } - } - if (!hasBody) - { - return false; - } - - // Skip functions marked with unsafeForceInlineDecoration - if (inst->findDecoration<IRUnsafeForceInlineEarlyDecoration>()) - { - return false; - } + return false; + } - // Skip non-simple HLSL data types, filters out generics - if (!isSimpleHLSLDataType(inst)) + // Skip functions with no body + bool hasBody = false; + for (auto child : inst->getChildren()) + { + if (child->getOp() == kIROp_Block) { - return false; + hasBody = true; + break; } + } + if (!hasBody) + { + return false; + } - return true; + // Skip functions marked with unsafeForceInlineDecoration + if (inst->findDecoration<IRUnsafeForceInlineEarlyDecoration>()) + { + return false; } - /* - * Precompile the module for the given target. - * - * This function creates a target program and emits the precompiled blob as - * an embedded blob in the module IR, e.g. DXIL, SPIR-V. - * Because the IR for the Slang Module may violate the restrictions of the - * target language, the emitted target blob may not be able to include the - * full module, but rather only the subset that can be precompiled. For - * example, DXIL libraries do not allow resources like structured buffers - * to appear in the library interface. Also, no target languages allow - * generics to be precompiled. - * - * Some restrictions can be enforced up front before linking, but some are - * done during target generation in between IR linking+legalization and - * target source emission. - * - * Functions which can be rejected up front: - * - Functions with no body - * - Functions marked with unsafeForceInlineDecoration - * - Functions that define or use generics - * - * The functions not rejected up front are marked with - * DownstreamModuleExportDecoration which indicates functions we're trying to - * export for precompilation, and this also helps to identify the functions - * in the linked IR which survived the additional pruning. - * - * Functions that are rejected after linking+legalization (inside - * emitPrecompiledDownstreamIR): - * - (DXIL) Functions that return or take a HLSLStructuredBufferType - * - (DXIL) Functions that return or take a Matrix type - * - * emitPrecompiled* produces the output artifact containing target language - * blob, and as metadata, the list of functions which survived the second - * phase of filtering. - * - * The original module IR functions matching those are then marked with - * "AvailableInDownstreamIRDecoration" to indicate to future - * module users which functions are present in the precompiled blob. - */ - SLANG_NO_THROW SlangResult SLANG_MCALL Module::precompileForTarget( - SlangCompileTarget target, - slang::IBlob** outDiagnostics) + // Skip non-simple HLSL data types, filters out generics + if (!isSimpleHLSLDataType(inst)) { - CodeGenTarget targetEnum = CodeGenTarget(target); + return false; + } + + return true; +} - auto module = getIRModule(); - auto linkage = getLinkage(); - auto builder = IRBuilder(module); +/* + * Precompile the module for the given target. + * + * This function creates a target program and emits the precompiled blob as + * an embedded blob in the module IR, e.g. DXIL, SPIR-V. + * Because the IR for the Slang Module may violate the restrictions of the + * target language, the emitted target blob may not be able to include the + * full module, but rather only the subset that can be precompiled. For + * example, DXIL libraries do not allow resources like structured buffers + * to appear in the library interface. Also, no target languages allow + * generics to be precompiled. + * + * Some restrictions can be enforced up front before linking, but some are + * done during target generation in between IR linking+legalization and + * target source emission. + * + * Functions which can be rejected up front: + * - Functions with no body + * - Functions marked with unsafeForceInlineDecoration + * - Functions that define or use generics + * + * The functions not rejected up front are marked with + * DownstreamModuleExportDecoration which indicates functions we're trying to + * export for precompilation, and this also helps to identify the functions + * in the linked IR which survived the additional pruning. + * + * Functions that are rejected after linking+legalization (inside + * emitPrecompiledDownstreamIR): + * - (DXIL) Functions that return or take a HLSLStructuredBufferType + * - (DXIL) Functions that return or take a Matrix type + * + * emitPrecompiled* produces the output artifact containing target language + * blob, and as metadata, the list of functions which survived the second + * phase of filtering. + * + * The original module IR functions matching those are then marked with + * "AvailableInDownstreamIRDecoration" to indicate to future + * module users which functions are present in the precompiled blob. + */ +SLANG_NO_THROW SlangResult SLANG_MCALL +Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnostics) +{ + CodeGenTarget targetEnum = CodeGenTarget(target); - DiagnosticSink sink(linkage->getSourceManager(), Lexer::sourceLocationLexer); - applySettingsToDiagnosticSink(&sink, &sink, linkage->m_optionSet); - applySettingsToDiagnosticSink(&sink, &sink, m_optionSet); + auto module = getIRModule(); + auto linkage = getLinkage(); + auto builder = IRBuilder(module); - RefPtr<TargetRequest> targetReq = new TargetRequest(linkage, targetEnum); + DiagnosticSink sink(linkage->getSourceManager(), Lexer::sourceLocationLexer); + applySettingsToDiagnosticSink(&sink, &sink, linkage->m_optionSet); + applySettingsToDiagnosticSink(&sink, &sink, m_optionSet); - List<RefPtr<ComponentType>> allComponentTypes; - allComponentTypes.add(this); // Add Module as a component type + RefPtr<TargetRequest> targetReq = new TargetRequest(linkage, targetEnum); - for (auto entryPoint : this->getEntryPoints()) - { - allComponentTypes.add(entryPoint); // Add the entry point as a component type - } + List<RefPtr<ComponentType>> allComponentTypes; + allComponentTypes.add(this); // Add Module as a component type - auto composite = CompositeComponentType::create( - linkage, - allComponentTypes); + for (auto entryPoint : this->getEntryPoints()) + { + allComponentTypes.add(entryPoint); // Add the entry point as a component type + } - composite = fillRequirements(composite); + auto composite = CompositeComponentType::create(linkage, allComponentTypes); - TargetProgram tp(composite, targetReq); - tp.getOrCreateLayout(&sink); - Slang::Index const entryPointCount = m_entryPoints.getCount(); - tp.getOptionSet().add(CompilerOptionName::GenerateWholeProgram, true); + composite = fillRequirements(composite); - switch (targetReq->getTarget()) - { - case CodeGenTarget::DXIL: - tp.getOptionSet().add(CompilerOptionName::Profile, Profile::RawEnum::DX_Lib_6_6); - break; - case CodeGenTarget::SPIRV: - break; - default: - return SLANG_FAIL; - } + TargetProgram tp(composite, targetReq); + tp.getOrCreateLayout(&sink); + Slang::Index const entryPointCount = m_entryPoints.getCount(); + tp.getOptionSet().add(CompilerOptionName::GenerateWholeProgram, true); - tp.getOptionSet().add(CompilerOptionName::EmbedDownstreamIR, true); + switch (targetReq->getTarget()) + { + case CodeGenTarget::DXIL: + tp.getOptionSet().add(CompilerOptionName::Profile, Profile::RawEnum::DX_Lib_6_6); + break; + case CodeGenTarget::SPIRV: break; + default: return SLANG_FAIL; + } - CodeGenContext::EntryPointIndices entryPointIndices; + tp.getOptionSet().add(CompilerOptionName::EmbedDownstreamIR, true); - entryPointIndices.setCount(entryPointCount); - for (Index i = 0; i < entryPointCount; i++) - entryPointIndices[i] = i; - CodeGenContext::Shared sharedCodeGenContext(&tp, entryPointIndices, &sink, nullptr); - CodeGenContext codeGenContext(&sharedCodeGenContext); + CodeGenContext::EntryPointIndices entryPointIndices; - // Mark all public functions as exported, ensure there's at least one. Store a mapping - // of function name to IRInst* for later reference. After linking is done, we'll scan - // the linked result to see which functions survived the pruning and are included in the - // precompiled blob. - Dictionary<String, IRInst*> nameToFunction; - bool hasAtLeastOneFunction = false; - for (auto inst : module->getGlobalInsts()) - { - if (attemptPrecompiledExport(inst)) - { - hasAtLeastOneFunction = true; - builder.addDecoration(inst, kIROp_DownstreamModuleExportDecoration); - nameToFunction[inst->findDecoration<IRExportDecoration>()->getMangledName()] = inst; - } - } + entryPointIndices.setCount(entryPointCount); + for (Index i = 0; i < entryPointCount; i++) + entryPointIndices[i] = i; + CodeGenContext::Shared sharedCodeGenContext(&tp, entryPointIndices, &sink, nullptr); + CodeGenContext codeGenContext(&sharedCodeGenContext); - // Bail if there are no functions to export. That's not treated as an error - // because it's possible that the module just doesn't have any simple HLSL. - if (!hasAtLeastOneFunction) + // Mark all public functions as exported, ensure there's at least one. Store a mapping + // of function name to IRInst* for later reference. After linking is done, we'll scan + // the linked result to see which functions survived the pruning and are included in the + // precompiled blob. + Dictionary<String, IRInst*> nameToFunction; + bool hasAtLeastOneFunction = false; + for (auto inst : module->getGlobalInsts()) + { + if (attemptPrecompiledExport(inst)) { - return SLANG_OK; + hasAtLeastOneFunction = true; + builder.addDecoration(inst, kIROp_DownstreamModuleExportDecoration); + nameToFunction[inst->findDecoration<IRExportDecoration>()->getMangledName()] = inst; } + } - ComPtr<IArtifact> outArtifact; - SlangResult res = codeGenContext.emitPrecompiledDownstreamIR(outArtifact); + // Bail if there are no functions to export. That's not treated as an error + // because it's possible that the module just doesn't have any simple HLSL. + if (!hasAtLeastOneFunction) + { + return SLANG_OK; + } - sink.getBlobIfNeeded(outDiagnostics); - if (res != SLANG_OK) - { - return res; - } + ComPtr<IArtifact> outArtifact; + SlangResult res = codeGenContext.emitPrecompiledDownstreamIR(outArtifact); - auto metadata = findAssociatedRepresentation<IArtifactPostEmitMetadata>(outArtifact); - if (!metadata) - { - return SLANG_E_NOT_AVAILABLE; - } + sink.getBlobIfNeeded(outDiagnostics); + if (res != SLANG_OK) + { + return res; + } - for (const auto& mangledName : metadata->getExportedFunctionMangledNames()) - { - auto moduleInst = nameToFunction[mangledName]; - builder.addDecoration(moduleInst, kIROp_AvailableInDownstreamIRDecoration, - builder.getIntValue(builder.getIntType(), (int)targetReq->getTarget())); - auto moduleDec = moduleInst->findDecoration<IRDownstreamModuleExportDecoration>(); - moduleDec->removeAndDeallocate(); - } + auto metadata = findAssociatedRepresentation<IArtifactPostEmitMetadata>(outArtifact); + if (!metadata) + { + return SLANG_E_NOT_AVAILABLE; + } + + for (const auto& mangledName : metadata->getExportedFunctionMangledNames()) + { + auto moduleInst = nameToFunction[mangledName]; + builder.addDecoration( + moduleInst, + kIROp_AvailableInDownstreamIRDecoration, + builder.getIntValue(builder.getIntType(), (int)targetReq->getTarget())); + auto moduleDec = moduleInst->findDecoration<IRDownstreamModuleExportDecoration>(); + moduleDec->removeAndDeallocate(); + } - // Finally, clean up the transient export decorations left over in the module. These are - // represent functions that were pruned from the IR after linking, before target generation. - for (auto moduleInst : module->getGlobalInsts()) + // Finally, clean up the transient export decorations left over in the module. These are + // represent functions that were pruned from the IR after linking, before target generation. + for (auto moduleInst : module->getGlobalInsts()) + { + if (moduleInst->getOp() == kIROp_Func) { - if (moduleInst->getOp() == kIROp_Func) + if (auto dec = moduleInst->findDecoration<IRDownstreamModuleExportDecoration>()) { - if (auto dec = moduleInst->findDecoration<IRDownstreamModuleExportDecoration>()) - { - dec->removeAndDeallocate(); - } + dec->removeAndDeallocate(); } } + } - ComPtr<ISlangBlob> blob; - outArtifact->loadBlob(ArtifactKeep::Yes, blob.writeRef()); + ComPtr<ISlangBlob> blob; + outArtifact->loadBlob(ArtifactKeep::Yes, blob.writeRef()); - // Add the precompiled blob to the module - builder.setInsertInto(module); + // Add the precompiled blob to the module + builder.setInsertInto(module); - builder.emitEmbeddedDownstreamIR(targetReq->getTarget(), blob); - return SLANG_OK; - } + builder.emitEmbeddedDownstreamIR(targetReq->getTarget(), blob); + return SLANG_OK; +} - SLANG_NO_THROW SlangResult SLANG_MCALL Module::getPrecompiledTargetCode( - SlangCompileTarget target, - slang::IBlob** outCode, - slang::IBlob** outDiagnostics) +SLANG_NO_THROW SlangResult SLANG_MCALL Module::getPrecompiledTargetCode( + SlangCompileTarget target, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) +{ + SLANG_UNUSED(outDiagnostics); + for (auto globalInst : getIRModule()->getModuleInst()->getChildren()) { - SLANG_UNUSED(outDiagnostics); - for (auto globalInst : getIRModule()->getModuleInst()->getChildren()) - { - if (auto inst = as<IREmbeddedDownstreamIR>(globalInst)) + if (auto inst = as<IREmbeddedDownstreamIR>(globalInst)) + { + static_assert(CodeGenTarget::DXIL == static_cast<CodeGenTarget>(SLANG_DXIL)); + static_assert(CodeGenTarget::SPIRV == static_cast<CodeGenTarget>(SLANG_SPIRV)); + if (inst->getTarget() == static_cast<CodeGenTarget>(target)) { - static_assert(CodeGenTarget::DXIL == static_cast<CodeGenTarget>(SLANG_DXIL)); - static_assert(CodeGenTarget::SPIRV == static_cast<CodeGenTarget>(SLANG_SPIRV)); - if (inst->getTarget() == static_cast<CodeGenTarget>(target)) - { - auto slice = inst->getBlob()->getStringSlice(); - auto blob = StringBlob::create(slice); - *outCode = blob.detach(); - return SLANG_OK; - } - } - } - return SLANG_FAIL; + auto slice = inst->getBlob()->getStringSlice(); + auto blob = StringBlob::create(slice); + *outCode = blob.detach(); + return SLANG_OK; + } + } } + return SLANG_FAIL; +} - SLANG_NO_THROW SlangInt SLANG_MCALL Module::getModuleDependencyCount() - { - return 0; - } +SLANG_NO_THROW SlangInt SLANG_MCALL Module::getModuleDependencyCount() +{ + return 0; +} - SLANG_NO_THROW SlangResult SLANG_MCALL Module::getModuleDependency( - SlangInt dependencyIndex, - IModule** outModule, - slang::IBlob** outDiagnostics) - { - SLANG_UNUSED(dependencyIndex); - SLANG_UNUSED(outModule); - SLANG_UNUSED(outDiagnostics); - return SLANG_OK; - } +SLANG_NO_THROW SlangResult SLANG_MCALL Module::getModuleDependency( + SlangInt dependencyIndex, + IModule** outModule, + slang::IBlob** outDiagnostics) +{ + SLANG_UNUSED(dependencyIndex); + SLANG_UNUSED(outModule); + SLANG_UNUSED(outDiagnostics); + return SLANG_OK; +} - // ComponentType +// ComponentType - SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::precompileForTarget( - SlangCompileTarget target, - slang::IBlob** outDiagnostics) - { - SLANG_UNUSED(target); - SLANG_UNUSED(outDiagnostics); - return SLANG_FAIL; - } +SLANG_NO_THROW SlangResult SLANG_MCALL +ComponentType::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnostics) +{ + SLANG_UNUSED(target); + SLANG_UNUSED(outDiagnostics); + return SLANG_FAIL; +} - SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getPrecompiledTargetCode( - SlangCompileTarget target, - slang::IBlob** outCode, - slang::IBlob** outDiagnostics) - { - SLANG_UNUSED(target); - SLANG_UNUSED(outCode); - SLANG_UNUSED(outDiagnostics); - return SLANG_FAIL; - } +SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getPrecompiledTargetCode( + SlangCompileTarget target, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) +{ + SLANG_UNUSED(target); + SLANG_UNUSED(outCode); + SLANG_UNUSED(outDiagnostics); + return SLANG_FAIL; +} - SLANG_NO_THROW SlangInt SLANG_MCALL ComponentType::getModuleDependencyCount() - { - return getModuleDependencies().getCount(); - } +SLANG_NO_THROW SlangInt SLANG_MCALL ComponentType::getModuleDependencyCount() +{ + return getModuleDependencies().getCount(); +} - SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getModuleDependency( - SlangInt dependencyIndex, - slang::IModule** outModule, - slang::IBlob** outDiagnostics) +SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getModuleDependency( + SlangInt dependencyIndex, + slang::IModule** outModule, + slang::IBlob** outDiagnostics) +{ + SLANG_UNUSED(outDiagnostics); + if (dependencyIndex < 0 || dependencyIndex >= getModuleDependencies().getCount()) { - SLANG_UNUSED(outDiagnostics); - if (dependencyIndex < 0 || dependencyIndex >= getModuleDependencies().getCount()) - { - return SLANG_E_INVALID_ARG; - } - *outModule = getModuleDependencies()[dependencyIndex]; - return SLANG_OK; + return SLANG_E_INVALID_ARG; } + *outModule = getModuleDependencies()[dependencyIndex]; + return SLANG_OK; } +} // namespace Slang |
