Exemple #1
0
int			is_prog(t_list *list, int max_elem)
{
	int				*index;
	int				*coords;
	struct termios	term;
	char			*buf;
	char			buffer[2048];

	if (tgetent(buffer, getenv("TERM")) < 1)
		return (-1);
	index = init_prog(&term, list, max_elem, &coords);
	while (1)
	{
		buf = init_read(list, index);
		if (buf[0] == 27 && buf[1] == 0 && buf[2] == 0)
			is_escape(term);
		else if (buf[0] == 27 && buf[1] == 91 && buf[2] != 51)
			coords = is_arrow(list, buf, index, coords);
		else if ((buf[0] == 127 && buf[1] == 0 && buf[2] == 0)
				|| (buf[0] == 27 && buf[1] == 91 && buf[2] == 51))
			coords = is_del(&list, term, index, coords);
		else if (buf[0] == 10 && buf[1] == 0 && buf[2] == 0)
			is_return(term, list);
		else if (buf[0] == 32 && buf[1] == 0 && buf[2] == 0)
			coords = is_space(list, index, coords);
	}
	return (0);
}
Exemple #2
0
/**
 * Analyze opcodes in the callee to see if they are problematic for inlining.
 */
bool MultiMethodInliner::cannot_inline_opcodes(DexMethod* callee) {
  int ret_count = 0;
  auto code = callee->get_code();
  uint16_t temp_regs =
      static_cast<uint16_t>(code->get_registers_size() - code->get_ins_size());
  for (auto insn : callee->get_code()->get_instructions()) {
    if (create_vmethod(insn)) return true;
    if (is_invoke_super(insn)) return true;
    if (writes_ins_reg(insn, temp_regs)) return true;
    if (unknown_virtual(insn, callee)) return true;
    if (unknown_field(insn, callee)) return true;
    if (insn->opcode() == OPCODE_THROW) {
      info.throws++;
      return true;
    }
    if (insn->opcode() == FOPCODE_FILLED_ARRAY) {
      info.array_data++;
      return true;
    }
    if (is_return(insn->opcode())) ret_count++;
  }
  // no callees that have more than a return statement (normally one, the
  // way dx generates code).
  // That allows us to make a simple inline strategy where we don't have to
  // worry about creating branches from the multiple returns to the main code
  if (ret_count > 1) {
    info.multi_ret++;
    return true;
  }
  return false;
}
Exemple #3
0
TEST_F(PreVerify, testArrayDataInCaller) {
  auto cls = find_class_named(
    classes, "Lcom/facebook/redexinline/InlineTest;");
  auto m = find_vmethod_named(*cls, "testArrayDataInCaller");

  // check that the callee indeed has a non-terminal if, which will exercise
  // the inliner code path that searches for fopcodes in the caller
  auto callee = find_invoke(m, OPCODE_INVOKE_DIRECT, "calleeWithIf");
  auto insns = callee->get_method()->get_code()->get_instructions();
  auto ret_it =
      std::find_if(insns.begin(), insns.end(), [&](DexInstruction* insn) {
        return is_return(insn->opcode());
      });
  ASSERT_NE(ret_it, insns.end());

  auto last_insn = m->get_code()->get_instructions().back();
  ASSERT_EQ(last_insn->opcode(), FOPCODE_FILLED_ARRAY);
}
Exemple #4
0
void	get_key_pressed(t_select *params)
{
	char	*key;

	key = ft_strnew(4);
	while (read(0, key, 3))
	{
		if (is_escape(key))
			break ;
		else if (is_space(key))
			space_key_pressed(params);
		else if (is_return(key))
			return_key_pressed(params);
		else if (is_arrow(key))
			arrow_key_pressed(key[2] - 64, params);
		ft_bzero(key, 4);
	}
}
Exemple #5
0
  // check that the only possible location of a return statement
  // is the last statement of the code block, and that the return
  // statement has to be there
  void check_return_location(Function_blockImpl *p)
  {
      list<Stat_ptr>::iterator iter;
      bool go = false;
      for(iter = p->m_stat_list->begin(); iter != p->m_stat_list->end(); ++iter)
	  {
          if (hasFound)
	  {
              this->t_error(ret_misplaced_err, (*iter)->m_attribute);
          }
          else if(is_return(*iter))
	  {
              hasFound = true;
          }
      }
      if(!go)
      {
          this->t_error(ret_missing_err, p->m_attribute);
      }
  }
Exemple #6
0
static int		check_key(t_elem **list, struct termios *backup, char *buf)
{
	int		key;

	if ((key = is_return(buf)))
	{
		ft_strdel(&buf);
		handle_rtn(*list, backup);
		exit(0);
	}
	else if ((key = is_del(buf)))
	{
		if (handle_del(list))
			return (-1);
	}
	else if ((key = is_arrow(buf)))
		handle_arrow(*list, key);
	else if ((key = is_space(buf)))
		handle_space(*list);
	else
		return (0);
	return (key);
}
char *get_token(char *lexeme , int mode){
	char *token=(char*)calloc(strlen(lexeme)+50,sizeof(char));
	//printf("Getting token\n");
	if(is_long(lexeme)){
		sprintf(token,"%d",LONG);
	}
	else if(is_static(lexeme)){
		sprintf(token,"%d",STATIC);
	}
	else if(is_union(lexeme)){
		sprintf(token,"%d",UNION);
	}
	else if(is_default(lexeme)){
		sprintf(token,"%d",DEFAULT);
	}
	else if(is_break(lexeme)){
		sprintf(token,"%d",BREAK);
	}
	else if(is_case(lexeme)){
		sprintf(token,"%d",CASE);
	}
	else if(is_continue(lexeme)){
		sprintf(token,"%d",CONTINUE);
	}
	else if(is_goto(lexeme)){
		sprintf(token,"%d",GOTO);
	}
	else if(is_struct(lexeme)){
		sprintf(token,"%d",STRUCT);
	}
	else if(is_const(lexeme)){
		sprintf(token,"%d",CONST);
	}
	else if(is_void(lexeme)){
		sprintf(token,"%d",VOID);
	}
	else if(is_switch(lexeme)){
		sprintf(token,"%d",SWITCH);
	}
	else if(is_for(lexeme)){
		sprintf(token,"%d",FOR);
	}
	else if(is_while(lexeme)){
		sprintf(token,"%d",WHILE);
	}
	else if(is_do(lexeme)){
		sprintf(token,"%d",DO);
	}
	else if(is_return(lexeme)){
		sprintf(token,"%d",RETURN);
	}
	else if(is_bool(lexeme)){
		sprintf(token,"%d",BOOL);
	}
	else if(is_char(lexeme)){
		sprintf(token,"%d",CHAR);
	}
	else if(is_signed(lexeme)){
		sprintf(token,"%d",SIGNED);
	}
	else if(is_unsigned(lexeme)){
		sprintf(token,"%d",UNSIGNED);
	}
	else if(is_short(lexeme)){
		sprintf(token,"%d",SHORT);
	}
	else if(is_int(lexeme)){
		sprintf(token,"%d",INT);
	}
	else if(is_float(lexeme)){
		sprintf(token,"%d",FLOAT);
	}
	else if(is_double(lexeme)){
		sprintf(token,"%d",DOUBLE);
	}
	else if(is_l_square(lexeme)){
		sprintf(token,"%d",L_SQUARE);
	}
	else if(is_r_square(lexeme)){
		sprintf(token,"%d",R_SQUARE);
	}
	else if(is_l_paraen(lexeme)){
		sprintf(token,"%d",L_PARAEN);
	}
	else if(is_r_paraen(lexeme)){
		sprintf(token,"%d",R_PARAEN);
	}
	else if(is_l_cbrace(lexeme)){
		sprintf(token,"%d",L_CBRACE);
	}
	else if(is_r_cbrace(lexeme)){
		sprintf(token,"%d",R_CBRACE);
	}
	else if(is_comma(lexeme)){
		sprintf(token,"%d",COMMA);
	}
	else if(is_semicol(lexeme)){
		sprintf(token,"%d",SEMICOL);
	}
	else if(is_eq_eq(lexeme)){
		sprintf(token,"%d",EQ_EQ);
	}
	else if(is_lesser(lexeme)){
		sprintf(token,"%d",LESSER);
	}
	else if(is_less_eq(lexeme)){
		sprintf(token,"%d",LESS_EQ);
	}
	else if(is_div(lexeme)){
		sprintf(token,"%d",DIV);
	}
	else if(is_greater(lexeme)){
		sprintf(token,"%d",GREATER);
	}
	else if(is_great_eq(lexeme)){
		sprintf(token,"%d",GREAT_EQ);
	}
	else if(is_plus_eq(lexeme)){
		sprintf(token,"%d",PLUS_EQ);
	}
	else if(is_minus_eq(lexeme)){
		sprintf(token,"%d",MINUS_EQ);
	}
	else if(is_div_eq(lexeme)){
		sprintf(token,"%d",DIV_EQ);
	}
	else if(is_mult_eq(lexeme)){
		sprintf(token,"%d",MULT_EQ);
	}
	else if(is_minus_minus(lexeme)){
		sprintf(token,"%d",MINUS_MINUS);
	}
	else if(is_plus_plus(lexeme)){
		sprintf(token,"%d",PLUS_PLUS);
	}
	else if(is_percent(lexeme)){
		sprintf(token,"%d",PERCENT);
	}
	else if(is_div(lexeme)){
		sprintf(token,"%d",DIV);
	}
	else if(is_mult(lexeme)){
		sprintf(token,"%d",MULT);
	}
	else if(is_minus(lexeme)){
		sprintf(token,"%d",MINUS);
	}
	else if(is_plus(lexeme)){
		sprintf(token,"%d",PLUS);
	}
	else if(is_int_const(lexeme)){
		printf("int");
		sprintf(token,"%d\t%s",INT_CONST,lexeme);
	}
	else if(is_flo_const(lexeme)){
		printf("float");
		sprintf(token,"%d\t%s",FLO_CONST,lexeme);
	}
	else if(is_comment_start(lexeme)){
		sprintf(token,"$start");
	}
	else if(is_comment_end(lexeme)){
		sprintf(token,"$end");
	}
	else if(is_identifier(lexeme)){
		printf("Identifier");
		if(mode==1) ht_set( symboltable, lexeme, "1");
		sprintf(token,"%d\t%s",IDNTIFIER,lexeme);
	}
	else sprintf(token,"%d",NOTOK);
	return token;
}
Exemple #8
0
void MethodTransform::build_cfg() {
  // Find the block boundaries
  std::unordered_map<MethodItemEntry*, std::vector<Block*>> branch_to_targets;
  std::vector<std::pair<DexTryItem*, Block*>> try_ends;
  std::unordered_map<DexTryItem*, std::vector<Block*>> try_catches;
  size_t id = 0;
  bool in_try = false;
  m_blocks.emplace_back(new Block(id++));
  m_blocks.back()->m_begin = m_fmethod->begin();
  // The first block can be a branch target.
  auto begin = m_fmethod->begin();
  if (begin->type == MFLOW_TARGET) {
    branch_to_targets[begin->target->src].push_back(m_blocks.back());
  }
  for (auto it = m_fmethod->begin(); it != m_fmethod->end(); ++it) {
    if (it->type == MFLOW_TRY) {
      if (it->tentry->type == TRY_START) {
        in_try = true;
      } else if (it->tentry->type == TRY_END) {
        in_try = false;
      }
    }
    if (!end_of_block(m_fmethod, it, in_try)) {
      continue;
    }
    // End the current block.
    auto next = std::next(it);
    if (next == m_fmethod->end()) {
      m_blocks.back()->m_end = next;
      continue;
    }
    // Start a new block at the next MethodItem.
    auto next_block = new Block(id++);
    if (next->type == MFLOW_OPCODE) {
      insert_fallthrough(m_fmethod, &*next);
      next = std::next(it);
    }
    m_blocks.back()->m_end = next;
    next_block->m_begin = next;
    m_blocks.emplace_back(next_block);
    // Record branch targets to add edges in the next pass.
    if (next->type == MFLOW_TARGET) {
      branch_to_targets[next->target->src].push_back(next_block);
      continue;
    }
    // Record try/catch blocks to add edges in the next pass.
    if (next->type == MFLOW_TRY) {
      if (next->tentry->type == TRY_END) {
        try_ends.emplace_back(next->tentry->tentry, next_block);
      } else if (next->tentry->type == TRY_CATCH) {
        try_catches[next->tentry->tentry].push_back(next_block);
      }
    }
  }
  // Link the blocks together with edges
  for (auto it = m_blocks.begin(); it != m_blocks.end(); ++it) {
    // Set outgoing edge if last MIE falls through
    auto lastmei = (*it)->rbegin();
    bool fallthrough = true;
    if (lastmei->type == MFLOW_OPCODE) {
      auto lastop = lastmei->insn->opcode();
      if (is_goto(lastop) || is_conditional_branch(lastop) ||
          is_multi_branch(lastop)) {
        fallthrough = !is_goto(lastop);
        auto const& targets = branch_to_targets[&*lastmei];
        for (auto target : targets) {
          (*it)->m_succs.push_back(target);
          target->m_preds.push_back(*it);
        }
      } else if (is_return(lastop) || lastop == OPCODE_THROW) {
        fallthrough = false;
      }
    }
    if (fallthrough && std::next(it) != m_blocks.end()) {
      Block* next = *std::next(it);
      (*it)->m_succs.push_back(next);
      next->m_preds.push_back(*it);
    }
  }
  /*
   * Now add the catch edges.  Every block inside a try-start/try-end region
   * gets an edge to every catch block.  This simplifies dataflow analysis
   * since you can always get the exception state by looking at successors,
   * without any additional analysis.
   *
   * NB: This algorithm assumes that a try-start/try-end region will consist of
   * sequentially-numbered blocks, which is guaranteed because catch regions
   * are contiguous in the bytecode, and we generate blocks in bytecode order.
   */
  for (auto tep : try_ends) {
    auto tryitem = tep.first;
    auto tryendblock = tep.second;
    size_t bid = tryendblock->id();
    always_assert(bid > 0);
    --bid;
    while (true) {
      auto block = m_blocks[bid];
      if (ends_with_may_throw(block)) {
        auto& catches = try_catches[tryitem];
        for (auto catchblock : catches) {
          block->m_succs.push_back(catchblock);
          catchblock->m_preds.push_back(block);
        }
      }
      auto begin = block->begin();
      if (begin->type == MFLOW_TRY) {
        auto tentry = begin->tentry;
        if (tentry->type == TRY_START && tentry->tentry == tryitem) {
          break;
        }
      }
      always_assert_log(bid > 0, "No beginning of try region found");
      --bid;
    }
  }
  TRACE(CFG, 5, "%s\n", show(m_method).c_str());
  TRACE(CFG, 5, "%s", show(m_blocks).c_str());
}
Exemple #9
0
bool MethodTransform::inline_16regs(InlineContext& context,
                                    DexMethod *callee,
                                    DexOpcodeMethod *invoke) {
  TRACE(INL, 2, "caller: %s\ncallee: %s\n",
      SHOW(context.caller), SHOW(callee));
  auto caller = context.caller;
  MethodTransformer mtcaller(caller);
  MethodTransformer mtcallee(callee);
  auto fcaller = mtcaller->m_fmethod;
  auto fcallee = mtcallee->m_fmethod;

  auto callee_code = callee->get_code();
  auto temps_needed =
      callee_code->get_registers_size() - callee_code->get_ins_size();
  uint16_t newregs = caller->get_code()->get_registers_size();
  if (context.inline_regs_used < temps_needed) {
    newregs = newregs + temps_needed - context.inline_regs_used;
    if (newregs > 16) return false;
    remap_caller_regs(caller, fcaller, newregs);
    context.inline_regs_used = temps_needed;
  }
  RegMap callee_reg_map;
  build_remap_regs(callee_reg_map, invoke, callee, context.new_tmp_off);

  auto pos = std::find_if(
    fcaller->begin(), fcaller->end(),
    [invoke](const MethodItemEntry& mei) {
      return mei.type == MFLOW_OPCODE && mei.insn == invoke;
    });
  // find the move-result after the invoke, if any. Must be the first
  // instruction after the invoke
  auto move_res = pos;
  while (move_res++ != fcaller->end() && move_res->type != MFLOW_OPCODE);
  if (!is_move_result(move_res->insn->opcode())) {
    move_res = fcaller->end();
  }

  // Skip dbg prologue in callee, we don't need two.
  auto it = fcallee->begin();
  if (it->type == MFLOW_DEBUG && it->dbgop->opcode() == DBG_SET_PROLOGUE_END) {
    ++it;
  }
  // find the last position entry before the invoke.
  // we need to decrement the reverse iterator because it gets constructed
  // as pointing to the element preceding pos
  auto position_it = --FatMethod::reverse_iterator(pos);
  while (++position_it != fcaller->rend()
      && position_it->type != MFLOW_POSITION);
  auto invoke_position =
    position_it == fcaller->rend() ? nullptr : position_it->pos;
  if (invoke_position != nullptr) {
    TRACE(MTRANS, 5, "Inlining call at %s:%d\n", invoke_position->file->c_str(),
        invoke_position->line);
  }

  // Copy the callee up to the return. Everything else we push at the end
  // of the caller
  auto splice = MethodSplicer(callee_reg_map, invoke_position);
  auto ret_it =
      std::find_if(it, fcallee->end(), [](const MethodItemEntry& mei) {
        return mei.type == MFLOW_OPCODE && is_return(mei.insn->opcode());
      });
  splice(fcaller, pos, it, ret_it);
  if (move_res != fcaller->end()) {
    std::unique_ptr<DexInstruction> ret_insn(ret_it->insn->clone());
    remap_registers(ret_insn.get(), callee_reg_map);
    DexInstruction* move = move_result(ret_insn.get(), move_res->insn);
    auto move_mei = new MethodItemEntry(move);
    fcaller->insert(pos, *move_mei);
  }
  // ensure that the caller's code after the inlined method retain their
  // original position
  if (invoke_position != nullptr) {
    fcaller->insert(pos, *(new MethodItemEntry(invoke_position)));
  }

  // remove invoke
  fcaller->erase_and_dispose(pos, FatMethodDisposer());
  // remove move_result
  if (move_res != fcaller->end()) {
    fcaller->erase_and_dispose(move_res, FatMethodDisposer());
  }
  // Copy the opcodes in the callee after the return and put them at the end of
  // the caller.
  splice(fcaller, fcaller->end(), std::next(ret_it), fcallee->end());

  // adjust method header
  caller->get_code()->set_registers_size(newregs);
  caller->get_code()->set_outs_size(
      std::max(callee->get_code()->get_outs_size(),
      caller->get_code()->get_outs_size()));
  return true;
}
Exemple #10
0
Term NextAction::result()
{
  assert(is_return());
  return value;
}