Example #1
0
void stmt_call_print(struct expr *curr, FILE *f) {
  switch(curr -> print_type) {
    case 0:
      fprintf(stderr, "Expr ");
      expr_fprint(stderr, curr);
      fprintf(stderr, " has bad print_type (%d)\n", curr -> print_type);
      exit(1);
      break;
    case 1:
      expr_func_codegen(curr, "print_boolean", f);
      register_free(curr -> reg);
      break;
    case 2:
      expr_func_codegen(curr, "print_character", f);
      register_free(curr -> reg);
      break;
    case 3:
      expr_func_codegen(curr, "print_integer", f);
      register_free(curr -> reg);
      break;
    case 4:
      expr_func_codegen(curr, "print_string", f);
      register_free(curr -> reg);
      break;
    default:
      fprintf(stderr, "Expr ");
      expr_fprint(stderr, curr);
      fprintf(stderr, " has bad print_type (%d)\n", curr -> print_type);
      exit(1);
      break;
  }
}
Example #2
0
void
print_expr(int mask, struct expr *e, int prevtoken)
{
    if (!(cdebug & mask))
	return;
    expr_fprint(e, stdout);
}
Example #3
0
File: expr.c Project: 020gzh/linux
static int expr_eq(struct expr *e1, struct expr *e2)
{
	int res, old_count;

	if (e1->type != e2->type)
		return 0;
	switch (e1->type) {
	case E_EQUAL:
	case E_GEQ:
	case E_GTH:
	case E_LEQ:
	case E_LTH:
	case E_UNEQUAL:
		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
	case E_SYMBOL:
		return e1->left.sym == e2->left.sym;
	case E_NOT:
		return expr_eq(e1->left.expr, e2->left.expr);
	case E_AND:
	case E_OR:
		e1 = expr_copy(e1);
		e2 = expr_copy(e2);
		old_count = trans_count;
		expr_eliminate_eq(&e1, &e2);
		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
		       e1->left.sym == e2->left.sym);
		expr_free(e1);
		expr_free(e2);
		trans_count = old_count;
		return res;
	case E_LIST:
	case E_RANGE:
	case E_NONE:
		/* panic */;
	}

	if (DEBUG_EXPR) {
		expr_fprint(e1, stdout);
		printf(" = ");
		expr_fprint(e2, stdout);
		printf(" ?\n");
	}

	return 0;
}
Example #4
0
static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
{
	struct expr *tmp;
	struct symbol *sym1, *sym2;

	if (expr_eq(e1, e2))
		return expr_copy(e1);
	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
		return NULL;
	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
		return NULL;
	if (e1->type == E_NOT) {
		tmp = e1->left.expr;
		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
			return NULL;
		sym1 = tmp->left.sym;
	} else
		sym1 = e1->left.sym;
	if (e2->type == E_NOT) {
		if (e2->left.expr->type != E_SYMBOL)
			return NULL;
		sym2 = e2->left.expr->left.sym;
	} else
		sym2 = e2->left.sym;
	if (sym1 != sym2)
		return NULL;
	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
		return NULL;

	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
		// (a) && (a='y') -> (a='y')
		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);

	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
		// (a) && (a!='n') -> (a)
		return expr_alloc_symbol(sym1);

	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
		// (a) && (a!='m') -> (a='y')
		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);

	if (sym1->type == S_TRISTATE) {
		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
			sym2 = e1->right.sym;
			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
							     : expr_alloc_symbol(&symbol_no);
		}
		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
			sym2 = e2->right.sym;
			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
							     : expr_alloc_symbol(&symbol_no);
		}
		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
			// (a!='y') && (a!='n') -> (a='m')
			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);

		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
			// (a!='y') && (a!='m') -> (a='n')
			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);

		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
			// (a!='m') && (a!='n') -> (a='m')
			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);

		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
			return NULL;
	}

	if (DEBUG_EXPR) {
		printf("optimize (");
		expr_fprint(e1, stdout);
		printf(") && (");
		expr_fprint(e2, stdout);
		printf(")?\n");
	}
	return NULL;
}
Example #5
0
File: expr.c Project: 16rd/rt-n56u
/*
 * e1 || e2 -> ?
 */
struct expr *expr_join_or(struct expr *e1, struct expr *e2)
{
	struct expr *tmp;
	struct symbol *sym1, *sym2;

	if (expr_eq(e1, e2))
		return expr_copy(e1);
	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
		return NULL;
	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
		return NULL;
	if (e1->type == E_NOT) {
		tmp = e1->left.expr;
		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
			return NULL;
		sym1 = tmp->left.sym;
	} else
		sym1 = e1->left.sym;
	if (e2->type == E_NOT) {
		if (e2->left.expr->type != E_SYMBOL)
			return NULL;
		sym2 = e2->left.expr->left.sym;
	} else
		sym2 = e2->left.sym;
	if (sym1 != sym2)
		return NULL;
	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
		return NULL;
	if (sym1->type == S_TRISTATE) {
		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
			// (a='y') || (a='m') -> (a!='n')
			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
		}
		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
			// (a='y') || (a='n') -> (a!='m')
			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
		}
		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
			// (a='m') || (a='n') -> (a!='y')
			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
		}
	}
	if (sym1->type == S_BOOLEAN && sym1 == sym2) {
		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
			return expr_alloc_symbol(&symbol_yes);
	}

	if (DEBUG_EXPR) {
		printf("optimize (");
		expr_fprint(e1, stdout);
		printf(") || (");
		expr_fprint(e2, stdout);
		printf(")?\n");
	}
	return NULL;
}
Example #6
0
void stmt_codegen(struct stmt *s, FILE *f) {
  if(!s) return;
  switch(s -> kind) {
    case STMT_DECL:
      decl_codegen(s -> decl, f, SYMBOL_LOCAL);
      break;
    case STMT_EXPR:
      expr_codegen(s -> expr, f);
      register_free(s -> expr -> reg);
      break;
    case STMT_IF_ELSE: {
      int done = assembly_jump_label++;
      expr_codegen(s -> expr, f);
      fprintf(f, "\tCMP $0, %s\n", register_name(s -> expr -> reg));
      register_free(s -> expr -> reg);
      if(s -> else_body) {
        int el = assembly_jump_label++;
        // jump to else
        fprintf(f, "\tJE L%d\n", el);
        stmt_codegen(s -> body, f);
        assembly_comment(f, "\t# jump to done label (don't evaluate else label)\n");
        fprintf(f, "JMP L%d\n", done);
        assembly_comment(f, "\t# else label\n");
        fprintf(f, "L%d:\n", el);
        stmt_codegen(s -> else_body, f);
        assembly_comment(f, "\t# done label\n");
        fprintf(f, "L%d:\n", done);
      }
      else {
        // jump to done
        fprintf(f, "\tJE L%d\n", done);
        stmt_codegen(s -> body, f);
        assembly_comment(f, "\t# done label\n");
        fprintf(f, "L%d:\n", done);
      }
      break;
    }
    case STMT_FOR: {
      // check for nulls since all exprs optional
      int loop = assembly_jump_label++;
      int done = assembly_jump_label++;
      if(s -> init_expr) {
        expr_codegen(s -> init_expr, f);
        register_free(s -> init_expr -> reg);
      }
      // loop label
      assembly_comment(f, "\t# loop label\n");
      fprintf(f, "L%d:\n", loop);
      if(s -> expr) {
        expr_codegen(s -> expr, f);
        // don't need the return value
        fprintf(f, "\tCMP $0, %s\n", register_name(s -> expr -> reg));
        register_free(s -> expr -> reg);
        assembly_comment(f, "\t# jump to done label (break condition)\n");
        fprintf(f, "\tJE L%d\n", done);
      }
      stmt_codegen(s -> body, f);
      if(s -> next_expr) {
        expr_codegen(s -> next_expr, f);
        register_free(s -> next_expr -> reg);
      }
      assembly_comment(f, "\t# unconditional jump to next loop\n");
      fprintf(f, "JMP L%d\n", loop);
      assembly_comment(f, "\t# done label\n");
      fprintf(f, "L%d:\n", done);
      break;
    }
    case STMT_WHILE:
      fprintf(stderr, "CODEGEN_ERROR: cminor does not support while loops\n");
      exit(1);
      break;
    case STMT_PRINT: {
      struct expr *curr = s -> expr;
      while(curr) {
        expr_codegen(curr, f);

        int count = 0;

        if(ASSEMBLY_COMMENT_FLAG) {
          fprintf(f, "\t# move arg %d (in %s) into %s\n", count, register_name(curr -> reg), register_arg_names[count]);
        }

        fprintf(f, "\tMOVQ %s, %s\n", register_name(curr -> reg), register_arg_names[count++]);

        register_free(curr -> reg);
        // calls func_codegen which save ret val in reg
        // so need to free reg beforehand
        stmt_call_print(curr, f);

        curr = curr -> next;
      }
      break;
    }
    case STMT_RET:
      expr_codegen(s -> expr, f);
      if(ASSEMBLY_COMMENT_FLAG) {
        fprintf(f, "\n\t# return statement (return ");
        expr_fprint(f, s -> expr);
        fprintf(f, ")\n");
      }
      if(s -> expr) {
        fprintf(f, "\tMOVQ %s, %%rax\n", register_name(s -> expr -> reg));
        register_free(s -> expr -> reg);
      }

      // postamble
      assembly_comment(f, "\t### function postamble\n");
      assembly_comment(f, "\t# restore callee-saved registers\n");
      fprintf(f, "\tPOPQ %%r15\n");
      fprintf(f, "\tPOPQ %%r14\n");
      fprintf(f, "\tPOPQ %%r13\n");
      fprintf(f, "\tPOPQ %%r12\n");
      fprintf(f, "\tPOPQ %%rbx\n");

      assembly_comment(f, "\t# reset stack to base pointer\n");
      fprintf(f, "\tMOVQ %%rbp, %%rsp\n");
      assembly_comment(f, "\t# restore the old base pointer\n");
      fprintf(f, "\tPOPQ %%rbp\n");
      fprintf(f, "\tRET\n");
      break;
    case STMT_BLOCK:
      stmt_codegen(s -> body, f);
      break;
  }
  stmt_codegen(s -> next, f);
}
Example #7
0
void stmt_typecheck(struct stmt *s, struct type *ret, int *returned) {
  if(!s) return;
  switch(s -> kind) {
    struct type *expr;
    struct expr *curr;
    case STMT_DECL:
      decl_typecheck(s -> decl);
      break;
    case STMT_EXPR:
      // need to typecheck, but don't need type
      type_delete(expr_typecheck(s -> expr));
      break;
    case STMT_IF_ELSE:
      expr = expr_typecheck(s -> expr);
      if(expr -> kind != TYPE_BOOLEAN) {
        fprintf(stderr, "TYPE_ERROR: cannot use a(n) ");
        type_fprint(stderr, expr);
        fprintf(stderr, " as the if statement expression (currently ");
        expr_fprint(stderr, s -> expr);
        fprintf(stderr, ") requires a boolean\n");
        type_error_count++;
      }
      stmt_typecheck(s -> body, ret, returned);
      stmt_typecheck(s -> else_body, ret, returned);
      type_delete(expr);
      break;
    case STMT_FOR:
      type_delete(expr_typecheck(s -> init_expr));
      expr = expr_typecheck(s -> expr);
      // need to check that the middle
      // expression is actually there
      if(expr && expr -> kind != TYPE_BOOLEAN) {
        fprintf(stderr, "TYPE_ERROR: cannot use a ");
        type_fprint(stderr, expr);
        fprintf(stderr, " as the middle expression requires a boolean (or an empty expression)\n");
        type_error_count++;
      }
      type_delete(expr);
      type_delete(expr_typecheck(s -> next_expr));
      stmt_typecheck(s -> body, ret, returned);
      break;
    case STMT_WHILE:
      break;
    case STMT_PRINT:
      curr = s -> expr;
      while(curr) {
        expr = expr_typecheck(curr);
        // pass type through new symbol
        if(!type_is_atomic(expr)) {
          fprintf(stderr, "TYPE_ERROR: cannot print (print ");
          expr_fprint(stderr, s -> expr);
          fprintf(stderr, ") a non-atomic value (");
          type_fprint(stderr, expr);
          fprintf(stderr, ")\n");
          type_error_count++;
        }
        switch(expr -> kind) {
          case TYPE_BOOLEAN:
            curr -> print_type = 1;
            break;
          case TYPE_CHARACTER:
            curr -> print_type = 2;
            break;
          case TYPE_INTEGER:
            curr -> print_type = 3;
            break;
          case TYPE_STRING:
            curr -> print_type = 4;
            break;
          case TYPE_ARRAY:
            curr -> print_type = 0;
            fprintf(stderr, "Bad entry into switch on type_kind in stmt_typecheck (case STMT_PRINT)\n");
            exit(1);
            break;
          case TYPE_ARRAY_DECL:
            curr -> print_type = 0;
            fprintf(stderr, "Bad entry into switch on type_kind in stmt_typecheck (case STMT_PRINT)\n");
            exit(1);
            break;
          case TYPE_FUNCTION:
            curr -> print_type = 0;
            fprintf(stderr, "Bad entry into switch on type_kind in stmt_typecheck (case STMT_PRINT)\n");
            exit(1);
            break;
          case TYPE_VOID:
            curr -> print_type = 0;
            fprintf(stderr, "Bad entry into switch on type_kind in stmt_typecheck (case STMT_PRINT)\n");
            exit(1);
            break;
        }
        type_delete(expr);
        curr = curr -> next;
      }
      break;
    case STMT_RET:
      // always set to 1
      *returned = 1;
      expr = expr_typecheck(s -> expr);
      if(!s -> expr) {
        type_delete(expr);
        expr = type_create(TYPE_VOID, 0, 0, 0);
      }
      if(!type_compare(expr, ret)) {
        fprintf(stderr, "TYPE_ERROR: the return statement (return ");
        expr_fprint(stderr, s -> expr);
        fprintf(stderr, ") does not match the function return type (");
        type_fprint(stderr, ret);
        fprintf(stderr, ")\n");
        type_error_count++;
      }
      type_delete(expr);
      break;
    case STMT_BLOCK:
      stmt_typecheck(s -> body, ret, returned);
      break;
  }
  stmt_typecheck(s -> next, ret, returned);
}
Example #8
0
void stmt_fprint(FILE *f, struct stmt *s, int indent) {
  if(!s) return;
  if(s -> kind != STMT_BLOCK)
    fprint_indent(f, indent);

  switch(s -> kind) {
    case STMT_DECL:
      decl_fprint(f, s -> decl, indent - 1);
      /*don't print new line because decl always prints new lines*/
      break;
    case STMT_EXPR:
      expr_fprint(f, s -> expr);
      fprintf(f, ";\n");
      break;
    case STMT_IF_ELSE:
      fprintf(f, "if(");
      expr_fprint(f, s -> expr);
      fprintf(f, ")");
      stmt_fprint_body(f, s -> body, indent);
      if(s -> else_body) {
        fprint_indent(f, indent);
        fprintf(f, "else");
        stmt_fprint_body(f, s -> else_body, indent);
      }
      break;
    case STMT_FOR:
      fprintf(f, "for(");
      expr_fprint(f, s -> init_expr);
      fprintf(f, "; ");
      expr_fprint(f, s -> expr);
      fprintf(f, "; ");
      expr_fprint(f, s -> next_expr);
      fprintf(f, ")");
      stmt_fprint_body(f, s -> body, indent);
      break;
    case STMT_WHILE:
      /*
       *while loops are not in the CMinor spec so this should not get called.
       *if it does, it breaks immediately
       */
      break;
    case STMT_PRINT:
      fprintf(f, "print");
      if(s -> expr) {
        fprintf(f, " ");
        expr_fprint(f, s -> expr);
      }
      fprintf(f, ";\n");
      break;
    case STMT_RET:
      fprintf(f, "return");
      if(s -> expr) {
        fprintf(f, " ");
        expr_fprint(f, s -> expr);
      }
      fprintf(f, ";\n");
      break;
    case STMT_BLOCK:
      fprintf(f, "{\n");
      stmt_fprint(f, s -> body, indent + 1);
      fprint_indent(f, indent);
      fprintf(f, "}\n");
      break;
  }
  stmt_fprint(f, s -> next, indent);
}