diff --git a/CMakeLists.txt b/CMakeLists.txt index d9e44b0583..782275fd76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,9 @@ get_git_version( project(slang VERSION "${SLANG_VERSION_NUMERIC}" LANGUAGES) set(PROJECT_VERSION "${SLANG_VERSION_FULL}") +# export compile_commands.json for clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + # # Global CMake options # diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp index 2757538a67..7ccbe3cd9f 100644 --- a/source/slang/slang-ir-specialize.cpp +++ b/source/slang/slang-ir-specialize.cpp @@ -1328,7 +1328,52 @@ struct SpecializationContext // If we never found a parameter or return type worth specializing, we should bail out. // if (!returnTypeNeedSpecialization && !argumentNeedSpecialization) + { + auto firstParam = calleeFunc->getFirstParam(); + if (!firstParam) + return false; + + auto firstArg = inst->getArg(0); + // If the first parameter is `this_type(interface_type)`, we will try to see if we + // can specialize this type to some concrete type. + // + // This is a corner case that we can't handle during maybeSpecializeGeneric() call. For + // the specialize call like this `specialize(base, this_type(interface_type), + // witness_table)`, this will specialize the function in the witness_table by using the + // 'this_type(interface_type)' as the first argument. However, we cannot handle this + // case in maybeSpecializeGeneric() because we the concrete type of the + // 'this_type(interface_type)' is not known at that time. So we have to handle this case + // here. + if (auto thisType = as(firstParam->getDataType())) + { + if (as(thisType->getConstraintType())) + { + auto argType = firstArg->getDataType(); + if (isCompileTimeConstantType(argType)) + { + IRBuilder builderStorage(module); + auto builder = &builderStorage; + auto newParam = builder->createParam(argType); + + // Replace the first parameter with the new parameter. + auto firstBlock = calleeFunc->getFirstBlock(); + firstBlock->insertParamAtHead(newParam); + firstParam->transferDecorationsTo(newParam); + firstParam->replaceUsesWith(newParam); + firstParam->removeAndDeallocate(); + + // Replace the first parameter of the function type with the + // concrete type. + auto functionType = calleeFunc->getDataType(); + auto firstParamType = functionType->getParamType(0); + firstParamType->replaceUsesWith(argType); + firstParamType->removeAndDeallocate(); + } + } + } + return false; + } // At this point, we believe we *should* and *can* specialize. //