static void gen_conditional(ClmStmtNode *node) { push_expression(node->conditionStmt.condition); if (node->conditionStmt.falseBody == NULL) { char end_label[LABEL_SIZE]; next_label(end_label); ClmScope *trueScope = clm_scope_find_child(data.scope, node->conditionStmt.trueBody); asm_pop(EAX); asm_cmp(EAX, "1"); asm_jmp_neq(end_label); data.scope = trueScope; gen_statements(node->conditionStmt.trueBody); asm_label(end_label); data.scope = trueScope->parent; } else { char end_label[LABEL_SIZE]; char false_label[LABEL_SIZE]; next_label(end_label); next_label(false_label); ClmScope *trueScope = clm_scope_find_child(data.scope, node->conditionStmt.trueBody); ClmScope *falseScope = clm_scope_find_child(data.scope, node->conditionStmt.falseBody); asm_pop(EAX); asm_cmp(EAX, "1"); asm_jmp_neq(false_label); data.scope = trueScope; gen_statements(node->conditionStmt.trueBody); asm_jmp(end_label); asm_label(false_label); data.scope = falseScope; gen_statements(node->conditionStmt.falseBody); asm_label(end_label); data.scope = falseScope->parent; } }
static void gen_while_loop(ClmStmtNode *node) { char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); asm_label(cmp_label); // don't need to store this - just evaulate every loop push_expression(node->whileLoopStmt.condition); pop_int_into(EAX); asm_cmp(EAX, "0"); asm_jmp_eq(end_label); gen_statements(node->whileLoopStmt.body); asm_jmp(cmp_label); asm_label(end_label); }
static void gen_for_loop(ClmStmtNode *node) { char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); ClmSymbol *var = clm_scope_find(data.scope, node->forLoopStmt.varId); char loop_var[32]; load_var_location(var, loop_var, 4, NULL); // don't need to store this - just evaluate and put into loop var push_expression(node->forLoopStmt.start); pop_int_into(loop_var); asm_label(cmp_label); // don't need to store this - just evaulate every loop push_expression(node->forLoopStmt.end); pop_int_into(EAX); asm_cmp(loop_var, EAX); asm_jmp_g(end_label); gen_statements(node->forLoopStmt.body); if (node->forLoopStmt.delta->type == EXP_TYPE_INT && node->forLoopStmt.delta->ival == 1) { asm_inc(loop_var); } else if (node->forLoopStmt.delta->type == EXP_TYPE_INT && node->forLoopStmt.delta->ival == -1) { asm_dec(loop_var); } else if (node->forLoopStmt.delta->type == EXP_TYPE_INT) { asm_add_i(loop_var, node->forLoopStmt.delta->ival); } else { push_expression(node->forLoopStmt.delta); asm_pop(EAX); asm_add(loop_var, EAX); } asm_jmp(cmp_label); asm_label(end_label); }
const char *clm_code_gen_main(ArrayList *statements, ClmScope *globalScope) { data.scope = globalScope; data.labelID = 0; data.temporaryID = 0; data.inFunction = 0; data.size = strlen(ASM_HEADER) + 1; data.capacity = data.size; data.code = malloc(strlen(ASM_HEADER) + 1); strcpy(data.code, ASM_HEADER); gen_functions(statements); writeLine(ASM_START); gen_statements(statements); writeLine(ASM_EXIT_PROCESS); writeLine(ASM_DATA); gen_globals(globalScope); return data.code; }
static void gen_func_dec(ClmStmtNode *node) { int i; char func_label[LABEL_SIZE]; sprintf(func_label, "_%s", node->funcDecStmt.name); ClmScope *funcScope = clm_scope_find_child(data.scope, node); asm_label(func_label); asm_push(EBP); asm_mov(EBP, ESP); int local_var_size = 2 * 4 * (funcScope->symbols->length - node->funcDecStmt.parameters->length); char local_var_size_str[32]; sprintf(local_var_size_str, "%d", local_var_size); asm_sub(ESP, local_var_size_str); // each local var has 2 slots on the stack, their type and the value // for matrices, the value is a pointer to the location on the stack // these are all declared below the local variables ClmSymbol *sym; ClmExpNode *dec; char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; char index_str[32]; for (i = 0; i < funcScope->symbols->length; i++) { sym = funcScope->symbols->data[i]; dec = sym->declaration; if (sym->location == LOCATION_PARAMETER) continue; // setting the type of the local var load_var_location(sym, index_str, 0, NULL); asm_mov_i(index_str, (int)sym->type); // setting the value of the local var load_var_location(sym, index_str, 4, NULL); asm_mov_i(index_str, 0); if (sym->type == CLM_TYPE_MATRIX) { // TODO what does this do? does it work? next_label(cmp_label); next_label(end_label); gen_exp_size(dec); asm_pop(EAX); // eax contains num of rows asm_pop(EBX); // ebx contains num of cols asm_mov(ECX, EAX); asm_imul(ECX, EBX); asm_label(cmp_label); asm_dec(ECX); asm_cmp(ECX, "0"); asm_jmp_eq(end_label); asm_push_const_i(0); asm_jmp(cmp_label); asm_label(end_label); asm_push(EBX); // cols // setting the pointer to point at the rows // note: push changes the value at esp and THEN // decrements it load_var_location(sym, index_str, 4, NULL); asm_mov(index_str, ESP); asm_push(EAX); // rows } } // TODO figure out strings though! data.inFunction = 1; data.scope = funcScope; gen_statements(node->funcDecStmt.body); data.scope = funcScope->parent; data.inFunction = 0; if (node->funcDecStmt.returnSize.rows == -1) { // no return value! asm_mov(ESP, EBP); asm_pop(EBP); } asm_ret(); }
void generate_code(is_node *node, prog_env* mySemantic) { is_node* aux; is_node* aux2; char* method_name; char* return_type; printf("\ndeclare i32 @printf(i8*, ...)\n"); printf("declare i32 @atoi(i8*) nounwind readonly\n"); printf("@str = private unnamed_addr constant [4 x i8] c\"%%d\\0A\\00\"\n"); printf("@.str2 = private unnamed_addr constant [4 x i8] c\"%%s\\0A\\00\"\n"); printf("@.str = private unnamed_addr constant [5 x i8] c\"true\\00\"\n"); printf("@.true = global i8* getelementptr inbounds ([5 x i8]* @.str, i32 0, i32 0)\n"); printf("@.str1 = private unnamed_addr constant [6 x i8] c\"false\\00\"\n"); printf("@.false = global i8* getelementptr inbounds ([6 x i8]* @.str1, i32 0, i32 0)\n\n"); aux = node->child; // passar o no 'Program' while(aux != NULL) { // tratar variaveis globais if(aux->type == VarDecl) { if(aux->child->type == Int) { aux2 = aux->child->next; while(aux2 != NULL) { printf("@%s = global i32 0\n", aux2->id); aux2 = aux2->next; } } else if(aux->child->type == Bool) { aux2 = aux->child->next; while(aux2 != NULL) { printf("@%s = global i1 0\n", aux2->id); aux2 = aux2->next; } } // criar metodos } else if(aux->type == MethodDecl) { counter = 0; method_name = aux->child->next->id; return_type = gen_type[aux->child->type]; // main com parametros if(strcmp(method_name, "main") == 0 && aux->child->next->next->child != NULL) printf("\ndefine i32 @main(i32 %%.argc, i8** %%.argv)\n{\n"); // ponto argc para nao override variaveis locais com nome argc // todas as funcoes excepto main com parametros else { char* return_type = gen_code_type(gen_type[aux->child->type]); // obter tipo do return is_node* params = aux->child->next->next; // MethodParams printf("\ndefine %s @%s(", return_type, method_name); if(params->child != NULL) { is_node* paramDecl = params->child; // ParamDeclaration while(paramDecl != NULL) { if(paramDecl->next != NULL) printf("%s %%%s, ", gen_code_type(gen_type[paramDecl->child->type]), paramDecl->child->next->id); else printf("%s %%%s", gen_code_type(gen_type[paramDecl->child->type]), paramDecl->child->next->id); paramDecl = paramDecl->next; } } printf(")\n{\n"); } aux2 = aux->child; while(aux2 != NULL) { if(aux2->type == MethodBody) gen_statements(method_name, aux2->child, mySemantic); aux2 = aux2->next; } printf("\tret %s 0\n}\n", gen_code_type(return_type)); } aux = aux->next; } }