Codegen for short-circuiting operators
Summary:
tl;dr; as in title - fixes several issues related to codegen for short-circuiting operators.
For many cases when emitting `JmpZ` or `JmpNZ` we can statically determine if condition will always be true or false - for these cases we emit `Jmp` instead. However we still emitted code for both branches of arguments coersion even though some of it will definitely be unreachable - this uncovered the problem with HHVM verifier.
For example for code
```lang=php
new f($s || 'default value')
```
we might generate something like
```
FPushCtorD ...
CGetL $s
JmpNZ L0 # check first argument
Jmp L0 # second argument is always truthy value, unconditionally jump to loading True
False # load False and jump to end of conditional expression - unreachable (*1)
Jmp L1
L0:
True
L1: (*2)
```
Per HHVM verification rules, stack depth on instruction that follows `Jmp` (and other instructions that unconditionally transfer control flow) is assumed to be 0. This means that at the point (*2) where control flow merges we'll get different depths since in regular case it will be 2 [constructor, True] and in case that starts at (*1) it will be 1 [False] which is illegal.
In this diff we make `emit_jmpz` / `emit_jmpnz` return two extra things:
- was generated instruction sequence ended with `Jmp`
- was label that was passed to `emit_*` ever used
With this bits of information we can be more precise when emitting code, i.e.:
- if for instruction sequence `[e1; e2]` control flow should fallthrough from from e1 to e2 and e1 ends with `Jmp` - we can omit e2 since it will definitely be unreachable
- if for instruction sequence we know that E1 never jumps to L1 (L1 is definitely not used) - we can omit E3 since it will definitely be unreachable
```
E1 (might jump to L1)
E2
JMP L_END
L1:
E3
L_END:
Reviewed By: oulgen
Differential Revision:
D7075742
fbshipit-source-id:
2b6820236f2555037763dc77df7a9d44475fc727