<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slang.git/source/slang/expr-defs.h, 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>2019-05-31T21:20:37+00:00</updated>
<entry>
<title>Use slang- prefix on slang compiler and core source (#973)</title>
<updated>2019-05-31T21:20:37+00:00</updated>
<author>
<name>jsmall-nvidia</name>
<email>jsmall@nvidia.com</email>
</author>
<published>2019-05-31T21:20:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f'/>
<id>urn:sha1:6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f</id>
<content type='text'>
* Prefixing source files in source/slang with slang-

* Prefix source in source/slang with slang- prefix.

* Rename core source files with slang- prefix.

* Update project files.

* Fix problems from automatic merge.
</content>
</entry>
<entry>
<title>Clean up variable declaration class hierarchy (#787)</title>
<updated>2019-01-22T22:57:25+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2019-01-22T22:57:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=a08a3140716b89146bf0a22dc014c5470e90e910'/>
<id>urn:sha1:a08a3140716b89146bf0a22dc014c5470e90e910</id>
<content type='text'>
The AST class hierarchy for variable declarations had a few messy bits.
First, there are more subclasses of `VarDeclBase` than seem strictly necessary; especially for stuff like `struct` member variable which use `StructField` even for `static` fields (which are effectively globals).
Second, the AST node type for the "cases" within an `enum` was made a subclass of `VarDeclBase` for expediency, but this isn't really semantically accurate (and doesn't seem to be paying off much in deduplication of code).

This change tries to address both of those problems.

First, we replace the existing `Variable` and `StructField` cases with a single `VarDecl` case that covers globals, locals, and member variables.
I haven't gone so far as to replace function parameters or generic value parameters, but that might be worth considering as a further clean-up.

Second, we change `EnumCaseDecl` to inherit directly from  `Decl` instead of `VarDeclBase` and add an explicit case for handling them where they were previously handled as if they were variable declarations (this was done by manually surveying all locations in the code that referenced `VarDeclBase`).</content>
</entry>
<entry>
<title>Initial support for dynamic dispatch using "tagged union" types (#772)</title>
<updated>2019-01-16T20:48:11+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2019-01-16T20:48:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=aedf61784606406c090302efd8b7ac668ac997fc'/>
<id>urn:sha1:aedf61784606406c090302efd8b7ac668ac997fc</id>
<content type='text'>
* Initial support for dynamic dispatch using "tagged union" types

Suppose a user declares some generic shader code, like the following:

```hlsl
interface IFrobnicator { ... }
type_param T : IFrobincator;
ParameterBlock&lt;T : IFrobnicator&gt; gFrobnicator;
...
gFrobincator.frobnicate(value);
```

and then they have some concrete implementations of the required interface:

```hlsl
struct A : IFrobnicator { ... }
struct B : IFrobnicator { ... }
```

The current Slang compiler allows them to generate  distinct compiled kernels for the case of `T=A` and the case of `T=B`. This means that the decision of which implementation to use must be made at or before the time when a shader gets bound in the application.

This change adds a new ability where the Slang compiler can generate code to handle the case where `T` might be *either* `A` or `B`, and which case it is will be determined dynamically at runtime. This means a single compiled kernel can handle both cases, and the decision about which code path to run can be made any time before the shader executes.

This new option is supported by defining a *tagged union* type. Via the API, the user specifies that `T` should be specialized to `__TaggedUnion(A,B)` (the double underscore indicates that this is an experimental and unsupported feature at present). We refer to the types `A` and `B` here as the "case" types of the tagged union. Conceptually, the compiler synthesizes a type something like:

```hlsl
struct TU { union { A a; B b; } payload; uint tag; }
```

The user can then allocate a constant buffer to hold their tagged union type, and when they pick a concrete type to use (say `B`), they fill in the first `sizeof(B)` bytes of their buffer with data describing a `B` instance, and then set the `tag` field to the appopriate 0-based index of the case type they chose (in this case the `B` case gets the tag value `1`).

Actually implementing tagged unions takes a few main steps:

* Type parsing was extended to special-case `__TaggedUnion` as a contextual keyword. This is really only intended to be used when parsing types from the API or command-line, and Bad Things are likely to happen if a user ever puts it directly in their code. Eventually construction of tagged unions should be an API feature and not part of the language syntax.

* Semantic checking was extended to recognize that a tagged union like `__TaggedUnion(A,B)` shoud support an interface like `IFrobnicator` whenever all of the case types suport it, as long as the interface is "safe" for use with tagged unions (which means it doesn't use a few of the advancd langauge features like associated types).

* The IR was extended with instructions to represent tagged union types and to extract their tag and the payload for the different cases as needed.

* IR generation was extended to synthesize implementations of interface methods for any interface that a tagged union needs to support. Right now the implementation is simplistic and only handles simple method requirements, which it does by emitting a `switch` instruction to pick between the different cases.

* A new IR pass was introduced to "desugar" any tagged union types used in the code. The downstream HLSL and GLSL compilers don't support `union`s, so we have to instead emit a tagged union as a "bag of bits" and implement loading the data for particular cases from it manually.

* Final code emit mostly Just Works after the above steps, but we had to introduce an explicit IR instruction for bit-casting to handle the output of the desugaring pass.

There are a bunch of gaps and caveats in this implementation, but that seems reasonable for something that is an experimental feature. The various `TODO` comments and assertion failures in unimplemented cases are intended, so that this work can be checked in even if it isn't feature-complete.

* fixup: missing files

* fixup: typos
</content>
</entry>
<entry>
<title>First step toward supporting use of interfaces as existential types (#716)</title>
<updated>2018-12-18T03:26:32+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2018-12-18T03:26:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=583c72af28d2dde5c564d5b56d3c5eb4ae4844f6'/>
<id>urn:sha1:583c72af28d2dde5c564d5b56d3c5eb4ae4844f6</id>
<content type='text'>
* First step toward supporting use of interfaces as existential types

Traditional generics involve universal quantification. E.g., a declaration like:

```
void drive&lt;T : IVehicle&gt;(T vehicle);
```

indicates for *for all* types `T` that implement the `IVehicle` interface, the `drive()` function is available.

In contrast, whend directly using an interface type like:

```
IVehicle v = ...;
v.doSomething();
```

we only know that there *exists* some concrete type (we could call it `E`) such that `v` refers to a value of type `E`, and `E` implements the `IVehicle` interface. In order to perform an operation like `v.doSomething()` we need to "open" the existential value so that we can look at the concrete type and how it implements the `IVehicle.doSomething` requirement.

This change adds a very explicit representation of existentials to Slang's IR. An operation like `e = makeExistential(v, w)` creates a value of some existential type (interfaces being our only existential types for now), by wrapping a concrete value `v` (the type of `v` can be seen as an implicit operand) and a witness table `w` showing that the type of `v` implements the requirements of the chosen interface type.

In turn, opening of an existential is handled with operations `extractExistential{Value|Type|WitnessTable}` which pull the corresponding piece of information out of a value of existential type (which somewhere in the code had to have been created with `makeExistential`).

The change includes a trivial simplification pass that can detect cases where an `extractExistential*` operation is applied direclty to a `makeExistential` operation, so that there is only one possible result that could be extracted. This allows for simplification of existential types used in trivial ways for local variables (this is mostly so I can check in a functional test, rather than to actually support useful code involving interfaces right now).

The logic in the semantic checking phase of the compiler is comparatively more complex.
When we are about to perform member lookup given an expression like `obj.member` we will first check if `obj` has an existential type, and if it does we will construct a suitable local context in which we extract the value, type, and witness table from the existential (these all become explicit AST expression nodes), and then use the extracted value as the base of the lookup operation.

The nature of existential values is that two different values with the same existential (interface) type could wrap concrete values with differnt types, so that we need to carefully refer only to the extracted type/value/witness-table of specific *values*. We handle this right now by conceptually moving the existential-type value into a local variable (by introducing a `LetExpr` that amounts to `let v = &lt;init&gt; in &lt;body&gt;`) and then require that the extract expressions must refer to the (immutable) variable declaration from which they are extracting a value.

(Eventually we should expand this so that when using an immutable local variable of existential type we just use that variable as-is rather than introduce a new temporary)

A simple test case is included that uses an interface type in an almost trivial way for a local variable; this test can be run and produces the expected results.
A more complex test case that passes an existential into a function is included, but left disabled because a more aggressive simplification approach is required to generate working code from it.

* Add missing file for expected test output

* Fixups for merge from top-of-tree
</content>
</entry>
<entry>
<title>Entry point attribute (#447)</title>
<updated>2018-03-19T19:45:23+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2018-03-19T19:45:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=72562144254145612c68534c6b7457764c28acf5'/>
<id>urn:sha1:72562144254145612c68534c6b7457764c28acf5</id>
<content type='text'>
* Typo

* Add [shader(...)] and clean up some literal handling

* Add supporting for validating the `[shader(...)]` attribute, by checking that its argument is a string literal that names a known shader stage.

* Split the `ConstantExpr` class into distinct subclasses rooted at `LiteralExpr`, so we have `BoolLiteralExpr`, `IntegerLiteralExpr`, `FloatingPointLiteralExpr`, and `StringLiteralExpr`

* Add a `String` type to the stdlib, to be used as the type of a string literal.

This change allows code using `[shader(...)]` to be accepted by the front-end again, but it does nothing about emitting it in final HLSL.

* Allow entry points to be specified via [shader(...)]

Before this change, the compiler would track a list of `EntryPointRequest` objects, based on what the suer specified via API and/or command-line options. Each entry point request would get matched up with an AST `FuncDecl` as part of semantic checking, and then the back end steps (layout, codegen, etc.) would work from that information.

This change makes the compiler modal, in that it can *either* continue to use an explicit list of entry point requests (this is the mode when the list is non-empty), or it can rely on user-supplied attributes on entry point functions to drive codegen (this is the mode when the list is empty).

User-specified `[shader(...)]` attributes are processed at the same place where the association from `EntryPointRequest`s to `FuncDecl`s would otherwise be made, and basically does the same thing in the opposite direction: looks for `FuncDecl`s with the appropriate attribute and synthesizes an `EntryPointRequest` for them.

Subsequent processing should ideally not know where a given `EntryPointRequest` came from, and should handle both methods of specifying the entry points equivalently.

One design choice that might not make immediate sense is that we do *not* process a function as an entry point (applying further validation, etc.) just because it has a `[shader(...)]` modifier, unless we are in the appropriate mode (which in this case is the mode where the user didn't specify their own entry points via API or command line). This is to handle cases where the user wants to explicitly compile only one entry point, so that they (1) don't want us to spend time validating code they don't care about, (2) don't want do get output they don't expect, and (3) might actually be presenting us with code that violates the language rules due to a combination of `#define`s in effect (e.g., they might have a `[shader("vertex")]` function that transitively executes a `discard` because of how the preprocessor was configured, but they don't care because they are compiling a fragment entry point). This decision might be something we revisit over time.

As part of this work, I had to add some logic to pick a "profile version" to use for a combination of a target and stage (because when you specify `[shader("vertex")]` the compiler can't tell if you want `vs_5_0`, `vs_5_1`, etc.). This isn't really complete right now, because something like `-target dxbc` *also* doesn't determine a profile, so there is a bit of a kludge at present. We need to figure out a good long-term plan here, which might involve keeping target format, feature level/version, and pipeline stage as truly orthogonal concepts, rather than conflating them. That would involve more work in the API and command-line layers to de-compose things when the user specifies, e.g., `vs_5_1`, but might make downstream logic easier to manage.

* Emit [shader(...)] attribute on entry point for SM 6.1 and later

This should help ensure that the output from Slang can be compiled with dxc `lib_*` profiles.

* Fix warning
</content>
</entry>
<entry>
<title>Remove support for the -no-checking flag (#392)</title>
<updated>2018-02-02T16:49:04+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2018-02-02T16:49:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=0360f81b9741ece65768a65731bd23455a3b7a96'/>
<id>urn:sha1:0360f81b9741ece65768a65731bd23455a3b7a96</id>
<content type='text'>
* Remove support for the -no-checking flag

Fixes #381
Fixes #383
Work on #382

- No longer expose flag through API (`SLANG_COMPILE_FLAG_NO_CHECKING`) and command-line (`-no-checking`) options

- Remove all logic in `check.cpp` that was withholding diagnostics (including errors) when the no-checking mode was enabled

- Remove `HiddenImplicitCastExpr`, which was only created to support no-checking mode (it represented an implicit cast that our checking through was needed, but couldn't emit because it might be wrong)

- Remove logic for storing function bodies as raw token lists when checking is turned off. I'm leaving in the `UnparsedStmt` AST node in case we ever need/want to lazily parse and check function bodies down the line.

- Remove a few of the code-generation paths we had to contend with, but keep the comment about them in place.

- Remove GLSL-based tests that can't meaningfully work with the new approach.

- Fix other tests that used a GLSL baseline so that their GLSL compiles with `-pass-through glslang` instead of invoking `slang` with the `-no-checking` flag.

- Remove tests that were explicitly added to test the "rewriter + IR" path, since that is no longer supported.

There is more cleanup that can be done here, now that we know that AST-based rewrite and IR will never co-exist, but it is probably easier to deal with that as part of removing the AST-based rewrite path.

We've lost some test coverage here, but actually not too much if we consider that we are dropping GLSL input anyway.

* Fixup: test runner was mis-counting ignored tests

* Fixup: turn on dumping on test failure under Travis

* Fixup: enable extensions in Linux build of glslang
</content>
</entry>
<entry>
<title>All compiler fixes to get ir branch work with falcor feature demo.</title>
<updated>2018-01-18T01:54:56+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2018-01-17T19:48:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=caf6f7a03793be3fc74683994414776f3604ad8a'/>
<id>urn:sha1:caf6f7a03793be3fc74683994414776f3604ad8a</id>
<content type='text'>
- support overloaded generic function. this involves adding a new expression type, `OverloadedExpr2` to hold the candidate expressions for the generic function decl being referenced.
- make BitNot a normal IROp instead of an IRPseudoOp
- make sure we clone the decorations of parameters when cloning ir functions
- propagate geometry shader entry point attributes (`[maxvertexcount]` and `[instance]`) through HLSL emit
- IR emit: handle geometry shader entry-point parameter decorations, such as 'triangle'.
- IR emit: treat geometry shader stream output typed ir value as `should fold into use`.
</content>
</entry>
<entry>
<title>Support explicit `this` expressions</title>
<updated>2017-10-30T16:40:04+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoley@nvidia.com</email>
</author>
<published>2017-10-30T15:54:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=42f1cff5c1471e6bc3988a9810c20b8bcc1c84dd'/>
<id>urn:sha1:42f1cff5c1471e6bc3988a9810c20b8bcc1c84dd</id>
<content type='text'>
This is the first step towards supporting traditional object-oriented method definitions; the second step will be to allow `this` expressions to be implicit.

- Add a test case using explicit `this`, and expected output

- Update parsing logic for expressions so that it handled identifiers similarly to the declaration and statement logic: first try to parse using a syntax declaration looked up in the curent scope, and otherwise fall back to the ordinary `VarExpr` case.

  * As long as I'm making that change: switch `true` and `false` to be parsed via the callback mechanism rather than be special-cased.

  * This change will also help out if we ever wanted to add `super`/`base` expressions, `new`, `sizeof`/`alignof` or any other expression keywords.

- Add a `ThisExpr` node and register a parser callback for it.

- Add semantic checks for `ThisExpr`: basically just look upwards through scopes until we find either an aggregate type declaration or an `extension` declaration, and then use that as the type of the expression.

  - TODO: eventually we need to guard against a `this` expression inside of a `static` member.

- The IR generation logic already handled creation of `this` parameters in function signatures; the missing piece was to register the appropriate parameter in the context, so that we can use it as the lowering of a `this` expression.
</content>
</entry>
<entry>
<title>Support IR-based codegen for a few more examples.</title>
<updated>2017-09-11T21:06:02+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoley@nvidia.com</email>
</author>
<published>2017-09-11T16:33:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=2055d540c5dd420448a6924d784d5aed0efcd93d'/>
<id>urn:sha1:2055d540c5dd420448a6924d784d5aed0efcd93d</id>
<content type='text'>
The main interesting change here is around support for lowering of calls to "subscript" operations (what a C++ programmer would think of as `operator[]`).

An important infrastructure change here was to add an explicit AST-node representation for a "static member expression" which we use whenever a member is looked up in a type as opposed to a value. The implementation of  this probably isn't robust yet, but it turns out to be important to be able to tell such cases apart.
</content>
</entry>
<entry>
<title>Move implicit conversion operations to stdlib</title>
<updated>2017-09-05T19:15:28+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoley@nvidia.com</email>
</author>
<published>2017-08-31T21:13:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=ff7c190b838dffc79e5acd555f41506cb52a9f47'/>
<id>urn:sha1:ff7c190b838dffc79e5acd555f41506cb52a9f47</id>
<content type='text'>
- Previously, there were a variety of rules in `check.cpp` to pick the conversion cost for various cases involving scalar, vector, and matrix types.

- The main problem of the previous approach is that any lowering pass would need to convert an arbitrary "type cast" node into the right low-level operation(s).

- The new approach is that a type conversion (implicit or explicit) always resolves as a call to a constructor/initializer for the destination type. This means that the existing rules around marking operations as builtins should work for lowering.

- The support this, the checking logic needs to perform lookup of intializers/constructors when asked to perform conversion between types. It does this by re-using the existing logic for lookup and overload resolution if/when a type was applied in an ordinary context.

- Next, we define a modifier that can be attached to constructors/initializers to mark them as suitable for implicit conversion, and associate them with the correct cost to be used when doing overload comparisons.

- We add the modifier to all the scalar-to-scalar cases in the stdlib, using the logic that previously existed in semantic checking.

- Next we add cases for general vector-to-scalar conversions that also convert type, using the same cost computation as above.

- This probably misses various cases, but at this point they can hopefully be added just in the stdlib.

- One gotcha here is that in lowering, we need to make sure to lower any kind of call expression to another call expression of the same AST node class, so that we don't lose information on what casts were implicit/hidden in teh source-to-source case.

Two notes for potential longer-term changes:

1. There is still some duplication between the type conversion declarations here and the "join" logic for types used for generic arguments. Ideally we'd eventually clean up the "join" logic to be based on convertability, but that isn't a high priority right now, as long as joins continue to pick the right type.

2. It is a bit gross to have to declare all the N^2 conversions for vector/matrix types to duplicate the cases for scalars. For the simple scalar-to-vector case, we might try to support multiple conversion "steps" where both a scalar-to-scalar and a scalar-to-vector step can be allowed (this could be tagged on the modifiers already introduced). That simple option doesn't scale to vector-to-vector element type conversions, though, where you'd really want to make it a generic with a constraint like:

    vector&lt;T,N&gt; init&lt;U&gt;(vector&lt;U,N&gt; value) where T : ConvertibleFrom&lt;U&gt;;

  Here the `ConvertibleFrom&lt;U&gt;` interface expresses the fact that a conforming type has an initializer that takes a `U`. What doesn't appear in this context is any notion of conversion costs. We'd need some kind of system for computing the conversion cost of the vector conversion from the cost of the `T` to `U` converion.
</content>
</entry>
</feed>
