summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-type-layout.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-08-19 15:03:56 -0700
committerGitHub <noreply@github.com>2024-08-19 15:03:56 -0700
commit453683bf44f2112719802eaac2b332d49eebd640 (patch)
treed399db4c9cba90c11980186d3df1ffcc4d423b5a /source/slang/slang-type-layout.cpp
parentecf85df6eee3da76ef54b14e4ab083f22da89e46 (diff)
Tuple swizzling, concat, comparison and `countof`. (#4856)
* Tuple swizzling and element access. * Update proposal status. * Cleanup. * Fix merrge error. * Address review.
Diffstat (limited to 'source/slang/slang-type-layout.cpp')
-rw-r--r--source/slang/slang-type-layout.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index f85fb2c5f..f5fbfafdf 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -4396,6 +4396,77 @@ static TypeLayoutResult _createTypeLayout(
type,
rules);
}
+ else if (auto tupleType = as<TupleType>(type))
+ {
+ // A `Tuple` type is laid out exactly the same way as a `struct` type,
+ // except that we want have a declref to the field.
+
+ StructTypeLayoutBuilder typeLayoutBuilder;
+ StructTypeLayoutBuilder pendingDataTypeLayoutBuilder;
+
+ typeLayoutBuilder.beginLayout(type, rules);
+ auto typeLayout = typeLayoutBuilder.getTypeLayout();
+
+ _addLayout(context, type, typeLayout);
+ for (Index i = 0; i < tupleType->getMemberCount(); i++)
+ {
+ // The members of a `Tuple` type may include existential (interface)
+ // types (including as nested sub-fields), and any types present
+ // in those fields will need to be specialized based on the
+ // input arguments being passed to `_createTypeLayout`.
+ //
+ // We won't know how many type slots each field consumes until
+ // we process it, but we can figure out the starting index for
+ // the slots its will consume by looking at the layout we've
+ // computed so far.
+ //
+ Int baseExistentialSlotIndex = 0;
+ if (auto resInfo = typeLayout->FindResourceInfo(LayoutResourceKind::ExistentialTypeParam))
+ baseExistentialSlotIndex = Int(resInfo->count.getFiniteValue());
+ //
+ // When computing the layout for the field, we will give it access
+ // to all the incoming specialized type slots that haven't already
+ // been consumed/claimed by preceding fields.
+ //
+ auto fieldLayoutContext = context.withSpecializationArgsOffsetBy(baseExistentialSlotIndex);
+
+ auto elementType = tupleType->getMember(i);
+ TypeLayoutResult fieldResult = _createTypeLayout(
+ fieldLayoutContext,
+ elementType,
+ nullptr);
+ auto fieldTypeLayout = fieldResult.layout;
+
+ auto fieldVarLayout = typeLayoutBuilder.addField(DeclRef<VarDeclBase>(), fieldResult);
+
+ // If any of the members of the `Tuple` type had existential/interface
+ // type, then we need to compute a second `StructTypeLayout` that
+ // represents the layout and resource using for the "pending data"
+ // that this type needs to have stored somewhere, but which can't
+ // be laid out in the layout of the type itself.
+ //
+ if (auto fieldPendingDataTypeLayout = fieldTypeLayout->pendingDataTypeLayout)
+ {
+ // We only create this secondary layout on-demand, so that
+ // we don't end up with a bunch of empty structure type layouts
+ // created for no reason.
+ //
+ pendingDataTypeLayoutBuilder.beginLayoutIfNeeded(type, rules);
+ auto fieldPendingVarLayout = pendingDataTypeLayoutBuilder.addField(DeclRef<VarDeclBase>(), fieldPendingDataTypeLayout);
+ fieldVarLayout->pendingVarLayout = fieldPendingVarLayout;
+ }
+ }
+
+ typeLayoutBuilder.endLayout();
+ pendingDataTypeLayoutBuilder.endLayout();
+
+ if (auto pendingDataTypeLayout = pendingDataTypeLayoutBuilder.getTypeLayout())
+ {
+ typeLayout->pendingDataTypeLayout = pendingDataTypeLayout;
+ }
+
+ return _updateLayout(context, type, typeLayoutBuilder.getTypeLayoutResult());
+ }
else if (auto declRefType = as<DeclRefType>(type))
{
auto declRef = declRefType->getDeclRef();