}
/* }}} */
-#define UPDATE_SSA_TYPE(_type, var) \
+#define UPDATE_SSA_TYPE(_type, _var) \
do { \
uint32_t __type = (_type); \
+ int __var = (_var); \
if (__type & MAY_BE_REF) { \
- __type |= MAY_BE_RC1 | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; \
+ __type |= MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; \
} \
- if (var >= 0) { \
- if (ssa_var_info[var].type != __type) { \
- check_type_narrowing(op_array, ssa, worklist, \
- var, ssa_var_info[var].type, __type); \
- ssa_var_info[var].type = __type; \
- add_usages(op_array, ssa, worklist, var); \
+ if (__var >= 0) { \
+ if (ssa_vars[__var].var < op_array->last_var) { \
+ if (__type & (MAY_BE_REF|MAY_BE_RCN)) { \
+ __type |= MAY_BE_RC1 | MAY_BE_RCN; \
+ } \
+ } \
+ if (ssa_var_info[__var].type != __type) { \
+ check_type_narrowing(op_array, ssa, worklist, \
+ __var, ssa_var_info[__var].type, __type); \
+ ssa_var_info[__var].type = __type; \
+ add_usages(op_array, ssa, worklist, __var); \
} \
/*zend_bitset_excl(worklist, var);*/ \
} \
break;
case ZEND_QM_ASSIGN:
case ZEND_COALESCE:
- if (opline->op1_type == IS_CV || opline->op1_type == IS_VAR) {
- tmp = (MAY_BE_RCN | t1) & ~(MAY_BE_UNDEF|MAY_BE_REF);
- } else {
- tmp = (MAY_BE_RC1 | t1) & ~(MAY_BE_UNDEF|MAY_BE_REF|MAY_BE_RCN);
- }
+ tmp = t1 & ~(MAY_BE_UNDEF|MAY_BE_REF);
if (t1 & MAY_BE_UNDEF) {
tmp |= MAY_BE_NULL;
}
+ if (opline->op1_type & (IS_CV|IS_VAR)) {
+ tmp |= MAY_BE_RCN;
+ }
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
if ((t1 & MAY_BE_OBJECT) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) {
UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def);
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
}
+ if (!(orig & (MAY_BE_OBJECT|MAY_BE_REF))) {
+ orig &= ~MAY_BE_RCN;
+ }
UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
if ((orig & MAY_BE_OBJECT) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) {
UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].op1_def);
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
}
+ if (!(orig & (MAY_BE_OBJECT|MAY_BE_REF))) {
+ orig &= ~MAY_BE_RCN;
+ }
UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
}
} else {
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
}
+ if (!(orig & (MAY_BE_OBJECT|MAY_BE_REF))) {
+ orig &= ~MAY_BE_RCN;
+ }
UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
}
} else {
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
}
+ if (!(orig & (MAY_BE_OBJECT|MAY_BE_REF))) {
+ orig &= ~MAY_BE_RCN;
+ }
UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
}
} else {
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
}
+ if (!(orig & (MAY_BE_OBJECT|MAY_BE_REF))) {
+ orig &= ~MAY_BE_RCN;
+ }
UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
}
} else {
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
}
+ if (!(orig & (MAY_BE_OBJECT|MAY_BE_REF))) {
+ orig &= ~MAY_BE_RCN;
+ }
UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
}
} else {
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
}
+ if (!(orig & (MAY_BE_OBJECT|MAY_BE_REF))) {
+ orig &= ~MAY_BE_RCN;
+ }
UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
}
} else {
break;
case ZEND_ASSIGN_DIM:
if (opline->op1_type == IS_CV) {
- tmp = (t1 & (MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF));
+ tmp = (t1 & (MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF));
tmp &= ~MAY_BE_NULL;
if (t1 & (MAY_BE_UNDEF | MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING)) {
tmp |= MAY_BE_ARRAY;
}
- if (tmp & MAY_BE_RCN) {
+ if (t1 & MAY_BE_REF) {
+ tmp |= MAY_BE_REF;
+ }
+ if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
tmp |= MAY_BE_RC1;
}
if (tmp & MAY_BE_ARRAY) {
tmp = OP1_INFO();
if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
if (tmp & MAY_BE_RC1) {
- if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
- tmp |= MAY_BE_RCN;
- }
+ tmp |= MAY_BE_RCN;
}
}
UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
break;
case ZEND_ASSIGN_OBJ:
if (opline->op1_type == IS_CV) {
- tmp = (t1 & (MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF));
+ tmp = (t1 & (MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF));
tmp &= ~MAY_BE_NULL;
if (t1 & (MAY_BE_UNDEF | MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING)) {
tmp |= MAY_BE_OBJECT;
}
- if (tmp & MAY_BE_RCN) {
+ if (t1 & MAY_BE_REF) {
+ tmp |= MAY_BE_REF;
+ }
+ if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
tmp |= MAY_BE_RC1;
}
UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
tmp = OP1_INFO();
if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
if (tmp & MAY_BE_RC1) {
- if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
- tmp |= MAY_BE_RCN;
- }
+ tmp |= MAY_BE_RCN;
}
}
UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
tmp = t2;
if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
if (tmp & MAY_BE_RC1) {
- if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
- tmp |= MAY_BE_RCN;
- }
+ tmp |= MAY_BE_RCN;
}
}
UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
if (t1 & MAY_BE_REF) {
tmp |= MAY_BE_REF;
}
- if ((t1 & MAY_BE_RCN) && !(opline->op2_type & (IS_CV|IS_VAR))) {
- tmp |= MAY_BE_RC1;
- }
- if ((t1 & MAY_BE_RCN) && (opline->op2_type & (IS_CV|IS_VAR))) {
+ if (t1 & (MAY_BE_RC1 | MAY_BE_RCN)) {
if (t2 & MAY_BE_REF) {
tmp |= MAY_BE_RC1;
}
if (t2 & MAY_BE_RC1) {
tmp |= MAY_BE_RC1;
- if (opline->op2_type == IS_CV) {
+ if (opline->op2_type & (IS_CV|IS_VAR)) {
tmp |= MAY_BE_RCN;
}
}
if (t2 & MAY_BE_RCN) {
tmp |= MAY_BE_RCN;
}
- }
- if ((t1 & MAY_BE_RC1) && !(opline->op2_type & (IS_CV|IS_VAR))) {
- tmp |= MAY_BE_RC1;
- }
- if ((t1 & MAY_BE_RC1) && (opline->op2_type & (IS_CV|IS_VAR))) {
- if (t2 & MAY_BE_REF) {
- tmp |= MAY_BE_RC1;
- }
- if (t2 & MAY_BE_RC1) {
- tmp |= MAY_BE_RC1;
- if (opline->op2_type == IS_CV) {
- tmp |= MAY_BE_RCN;
- }
- }
- if (t2 & MAY_BE_RCN) {
+ if (RETURN_VALUE_USED(opline) && (tmp & MAY_BE_RC1)) {
tmp |= MAY_BE_RCN;
}
}
- if (RETURN_VALUE_USED(opline) && (tmp & MAY_BE_RC1)) {
- tmp |= MAY_BE_RCN;
- }
if (ssa_ops[i].op1_def >= 0) {
if (ssa_var_info[ssa_ops[i].op1_def].use_as_double) {
tmp &= ~MAY_BE_LONG;
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
break;
case ZEND_CLONE:
- UPDATE_SSA_TYPE(MAY_BE_OBJECT, ssa_ops[i].result_def);
+ UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT, ssa_ops[i].result_def);
if ((t1 & MAY_BE_OBJECT) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) {
UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def);
} else {
break;
case ZEND_FETCH_CONSTANT:
case ZEND_FETCH_CLASS_CONSTANT:
- UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY, ssa_ops[i].result_def);
+ UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY, ssa_ops[i].result_def);
break;
case ZEND_STRLEN:
tmp = MAY_BE_RC1|MAY_BE_LONG;