diff options
| author | Yong He <yonghe@outlook.com> | 2025-07-17 16:04:20 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-17 23:04:20 +0000 |
| commit | 094d1ba7cd1eb5f09be05b2e57b5fbd3041cca38 (patch) | |
| tree | f9768d9608ae27ac56aef641fbf9c1cac651711a /source/slang/slang-lower-to-ir.cpp | |
| parent | ed1a0b8b53c7556fbf0ccab4f3496078eea4c8a2 (diff) | |
Prelink ForceInlined functions during lowering. (#7812)
* Prelink ForceInlined functions during lowering.
* Fixes and cleanups.
* Fix warning.
* Fix crash.
Diffstat (limited to 'source/slang/slang-lower-to-ir.cpp')
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 1f5909e94..ab9f85b21 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -18,6 +18,7 @@ #include "slang-ir-inline.h" #include "slang-ir-insert-debug-value-store.h" #include "slang-ir-insts.h" +#include "slang-ir-link.h" #include "slang-ir-loop-inversion.h" #include "slang-ir-lower-defer.h" #include "slang-ir-lower-error-handling.h" @@ -494,6 +495,10 @@ struct SharedIRGenContext Dictionary<IntVal*, IRInst*> mapSpecConstValToIRInst; + // External (imported) unsafeForceInline functions that need to + // prelink into the current module after lowering. + List<IRInst*> externalSymbolsToPrelink; + void setGlobalValue(Decl* decl, LoweredValInfo value) { globalEnv.mapDeclToValue[decl] = value; @@ -10636,6 +10641,30 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> FunctionDeclBase* decl, bool emitBody = true) { + bool isFromDifferentModule = isDeclInDifferentModule(context, decl); + if (isFromDifferentModule && isForceInlineEarly(decl)) + { + // If a function is imported from another module then + // we usually don't want to emit it as a definition, and + // will instead only emit a declaration for it with an + // appropriate `[import(...)]` linkage decoration. + // + // However, if the function is marked with `[__unsafeForceInlineEarly]` + // then we need to make sure the IR for its definition is available + // to the mandatory optimization passes. + // + // We do so by finding the IR function from the imported module, and clone + // the body of the IRFunc from the imported module to the current module. + // + auto importedModule = getModule(decl); + auto irModule = importedModule->getIRModule(); + SLANG_ASSERT(irModule && "Module containing imported decl does not have an IRModule."); + String mangledName = getMangledName(context->astBuilder, decl); + auto importedFunc = irModule->findSymbolByMangledName(mangledName); + SLANG_ASSERT(importedFunc.getCount() > 0); + subContext->shared->externalSymbolsToPrelink.add(importedFunc[0]); + } + IRGeneric* outerGeneric = nullptr; subContext->funcDecl = decl; @@ -10726,32 +10755,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> subBuilder->setInsertInto(irFunc); - // If a function is imported from another module then - // we usually don't want to emit it as a definition, and - // will instead only emit a declaration for it with an - // appropriate `[import(...)]` linkage decoration. - // - // However, if the function is marked with `[__unsafeForceInlineEarly]` - // then we need to make sure the IR for its definition is available - // to the mandatory optimization passes. - // - // TODO: The design here means that we will re-emit the inline - // function from its AST in every module that uses it. We should - // instead have logic to clone the target function in from the - // pre-generated IR for the module that defines it (or do some kind - // of minimal linking to bring in the inline functions). - // - if (!decl->body) - { - // This is a function declaration without a body. - // In Slang we currently try not to support forward declarations - // (although we might have to give in eventually), so - // this case should really only occur for builtin declarations. - } - else if (isDeclInDifferentModule(context, decl) && !isForceInlineEarly(decl)) - { - } - else if (emitBody) + if (emitBody && decl->body && !isFromDifferentModule) { // This is a function definition, so we need to actually // construct IR for the body... @@ -12103,7 +12107,6 @@ RefPtr<IRModule> generateIRForTranslationUnit( validateIRModuleIfEnabled(compileRequest, module); - // We will perform certain "mandatory" optimization passes now. // These passes serve two purposes: // @@ -12122,6 +12125,10 @@ RefPtr<IRModule> generateIRForTranslationUnit( // dumpIR(module); + // Before we can do any validation, we need to prelink [unsafeForceInlineEarly] + // functions. + prelinkIR(translationUnit->module, module, context->shared->externalSymbolsToPrelink); + // First, lower error handling logic into normal control flow. // This includes lowering throwing functions into functions that // returns a `Result<T,E>` value, translating `tryCall` into |
