To ensure back branches always go to a header block, create a header
block even for !testFirst loops. Then unify common code between the
testFirst/!testFirst cases.
Generate the header-block code first, so update golden files.
Realize that certain infinite loops generate invalid SPIR-V, so put a
TODO to instead abort code generation in such cases.
Change-Id: I1e173c8f73daad186cfc666b7d72bd563ed7665d
Depending on specific optimization settings VS2013 will sometimes
execute the operands to
new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi)
left-to-right, and sometimes right-to-left. Since makeBoolType can
also call getUniqueId(), the IDs to the OpPhi can sometimes be swapped.
This guarantees an explicit ordering of the Ids so that tests work
reliably.
Structured control-flow rules allow leaving the middle of a construct through
a return, but not through a jump to a block that does a return.
Addresses issue #58.
This generally simplifies access chain generation, with far fewer type conversions.
It is particularly important to future SPIR-V changes where there is less aggregate
type uniqueness due to carrying different layout information with the type.
Previously if a non-void function implictly returned, a dummy variable
was created as return value. Now instead it returns the result of the
OpUndef instruction. This better conveys the presence of undefined
behavior to SPIR-V consuming tools (and humans).
It also saves one ID per occurrence...
After construction, the Loop is effectively const.
This perturbs the IDs in SPIR-V tests because the body block
is created before generating any of the loop code, rather than
only when the body is first referenced.
The loop test is always emitted before the loop body.
For do-while loops, use a phi node to track whether we're
on the first loop iteration, and only check the loop test
on the second and subsequent iterations.
For do-while loops, the loop test branch no longer occurs
at the top of the loop, so it must get its own selection
merge instruction.
A block can't be the target of more than one merge instruction.
So when the loop test executes after the body (as in do-while in GLSL)
we need to introduce a dummy block to be the target of the selection
merge just before the loop test conditional branch.
The other arm of the branch exits the loop and hence is the
"break block" exception in the structured control flow rules.