Exemple #1
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);
}
void decl_codegen(struct decl *d, FILE * file){
	if(!d)return;
	if(d->symbol->kind == SYMBOL_GLOBAL){
		if(!d->code && !d->value && d->type->kind != TYPE_FUNCTION){
			if(d->type->kind != TYPE_STRING)fprintf(file,".data\n%s: .quad 0\n",d->name);
			else{
				
				//printf("teste");
				fprintf(file,".data\n.global %s\n%s:\n	.string \"\" \n",d->name,d->name);
			}
		}
		else{
			if(d->value && d->type->kind != TYPE_FUNCTION){
				if(d->type->kind == TYPE_STRING && d->type->kind != TYPE_FUNCTION){
					fprintf(file,".data\n.global %s\n%s:\n	.string ""%s""\n",d->name,d->name,d->value->string_literal);//nao esquecer de tratar quebras de linha	  	
				}
				else if(d->type->kind != TYPE_FUNCTION) fprintf(file,".data\n.global %s\n%s:\n	.quad %d\n",d->name,d->name,d->value->literal_value);//pode ter expressoes do tipo 10+1 na declaracao?
			}else{
				if(d->code){
				fprintf(file,".text\n.global %s\n%s:\n",d->name,d->name);
				struct param_list *p = d->type->params;
				fprintf(file,"	pushq %%rbp\n	movq  %%rsp, %%rbp\n");
				int parameters_cont = 0;
				while(p){
					p = p->next;
					parameters_cont++;
				}
				if(parameters_cont >= 1){
				   	fprintf(file,"	pushq %%rdi\n");	
				}
				if(parameters_cont >= 2){
				  	fprintf(file,"	pushq %%rsi\n");
				}
				if(parameters_cont >= 3){
					fprintf(file,"	pushq %%rdx\n");
				}
				if(parameters_cont >= 4){
					fprintf(file,"	pushq %%rcx\n");
				}
				if(parameters_cont >= 5){
					fprintf(file,"	pushq %%r8\n");
				}
				if(parameters_cont == 6){
					fprintf(file,"	pushq %%r9\n");
				}
				if(d->symbol->total_locals > 0){		
					fprintf(file,"	subq $%d,%%rsp\n",d->symbol->total_locals*8);
				}
				fprintf(file,"	pushq %%rbx\n");
				fprintf(file,"	pushq %%r12\n");
				fprintf(file,"	pushq %%r13\n");
				fprintf(file,"	pushq %%r14\n");
				fprintf(file,"	pushq %%r15\n\n");		
				stmt_codegen(d->code,file);
				fprintf(file,"FUNCAO%d:\n",funcoes);
				fprintf(file,"\n");
				fprintf(file,"	popq %%r15\n");
				fprintf(file,"	popq %%r14\n");
				fprintf(file,"	popq %%r13\n");
				fprintf(file,"	popq %%r12\n");
				fprintf(file,"	popq %%rbx\n");
				fprintf(file,"	movq %%rbp,%%rsp\n");
				fprintf(file,"	popq %%rbp\n");
				fprintf(file,"	ret\n");
				funcoes++;	
				//postamble como tratar
				}
			}
		}

    }
	else if(d->symbol->kind == SYMBOL_LOCAL){
			if(d->value){
				expr_codegen(d->value,file);
				fprintf(file,"	movq %s,-%d(%%rbp)\n",register_name(d->value->reg),d->symbol->param_local_variables*8);//arrumar isso, voce usou valor aleatorio,
				register_free(d->value->reg);
				//dont forget to free registers
				//voltar no video do dia 20, minuto 35 para tratar o caso das strings
			}
		}
	decl_codegen(d->next,file);
}
Exemple #3
0
void stmt_codegen(struct stmt *s, FILE * output) {
	struct expr * e_cursor;
	int label_save;
	if (!s) return;
	switch (s->kind) {
		case STMT_DECL:
			decl_codegen(s->decl, output);
			break;
		case STMT_EXPR:
			expr_codegen(s->expr, output);
			register_free(s->expr->reg);
			break;
		case STMT_IF_ELSE:
			fprintf(output, "\n\t## if statement ##\n");
			label_save = label_count;
			label_count+=2;
			expr_codegen(s->expr, output);
			fprintf(output, "\tCMP $0, %s\n", register_name(s->expr->reg));
			register_free(s->expr->reg);
			fprintf(output, "\tJE .L%d\n", label_save);
			stmt_codegen(s->body, output);
			fprintf(output, "\tJMP .L%d\n", label_save+1);
			fprintf(output, "\t.L%d:\n", label_save);
			stmt_codegen(s->else_body, output);
			fprintf(output, "\t.L%d:\n", label_save+1);
			fprintf(output, "\n\t## end of if statement ##\n");
			break;
		case STMT_FOR:
			label_save = label_count;
			label_count+=2;
			fprintf(output, "\n\t## for loop ##\n");
			expr_codegen(s->init_expr, output);
			if(s->init_expr) {	// for infinite for loops
				register_free(s->init_expr->reg);
			}
			fprintf(output, "\t.L%d:\n", label_save);
			expr_codegen(s->expr, output);
			if (s->expr) {		// for infinite for loops
				register_free(s->expr->reg);
				fprintf(output, "\tCMP $0, %s\n", register_name(s->expr->reg));
				fprintf(output, "\tJE .L%d\n", label_save+1);
			}
			stmt_codegen(s->body, output);
			expr_codegen(s->next_expr, output);
			if (s->next_expr) {
				register_free(s->next_expr->reg);
			}
			fprintf(output, "\tJMP .L%d\n", label_save);
			fprintf(output, "\t.L%d:\n", label_save+1);
			fprintf(output, "\t## end of for loop ##\n");
			break;
		case STMT_PRINT:
			if(s->expr) {
				if(s->expr->kind == EXPR_LIST) {	// multiple things to print
					e_cursor = s->expr;	// traverse the expr_list
					while(e_cursor) {
						expr_print_codegen(e_cursor->left, output);
						e_cursor = e_cursor->right;
					}
				}
				else {	// single thing to print
					expr_print_codegen(s->expr, output);
				}
			}
			break;
		case STMT_RETURN:
			fprintf(output, "\n\t## return statement ##\n");
			if (s->expr) {
				expr_codegen(s->expr, output);
				fprintf(output, "\tMOV %s, %%rax\n", register_name(s->expr->reg));
				register_free(s->expr->reg);
				fprintf(output, "\tJMP .ret%d\n", ret_count);                	// return to caller
			}
			else {
				fprintf(output, "\tJMP .ret%d\n", ret_count); 
			}
			fprintf(output, "\t## end return statement ##\n\n");
			break;
		case STMT_BLOCK:
			stmt_codegen(s->body, output);
			break;
		case STMT_EMPTY:
			break;
	} 
	stmt_codegen(s->next, output);
}