void emitstmt(void* stmt){
	Syntax *st = (Syntax*) stmt;
	if(st->type == IF_STATEMENT){
		int label = labelconditionid++;
		char c[10];
		emit_condition(st->if_statement->condition,label);
		emitblock(st->if_statement->then);
		sprintf(c,".LC%d",label);
		emit_label(c);
	}else if(st->type == WHILE_SYNTAX){
		int labelcondition,labelblock;
		labelcondition = labelconditionid++;
		labelblock = labelconditionid++;
		char c[10];
		emit_instr_format("jmp",".LC%d",labelcondition);//to check condition
		sprintf(c,".LC%d",labelblock);
		emit_label(c);
		emitblock(st->while_statement->body);
		sprintf(c,".LC%d",labelcondition);
		emit_label(c);
		emit_condition(st->while_statement->condition,labelblock);
	}else if(st->type == PRINT_STATEMENT){
		emit_instr_format("leaq","%s(%%rip), %%rcx",st->printstmt->tag);
		emit_ins("call","printf");
	}else if(st->type == PRINTDEC_STATEMENT){
		emit_expression(st->printexp->exp);
		emit_ins("movq","%%rax, %%rdx");
		emit_ins("leaq",".DEC(%%rip), %%rcx");//.DEC print dec format
		emit_ins("call","printf");
	}else if(st->type == PRINTHEX_STATEMENT){
		emit_expression(st->printexp->exp);
		emit_ins("movq","%%rax, %%rdx");
		emit_ins("leaq",".HEX(%%rip), %%rcx");//.HEX print hex format
		emit_ins("call","printf");
	}else if(st->type == ASSIGNMENT){
		int tempoffset = findOffsetVar(st->assignment->var_name);//not found is -1
		if(tempoffset == -1){
			OffsetVarmap* temp = (OffsetVarmap*)malloc(sizeof(OffsetVarmap));
			temp->varname = st->assignment->var_name;
			temp->offset = offset;
			tempoffset = offset;
			//printf("offset %d \n",offset);
			offset = offset+8;
			list_push(tablevar,temp);
		}
		emit_expression(st->assignment->expression);
		emit_instr_format("movq","%%rax, -%d(%%rbp)",tempoffset);//result to variable.
	}else if(st->type == VARIABLE){
		OffsetVarmap *temp = (OffsetVarmap*)malloc(sizeof(OffsetVarmap));
		temp->varname = st->variable->var_name;
		temp->offset = offset;
		offset = offset+8;
		list_push(tablevar,temp);
	}else{
		fprintf(fp,"statement error");
	}
}
void emit_condition(Syntax* condition,int label){
	if(condition->type == BINARY_OPERATOR){
		BinaryExpression *binary_syntax = condition->binary_expression;
		char l[20];
		char r[20];//digit no exceed 20 digit.
		if(binary_syntax->left->type == VARIABLE){
			int os = findOffsetVar(binary_syntax->left->variable->var_name);
			if(os == -1)
				printf("%s not initialize",binary_syntax->left->variable->var_name);
			sprintf(l,"-%d(%%rbp)",os);
		}else if(binary_syntax->left->type == IMMEDIATE){
			sprintf(l,"$%d",binary_syntax->left->immediate->value);
		}else{
			printf("condition accept only variable or immediate : left operand");
			exit(0);
		}
		emit_instr_format("movq","%s, %%rax",l);
		if(binary_syntax->right->type == VARIABLE){
			int os = findOffsetVar(binary_syntax->right->variable->var_name);
			if(os == -1)
				printf("%s not initialize",binary_syntax->right->variable->var_name);
			sprintf(r,"-%d(%%rbp)",os);
		}else if(binary_syntax->right->type == IMMEDIATE){
			sprintf(r,"$%d",binary_syntax->right->immediate->value);
		}else{
			printf("condition accept only variable or immediate : right operand");
			exit(0);
		}
		
		emit_instr_format("movq","%s, %%r8",r);
		if(binary_syntax->binary_type == LESS_THAN){// l = arg1 r= arg2
			emit_instr_format("cmpq","%%r8, %%rax"); //cmpq arg2, arg1 gas syntax.
			emit_instr_format("jl",".LC%d",label);
		}else if(binary_syntax->binary_type == LESS_THAN_OR_EQUAL){
			emit_instr_format("cmpq","%%r8, %%rax");
			emit_instr_format("jle",".LC%d",label);
		}else if(binary_syntax->binary_type == EQUAL){
			emit_instr_format("cmpq","%%rax, %%r8");
			emit_instr_format("je",".LC%d",label);
		}else if(binary_syntax->binary_type == NOT_EQ){
			emit_instr_format("cmpq","%%rax ,%%r8");
			emit_instr_format("jne",".LC%d",label);
		}else{
			printf("unknown condition");
		}
	}else
		printf("invalid condition");
}
void emit_expression(Syntax *exp){
	if (exp->type == UNARY_OPERATOR) {
        UnaryExpression *unary_syntax = exp->unary_expression;
		emit_expression(unary_syntax->expression);
        
        if (unary_syntax->unary_type == BITWISE_NEGATION) {
            emit_ins("notq", "%%rax");
        } else {
            emit_ins("testq", "$0xFFFFFFFF, %%rax");
            emit_ins("setz", "%%al");
        }
    } else if (exp->type == IMMEDIATE) {
		//may be fix 64 bit
        emit_instr_format("movq", "$%d, %%rax", exp->immediate->value);

    } else if (exp->type == VARIABLE) {
		int tempoffset = findOffsetVar(exp->variable->var_name);
        emit_instr_format("movq", "-%d(%%rbp), %%rax",tempoffset);

    } else if (exp->type == BINARY_OPERATOR) {
        BinaryExpression *binary_syntax = exp->binary_expression;
		char l[20];
		char r[20];//digit no exceed 20 digit.
		if(binary_syntax->left->type == VARIABLE){
			int os = findOffsetVar(binary_syntax->left->variable->var_name);
			if(os == -1)
				printf("%s not initialize",binary_syntax->left->variable->var_name);
			sprintf(l,"-%d(%%rbp)",os);
		}else if(binary_syntax->left->type == IMMEDIATE){
			sprintf(l,"$%d",binary_syntax->left->immediate->value);
		}else{
			emit_expression(binary_syntax->left);
		}
		
		if(binary_syntax->right->type == VARIABLE){
			int os = findOffsetVar(binary_syntax->right->variable->var_name);
			if(os == -1)
				printf("%s not initialize",binary_syntax->right->variable->var_name);
			sprintf(r,"-%d(%%rbp)",os);
		}else if(binary_syntax->right->type == IMMEDIATE){
			sprintf(r,"$%d",binary_syntax->right->immediate->value);
		}else{
			emit_expression(binary_syntax->right);
		}
		/*
        int stack_offset = ctx->stack_offset;
        ctx->stack_offset -= WORD_SIZE;

        emit_instr(out, "sub", "$4, %esp");
        write_syntax(out, binary_syntax->left, ctx);
        emit_instr_format(out, "mov", "%%eax, %d(%%ebp)", stack_offset);

        write_syntax(out, binary_syntax->right, ctx);
		*/
		emit_instr_format("movq", "%%rax ,%%r8");//bug
		emit_instr_format("movq","%s ,%%rax",l);
        if (binary_syntax->binary_type == MULTIPLICATION) {
            emit_instr_format("imulq", "%s ,%%rax",r);

        } else if (binary_syntax->binary_type == ADDITION) {
            emit_instr_format("addq", "%s ,%%rax",r);

        } else if (binary_syntax->binary_type == SUBTRACTION) {
			emit_instr_format("movq", "%s, %%r10", r);
            emit_ins("subq", "%%r10, %%rax");
            //emit_instr_format("movq", "%s, %%rax", r);

        } else if (binary_syntax->binary_type == DIVIDE) {
			emit_ins("cltd",NULL);
			emit_instr_format("idivl","%s",r);
		} else if (binary_syntax->binary_type == MODULO){
			emit_ins("cltd",NULL);
			emit_instr_format("idivl","%s",r);
			emit_ins("movq","%rdx, %rax");
		} else{
			printf("expression error");
		}

    } 
}
예제 #4
0
void write_syntax(FILE *out, Syntax *syntax){
	printf("write_syntax\n");
	if(syntax->type == IMMEDIATE){
	    printf("case gen immediate\n");
	    emit_instr_format(out, "mov", "$%d, %%eax", syntax->immediate->value);
	} else if (syntax->type == VARIABLE) {
	    printf("case gen var\n");
            emit_instr_format(out, "mov", "-%d(%%ebp), %%eax", 4*(syntax->variable->var_index+1));
	} else if (syntax->type == BINARY_OPERATOR){
		printf("case gen binary\n");
		BinaryExpression *binary_syntax = syntax->binary_expression;
		//reserve space for temporary 
		write_syntax(out, binary_syntax->left);

		emit_instr(out, "sub", "$4, %esp");
		emit_instr(out, "mov", "%eax, 0(%esp)");
		
		write_syntax(out, binary_syntax->right);
		
		if(binary_syntax->binary_type == MULTIPLICATION){
		    emit_instr(out, "mull", "0(%esp)");
		    //emit_instr(out, "mull", "%ebx");
		    emit_instr(out, "add", "$4, %esp");
		} else if (binary_syntax->binary_type == DIVISION) {
		    //edx:eax / 0(%esp)
	            emit_instr(out, "mov", "$0, %edx");
	            emit_instr(out, "xchg", "0(%esp), %eax");
	            emit_instr(out, "divl", "0(%esp)");

		    emit_instr(out, "add", "$4, %esp");
		} else if (binary_syntax->binary_type == MOD) {
		    emit_instr(out, "mov", "$0, %edx");
	            emit_instr(out, "xchg", "0(%esp), %eax");
	            emit_instr(out, "divl", "0(%esp)");
	            emit_instr(out, "mov", "%edx, %eax");

		    emit_instr(out, "add", "$4, %esp");
		} else if (binary_syntax->binary_type == ADDITION){
		    emit_instr(out, "add", "0(%esp), %eax");
		    //emit_instr(out, "add", "%ebx, %eax");
		    //TODO: check if this instruction redundant
		    emit_instr(out, "add", "$4, %esp");
		} else if (binary_syntax->binary_type == SUBTRACTION) {
		    emit_instr(out, "sub", "%eax, 0(%esp)");
           	    emit_instr(out, "mov", "0(%esp), %eax");
		    emit_instr(out, "add", "$4, %esp");
		} else if (binary_syntax->binary_type == COMPARISION) {
		    emit_instr(out, "xor", "0(%esp), %eax");
		    emit_instr(out, "add", "$4, %esp");
		}
	} else if (syntax->type == ASSIGNMENT) {
	    printf("case gen assignment\n");
	    write_syntax(out, syntax->assignment->expression);

	    emit_instr_format(out, "mov", "%%eax, -%d(%%ebp)", 4*(syntax->assignment->var_index+1));
	} else if (syntax->type == SHOW_STATEMENT){
	    printf("case get SHOW statement");
	    if(syntax->show_statement->decOrHex == 'd'){
	    	emit_instr_format(out, "pushl", "-%d(%%ebp)", 4*(syntax->show_statement->var->variable->var_index+1));
	    	emit_instr(out, "pushl", "$.LC0");
        	emit_instr(out, "call", "_printf");
	    } else if (syntax->show_statement->decOrHex == 'h') {
	    	emit_instr_format(out, "pushl", "-%d(%%ebp)", 4*(syntax->show_statement->var->variable->var_index+1));
	    	emit_instr(out, "pushl", "$.LC1");
        	emit_instr(out, "call", "_printf");
	    }
	} 
	else if (syntax->type == IF_STATEMENT){
	    char *label;
	    printf("case if statement kaa");
	    write_syntax(out, syntax->if_statement->condition);
	    emit_instr(out, "test", "%eax, %eax");
	    label = gen_label("LC");
	    emit_instr_format(out, "jne", "%s", label);
	    write_syntax(out, syntax->if_statement->then);
	    emit_label(out, label);
	    //emit_instr(out, "call", "_printf");
	} else if (syntax->type ==  FOR_STATEMENT) {
	    char *start_label;
	    char *end_label;
	    if(syntax->for_statement->startNum->type == IMMEDIATE){
	    	emit_instr_format(out, "mov", "$%d, %%edi", syntax->for_statement->startNum->immediate->value);
	    } else if (syntax->for_statement->startNum->type == VARIABLE) {
	    	emit_instr_format(out, "mov", "-%d(%%ebp), %%edi", 4*(syntax->for_statement->startNum->variable->var_index+1));
	    }
	    if(syntax->for_statement->stopNum->type == IMMEDIATE){
	    	emit_instr_format(out, "mov", "$%d, %%esi", syntax->for_statement->stopNum->immediate->value);
	    } else if (syntax->for_statement->stopNum->type == VARIABLE) {
                emit_instr_format(out, "mov", "-%d(%%ebp), %%esi", 4*(syntax->for_statement->stopNum->variable->var_index+1));
	    }
	    start_label = gen_label("LC");
	    end_label = gen_label("LC");
	    emit_label(out, start_label);
	    emit_instr(out, "cmp", "%edi, %esi");
	    //confuse which jump condition to use.
	    emit_instr_format(out, "jg", "%s", end_label);
	    write_syntax(out, syntax->for_statement->expression);
	    emit_instr(out, "inc", "%esi");
	    emit_instr_format(out, "jmp", "%s", start_label);
	    emit_label(out, end_label);
	} else if (syntax->type == INPUT) {
	    //printf("gen INPUT\n");
	    List *lines = syntax->input->lines;
	    int i;
            for (i = list_length(lines)-1; i >= 0; i--) {
            	//printf("*");
                write_syntax(out, list_get(lines, i));
            }
	} else if(syntax->type = MINUS){
		printf("gen minus\n");
		write_syntax(out,syntax->minus->expression);
		emit_instr(out, "xor", "%ebx, %ebx");
		emit_instr(out, "sub", "%eax, %ebx");
		emit_instr(out, "mov", "%ebx, %eax");
	} else {
	    printf("last case\n");
	}
	/*else if(syntax->type = MINUS){
		write_syntax(out,syntax->expression);
		emit_instr(out, "sub", "0(%esp), %eax");
	}*/
}