Beispiel #1
0
void jsil_typecheckt::typecheck_expr_concatenation(exprt &expr)
{
  if(expr.operands().size()!=2)
  {
    err_location(expr);
    error() << "operator `" << expr.id()
            << "' expects two operands" << eom;
    throw 0;
  }

  make_type_compatible(expr.op0(), string_typet(), true);
  make_type_compatible(expr.op1(), string_typet(), true);

  expr.type()=string_typet();
}
Beispiel #2
0
void jsil_typecheckt::typecheck_expr_ref(exprt &expr)
{
  if(expr.operands().size()!=3)
  {
    err_location(expr);
    error() << "operator `" << expr.id()
            << "' expects three operands" << eom;
    throw 0;
  }

  make_type_compatible(expr.op0(), jsil_value_type(), true);
  make_type_compatible(expr.op1(), string_typet(), true);

  exprt &operand3=expr.op2();
  make_type_compatible(operand3, jsil_kind(), true);

  if(operand3.id()==ID_member)
    expr.type()=jsil_member_reference_type();
  else if(operand3.id()=="variable")
    expr.type()=jsil_variable_reference_type();
  else
  {
    err_location(expr);
    error() << "operator `" << expr.id()
            << "' expects reference type in the third parameter. Got:"
            << operand3.pretty() << eom;
    throw 0;
  }
}
Beispiel #3
0
void java_root_class(symbolt &class_symbol)
{
  struct_typet &struct_type=to_struct_type(class_symbol.type);
  struct_typet::componentst &components=struct_type.components();

  {
    // for monitorenter/monitorexit
    struct_typet::componentt component;
    component.set_name("@lock");
    component.set_pretty_name("@lock");
    component.type()=java_boolean_type();

    // add at the beginning
    components.insert(components.begin(), component);
  }

  {
    // the class identifier is used for stuff such as 'instanceof'
    struct_typet::componentt component;
    component.set_name("@class_identifier");
    component.set_pretty_name("@class_identifier");
    component.type()=string_typet();

    // add at the beginning
    components.insert(components.begin(), component);
  }
}
Beispiel #4
0
typet jsil_prim_type()
{
  return jsil_union_typet({
                          floatbv_typet(),
                          string_typet(),
                          bool_typet()
                          });
}
Beispiel #5
0
void jsil_typecheckt::typecheck_expr_unary_string(exprt &expr)
{
  if(expr.operands().size()!=1)
  {
    err_location(expr);
    error() << "operator `" << expr.id()
            << "' expects one operand" << eom;
    throw 0;
  }

  make_type_compatible(expr.op0(), string_typet(), true);

  expr.type()=floatbv_typet();
}
Beispiel #6
0
void jsil_typecheckt::typecheck_expr_field(exprt &expr)
{
  if(expr.operands().size()!=1)
  {
    err_location(expr);
    error() << "operator `" << expr.id()
            << "' expects single operand" << eom;
    throw 0;
  }

  make_type_compatible(expr.op0(), jsil_reference_type(), true);

  expr.type()=string_typet();
}
Beispiel #7
0
void jsil_typecheckt::typecheck_expr_proto_field(exprt &expr)
{
  if(expr.operands().size()!=2)
  {
    err_location(expr);
    error() << "operator `" << expr.id()
            << "' expects two operands" << eom;
    throw 0;
  }

  make_type_compatible(expr.op0(), jsil_object_type(), true);
  make_type_compatible(expr.op1(), string_typet(), true);

  expr.type()=jsil_value_or_empty_type();
}
Beispiel #8
0
void jsil_typecheckt::typecheck_expr_index(exprt &expr)
{
  if(expr.operands().size()!=2)
  {
    err_location(expr);
    error() << "operator `" << expr.id()
            << "' expects two operands" << eom;
    throw 0;
  }

  make_type_compatible(expr.op0(), jsil_object_type(), true);
  make_type_compatible(expr.op1(), string_typet(), true);

  // special case for function identifiers
  if (expr.op1().id()=="fid" || expr.op1().id()=="constructid")
    expr.type()=code_typet();
  else
    expr.type()=jsil_value_type();
}
void set_class_identifier(
  struct_exprt &expr,
  const namespacet &ns,
  const symbol_typet &class_type)
{
  const struct_typet &struct_type=
    to_struct_type(ns.follow(expr.type()));
  const struct_typet::componentst &components=struct_type.components();

  if(components.empty()) return;
  assert(!expr.operands().empty());
  
  if(components.front().get_name()=="@class_identifier")
  {
    assert(expr.op0().id()==ID_constant);
    expr.op0()=constant_exprt(class_type.get_identifier(), string_typet());
  }
  else
  {
    assert(expr.op0().id()==ID_struct);
    set_class_identifier(to_struct_expr(expr.op0()), ns, class_type);
  }
}
void remove_virtual_functionst::remove_virtual_function(
  goto_programt &goto_program,
  goto_programt::targett target)
{
  const code_function_callt &code=
    to_code_function_call(target->code);

  const auto &vcall_source_loc=target->source_location;

  const exprt &function=code.function();
  assert(function.id()==ID_virtual_function);
  assert(!code.arguments().empty());

  functionst functions;
  get_functions(function, functions);

  if(functions.empty())
  {
    target->make_skip();
    return; // give up
  }

  // only one option?
  if(functions.size()==1)
  {
    assert(target->is_function_call());
    if(functions.begin()->symbol_expr==symbol_exprt())
      target->make_skip();
    else
      to_code_function_call(target->code).function()=
        functions.begin()->symbol_expr;
    return;
  }

  // the final target is a skip
  goto_programt final_skip;

  goto_programt::targett t_final=final_skip.add_instruction();
  t_final->source_location=vcall_source_loc;

  t_final->make_skip();

  // build the calls and gotos

  goto_programt new_code_calls;
  goto_programt new_code_gotos;

  exprt this_expr=code.arguments()[0];
  // If necessary, cast to the last candidate function to
  // get the object's clsid. By the structure of get_functions,
  // this is the parent of all other classes under consideration.
  const auto &base_classid=functions.back().class_id;
  const auto &base_function_symbol=functions.back().symbol_expr;
  symbol_typet suggested_type(base_classid);
  exprt c_id2=get_class_identifier_field(this_expr, suggested_type, ns);

  std::map<irep_idt, goto_programt::targett> calls;
  // Note backwards iteration, to get the least-derived candidate first.
  for(auto it=functions.crbegin(), itend=functions.crend(); it!=itend; ++it)
  {
    const auto &fun=*it;
    auto insertit=calls.insert(
      {fun.symbol_expr.get_identifier(), goto_programt::targett()});

    // Only create one call sequence per possible target:
    if(insertit.second)
    {
      goto_programt::targett t1=new_code_calls.add_instruction();
      t1->source_location=vcall_source_loc;
      if(!fun.symbol_expr.get_identifier().empty())
      {
      // call function
        t1->make_function_call(code);
        auto &newcall=to_code_function_call(t1->code);
        newcall.function()=fun.symbol_expr;
        pointer_typet need_type(symbol_typet(fun.symbol_expr.get(ID_C_class)));
        if(!type_eq(newcall.arguments()[0].type(), need_type, ns))
          newcall.arguments()[0].make_typecast(need_type);
      }
      else
      {
        // No definition for this type; shouldn't be possible...
        t1->make_assertion(false_exprt());
      }
      insertit.first->second=t1;
      // goto final
      goto_programt::targett t3=new_code_calls.add_instruction();
      t3->source_location=vcall_source_loc;
      t3->make_goto(t_final, true_exprt());
    }

    // If this calls the base function we just fall through.
    // Otherwise branch to the right call:
    if(fun.symbol_expr!=base_function_symbol)
    {
      exprt c_id1=constant_exprt(fun.class_id, string_typet());
      goto_programt::targett t4=new_code_gotos.add_instruction();
      t4->source_location=vcall_source_loc;
      t4->make_goto(insertit.first->second, equal_exprt(c_id1, c_id2));
    }
  }

  goto_programt new_code;

  // patch them all together
  new_code.destructive_append(new_code_gotos);
  new_code.destructive_append(new_code_calls);
  new_code.destructive_append(final_skip);

  // set locations
  Forall_goto_program_instructions(it, new_code)
  {
    const irep_idt property_class=it->source_location.get_property_class();
    const irep_idt comment=it->source_location.get_comment();
    it->source_location=target->source_location;
    it->function=target->function;
    if(!property_class.empty())
      it->source_location.set_property_class(property_class);
    if(!comment.empty())
      it->source_location.set_comment(comment);
  }

  goto_programt::targett next_target=target;
  next_target++;

  goto_program.destructive_insert(next_target, new_code);

  // finally, kill original invocation
  target->make_skip();
}
Beispiel #11
0
void remove_virtual_functionst::remove_virtual_function(
  goto_programt &goto_program,
  goto_programt::targett target)
{
  const code_function_callt &code=
    to_code_function_call(target->code);

  const exprt &function=code.function();
  assert(function.id()==ID_virtual_function);
  assert(!code.arguments().empty());
  
  functionst functions;
  get_functions(function, functions);
  
  if(functions.empty())
  {
    target->make_skip();
    return; // give up
  }

  // the final target is a skip
  goto_programt final_skip;

  goto_programt::targett t_final=final_skip.add_instruction();
  t_final->make_skip();
  
  // build the calls and gotos

  goto_programt new_code_calls;
  goto_programt new_code_gotos;

  for(functionst::const_iterator
      it=functions.begin();
      it!=functions.end();
      it++)
  {
    // call function
    goto_programt::targett t1=new_code_calls.add_instruction();
    t1->make_function_call(code);
    to_code_function_call(t1->code).function()=it->symbol_expr;
    
    // goto final
    goto_programt::targett t3=new_code_calls.add_instruction();
    t3->make_goto(t_final, true_exprt());

    exprt this_expr=code.arguments()[0];    
    if(this_expr.type().id()!=ID_pointer ||
       this_expr.type().id()!=ID_struct)
    {
      symbol_typet symbol_type(it->class_id);
      this_expr=typecast_exprt(this_expr, pointer_typet(symbol_type));
    }
    
    exprt deref=dereference_exprt(this_expr, this_expr.type().subtype());
    exprt c_id1=constant_exprt(it->class_id, string_typet());
    exprt c_id2=build_class_identifier(deref);
    
    goto_programt::targett t4=new_code_gotos.add_instruction();
    t4->make_goto(t1, equal_exprt(c_id1, c_id2));
  }

  goto_programt new_code;
  
  // patch them all together
  new_code.destructive_append(new_code_gotos);
  new_code.destructive_append(new_code_calls);
  new_code.destructive_append(final_skip);
  
  // set locations
  Forall_goto_program_instructions(it, new_code)
  {
    irep_idt property_class=it->source_location.get_property_class();
    irep_idt comment=it->source_location.get_comment();
    it->source_location=target->source_location;
    it->function=target->function;
    if(!property_class.empty()) it->source_location.set_property_class(property_class);
    if(!comment.empty()) it->source_location.set_comment(comment);
  }
Beispiel #12
0
void jsil_typecheckt::typecheck_expr_main(exprt &expr)
{
  if(expr.id()==ID_code)
  {
    err_location(expr);
    error() << "typecheck_expr_main got code: " << expr.pretty() << eom;
    throw 0;
  }
  else if(expr.id()==ID_symbol)
    typecheck_symbol_expr(to_symbol_expr (expr));
  else if(expr.id()==ID_constant)
  {
  }
  else
  {
    // expressions are expected not to have type set just yet
    assert(expr.type().is_nil()||expr.type().id().empty());

    if (expr.id()==ID_null ||
        expr.id()=="undefined" ||
        expr.id()==ID_empty)
      typecheck_expr_constant(expr);
    else if(expr.id()=="null_type" ||
            expr.id()=="undefined_type" ||
            expr.id()==ID_boolean ||
            expr.id()==ID_string ||
            expr.id()=="number" ||
            expr.id()=="builtin_object" ||
            expr.id()=="user_object" ||
            expr.id()=="object" ||
            expr.id()==ID_reference ||
            expr.id()==ID_member ||
            expr.id()=="variable")
      expr.type()=jsil_kind();
    else if(expr.id()=="proto" ||
            expr.id()=="fid" ||
            expr.id()=="scope" ||
            expr.id()=="constructid" ||
            expr.id()=="primvalue" ||
            expr.id()=="targetfunction" ||
            expr.id()==ID_class)
    {
      // TODO: have a special type for builtin fields
      expr.type()=string_typet();
    }
    else if(expr.id()==ID_not)
      typecheck_expr_unary_boolean(expr);
    else if(expr.id()=="string_to_num")
      typecheck_expr_unary_string(expr);
    else if(expr.id()==ID_unary_minus ||
            expr.id()=="num_to_int32" ||
            expr.id()=="num_to_uint32" ||
            expr.id()==ID_bitnot)
    {
      typecheck_expr_unary_num(expr);
      expr.type()=floatbv_typet();
    }
    else if(expr.id()=="num_to_string") {
      typecheck_expr_unary_num(expr);
      expr.type()=string_typet();
    }
    else if(expr.id()==ID_equal)
      typecheck_exp_binary_equal(expr);
    else if(expr.id()==ID_lt ||
            expr.id()==ID_le)
      typecheck_expr_binary_compare(expr);
    else if(expr.id()==ID_plus ||
            expr.id()==ID_minus ||
            expr.id()==ID_mult ||
            expr.id()==ID_div ||
            expr.id()==ID_mod ||
            expr.id()==ID_bitand ||
            expr.id()==ID_bitor ||
            expr.id()==ID_bitxor ||
            expr.id()==ID_shl ||
            expr.id()==ID_shr ||
            expr.id()==ID_lshr)
      typecheck_expr_binary_arith(expr);
    else if(expr.id()==ID_and ||
            expr.id()==ID_or)
      typecheck_expr_binary_boolean(expr);
    else if(expr.id()=="subtype_of")
      typecheck_expr_subtype(expr);
    else if(expr.id()==ID_concatenation)
      typecheck_expr_concatenation(expr);
    else if(expr.id()=="ref")
      typecheck_expr_ref(expr);
    else if(expr.id()=="field")
      typecheck_expr_field(expr);
    else if(expr.id()==ID_base)
      typecheck_expr_base(expr);
    else if(expr.id()==ID_typeof)
      expr.type()=jsil_kind();
    else if(expr.id()=="new")
      expr.type()=jsil_user_object_type();
    else if(expr.id()=="hasField")
      typecheck_expr_has_field(expr);
    else if(expr.id()==ID_index)
      typecheck_expr_index(expr);
    else if(expr.id()=="delete")
      typecheck_expr_delete(expr);
    else if(expr.id()=="protoField")
      typecheck_expr_proto_field(expr);
    else if(expr.id()=="protoObj")
      typecheck_expr_proto_obj(expr);
    else if(expr.id()==ID_side_effect)
      typecheck_expr_side_effect_throw(to_side_effect_expr_throw(expr));
    else
    {
      err_location(expr);
      error() << "unexpected expression: " << expr.pretty() << eom;
      throw 0;
    }
  }
}