Switching to native ruamoko bool for vkgen resulted in bool getting
incorrectly parsed as a string (which mean getting the string's address
written to the value). Fixes the randomly enabled debug pipelines (and
probably a few randomly disabled normal pipelines, though less likely as
they're usually implicitly initialized). The one bit of actual legit UB
(ie, that which wasn't immediately mitigated one way or another) found
by ubsan, and it was a data error.
Fixes ubsan's (random!) complaints about memblock not being aligned. I
should probably look into making the progs loader code ensure the memory
is aligned itself.
While I guess ubsan is right that shifting a 1 bit into the sign of an
int can cause problems, but that's assuming the int is numeric. And it
doesn't help that unsigned char promotes to int instead of unsigned int.
Recent vulkan validation layers started complaining about vertex
processing stages having read-write buffers without atomics enabled
(fair enough), but I decided to get all the buffers that don't need to
be written.
They're currently wrong since they're meant to be for specialization
constants (and that whole system is currently broken anyway) but are
instead raw code expressions, but progress is progress.
Result type and constant handling is now table-driven, resulting in the
removal of seven switch statements (and thus a lot less hassle when
extending types or expressions). Also, (u)long and (u)short are fully
implemented.
In addition, other than result type handing for boolean results, any
back-end specific implementation is now in the back-end.
It's nowhere near complete, but unary and binary expressions that are
marked as constant will not be subject to constant folding. This is
necessary for proper support of specialization constants.
The imports need their result id recorded somewhere (and the hard-coding
in qc-parse.y removed), but that's a little bit of progress getting
spir-v working.
I'm not sure what's up (I doubt it's actually ub, it's just that it took
enabling ubsan *and* link-time-optimizations to see the warning), and
the warning is technically correct, though going from -1 (int) to
0xfffffff400000000 has me stumped, but ensuring width is 2-4 does take
care of it. All because I got a weird test failure that I wound up being
unable to reproduce after rebuilding qfcc (thus the ubsan pass, but no
other sniffles).
I don't know why I thought it was a good idea to make sy_var context
dependent. Renaming sy_var to sy_def makes it a little easier to know to
use the def field, too.
While I'm not happy with the module "creation" (at least it's limited to
two places), setting it up with spir-v capabilities and memory model
seems quite nice and should play nicely with being set up from within
source code, though using uint constant expressions might be overkill.
A few more types and function parameters are set up more or less
correctly (however, the pointer storage class is hard-coded for now:
need to add attributes to everything).
It was a bit of a surprise seeing a test case fail and then succeed
after making a minor edit to help find the bug, but valgrind to the
rescue. I'm surprised nothing showed up earlier.
It seemed like a good idea since vulkan and gltf resources use JSON.
However, plist and json parsing and writing are separate: there's no
auto-detection for parsing, and the appropriate function must be used
for writing (though reading one then writing the other will work, but
may result in some information loss, or even invalid json (binary)).
Escape characters aren't handled quite to spec yet (eg, no \uxxxx).
The tests are pretty lame, but they're taken from rfc7159 and round-trip
correctly (which is a surprise for the fp numbers).
I don't remember why I thought it was a good idea to respect embedded
nul characters, but doing so makes appendstr O(N) instead of O(1) (or
O(N^2) instead of O(N) for multiple appends of n chars (N = sum(n)).
Also, this makes appendstr consistent with dasprintf.
I've decided that I want reserve to mean only allocate backing memory,
not modify the size of the string, but I didn't want to rework much code
in the process. I might eventually get right of the open functions, but
I wouldn't be surprised if that's another decade or two in the future.
Thare are still many const casts, but this does get rid of one set. I
had tried to replace the paren flag with a () unary expression, but that
brought out a whole pile of places that had problems (especially
anything to do with boolean expressions).
It seems it was needed for dealing with the result expression for block
expressions, but it turns out (possibly thanks to dags), that it's easy
to check for the result value and using the appropriate call to emit the
code thus avoiding the non-executable code warning.
I'm surprised other types weren't affected, but vec4's ecoding was being
picked up for float. Thankfully, all that was needed was checking width
and columns.
They can have a variety (min int and long) of backing types, so
requiring ev_invalid (which is used for struct and union).
Also, ensure is_int etc fail for handle types.
Fortunately, there was a reserved spot that could be used for the name
thus no need for a version update. The name isn't used yet but will be
for glsl support.
Each interface type (in, out, uniform etc) gets its own namespace, and
non-instanced blocks get a namespace (their block name) within the
interface namespace.
The defs for the block members are currently "allocated" to be at offset
-1, but the idea is to allow layout qualifiers to know if the member has
already been located.
It came about from a discussion in the bivector discord about
programmatic testing for blade commutativity and why no texts talked
about it. I came up with an idea that turned out not to work (I guess
I'd overthought how count_flips works). In the end, I decided to keep
it, and simplified metric's sign check.
I'm not sure I got all the checks right, but bsp_gbuf.geom passes the
validity (but failes due to not having implemented the application of
the qualifiers).
Attributes seem appropriate as GLSL's qualifiers affect variables rather
than types (since there's no typedef).
Not much is done with the attributes yet other than some basic error
checking (duplicates of non-layout attributes) and debug output, but
most (if not all) declarations get to the declaration code with
attributes intact.