src/quadr.c
static quadr_arg_t gen_quadr_expr(expr_t *node)
{
  assert (is_expr(node));

  if (node->node_type != NODE_IDENT && node->node_type != NODE_ARRAY &&
      node->type == type_boolean)
    {
      quadr_arg_t arg = new_var(node->type);
      var_t *var = arg.u.var;
      basic_block_t *if_true = new_basic_block();
      gen_quadr_bool_expr(node, if_true, true);
      add_basic_blocks(new_basic_block());
      basic_block_t *end = new_basic_block();
      gen_copy(var, quadr_arg0(TYPE_BOOLEAN, false));
      gen_goto(end);
      add_basic_blocks(if_true);
      gen_copy(var, quadr_arg0(TYPE_BOOLEAN, true));
      add_basic_blocks(end);
      return arg;
    }

  if (is_binop(node))
    {
      quadr_t *quadr = alloc_quadr();
      switch (node->node_type){
      case NODE_ADD:
        quadr->op = Q_ADD;
        break;
      case NODE_SUB:
        quadr->op = Q_SUB;
        break;
      case NODE_MUL:
        quadr->op = Q_MUL;
        break;
      case NODE_DIV:
        quadr->op = Q_DIV;
        break;
      case NODE_MOD:
        quadr->op = Q_MOD;
        break;
      default:
        xabort("Programming error - binop");
        break;
      };
      quadr->result = new_var(node->type);
      quadr->arg1 = gen_quadr_expr(((binary_t*)node)->left);
      quadr->arg2 = gen_quadr_expr(((binary_t*)node)->right);
      add_quadr(cur_block, quadr);
      return quadr->result;
    }

  switch (node->node_type){
  case NODE_INT:
    return quadr_arg(node->type->cons, ((int_t*) node)->value);

  case NODE_DOUBLE:
    return quadr_arg(node->type->cons, ((node_double_t*) node)->value);

  case NODE_BOOL:
    return quadr_arg(node->type->cons, ((bool_t*) node)->value);

  case NODE_STR:
    {
      quadr_arg_t arg;
      arg.tag = QA_STR;
      arg.u.str_val = ((str_t*)node)->value;
      return arg;
    }

  case NODE_IDENT:
    return quadr_arg_ident(((ident_t*)node)->ident->decl->u.var);

  case NODE_ARRAY:
    return gen_array_ref((array_t*)node);

  case NODE_CALL:
    return gen_call((call_t*)node);

  case NODE_PLUS:
    return gen_quadr_expr(((unary_t*) node)->arg);

  case NODE_NEG:
    {
      quadr_t *quadr = alloc_quadr();
      quadr->op = Q_SUB;
      quadr->result = new_var(node->type);
      quadr->arg1 = quadr_arg(node->type->cons, (node->type == type_double ? 0.0 : 0));
      quadr->arg2 = gen_quadr_expr(((unary_t*) node)->arg);
      add_quadr(cur_block, quadr);
      return quadr->result;
    }

  case NODE_NOT:
    { // compute 1 - x (x = 1 -> x = 0; x = 0 -> x = 1)
      quadr_t *quadr = alloc_quadr();
      assert (node->type == type_boolean);
      quadr->op = Q_SUB;
      quadr->result = new_var(node->type);
      quadr->arg1 = quadr_arg(node->type->cons, true);
      quadr->arg2 = gen_quadr_expr(((unary_t*) node)->arg);
      add_quadr(cur_block, quadr);
      return quadr->result;
    }

  default:
    xabort("Programming error - gen_quadr_expr().");
    break;
  };
  // that's OK, no return
}
// Generate an expression not used for a jump.
Generate an expression not used for a jump.
Generate an expression not used for a jump .
static quadr_arg_t gen_quadr_expr(expr_t *node)
{
  assert (is_expr(node));
  if (node->node_type != NODE_IDENT && node->node_type != NODE_ARRAY &&
      node->type == type_boolean)
    {
      quadr_arg_t arg = new_var(node->type);
      var_t *var = arg.u.var;
      basic_block_t *if_true = new_basic_block();
      gen_quadr_bool_expr(node, if_true, true);
      add_basic_blocks(new_basic_block());
      basic_block_t *end = new_basic_block();
      gen_copy(var, quadr_arg0(TYPE_BOOLEAN, false));
      gen_goto(end);
      add_basic_blocks(if_true);
      gen_copy(var, quadr_arg0(TYPE_BOOLEAN, true));
      add_basic_blocks(end);
      return arg;
    }
  if (is_binop(node))
    {
      quadr_t *quadr = alloc_quadr();
      switch (node->node_type){
      case NODE_ADD:
        quadr->op = Q_ADD;
        break;
      case NODE_SUB:
        quadr->op = Q_SUB;
        break;
      case NODE_MUL:
        quadr->op = Q_MUL;
        break;
      case NODE_DIV:
        quadr->op = Q_DIV;
        break;
      case NODE_MOD:
        quadr->op = Q_MOD;
        break;
      default:
        xabort("Programming error - binop");
        break;
      };
      quadr->result = new_var(node->type);
      quadr->arg1 = gen_quadr_expr(((binary_t*)node)->left);
      quadr->arg2 = gen_quadr_expr(((binary_t*)node)->right);
      add_quadr(cur_block, quadr);
      return quadr->result;
    }
  switch (node->node_type){
  case NODE_INT:
    return quadr_arg(node->type->cons, ((int_t*) node)->value);
  case NODE_DOUBLE:
    return quadr_arg(node->type->cons, ((node_double_t*) node)->value);
  case NODE_BOOL:
    return quadr_arg(node->type->cons, ((bool_t*) node)->value);
  case NODE_STR:
    {
      quadr_arg_t arg;
      arg.tag = QA_STR;
      arg.u.str_val = ((str_t*)node)->value;
      return arg;
    }
  case NODE_IDENT:
    return quadr_arg_ident(((ident_t*)node)->ident->decl->u.var);
  case NODE_ARRAY:
    return gen_array_ref((array_t*)node);
  case NODE_CALL:
    return gen_call((call_t*)node);
  case NODE_PLUS:
    return gen_quadr_expr(((unary_t*) node)->arg);
  case NODE_NEG:
    {
      quadr_t *quadr = alloc_quadr();
      quadr->op = Q_SUB;
      quadr->result = new_var(node->type);
      quadr->arg1 = quadr_arg(node->type->cons, (node->type == type_double ? 0.0 : 0));
      quadr->arg2 = gen_quadr_expr(((unary_t*) node)->arg);
      add_quadr(cur_block, quadr);
      return quadr->result;
    }
  case NODE_NOT:
    { 
      quadr_t *quadr = alloc_quadr();
      assert (node->type == type_boolean);
      quadr->op = Q_SUB;
      quadr->result = new_var(node->type);
      quadr->arg1 = quadr_arg(node->type->cons, true);
      quadr->arg2 = gen_quadr_expr(((unary_t*) node)->arg);
      add_quadr(cur_block, quadr);
      return quadr->result;
    }
  default:
    xabort("Programming error - gen_quadr_expr().");
    break;
  };
}
static quadr_arg_t gen_quadr_expr ( expr_t * node ) { assert ( is_expr ( node ) ) ; if ( node -> node_type != NODE_IDENT && node -> node_type != NODE_ARRAY && node -> type == type_boolean ) { quadr_arg_t arg = new_var ( node -> type ) ; var_t * var = arg . u . var ; basic_block_t * if_true = new_basic_block ( ) ; gen_quadr_bool_expr ( node , if_true , true ) ; add_basic_blocks ( new_basic_block ( ) ) ; basic_block_t * end = new_basic_block ( ) ; gen_copy ( var , quadr_arg0 ( TYPE_BOOLEAN , false ) ) ; gen_goto ( end ) ; add_basic_blocks ( if_true ) ; gen_copy ( var , quadr_arg0 ( TYPE_BOOLEAN , true ) ) ; add_basic_blocks ( end ) ; return arg ; } if ( is_binop ( node ) ) { quadr_t * quadr = alloc_quadr ( ) ; switch ( node -> node_type ) { case NODE_ADD : quadr -> op = Q_ADD ; break ; case NODE_SUB : quadr -> op = Q_SUB ; break ; case NODE_MUL : quadr -> op = Q_MUL ; break ; case NODE_DIV : quadr -> op = Q_DIV ; break ; case NODE_MOD : quadr -> op = Q_MOD ; break ; default : xabort ( " " ) ; break ; } ; quadr -> result = new_var ( node -> type ) ; quadr -> arg1 = gen_quadr_expr ( ( ( binary_t * ) node ) -> left ) ; quadr -> arg2 = gen_quadr_expr ( ( ( binary_t * ) node ) -> right ) ; add_quadr ( cur_block , quadr ) ; return quadr -> result ; } switch ( node -> node_type ) { case NODE_INT : return quadr_arg ( node -> type -> cons , ( ( int_t * ) node ) -> value ) ; case NODE_DOUBLE : return quadr_arg ( node -> type -> cons , ( ( node_double_t * ) node ) -> value ) ; case NODE_BOOL : return quadr_arg ( node -> type -> cons , ( ( bool_t * ) node ) -> value ) ; case NODE_STR : { quadr_arg_t arg ; arg . tag = QA_STR ; arg . u . str_val = ( ( str_t * ) node ) -> value ; return arg ; } case NODE_IDENT : return quadr_arg_ident ( ( ( ident_t * ) node ) -> ident -> decl -> u . var ) ; case NODE_ARRAY : return gen_array_ref ( ( array_t * ) node ) ; case NODE_CALL : return gen_call ( ( call_t * ) node ) ; case NODE_PLUS : return gen_quadr_expr ( ( ( unary_t * ) node ) -> arg ) ; case NODE_NEG : { quadr_t * quadr = alloc_quadr ( ) ; quadr -> op = Q_SUB ; quadr -> result = new_var ( node -> type ) ; quadr -> arg1 = quadr_arg ( node -> type -> cons , ( node -> type == type_double ? 0.0 : 0 ) ) ; quadr -> arg2 = gen_quadr_expr ( ( ( unary_t * ) node ) -> arg ) ; add_quadr ( cur_block , quadr ) ; return quadr -> result ; } case NODE_NOT : { quadr_t * quadr = alloc_quadr ( ) ; assert ( node -> type == type_boolean ) ; quadr -> op = Q_SUB ; quadr -> result = new_var ( node -> type ) ; quadr -> arg1 = quadr_arg ( node -> type -> cons , true ) ; quadr -> arg2 = gen_quadr_expr ( ( ( unary_t * ) node ) -> arg ) ; add_quadr ( cur_block , quadr ) ; return quadr -> result ; } default : xabort ( " " ) ; break ; } ; }
Generate an expression not used for a jump.
Generate an expression not used for a jump .
// compute 1 - x (x = 1 -> x = 0; x = 0 -> x = 1) // that's OK, no return