Exemple #1
0
void first_pass(const Index& index,
                const Context ctx,
                borrowed_ptr<php::Block> const blk,
                State state) {
  std::vector<Bytecode> newBCs;
  newBCs.reserve(blk->hhbcs.size());

  PropertiesInfo props(index, ctx, nullptr);
  auto interp = Interp { index, ctx, props, blk, state };
  for (auto& op : blk->hhbcs) {
    FTRACE(2, "  == {}\n", show(op));

    auto gen = [&] (const Bytecode& newb) {
      newBCs.push_back(newb);
      newBCs.back().srcLoc = op.srcLoc;
      FTRACE(2, "   + {}\n", show(newBCs.back()));
    };

    auto const flags = step(interp, op);
    if (flags.calledNoReturn) {
      gen(op);
      gen(bc::BreakTraceHint {}); // The rest of this code is going to
                                  // be unreachable.
      // It would be nice to put a fatal here, but we can't because it
      // will mess up the bytecode invariant about blocks
      // not-reachable via fallthrough if the stack depth is non-zero.
      // It can also mess up FPI regions.
      continue;
    }

    if (options.RemoveDeadBlocks && flags.tookBranch) {
      always_assert(!flags.wasPEI);
      switch (op.op) {
      case Op::JmpNZ:     blk->fallthrough = op.JmpNZ.target;     break;
      case Op::JmpZ:      blk->fallthrough = op.JmpZ.target;      break;
      case Op::IterInit:  blk->fallthrough = op.IterInit.target;  break;
      case Op::IterInitK: blk->fallthrough = op.IterInitK.target; break;
      default:
        // No support for switch, etc, right now.
        always_assert(0 && "unsupported tookBranch case");
      }
      /*
       * We need to pop the cell that was on the stack for the
       * conditional jump.  Note: for jumps this also conceptually
       * needs to execute any side effects a conversion to bool can
       * have.  (Currently that is none.)
       */
      gen(bc::PopC {});
      continue;
    }

    if (options.ConstantProp && flags.canConstProp) {
      if (propagate_constants(op, state, gen)) continue;
    }

    if (options.StrengthReduce && flags.strengthReduced) {
      for (auto& hh : *flags.strengthReduced) gen(hh);
      continue;
    }

    gen(op);
  }

  blk->hhbcs = std::move(newBCs);
}
Exemple #2
0
struct code* code_analyse(struct prx *p) {
	struct code *c = code_alloc();
	struct subroutine *sub;
	element el;

	c->file = p;

	if (!decode_instructions(c)) {
		code_free(c);
		return NULL ;
	}

	extract_switches(c);
	extract_subroutines(c);

	live_registers(c);

	el = list_head(c->subroutines);
	while (el) {
		sub = element_getvalue(el);
		if (!sub->import && !sub->haserror) {
			cfg_traverse(sub, FALSE);
			if (!sub->haserror) {
				sub->status |= SUB_STAT_CFG_TRAVERSE;
				cfg_traverse(sub, TRUE);
			}

			if (!sub->haserror) {
				sub->status |= SUB_STAT_CFG_TRAVERSE_REV;
				fixup_call_arguments(sub);
			}

			if (!sub->haserror) {
				sub->status |= SUB_STAT_FIXUP_CALL_ARGS;
				build_ssa(sub);
			}

			if (!sub->haserror) {
				sub->status |= SUB_STAT_SSA;
			}
		}
		el = element_next(el);
	}

	live_registers_imports(c);

	el = list_head(c->subroutines);
	while (el) {
		sub = element_getvalue(el);
		if (!sub->import && !sub->haserror) {
			if (!(sub->status & SUB_STAT_FIXUP_CALL_ARGS)) {
				fixup_call_arguments(sub);
				if (!sub->haserror) {
					sub->status |= SUB_STAT_FIXUP_CALL_ARGS;
					build_ssa(sub);
				}
			}

			if (!sub->haserror) {
				sub->status |= SUB_STAT_SSA;
				propagate_constants(sub);
			}

			if (!sub->haserror) {
				sub->status |= SUB_STAT_CONSTANTS_EXTRACTED;
				extract_variables(sub);
			}

			if (!sub->haserror) {
				sub->status |= SUB_STAT_VARIABLES_EXTRACTED;
				extract_structures(sub);
			}

			if (!sub->haserror) {
				sub->status |= SUB_STAT_STRUCTURES_EXTRACTED;
			}
		}
		el = element_next(el);
	}

	return c;
}