I suspect this is actually a bug in parameter setup for inline function
calls, but it would certainly be a bug to get an unprocessed swizzle
expression as they're generated from field expressions.
It's just a jump to a label at the end of the block, but it's enough for
now as it takes care of the assumption that the return is the last
expression in the inlined function.
The code is pretty lousy in that it assumes there's only one `return`
and it's the end of the function, and the generated code is even worse
(too many load/store ops in the spir-v), but it looks like it at least
works. It does pass validation.
This gets the incoming parameters initialized, though currently rather
suboptimally (but that's due to the setup of the call). Next, just need
to handle `return` in inline functions.
Sometimes, premature optimization can help, but whatever. Finally,
alias.vert compiles, but the output is fairly broken (incorrect handling
of `return` and the parameters aren't initialized).
They need a valid name for the stricter checks. The name is taken from
the interface name, and since that needs to be unique, prepending a `.`
should be enough.
However, once past a couple of errors, they're not getting initialized
in the spir-v, so I've probably missed something there. For now I've
kept things simple and made them regular variables regardless of
qualifiers (and no support for out/inout yet).
If the block's result is just a variable reference, it won't match any
expression in the block's list so it needs to be processed independently
in such cases. The `mix(genFType x, genFType y, float a)` inline now
gets as far as spir-v code gen although there are still many issues to
fix (parameter symbols, `return` handling, etc).
I decided to not mess with actual casts. In retrospect, this is probably
for the best as it avoids any bit-cast conflicts, but should allow for
block initializers with a few tweaks. `@construct (type, args...)` in
Ruamoko follows the same path as `type(args...)` in glsl.
They're buggy in that the defspaces for parameters and locals are
incorrect (they need to point to the calling scope's space). Also,
parameters are not yet hooked up correctly. However, errors (because I
need to allow casts from scalars to vectors) do get handled.
Because the symbol tables for generic functions are ephemeral (as such),
they need to be easily removed from the scope chain, it's easiest if
definitions are never added to them (instead, they get added to the
parent symbol table). This keeps handling of function declarations or
definitions and their parameter scopes simple as the function gets put
in the global scope still, and the parameter scope simply gets
reconnected to the global scope (really, the generic scope's parent)
when the parameter scope is popped within a generic scope.
I guess either I goofed and thought void functions had no return type at
all, or at one stage that was the case, but either way, I had never
tested procedures.
The back-end support for renamed builtins (fte's = #0:name) was needed
for pascal functions because the internal name is now prefixed with an @
to allow the lvalue/rvalue selection of behavior for function symbols
This catches qp up with qc and glsl, which means I can modify all three
languages to support inline functions at the same time. There is the
minor(?) problem of attempting to pass parameters to a
function/procedure that takes none producing the wrong error, but that's
documented in the parser.
xvalue symbols refer to two expressions: an lvalue and an rvalue. They
are meant to be used with xvalue expressions.
xvalue expressions are useful when a distinction must be made between
the behavior of something (eg, a pascal function symbol) must change
depending on whether it's an lvalue (assignment of the function's return
value) or an rvalue (a call to the function, especially when the
function takes no parameters).
Because the glsl front-end uses Ruamoko to compile its builtins, it
needs to switch languages, and the cleanest way to do so is to use a
context object that gets passed around. This removes not only the
current_language global, but also (as a bonus) any real references to
flex's scanner object (there's still a pointer in rua_ctx_t, but it's no
longer a parameter (which caused some pain in the change)).
While it is a pessimism, I really want to get rid of fold_constants (in
favor of something smarter), and it's currently in the way of more
important things.
The main goal was to make it possible to give generic functions
definitions (since the code would be very dependent on the actual
parameter types), but will also allow for inline functions. It also
helped move a lot of the back-end dependent code out of semantics
processing and almost completely (if not completely) out of the parser.
Possibly more importantly, it gets the dags flushing out of the parser,
which means such is now shared by all front-ends.
There's probably a lot of dead code in expr.c now, but that can be taken
care of another time.
When getting an offset alias of an already aliased def, the offset needs
to be updated so it points to the correct part of the def. This is
actually a rather old bug but it got uncovered somehow with my rework of
the ruamoko semantic processing (probably an altered cast).
I guess I'd wanted to avoid supporting automatic types in type
functions, but that broke long and unsigned int: either no type, or just
int, depending on the decl style.
Unfortunately, it turns out that generic functions are over-grouped so
all functions with the same name get the last definition, so `mix` with
a float (which should get GLSLstd450FMix) gets the bool version instead
(SpvOpSelect).
When the number of supplied vectors matches the number of columns in the
matrix and all vectors have the same width as the number of rows in the
matrix, there's no need to expand the vectors into components only to be
gathered again.
SPIR-V requires that matrices are constructed from vectors rather than
individual components. While not optimal, iqm.vert's output now passes
spirv-val. Also probably still lots wrong with fine details.