Skip to content

Commit f42bf52

Browse files
committed
Resolve 'extern' types during type layout generation if possible
Closes shader-slang#5994 Closes shader-slang#6437
1 parent f7b9745 commit f42bf52

File tree

6 files changed

+356
-8
lines changed

6 files changed

+356
-8
lines changed

cmake/SlangTarget.cmake

+4-8
Original file line numberDiff line numberDiff line change
@@ -507,14 +507,10 @@ function(slang_add_target dir type)
507507
endif()
508508
install(
509509
TARGETS ${target} ${export_args}
510-
ARCHIVE DESTINATION ${archive_subdir}
511-
${ARGN}
512-
LIBRARY DESTINATION ${library_subdir}
513-
${ARGN}
514-
RUNTIME DESTINATION ${runtime_subdir}
515-
${ARGN}
516-
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
517-
${ARGN}
510+
ARCHIVE DESTINATION ${archive_subdir} ${ARGN}
511+
LIBRARY DESTINATION ${library_subdir} ${ARGN}
512+
RUNTIME DESTINATION ${runtime_subdir} ${ARGN}
513+
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ${ARGN}
518514
)
519515
endmacro()
520516

source/slang/slang-parameter-binding.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -2383,6 +2383,21 @@ static RefPtr<TypeLayout> processEntryPointVaryingParameter(
23832383
else if (auto declRefType = as<DeclRefType>(type))
23842384
{
23852385
auto declRef = declRefType->getDeclRef();
2386+
2387+
// If we are trying to get the layout of some extern type, do our best
2388+
// to look it up in other loaded modules and generate the type layout
2389+
// based on that.
2390+
const auto isExtern = declRef.getDecl()->hasModifier<ExternAttribute>() ||
2391+
declRef.getDecl()->hasModifier<ExternModifier>();
2392+
if (isExtern)
2393+
{
2394+
if (const auto declDef = context->layoutContext.lookupExternDecl(declRef.getDecl()))
2395+
{
2396+
declRefType = declDef;
2397+
declRef = declRefType->getDeclRef();
2398+
}
2399+
}
2400+
23862401
if (auto structDeclRef = declRef.as<StructDecl>())
23872402
{
23882403
RefPtr<StructTypeLayout> structLayout = new StructTypeLayout();

source/slang/slang-type-layout.cpp

+82
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "../compiler-core/slang-artifact-desc-util.h"
55
#include "slang-check-impl.h"
66
#include "slang-ir-insts.h"
7+
#include "slang-mangle.h"
78
#include "slang-syntax.h"
89

910
#include <assert.h>
@@ -5015,6 +5016,20 @@ static TypeLayoutResult _createTypeLayout(TypeLayoutContext& context, Type* type
50155016
{
50165017
auto declRef = declRefType->getDeclRef();
50175018

5019+
// If we are trying to get the layout of some extern type, do our best
5020+
// to look it up in other loaded modules and generate the type layout
5021+
// based on that.
5022+
const auto isExtern = declRef.getDecl()->hasModifier<ExternAttribute>() ||
5023+
declRef.getDecl()->hasModifier<ExternModifier>();
5024+
if (isExtern)
5025+
{
5026+
if (const auto declDef = context.lookupExternDecl(declRef.getDecl()))
5027+
{
5028+
declRefType = declDef;
5029+
declRef = declRefType->getDeclRef();
5030+
}
5031+
}
5032+
50185033
if (auto structDeclRef = declRef.as<StructDecl>())
50195034
{
50205035
StructTypeLayoutBuilder typeLayoutBuilder;
@@ -5694,4 +5709,71 @@ GlobalGenericParamDecl* GenericParamTypeLayout::getGlobalGenericParamDecl()
56945709
return rsDeclRef.getDecl();
56955710
}
56965711

5712+
DeclRefType* TypeLayoutContext::lookupExternDecl(Decl* decl)
5713+
{
5714+
if (!externTypeMap)
5715+
buildExternTypeMap();
5716+
DeclRefType* ret = nullptr;
5717+
const auto mangledName = getMangledName(targetReq->getLinkage()->getASTBuilder(), decl);
5718+
externTypeMap->tryGetValue(mangledName, ret);
5719+
return ret;
5720+
}
5721+
5722+
void TypeLayoutContext::buildExternTypeMap()
5723+
{
5724+
externTypeMap.emplace();
5725+
const auto linkage = targetReq->getLinkage();
5726+
5727+
HashSet<String> externNames;
5728+
Dictionary<String, DeclRefType*> allTypes;
5729+
5730+
// Traverse the AST and keep track of all extern names and all type definitions
5731+
// We'll match them up later
5732+
auto processDecl = [&](auto&& go, Decl* decl) -> void
5733+
{
5734+
const auto isExtern =
5735+
decl->hasModifier<ExternAttribute>() || decl->hasModifier<ExternModifier>();
5736+
5737+
if (auto declRefType = as<DeclRefType>(DeclRefType::create(astBuilder, decl)))
5738+
{
5739+
String mangledName = getMangledName(astBuilder, decl);
5740+
5741+
if (isExtern)
5742+
{
5743+
externNames.add(mangledName);
5744+
}
5745+
else
5746+
{
5747+
allTypes[mangledName] = declRefType;
5748+
}
5749+
}
5750+
5751+
if (auto scopeDecl = as<ScopeDecl>(decl))
5752+
{
5753+
for (auto member : scopeDecl->members)
5754+
{
5755+
go(go, member);
5756+
}
5757+
}
5758+
};
5759+
5760+
for (const auto& m : linkage->loadedModulesList)
5761+
{
5762+
const auto& ast = m->getModuleDecl();
5763+
for (auto member : ast->members)
5764+
{
5765+
processDecl(processDecl, member);
5766+
}
5767+
}
5768+
5769+
// Only keep the types that have matching extern declarations
5770+
for (const auto& externName : externNames)
5771+
{
5772+
if (allTypes.containsKey(externName))
5773+
{
5774+
externTypeMap.value()[externName] = allTypes[externName];
5775+
}
5776+
}
5777+
}
5778+
56975779
} // namespace Slang

source/slang/slang-type-layout.h

+7
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,13 @@ struct TypeLayoutContext
11831183
// Options passed to object layout
11841184
ObjectLayoutRulesImpl::Options objectLayoutOptions;
11851185

1186+
// Mangled names to DeclRefType, this is used to match up 'extern' types to
1187+
// their linked in definitions during layout generation
1188+
std::optional<Dictionary<String, DeclRefType*>> externTypeMap;
1189+
1190+
DeclRefType* lookupExternDecl(Decl* decl);
1191+
void buildExternTypeMap();
1192+
11861193
LayoutRulesImpl* getRules() { return rules; }
11871194
LayoutRulesFamilyImpl* getRulesFamily() const { return rules->getLayoutRulesFamily(); }
11881195

0 commit comments

Comments
 (0)