Fix some code suppression fallout

Some more subtle issues with code suppression:
- outputting asms but not their operand setup is broken
- but global asms must always be output
- statement expressions are transparent to code suppression
- vtop can't be transformed from VT_CMP/VT_JMP when nocode_wanted

Also remove .exe files from tests2 if they don't fail.
This commit is contained in:
Michael Matz
2016-12-20 04:49:22 +01:00
parent 559ee1e940
commit 42e2a67f23
8 changed files with 138 additions and 20 deletions

View File

@ -575,8 +575,16 @@ static void vsetc(CType *type, int r, CValue *vc)
tcc_error("memory full (vstack)");
/* cannot let cpu flags if other instruction are generated. Also
avoid leaving VT_JMP anywhere except on the top of the stack
because it would complicate the code generator. */
if (vtop >= vstack) {
because it would complicate the code generator.
Don't do this when nocode_wanted. vtop might come from
!nocode_wanted regions (see 88_codeopt.c) and transforming
it to a register without actually generating code is wrong
as their value might still be used for real. All values
we push under nocode_wanted will eventually be popped
again, so that the VT_CMP/VT_JMP value will be in vtop
when code is unsuppressed again. */
if (vtop >= vstack && !nocode_wanted) {
v = vtop->r & VT_VALMASK;
if (v == VT_CMP || (v & ~1) == VT_JMP)
gv(RC_INT);
@ -4367,13 +4375,18 @@ ST_FUNC void unary(void)
gen_cast(&type);
}
} else if (tok == '{') {
int saved_nocode_wanted = nocode_wanted;
if (const_wanted)
tcc_error("expected constant");
/* save all registers */
save_regs(0);
/* statement expression : we do not accept break/continue
inside as GCC does */
inside as GCC does. We do retain the nocode_wanted state,
as statement expressions can't ever be entered from the
outside, so any reactivation of code emission (from labels
or loop heads) can be disabled again after the end of it. */
block(NULL, NULL, 1);
nocode_wanted = saved_nocode_wanted;
skip(')');
} else {
gexpr();