Example #1
0
static int
array_check_bounds(array_t *array, size_t index, size_t within) {
    if (index >= (array->e_end + within)) {
        array_error("array bounds error: %zu (of %zu elements)", index, array->e_end);
        return BOUNDS_FAIL;
    }
    return BOUNDS_OK;
}
Example #2
0
static int
array_check_alloc(array_t *array, size_t elements) {
    if (elements <= 0)
        elements = 1;
    // Is array large enough to handle <element> elements?
    size_t count = array->e_all;
    while (count <= array->e_end + elements)
        count += array->e_inc; // Add a block and retest
    if (count > array->e_all) {
        void *buf = realloc(array->data, count * array->e_size);
        if (buf == NULL) {
            array_error("array_check_alloc reallocation failure(%d): %s", errno, strerror(errno));
            return -1;
        }
        array->data = buf;
        size_t added = count - array->e_all;
        memset(array->data + array->e_all * array->e_size, '\0', added * array->e_size);
        array->e_all = count;
    }
    return 0;
}
Example #3
0
//Generates code and writes it to a file
void expr_codegen(struct expr *e, FILE *file) {
	if(!e) return;
	struct expr *e2;
	switch(e->kind) {
		case EXPR_ASSIGNMENT:
			fprintf(file, "\n\t#Assignment of %s %d right value\n", e->left->symbol->name, e->left->symbol->which);
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Assignment assign to %s %d\n", e->left->symbol->name, e->left->symbol->which);
			fprintf(file, "\tMOV %s, %s\n", register_name(e->right->reg), symbol_code(e->left->symbol));
			e->reg = e->right->reg;
			register_free(e->left->reg);
			break;
		case EXPR_GE: //all of these go to the compare function
		case EXPR_LE:
		case EXPR_GT:
		case EXPR_LT:
		case EXPR_EQ:
		case EXPR_NE:
			compare(e, file);
			break;
		case EXPR_ADD:
			expr_codegen(e->left, file);
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Addition\n");
			fprintf(file, "\tADD %s, %s\n", register_name(e->left->reg), register_name(e->right->reg));
			e->reg = e->right->reg;
			register_free(e->left->reg);
			break;
		case EXPR_SUB:
			expr_codegen(e->left, file);
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Subtraction\n");
			fprintf(file, "\tSUB %s, %s\n", register_name(e->right->reg), register_name(e->left->reg));
			e->reg = e->left->reg;
			register_free(e->right->reg);
			break;
		case EXPR_MUL:
			expr_codegen(e->left, file);
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Multiplication\n");
			fprintf(file, "\tMOV %s, %%rax\n", register_name(e->left->reg));
			fprintf(file, "\tIMUL %s\n", register_name(e->right->reg));
			fprintf(file, "\tMOV %%rax, %s\n", register_name(e->right->reg));
			register_free(e->left->reg);
			e->reg = e->right->reg;
			break;
		case EXPR_DIV:
			expr_codegen(e->left, file);
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Division\n");
			fprintf(file, "\tMOV %s, %%rax\n", register_name(e->left->reg));
			fprintf(file, "\tCQO\n");
			fprintf(file, "\tIDIV %s\n", register_name(e->right->reg));
			fprintf(file, "\tMOV %%rax, %s\n", register_name(e->right->reg));
			register_free(e->left->reg);
			e->reg = e->right->reg;
			break;
		case EXPR_MOD:
			expr_codegen(e->left, file);
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Modulus\n");
			fprintf(file, "\tMOV %s, %%rax\n", register_name(e->left->reg));
			fprintf(file, "\tCQO\n");
			fprintf(file, "\tIDIV %s\n", register_name(e->right->reg));
			fprintf(file, "\tMOV %%rdx, %s\n", register_name(e->right->reg));
			register_free(e->left->reg);
			e->reg = e->right->reg;
			break;
		case EXPR_POW:
			expr_codegen(e->left, file);
			expr_codegen(e->right, file);
			int label_start = label_count++;
			int label_end = label_count++;
			fprintf(file, "\n\t#Exponent function\n");
			fprintf(file, "\tMOV $1, %%rax\n");
			fprintf(file, "L%d:\n", label_start);
			fprintf(file, "\tCMP $0, %s\n", register_name(e->right->reg));
			fprintf(file, "\tJE L%d\n", label_end);
			fprintf(file, "\tSUB $1, %s\n", register_name(e->right->reg));
			fprintf(file, "\tMUL %s\n", register_name(e->left->reg));
			fprintf(file, "\tJMP L%d\n", label_start);
			fprintf(file, "L%d:\n", label_end);
			register_free(e->left->reg);
			register_free(e->right->reg);
			e->reg = register_alloc();
			fprintf(file, "\tMOV %%rax, %s\n", register_name(e->reg));
			break;
		case EXPR_LOGICAL_NOT:
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Logical Not\n");
			e->reg = e->right->reg;		
			fprintf(file, "\tCMPQ $0, %s\n", register_name(e->reg));
			fprintf(file, "\tJNE L%d\n", label_count);
			fprintf(file, "\tMOV $1, %s\n", register_name(e->reg));
			fprintf(file, "\tJMP L%d\n", label_count+1);
			fprintf(file, "L%d:\n", label_count++);
			fprintf(file, "\tMOV $0, %s\n", register_name(e->reg));
			fprintf(file, "L%d:\n", label_count++);
			break;
		case EXPR_LOGICAL_AND:
			expr_codegen(e->left, file);
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Logical And\n");
			fprintf(file, "\tAND %s, %s\n", register_name(e->left->reg), register_name(e->right->reg));
			e->reg = e->right->reg;
			register_free(e->left->reg);
			break;
		case EXPR_LOGICAL_OR:
			expr_codegen(e->left, file);
			expr_codegen(e->right, file);
			fprintf(file, "\n\t#Logical Or\n");
			fprintf(file, "\tOR %s, %s\n", register_name(e->left->reg), register_name(e->right->reg));
			e->reg = e->right->reg;
			register_free(e->left->reg);
			break;
		case EXPR_POSTFIX_PLUS:
			expr_codegen(e->left, file);
			fprintf(file, "\n\t#Increment\n");
			e->reg = register_alloc();
			fprintf(file, "\tMOV %s, %s\n", register_name(e->left->reg), register_name(e->reg));
			fprintf(file, "\tADD $1, %s\n", register_name(e->left->reg));
			fprintf(file, "\tMOV %s, %s\n", register_name(e->left->reg), symbol_code(e->left->symbol));
			register_free(e->left->reg);
			break;
		case EXPR_POSTFIX_MINUS:
			expr_codegen(e->left, file);
			fprintf(file, "\n\t#Increment\n");
			e->reg = register_alloc();
			fprintf(file, "\tMOV %s, %s\n", register_name(e->left->reg), register_name(e->reg));
			fprintf(file, "\tSUB $1, %s\n", register_name(e->left->reg));
			fprintf(file, "\tMOV %s, %s\n", register_name(e->left->reg), symbol_code(e->left->symbol));
			register_free(e->left->reg);
			break;
		case EXPR_IDENT:
			fprintf(file, "\n\t#Identifier %d %s\n", e->symbol->which, e->symbol->name);
			
			e->reg = register_alloc();
			if(e->symbol->type->kind == TYPE_STRING && e->symbol->kind == SCOPE_GLOBAL){
				fprintf(file, "\tLEA %s, %s\n", symbol_code(e->symbol), register_name(e->reg));
			} else {
				fprintf(file, "\tMOV %s, %s\n", symbol_code(e->symbol), register_name(e->reg));
			}
			break;
		case EXPR_INTEGER_LITERAL:
			//comment label
			fprintf(file, "\n\t#Integer literal %d\n", e->literal_value);

			e->reg = register_alloc();
			fprintf(file, "\tMOV $%d, %s\n", e->literal_value, register_name(e->reg));
			break;
		case EXPR_STRING_LITERAL:
			//comment label
			fprintf(file, "\n\t#String literal %s\n", e->string_literal);

			e->reg = register_alloc();
			fprintf(file, ".data\nSTR%d: \n.string \"%s\"\n.text\n", string_number, e->string_literal);
			fprintf(file, "\tLEA STR%d, %s\n", string_number++, register_name(e->reg));
			break;
		case EXPR_CHAR_LITERAL:
			fprintf(file, "\n\t#Char literal %c\n", e->literal_value);
			e->reg = register_alloc();
			fprintf(file, "\tMOV $%d, %s\n", e->literal_value, register_name(e->reg));
			break;
		case EXPR_TRUE:
			fprintf(file, "\n\t#True\n");
			e->reg = register_alloc();
			fprintf(file, "\tMOV $%d, %s\n", e->literal_value, register_name(e->reg));
			break;
		case EXPR_FALSE:
			fprintf(file, "\n\t#False\n");
			e->reg = register_alloc();
			fprintf(file, "\tMOV $%d, %s\n", e->literal_value, register_name(e->reg));
			register_free(e->reg);
			break;
		case EXPR_FCALL:
			if(function_params(e) >= 6) fcall_error();
			e->reg = register_alloc();
			fprintf(file, "\n\t#Calling function %s\n", e->left->name);
			if(!e->right){
				/* do nothing for no params */
			} else if(e->right->kind != EXPR_COMMA){ //this means single argument
				expr_codegen(e->right, file);
				fprintf(file, "\n\t#Move Only Argument\n");
				fprintf(file, "\tMOV %s, %%rdi\n", register_name(e->right->reg));
				register_free(e->right->reg);
			} else { //multiple parameters
				struct expr *param = e->right;
				int param_number = 0;
				while(param->kind == EXPR_COMMA){
					expr_codegen(param->left, file);
					fprintf(file, "\n\t#Move Argument %d\n", param_number);
					fprintf(file, "\tMOV %s, ", register_name(param->left->reg));
					register_free(param->left->reg);
					switch(param_number++){
						case 0: fprintf(file, "%%rdi"); break;
						case 1: fprintf(file, "%%rsi"); break;
						case 2: fprintf(file, "%%rdx"); break;
						case 3: fprintf(file, "%%rcx"); break;
						case 4: fprintf(file, "%%r8"); break;
						case 5: fprintf(file, "%%r9"); break;
					}	
					fprintf(file, "\n");
					param = param->right;
				}
				expr_codegen(param, file);
				fprintf(file, "\n\t#Move Argument %d\n", param_number);
				fprintf(file, "\tMOV %s, ", register_name(param->reg));
				switch(param_number++){
					case 0: fprintf(file, "%%rdi"); break;
					case 1: fprintf(file, "%%rsi"); break;
					case 2: fprintf(file, "%%rdx"); break;
					case 3: fprintf(file, "%%rcx"); break;
					case 4: fprintf(file, "%%r8"); break;
					case 5: fprintf(file, "%%r9"); break;
				}	
				fprintf(file, "\n");
				register_free(param->reg);
			}
			
			fprintf(file, "\tPUSH %%r10\n");
			fprintf(file, "\tPUSH %%r11\n");
			fprintf(file, "\n\tCALL %s\n\n", e->left->name);
			fprintf(file, "\tPOP %%r11\n");
			fprintf(file, "\tPOP %%r10\n");
			fprintf(file, "\tMOV %%rax, %s\n", register_name(e->reg));
			
			break;
		case EXPR_PARENS:
			expr_codegen(e->right, file);
			e->reg = e->right->reg;
			break;
		case EXPR_ARRCALL:	//These 4 have to do with arrays
		case EXPR_ARRINDEX:	//We are not implementing arrays for codegen
		case EXPR_BLOCK:
		case EXPR_BLOCK_COMMA:
			array_error();
			break;
	}
}