<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slang.git/source/slang/slang-ast-builder.cpp, branch master</title>
<subtitle>Making it easier to work with shaders</subtitle>
<id>https://git.yummers.dev/slang.git/atom?h=master</id>
<link rel='self' href='https://git.yummers.dev/slang.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/'/>
<updated>2025-10-03T04:48:11+00:00</updated>
<entry>
<title>Rename some symbols related to pointers types (#8592)</title>
<updated>2025-10-03T04:48:11+00:00</updated>
<author>
<name>Theresa Foley</name>
<email>10618364+tangent-vector@users.noreply.github.com</email>
</author>
<published>2025-10-03T04:48:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=cc8f6a241edb47c43c5698ee33abed4fe57d4566'/>
<id>urn:sha1:cc8f6a241edb47c43c5698ee33abed4fe57d4566</id>
<content type='text'>
Note that while this change touched a large numer of files, there are no
changes to functionality being made here. The only things being done are
renaming various symbols and, in a few cases, updating or adding
comments for consistency with the new names.

The core of the naming changes are:

* Most things named to refer to `OutType` (e.g., `IROutType`,
`IRBuilder::getOutType()`, etc.) have been consistently renamed to refer
to `OutParamType`, to emphasize that the relevant AST/IR node types are
only intended for use to represent `out` parameters.

* The same change as described above for `OutType` is also made for
`RefType`, which becomes `RefParamType` in most cases. One mess that
this exposes is the way that the `ExplicitRef&lt;T&gt;` type in the core
module currently lowers to `IRRefParamType`. This change sticks to the
rule of not making functional changes, so that mess is left as-is for
now.

* Names referring to `InOutType` have been changed to instead refer to
`BorrowInOutType`. The intention with this naming change is to emphasize
that the Slang rules for `inout` are semantically those of a borrow (or
at least our interpretation of what a borrow means).

* Names referring to `ConstRefType` have been changed to instead refer
to `BorrowInType`. This change starts work on clarifying that the
existing `__constref` modifier was never intended to be a read-only
analogue of `__ref`, and instead is the input-only analogue of `inout`.

* The `ParameterDirection` enum type has been changed to
`ParamPassingMode`, to reflect the fact that the concept of "direction"
fails to capture what is actually being encoded, particularly once we
have modes beyond simple `in`/`out`/`inout`.

While this change does not alter behavior in any case (the user-exposed
Slang language is unchanged), it is intended to set up subsequence
changes that will work to make the handling of these types in the
compiler more nuanced and correct. Breaking this part of the change out
separately is primarily motivated by a desire to minimize the effort for
reviewers.

---------

Co-authored-by: slangbot &lt;186143334+slangbot@users.noreply.github.com&gt;</content>
</entry>
<entry>
<title>fix a crash when using type equality constaint (#8515)</title>
<updated>2025-09-23T15:12:09+00:00</updated>
<author>
<name>kaizhangNV</name>
<email>149626564+kaizhangNV@users.noreply.github.com</email>
</author>
<published>2025-09-23T15:12:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=7740f7905fdebebdbe22011787d432b385f4cd9d'/>
<id>urn:sha1:7740f7905fdebebdbe22011787d432b385f4cd9d</id>
<content type='text'>
Close #8193.

When constructing `TransitiveTypeWitness` node, we should check if there
is operand that represents two equal times. Currently, we only check
whether the operand is `TypeEqualityWitness`, which is not good enough,
because a `DeclaredSubtypeWitness` could also be representing two same
types, in that case, we should also const fold this kind of witness.

Fails to do so, we could finally ends up with a generating a lookup
witness IR on a generic parameter that is not supposed to be looked up.</content>
</entry>
<entry>
<title>Split overloaded uses of RefType in front-end (#8427)</title>
<updated>2025-09-23T01:20:13+00:00</updated>
<author>
<name>Theresa Foley</name>
<email>10618364+tangent-vector@users.noreply.github.com</email>
</author>
<published>2025-09-23T01:20:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=c35b763f811298a6e9c61a4a8eaf805ea98bd608'/>
<id>urn:sha1:c35b763f811298a6e9c61a4a8eaf805ea98bd608</id>
<content type='text'>
Overview
========

This change is the start of an attempt to address how the Slang compiler
codebase has ended up conflating two similar, but semantically distinct,
concepts:

* The long-standing notion of `ref` parameters (only allowed for use in
the builtin modules), which are encoded using a wrapper `Type` in the
AST as part of the representation of the parameters of a `FuncType`.

* A recently-introduced notion of explicit reference types that mirror
the built-in `Ptr` type, with a relationship comparable to that between
pointer and reference types in C++.

The change splits the `Ref&lt;T&gt;` type in the core module into two distinct
types, with one for each of the two use cases. Similarly, the `RefType`
class in the compiler's AST is split into two distinct classes, to
represent the two cases.

Background
==========

The `Ref&lt;T&gt;` type in the core module (hidden and not intended for users
to ever see or use) was originally introduced to encode the `ref`
parameter-passing mode, comparable to the hidden `Out&lt;T&gt;` and `InOut&lt;T&gt;`
types used to encode `out` and `inout` parameter-passing modes. The
`Ref&lt;T&gt;` type in the core module was encoded as a instance of the
`RefType` class in the Slang AST (similar to how `Out&lt;T&gt;` mapped to an
`OutType`). These AST classes were *only* intended to be used by the
compiler front-end as part of its encoding of function types. The
`FuncType` class needed a way to distinguish an `inout int` parameter
from a plain (implicitly `in`) `int` parameter, so these wrapper like
`RefType` and `OutType` were introduced to encode both the parameter
type (`T`) and the parameter-passing mode in a form that could be passed
around as a `Type`.

Notably, the `Ref&lt;T&gt;` type (and `Out&lt;T&gt;`, etc.) were *not* intended to
be type names that ever get uttered in Slang code (not even in the
builtin modules), and the vast majority of the compiler code was not
supposed to ever encounter them. They were an implementation detail of
`FuncType`, and nothing else.

(In hindsight it may have been a mistake to use a nominal type declared
in the core module to implement these wrappers; it might have been a
good idea to use an entirely separate class of `Type` for this case...)

Recent changes to the builtin modules introduced functions that wanted
to *return* a reference (so that the parameter-passing-mode modifiers
like `ref` could not trivially be used), and as part of those changes
the appealingly-named `Ref&lt;T&gt;` type in the core module was re-used for
this new case. Builtin operations were declared with an explicit
`Ref&lt;T&gt;` return type, and parts of the compiler front-end that had
previously been blissfully unaware of the AST's `RefType` (and
`InOutType`, etc.) had to start accounting for the possibility that an
explicit `Ref&lt;T&gt;` would show up.

Related changes also introduced a comparable conflation of the
(unfortunately-named) `constref` parameter-passing modifier and builtin
operations that wanted to return an explicit reference that is
read-only. Both use cases were mapped to the core-module `ConstRef&lt;T&gt;`
type, which appeared in the AST as an instance of the `ConstRefType`
class.

The overlapping use of `ConstRef&lt;T&gt;`` is actually significantly more
troublesome than the `Ref&lt;T&gt;` case because, despite what its name
implies, `constref` was not really supposed to be the read-only analogue
of `ref`, but rather it is closer to the "immutable value borrow"
analogue to `inout`'s "mutable value borrow." The semantics of a "value
borrow" vs. a "memory reference" in Slang have not been very carefully
codified, and the conflation around `ConstRef&lt;T&gt;` has contributed to
things becoming increasingly muddy in the compiler back-end.

Main Changes
============

Core Module
-----------

The `Ref&lt;T&gt;` type has been replaced with two distinct types, with one
for each use case:

* `RefParam&lt;T&gt;` is intended for use when encoding a `ref` parameter in a
function type

* `ExplicitRef&lt;T&gt;` is intended for use when an operation in a builtin
module wants to return a reference

The other types used to represent parameter-passing modes (e.g.,
`InOut&lt;T&gt;`) were renamed to better indicate that their role in defining
parameter types (e.g., `InOutParam&lt;T&gt;`).

The `ExplicitRef&lt;T&gt;` type was given additional generic parameters for
the allowed access and the address space, akin to what `Ptr&lt;T&gt;` now
supports. The pointer dereference operator (prefix `*`) in the core
module should now properly propagate the access and address space of the
pointer over to the reference that gets returned.

The two distinct use cases of `ConstRef&lt;T&gt;` were not split in the way as
`Ref&lt;T&gt;`, instead the case for the `constref` parameter-passing mode
uses `ConstParamRef&lt;T&gt;`, while cases that previously used `ConstRef&lt;T&gt;`
to represent a read-only explicit reference instead now use
`ExplicitRef&lt;T, Access.Read&gt;`.

Prior to this change there were two subscripts declared on pointers: one
in the `Ptr` type itself, and another in an `extension` for pointers
with `Access.ReadWrite`. The comments on the code seemed to indicate
that the catch-all subscript used to only have a `get` accessor, while
the `ref` was only available on read-write pointers, but it seems that
subsequent changes converted the default subscript to support `ref`.
This change eliminates the subscript added via `extension`, since it is
redundant.

AST and Front-End
=================

Similar to the changes in the core module, the AST `RefType` class was
split into:

* `RefParamType` for the case of encoding `ref` parameters

* `ExplicitRefType` for the case where the user meant an explicit
reference type

All the other classes that represent wrappers for encoding
parameter-passing modes (e.g., `OutType`) were similarly renamed (e.g.,
`OutParamType`).

The `ConstRefType` class was simply renamed to `ConstRefParamType`,
because any use cases of `ConstRefType` that intended an explicit
reference type will now use `ExplicitRefType` with `Acccess.Read`.

For convenience, this change includes type aliases to map the old names
for these types over to the new ones (e.g., `using OutType =
OutParamType`) so that the change doesn't need to affect quite so many
lines of code. The `RefType` and `ConstRefType` names are intentionally
left undefined, since it woudl be unsafe to assume that existing use
sites should default to either of the two possible interpretations.

All use cases of `RefType` and `ConstRefType` (and their former shared
base class `RefTypeBase`) were audited and updated to refer to either
`RefParamType`/`ConstRefParamType` or `ExplicitRefType`, as appropriate
(based on whether the context of the code indicated it was working with
parameter-passing mode wrapper types, or explicit reference types).

In many (many) cases comments were added to the code that was updated
(and some unrelated code that needed to be audited along the way) to
note cases where there appears to be something fishy going on in the
compiler and/or there are obvious opportunities for next-step
improvement.

The `QualType` constructor used to infer l-value-ness when passed a
`RefType` or `ConstRefType`; that code was introduced to support
explicit reference types. The code was updated to consult the access
argument of an `ExplicitRefType` to try and determine the right
l-value-ness to use. There is some ambiguity about what should be done
in the case where the value of the generic argument representing the
access cannot be statically determined; a better solution may be needed.

Many other cases in the front-end that were working with `RefType` and
`ConstRefType` for explicit references also need to figure out
l-value-ness, and these were changed to rely on the logic already added
to `QualType` so that it wouldn't have to be duplicated. It isn't clear
if this structure is the best way to tackle the problem, but it seems to
at least be an upgrade over the more strictly ad-hoc logic that was in
place before.

Future Work
===========

IR-Level Work
-------------

The most obvious next step to take is that the split that was made in
the compiler front-end needs to be properly plumbed through all of the
back-end. There appears to be a lot of code in the back end of the
compiler that has made the same conflation of `ref` parameters and
explicit reference types that the front-end did. In practice, any uses
of `ExplicitRef&lt;T&gt;` in the front-end should desugar into plain
pointer-based code in the IR.

Clean Up Parameter-Passing Modes
--------------------------------

The code that handles different parameter-passing modes
(`ParameterDirection`s) and their wrapper types is somewhat scattered
and messy (as found while auditing use cases of `RefType`). A cleanup
pass is warranted to ensure that most code only needs to think about
`ParameterDirection`s. There should ideally be only a single operation
in the front-end that handles determining the `ParameterDirection` of a
parameter based on its modifiers. Similarly, there should be one
operation to wrap a value type based on a parameter direction, and one
operation to derive a `ParameterDirection` from the wrapper type.
Ideally, the accessors for `FuncType` should not provide unrestricted
access to the potentially-wrapped parameter types, and should instead
return some kind of `ParamInfo` struct that encodes both a
`ParameterDirection` and the unwrapped `Type` of the parameter.

Clean Up `QualType`
-------------------

A significant piece of future work that appears required is to
drastically clean up and improve the way that `QualType`s are represente
and handled in the front-end. There are currently various distinct
`bool` flags in `QualType` (some with very unclear meaning) and
differnet parts of the codebase consult/modify only subsets of them; a
clear enumeration of the "value categories" (to use the C++ terminology)
that Slang supports could be quite helpful. Naively, a `QualType` should
at least encode the basic information that a `Ptr` type encodes:

* A value type
* Allowed access (read-only, read-write, etc.)
* Address space

The main additional thing that a `QualType` needs is a way to
distinguish cases where an expression evaluates to:

* A reference to a memory location, where all the information from a
`Ptr` is relevant
* A simple value, such that the access and address space are irrelevant
* A reference to an abstract storage location (a `property`,
`subscript`, or an implicit conversion that needs to support being an
l-value), in which case address space is irrelevant and the "allowed
access" basically amounts to a listing of the accessors the storage
location supports

Eliminate Explicit Reference Types
----------------------------------

Finally, twe should eventually eliminate the `ExplicitRef&lt;T&gt;` type from
the core module (and all of the supporting code from the front-end),
since the feature is not a good fit for the Slang language. We should
find some other way to decorate operations in the builtin module that
need to returns a reference rather than a value (note how `ref`
accessors already avoided exposing explicit reference types, by design).

---------

Co-authored-by: slangbot &lt;186143334+slangbot@users.noreply.github.com&gt;</content>
</entry>
<entry>
<title>Added __magic_enum (#8436)</title>
<updated>2025-09-17T12:46:27+00:00</updated>
<author>
<name>Ronan</name>
<email>ro.cailleau@gmail.com</email>
</author>
<published>2025-09-17T12:46:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=b5078d12127f4ab348b8d6d4c4e8139ba7bfb47f'/>
<id>urn:sha1:b5078d12127f4ab348b8d6d4c4e8139ba7bfb47f</id>
<content type='text'>
Fixes #8406 (and #8410).

`AddressSpace`, `MemoryScope` and `AccessQualifier` are no longer
`BaseType`.
I added a new `__magic_enum` (very similar to `__magic_type`) syntax to
be able to easily create values or these enums from the compiler. (I
don't know if it was the right way to do it, but it works and the
changes are small enough?).

I had a weird bug: `tests/language-feature/capability/address-of.slang`
was failing in `IRBuilder::_findOrEmitConstant(IRConstant&amp; keyInst)`.
When needing a new `u64(0)`, it did not find it in the `ConstantMap`
first, but then failed to add it right after because it already existed
in the map! But this was triggered by `IRPtrType*
IRBuilder::getPtrType(IROp op, IRType* valueType, AccessQualifier
accessQualifier, AddressSpace addressSpace)`, which is a strange
coincidence... but I could not find the issue in what I did. I ended up
bumping unordered_dense, and it solved the issue (so there was a bug in
there).</content>
</entry>
<entry>
<title>[CBP] Pointer frontend changes + groupshared pointer support (#7848)</title>
<updated>2025-08-29T22:52:34+00:00</updated>
<author>
<name>ArielG-NV</name>
<email>159081215+ArielG-NV@users.noreply.github.com</email>
</author>
<published>2025-08-29T22:52:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=7758625d3fea67e55e98e7e4103d56c9918365be'/>
<id>urn:sha1:7758625d3fea67e55e98e7e4103d56c9918365be</id>
<content type='text'>
Resolves #7628
Resolves: #8197

Primary Goals:
1. Add `Access` to pointer
2. AddressSpace::GroupShared support for pointers (SPIR-V)
3. Add `__getAddress()` to replace `&amp;`
* `&amp;` is not updated to `require(cpu)` since slangpy uses `&amp;`. This
means we must: (1) merge PR; (2) replace `&amp;` with `__getAddress()`; (3)
add `require(cpu)` to `&amp;`

Changes:
* Added to `Ptr` the `Access` generic argument &amp; logic (for
`Access::Read`).
* Moved the generic argument `AddressSpace` from `Ptr` to the end of the
type.
* Added pointer casting support between any `Ptr` as long as the
`AddressSpace` is the same
* Disallow globallycoherent T* and coherent T*
* Disallow const T*, T const*, and const T*
* Fixed .natvis display of `ConstantValue` `ValOperandNode`
* Support generic resolution of type-casted integers
* Added `VariablePointer` emitting for spirv + other minor logic needed
for groupshared pointers

Breaking Changes:
* Anyone using the `AddressSpace` of `Ptr` will now have to account for
the `Access` argument
* we disallow various syntax paired with `Ptr` and `T*`

---------

Co-authored-by: slangbot &lt;186143334+slangbot@users.noreply.github.com&gt;</content>
</entry>
<entry>
<title>Introduce CDataLayout &amp; -fvk-use-c-layout (#8136)</title>
<updated>2025-08-21T05:47:18+00:00</updated>
<author>
<name>Julius Ikkala</name>
<email>julius.ikkala@gmail.com</email>
</author>
<published>2025-08-21T05:47:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=35f8e092f2aa3ed5e3cf03387e712f798ff4850e'/>
<id>urn:sha1:35f8e092f2aa3ed5e3cf03387e712f798ff4850e</id>
<content type='text'>
Closes #8112. ~~The issue asks for a "C layout", but in this PR I use
the term "CPU layout" because this naming was pre-existing in the
codebase as `kCPULayoutRulesImpl_`. The primary purpose of this layout
is to match CPU-side struct definitions with the shader side. I'm open
to better naming suggestions, though.~~

Edit: switched back to using `CDataLayout` &amp; `-fvk-use-c-layout`, as the
CPU target depends on the object layout rules of existing CPU layout
rules, but they're incompatible with actual shaders. So a new
`kCLayoutRulesImpl_` was needed anyway.

---------

Co-authored-by: Ellie Hermaszewska &lt;ellieh@nvidia.com&gt;</content>
</entry>
<entry>
<title>A new approach to AST node deduplication (#8072)</title>
<updated>2025-08-06T19:48:02+00:00</updated>
<author>
<name>Theresa Foley</name>
<email>10618364+tangent-vector@users.noreply.github.com</email>
</author>
<published>2025-08-06T19:48:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=352576546bf192b06e425e922d305f0a7d0845fb'/>
<id>urn:sha1:352576546bf192b06e425e922d305f0a7d0845fb</id>
<content type='text'>
* A new approach to AST node deduplication

Background
----------

The Slang compiler currently relies on the idea that AST nodes derived from `Val` are always deduplicated based on their opcode and operands.
Deduplication requires caching, and we thus have to determine the right scope at which to allocate and cache different `Val`s.

We need to ensure that `Val`s that refer to declarations/nodes in a specific compilation session/linkage are not cached in a scope that will outlive that session/linkage (or else the cache will contain garbage pointers).
Conversely, we also need to ensure that any `Val`s that are referred to by something like a builtin module's AST will remain alive at least as long as that module/AST, and that every compilation session/linkage that refers to that module will find that `Val` cached if they try to create an equivalent one.

The existing approach to deduplication has some subtleties:

* A builtin module like the core module needs to be fully loaded (using the `ASTBuilder` for the global session) before any other compilation session might construct `Val`s referring to nodes in the AST of that module.

* The various declarations/types/values cached on the `SharedASTBuilder` need to be created before any user-defined compilation occurs, to ensure that all of the relevant `Val`s are created on the global session's AST builder (see `Session::finalizeSharedASTBuilder`).

* Related to all of the above: the deduplication cache on a non-top-level `ASTBuilder` is initialized by copying the cache from the top-level (global session) `ASTBuilder` on creation. Any subsequent allocations on the global-session `ASTBuilder` will not be visible to the linkage-level `ASTBuilder`. This led to weird things like the *options parsing* logic for `-load-core-module` reaching in and performing a manual copy of the cache from the global session to a linkage to try to restore the invariants.

* Notably, the deduplication logic doesn't actually care if two different linkages create distinct `Val`s that represent the same thing, so long as nothing in the AST of a builtin module will refer to that thing. E.g., if the builtin modules never mention `Ptr&lt;String&gt;`, then two different linkages that both refer to that type will likely construct distinct `Val`s to represent it. Thus the deduplication is not as complete as some might assume.

The subtle ordering considerations when creating `Val`s related to builtin modules has proved to be a sticking point for implementing on-demand deserialization of the builtin modules (in order to improve startup times).

Overview
--------

This change implements a new approach that hopefully makes it easier to ensure correctness, even in the case where AST nodes for builtin modules and `Val`s that refer to those nodes sometimes get created after other compilation has been performed.
The key points of the new approach are:

* `ASTBuilder`s are now explicitly (rather than just implicitly) linked into a hierarchy. Currently the compiler codebase will only create a two-level hierarchy: the `ASTBuilder` for a global session is the parent to all of the `ASTBuilder`s created for `Linkage`s. The expectation is that the code can and will generalize to more levels of nesting.

* When a request is made to create a `Val` (or find it in a cache), there is a single `ASTBuilder` that is determined to be responsible for owning that `Val` for its lifetime. The logic involved is comparable to the way that the `IRBuilder` decides where to insert a "hoistable" (deduplicated) instruction, with the simplification that we are dealing with a tree instead of a CFG.

Details
-------

* `Session::finalizeASTBuilder()` is gone, because it is no longer needed

* The logic in the `ASTBuilder` constructor and in `slang-options.cpp` that was manually copying the `m_cachedNodes` from the global-session `ASTBuilder` over to a linkage's `ASTBuilder` is removed, since it is no longer needed.

* Made every AST node (`NodeBase`) carry a pointer to the `ASTBuilder` that created it. This is wasteful, but makes it easier to be sure the implementation will work.

* Introduced a class `RootASTBuilder`, derived from `ASTBuilder` to represent the root of a given hierarchy of AST builders.

* Every non-root `ASTBuilder` is now constructed with a pointer to its parent builder.

* Changed it so that instead of allocating a `SharedASTBuilder` and then passing it in to create one or more `ASTBuilder`s, the shared AST builder state is more of an implementation detail of the `ASTBuilder` type, and is automatically allocated behind the scenes as part of creating an `ASTBuilder`.

* The inline (defined in header) `ASTBuilder::_getOrCreateImpl()` now just does a first-pass check for an existing cached `Val` and, if it doesn't find one, delegates to `ASTBuilder::_getOrCreateImplSlowPath()`, which encapsulates the logic for the cache-miss case (even if that logic is just two lines).

* The `ASTBuilder::_findAppropriateASTBuilderForVal()` method inspects a `ValNodeDesc` to determine the "deepest" of the AST builders among its operands (falling back to the root AST builder if there are no relevant operands).

* The `ASTBuilder::_getOrCreateValDirectly()` is intended for use when the correct AST builder to use for caching/allocation has already been identified.

* Moved the caching of generic arguments for "default substitutions" out of `ASTBuilder` and onto `GenericDecl` itself. Note that the naming of the old field (`m_cachedGenericDefaultArgs`) was unclear about the fact that this is related to "default substitutions" (where each generic parameter is fed an argument that refers to the parameter itself), and has *nothing* to do with any default argument values that might be set on the generic parameters.

* Changed the global session (`Session`) so that instead of storing pointers to both the root/builtin `ASTBuilder` *and* the corresponding `SharedASTBuilder`, it just retains a pointer to the root `ASTBuilder`. This is consistent with the move toward making the `SharedASTBuilder` just an implementation detail.

Possible Future Work
--------------------

* In theory this change should unblock on-demand AST deserialization, so it would be good to get back to those changes once this new approach lands.

* Many AST node subclasses end up storing their own `ASTBuilder` pointers, which are likely now redundant with the one in `NodeBase`. These should be eliminated where possible.

* A lot of code for AST-related manipulations has been changed over time to require an `ASTBuilder` to be passed in, but at this point such a builder should always be derive-able so long as the operation has at least one non-null AST node available to it.

* Most of the accessors that are currently on `SharedASTBuilder` can/should be migrated to just be on `ASTBuilder`, where they can use the data from the `SharedASTBuilder` as part of their implementation. Ideally most code should only nee to interface with `ASTBuilder`s directly, and will never need to talk to the `SharedASTBuilder`.

* This change cleaned up some of the ownership hierarchy, and made it so that the global session only retains a pointer to the root AST builder (and not the shared state as well). A logical follow-on for that would be to make the `Linkage` more properly own (and thus allocate) its own AST builder (and other related objects), and have the global session only store a pointer to the root linkage (and not point to the various sub-objects directly).

* The `Linkage` and `SourceManager` types have their own form of parent/child hierarchy (restricted to two levels), and could be generalized in a way that is similar to what this change does for `ASTBuilder`. Support for a hierarchy of `Linkage`s could be a powerful tool for end users, if we expose it in the right way.

* format code

---------

Co-authored-by: slangbot &lt;186143334+slangbot@users.noreply.github.com&gt;</content>
</entry>
<entry>
<title>Add check for the variable requirement (#6677)</title>
<updated>2025-05-31T00:16:59+00:00</updated>
<author>
<name>Gangzheng Tong</name>
<email>tonggangzheng@gmail.com</email>
</author>
<published>2025-05-31T00:16:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=da5cf478c6be06c9e6c20917a7d472cbdcb624e3'/>
<id>urn:sha1:da5cf478c6be06c9e6c20917a7d472cbdcb624e3</id>
<content type='text'>
* Add check for the variable requirement

This change adds the capability check for the variables requirement.
With this check, the shader
```
[require(cpp_cuda_glsl_hlsl_metal_spirv)]
Buffer&lt;float&gt; InputTyped;
[require(cpp_cuda_glsl_hlsl_metal_spirv)]
RWBuffer&lt;float&gt; OutputTyped;
```
will issue error if targeting to WSGL
e.g. `.\build\Debug\bin\slangc .\tests\wgsl_no_buffer.slang -o
wgsl_no_buffer.txt -target wgsl -entry Main -stage compute`

.\tests\wgsl_no_buffer.slang(2): error 36108: 'InputTyped' has dependencies that are not compatible on the required target 'wgsl'.
Buffer&lt;float&gt; InputTyped;
              ^~~~~~~~~~
.\tests\wgsl_no_buffer.slang(4): error 36108: 'OutputTyped' has dependencies that are not compatible on the required target 'wgsl'.
RWBuffer&lt;float&gt; OutputTyped;
                ^~~~~~~~~~~

Fixes #6304

* Add var capability tests

* Do capability checks for global var only

* Add inferredCapabilityRequirements to var capability check

* Add requirement to the intrinsic types Buffer/RWBuffer

* format code

* Update capabliity test

* use DefaultDataLayout as default data layout

* Use visitMemberExpr to check the capabilities

* Update the cap tests to match the error messages

* update test to use the ScalarDataLayout for hlsl target

* Update tests check condition to use error number only

* Add default push_constant data layout type

---------

Co-authored-by: slangbot &lt;186143334+slangbot@users.noreply.github.com&gt;</content>
</entry>
<entry>
<title>support specialization constant sized array (#6871)</title>
<updated>2025-05-14T17:11:53+00:00</updated>
<author>
<name>kaizhangNV</name>
<email>149626564+kaizhangNV@users.noreply.github.com</email>
</author>
<published>2025-05-14T17:11:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=375ecfe2903b09f07abeba2eafb88d9a564c1458'/>
<id>urn:sha1:375ecfe2903b09f07abeba2eafb88d9a564c1458</id>
<content type='text'>
Close #6859

Goal of this PR
We want to support an array whose size can be specialization constant for shared/global variable e.g.

layout (constant_id = 0) const uint BLOCK_SIZE = 64;
shared float buf_a[(BLOCK_SIZE + 5) * 4];
Overview of the solution:

During IndexExpr check, we will loose the restriction to allow SpecConst passing, but the size parameter will not be a constant value because it cannot be folded into a constant, so we will make it follow the same logic as generic parameter value, and the size will be represented by FuncCallIntVal/PolynomialIntVal/DeclRefIntVal.

During IR lowering, we will detect whether there is spec constant in the IntVal, and wrap the IRInst with a SpecConstRateType, and propagate the type though the lowering logic, such that the IntVal representing the array size will have SpecConstRateType.

During spirv emit stage, if we detect that a IRInst has SpecConstRateType, we will emit it as SpecConstantOp.

We have to implement new logic to emit OpSpecConstantOp, the existing emit logic doesn't support emitting OpSpecConstantOp, especially this op can embed arithmetic operation at global scope, where we can only emit arithmetic instruct at local. But there are only few instructs we need to support.

Overview of the solution:
This PR doesn't support generic, and we will create a separate PR to extend that, tracked in #6840.</content>
</entry>
<entry>
<title>A new approach to AST serialization (#6854)</title>
<updated>2025-04-22T20:26:57+00:00</updated>
<author>
<name>Theresa Foley</name>
<email>10618364+tangent-vector@users.noreply.github.com</email>
</author>
<published>2025-04-22T20:26:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=1cf3f18a9ca1905a5bc51790ca723815dd5b1400'/>
<id>urn:sha1:1cf3f18a9ca1905a5bc51790ca723815dd5b1400</id>
<content type='text'>
* A new approach to AST serialization

This change completely overhauls the way that AST nodes are being serialized, and the offline source-code generation steps that enable that serialization.
In practice, this ends up being a complete overhaul of the way that *modules* are being serialized (not just the AST part), although things like the serialization format for the Slang IR and for source locations are not affected.

The rest of this commit message is broken down in to sections, in an attempt to help guide anybody looking at the code in how to make sense of all the changes.

The Old C++ Extractor
---------------------

AST serialization used to be driven by information scraped using the `slang-cpp-extractor` tool, which did an ad hoc parse of the C++ declarations of the AST node types and then generated a set of "X macros" that could be for macro-based code generation within the rest of the compiler.
While the existing approach was functional, it wasn't easy to understand or maintain, and it has been getting in the way of forward progress on other features we'd like to work on in the language and compiler.

This change removes the `slang-cpp-extractor` tool entirely.

Marking Up the AST Declarations
-------------------------------

The most notable change that contributors to the compiler may notice is the large number of invocations of a macro `FIDDLE()` on the declarations of the AST node types.

The basic idea is that only declarations (namespaces, types, fields) that are preceded by `FIDDLE()` are visible to the code generator tool.
So if somebody is working with the AST and wondering why a new node type isn't working, or why a field they added isn't being serialized correctly, it is probably because they need to add `FIDDLE()` in front of it.

Generating the Boilerplate Code
-------------------------------

The file `slang-ast-boilerplate.cpp` provides a good example of how the information extracted from the marked-up AST declarations gets used.
In that file, the `FIDDLE TEMPLATE` construct is used to generate type information for each of the AST node types.

Similar logic is used in `slang-ast-forward-declarations.h` to generate the declaration of the `ASTNodeType` enumeration, and forward-declare all the AST node classes.
For many parts of the code, simply including that file replaces the need for the old `slang-generated-*.h` files.

Replacing Visitors and Related Logic
------------------------------------

The old visitor types for the AST used the macros that were generated by `slang-cpp-extractor`, so something new was needed to replace them.
The same goes for the `SLANG_AST_NODE_VIRTUAL_CALL` macros.

The core of the solution implemented here is in `slang-ast-dispatch.h`.
Given a "dispatchable" AST node type (say, `Expr`), a call like:

```
ASTNodeDispatcher&lt;Expr,R&gt;(expr, [&amp;](auto e) { return doSomething(e); })
```

is an expression of type `R`, which does the equivalent of something like:

```
switch(expr-&gt;getTag())
{
case ASTNodeType::VarExpr: return doSomething(static_cast&lt;VarExpr*&gt;(expr));
// ...
}
```

The `SLANG_AST_NODE_VIRTUAL_CALL` macro is now implemented in terms of `ASTNodeDispatcher`.

The implementation of the visitor types is more involved.
The code in this change retains some of the macro names from the original version, just to try and make the parallels more clear.
The visitor types are all implemented on top of the `ASTNodeDispatcher` approach, and use `FIDDLE TEMPLATE` to generate all the boilerplate `visit*()` method declarations.

Refactoring of `Linkage` Module Loading
---------------------------------------

Needing to revisit all the places where modules get deserialized made it clear that there is a lot of complexity and apparent duplication in the core routines on the `Linkage` that get used for loading modules.

This change tries to clean up some of that logic, but it is worth noting that there are two legacy features that get in the way of making things as clean as they should be:

* The `LoadedModuleDictionary` type that gets passed around a lot exists entirely to handle the corner case where somebody uses the Slang API to perform a compilation with multiple `TranslationUnitRequest`s in the same `FrontEndCompileRequest`, and one of the translation units `import`s the module defined by another of the translation units.

* There are a lot of special-case behaviors and routines entirely there to support the `ModuleLibrary` feature, although that feature should be considered deprecated (or at least subject to getting entirely re-designed down the line).

The basic idea of the cleanup is that all of the (non-deprecated) ways load a module from a serialized binary, or compile one from source should now bottleneck through `loadModuleImpl`, which then bifurcates into `loadSourceModuleImpl` for the compilation case and `loadBinaryModuleImpl` for the deserialization case.

High-Level Serialization Approach
---------------------------------

The old serialization logic used the [RIFF](https://en.wikipedia.org/wiki/Resource_Interchange_File_Format) format to encode the high-level structure of things, and this change retains that usage (and actually doubles down on the RIFF usage).

The old serialization system relied on the idea that for any given type `Foo` that wants to support serialization, there should be something like a `SerialFooData` type in C++, that can represent the state of a `Foo`, and then the actual serialization applied to that `SerialFooData`. This means that in most cases there are four pieces of code written:

* During serialization:
  * Copying the data of a `Foo` in memory over to a `SerialFooData` in memory
  * Writing the state of a `SerialFooData` into the serialized data stream

* During deserialization:
  * Reading the state of a `SerialFooData` from a serialized data stream
  * Copying the data of the `SerialFooData` in memory over to a `Foo`

The new logic gets rid of the intermediate `SerialFooData`.

In the serialization direction, we take a `Foo` and write it to the `RIFFContainer` directly, or using some other utilities layered on top of it.

In the deserialization direction, we have additional flexibility. Given a `RIFFContainer::Chunk*` that represents a serialized `Foo`, we often navigate through the in-memory representation of the RIFF data to get to the parts of the serialized value that we actually want/need, without needing to deserialize the entire `Foo`.

To support this kind of operation, this change introduces a few helper types like `ContainerChunkRef` an `ModuleChunkRef`, that are little more than typed wrappers around a `RIFFContainer::Chunk*`.

The Module "Container" Part
---------------------------

A serialized `Module` is encoded as a RIFF chunk, using logic in `slang-serialize-container.cpp` - both before and after this change.
This change reorganizes a lot of the code in that file, to account for the way that eliminating the intermediate `SerialContainerData` type streamlines the overall task of writing out the parts of the module.

In the deserialization logic... there isn't really much to do in `slang-serialize-container.cpp`. Most of the logic in `slang.cpp` and `slang-module-library.cpp` that pertains to deserializing modules uses the `ModuleChunkRef`-based approach, and simply extracts the pieces of the serialized module that it needs.

The Actual Serialization of the AST
-----------------------------------

The actual AST serialization logic is in `slang-serialize-ast.cpp`.
The basic approach in both the writing and reading directions is:

* Use the `FIDDLE TEMPLATE` system to generate a set of functions, one for each AST node type, that recursively invoke the read/write logic on each field of that node (after recursively invoking the case for its direct superclass)

* Use the `ASTNodeDispatcher` system to dispatch out to those functions whene reading or writing anything derived from `NodeBase`

* For now, handle all types *not* derived from `NodeBase` by hand.

There's a lot of room for improvement around that last item: it should be just as easy to generate the serialization and deserialization logic for other types that don't inherit from `NodeBase`, but the current change tries to err on the side of making the logic as explicit and simplistic as possible, rather than trying to get too clever too soon.

The actual serialization *format* used for the AST is almost comically simplistic: the code uses hierarchical RIFF chunks to emulate a JSON-like structure. This is a very wasteful representation (e.g., a `bool` or a null pointer each take up *8 bytes*), but the goal for now is to start with the simplest thing that could possibly work, and only add more cleverness once we are sure it won't get in the way of important future improvements (like lazy/on-demand deserialization or IR and AST, to improve compiler startup times).

The files `slang-serialize.{h,cpp}` have been co-opted to define a new pair of types `Encoder` and `Decoder` that are used for a more-or-less stream-oriented way or reading or writing RIFF chunks for the JSON-like structure.

Almost everything related to the actual AST serialization could do with a cleanup pass, and some time spent on picking good/better names for everything.

Smaller Stuff
-------------

* Cleaned up a lot of code that was using bare `ASTNodeType` or the extractor's `ReflectClassInfo` type to consistently use `SyntaxClass`.

* Fixed an apparent bug in how the destination-driven code genarator was handling `TryExpr`s

* Fixed an apparent bug in how the GLSL legalization pass was handling translation of certain `SV_*` semantics.

* format code

* fixup: template errors caught by non-VS compilers

* format code

* fixup: more template errors

* fixup: more stuff VS didn't catch

* fixup: it's amazing VS doesn't catch these...

* fixup: yet more template stuff VS ignores

* fixup: more VS template nonsense

* fixup: unreachable return macro usage

* fixup: more unreacable returns

* fixup: unused parameter

* fixup: strict aliasing

* fixup: allow missing entry point list chunk

* fixup: wasm build script

* fixup: AST changes since this PR was created

---------

Co-authored-by: slangbot &lt;186143334+slangbot@users.noreply.github.com&gt;
Co-authored-by: Yong He &lt;yonghe@outlook.com&gt;</content>
</entry>
</feed>
