Eliminate dead branches in IF/AND/OR forms if the type of the object
returned by the test form is known to be null or non-null. Get rid of
unnecessary tests in AND/OR forms if we know that a clause cannot
short-circuit the evaluation. Replace NOT forms by T or NIL constants
if we know that the argument is null or non-null.
Make the types more precise to improve type propagation. We will fall
back to using object-type as appropriate in later stages of the
compilation.
Also return a new copy for each invocation instead of the same *c1nil*
and *c1t* since we may later set the type of the c1form (e.g. in
enforce-types). This can happen for invalid code which can permanently
set the type of *c1nil* to NIL, leading to miscompilations later on
for unrelated valid code.
Fix errors in handling values types for (and) and (or) (all forms but
the last form return only the primary value). Also be more precise if
branches are not taken or the evaluation is known to short circuit.
Previously we've named the function's variable with the function name. That
could lead to a varible named (SETF FOO), and that can break down the road
because variable names are assumed to be symbols.
Moreover this change will prevent a possible fail scenario where we inline a
constant value with a known name instead of the function with the same name.
C inliners for arithmetic operations assumed that there may be more than two
arguments and worked similar to reduce:
ARG_n+3 <- (inline-binop ARG_n+2 ARG_n+1) op ARG_n
that said ECL has compiler macros that simplify the arithmetic so there are
always at most two arguments, so it is enough to inline:
(inline-binop ARG1 ARG2)
As for the incorrect code -- when there were remaining arguments, the result of
the previous operation was saved with save-inline-loc, but(!) save-inline-loc
expected an inlined argument, while inline-binop calls produce-inline-loc that
returns a "normal" location - that's probably some change from the past, because
produce-inline-loc seems to clearly indicate that it should return inlined value
- and save-inline-loc would always error because of the argument type mismatch.
This commit removes the dead code and now unused save-inline-loc function.
After understanding better the code I've moved argument inlining and function
inlining close to each other, also negate-argument clearly belongs in there too.
INLINED-ARG is now a structure (not a naked list) - that helps with
understanding abstractions better.
Previously our call for conditional jumps worked like:
unwind-exit -> unwind-cjump -> unwind-exit -> unwind-{label,exit}
The roundtrip to unwind-exit makes tracking invocations harder. The new
invocation chain is:
unwind-exit -> unwind-cjump -> unwind-{label,exit}
The operator UNWIND-FLEE is used to perform a dynamic unwind. Previously we've
opencoded this type of exits in appropriate operators.
The operator UNWIND-COND is used to perform a conditional unwind. It is expected
to be called to produce the IF statement body. With this commit all every
transfer of control goes through the exit manager.
Ultimately we will want to include the if test directly in UNWIND-COND.
There is no need to carry the location value across the unwind when the
destination is not special, because then we may assign the destination before we
unwind the stack. That allows us to skip examining the unwind requirements.
EMIT-TOPLEVEL-FORM bound *compile-file-truename* and *compile-file-position* to
be immedietely rebound in T2EXPR (to the same value!).
*COMPILE-TO-LINKING-CALL* is not used anywhere.
set-loc saves the location to the destination, and while doing so it coerces the
former to the type of the latter. Our code used *destination* as the argument to
LOC-REPRESENTATION-TYPE, but DESTINATION and *DESTINATION* may not be the same.
Most of the time when we've used SET-LOC we've rebound *DESTINATION* for that
particular operation. Instead of doing so right now the argument is explicit and
when we want to use the *DESTINATION* then we simply use it (literally 2 cases).