intercodes translate_VarDec(struct Node *node,operand *place) { intercodes code1,code2,code3,code4; struct Node *child = node->child; assert(child != NULL); //ID if (strcmp(child->type,"ID") == 0) { int id = getVarID(child); enum varType type; union varp vp = getVar(child,&type); operand v1 = new_var(id); if (place != NULL) { *place = v1; } if (type == varInt || type == varFloat) { return NULL; } else if (type == varArray || type == varStruct) { int size = get_structure_size(vp,type); operand c1 = new_constant(size); code1 = gen_assign(DEC_K,v1,c1); return code1; } else { printf("type is varError%d\n",type == varError); exit(-1); } } //VarDec INT LB INT RB return translate_VarDec(child,NULL); }
void stmt_list_parse(node* list) { while(list) { if(list && list->type == LIST_NODE) { node* n = list->u.list.start; if(n->type == ASSIGN_NODE) { //printf("generating assignment quad in BB %s\n", currentBlock->name); gen_assign(n); } else if(n->type == BINOP_NODE) { gen_rvalue(n, NULL); } else if(n->type == UNOP_NODE) { gen_rvalue(n, NULL); } else if(n->type == IF_NODE || n->type == IFELSE_NODE) { gen_if(n); } else if(n->type == FOR_NODE) { gen_for(n); } else if(n->type == WHILE_NODE) { gen_while(n); } else if(n->type == JUMP_NODE) { gen_jmp(n); } else if(n->type == CALL_NODE) { //Function Call int argnum = n->u.call.argnum; qnode* num = qnode_new(Q_CONSTANT); num->name = malloc(100); sprintf(num->name, "%i", argnum); num->u.value = argnum; emit(O_ARGNUM, NULL, num, NULL); if(argnum) { //Generate argument quad node* argptr = n->u.call.args; while(argptr) { emit(O_ARGDEF, NULL, gen_rvalue(argptr->u.list.start, NULL), NULL); if(argptr->next) { argptr = argptr->next; } else { break; } } } emit(O_CALL, NULL, gen_rvalue(n->u.call.function, NULL), NULL); } else if(n->type == IDENT_NODE || n->type == DEFAULT_NODE) { //do nothing } else { fprintf(stderr, "QUAD ERROR: Unrecognized Node Type %i\n", n->type); exit(1); } if(list->next) { list = list->next; } else { break; } } else { fprintf(stderr, "QUAD ERROR: Invalid Statement List\n"); break; } } }
intercodes translate_Dec(struct Node *node) { struct Node *child = node->child; assert(child != NULL); intercodes code1,code2,code3; //VarDec if (child->sibling == NULL) { return translate_VarDec(child,NULL); } //VarDec ASSIGNOP Exp if (child->sibling != NULL && strcmp(child->sibling->type,"ASSIGNOP") == 0) { operand t1 = NULL; code1 = translate_VarDec(child,&t1); operand t2 = new_tmp(); code2 = translate_Exp(child->sibling->sibling,t2); code3 = gen_assign(ASSIGN_K,t1,t2); code1 = link(code1,code2); code1 = link(code1,code3); return code1; } }
LLVMValueRef gen_expr(compile_t* c, ast_t* ast) { LLVMValueRef ret; bool has_scope = ast_has_scope(ast); bool has_source = codegen_hassource(c); if(has_scope) { codegen_pushscope(c); // Dwarf a new lexical scope, if necessary. if(has_source) dwarf_lexicalscope(&c->dwarf, ast); } switch(ast_id(ast)) { case TK_SEQ: ret = gen_seq(c, ast); break; case TK_FVARREF: case TK_FLETREF: ret = gen_fieldload(c, ast); break; case TK_PARAMREF: ret = gen_param(c, ast); break; case TK_VAR: case TK_LET: ret = gen_localdecl(c, ast); break; case TK_VARREF: case TK_LETREF: ret = gen_localload(c, ast); break; case TK_IF: ret = gen_if(c, ast); break; case TK_WHILE: ret = gen_while(c, ast); break; case TK_REPEAT: ret = gen_repeat(c, ast); break; case TK_TRY: case TK_TRY_NO_CHECK: ret = gen_try(c, ast); break; case TK_MATCH: ret = gen_match(c, ast); break; case TK_CALL: ret = gen_call(c, ast); break; case TK_CONSUME: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_RECOVER: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_BREAK: ret = gen_break(c, ast); break; case TK_CONTINUE: ret = gen_continue(c, ast); break; case TK_RETURN: ret = gen_return(c, ast); break; case TK_ERROR: ret = gen_error(c, ast); break; case TK_IS: ret = gen_is(c, ast); break; case TK_ISNT: ret = gen_isnt(c, ast); break; case TK_ASSIGN: ret = gen_assign(c, ast); break; case TK_THIS: ret = gen_this(c, ast); break; case TK_TRUE: ret = LLVMConstInt(c->i1, 1, false); break; case TK_FALSE: ret = LLVMConstInt(c->i1, 0, false); break; case TK_INT: ret = gen_int(c, ast); break; case TK_FLOAT: ret = gen_float(c, ast); break; case TK_STRING: ret = gen_string(c, ast); break; case TK_TUPLE: ret = gen_tuple(c, ast); break; case TK_FFICALL: ret = gen_ffi(c, ast); break; case TK_AMP: ret = gen_addressof(c, ast); break; case TK_IDENTITY: ret = gen_identity(c, ast); break; case TK_DONTCARE: ret = GEN_NOVALUE; break; case TK_COMPILER_INTRINSIC: ast_error(ast, "unimplemented compiler intrinsic"); LLVMBuildUnreachable(c->builder); ret = GEN_NOVALUE; break; default: ast_error(ast, "not implemented (codegen unknown)"); return NULL; } if(has_scope) { codegen_popscope(c); if(has_source) dwarf_finish(&c->dwarf); } return ret; }
LLVMValueRef gen_expr(compile_t* c, ast_t* ast) { LLVMValueRef ret; bool has_scope = ast_has_scope(ast); if(has_scope) codegen_pushscope(c, ast); switch(ast_id(ast)) { case TK_SEQ: ret = gen_seq(c, ast); break; case TK_FVARREF: case TK_FLETREF: ret = gen_fieldload(c, ast); break; case TK_EMBEDREF: ret = gen_fieldptr(c, ast); break; case TK_PARAMREF: ret = gen_param(c, ast); break; case TK_VAR: case TK_LET: case TK_MATCH_CAPTURE: ret = gen_localdecl(c, ast); break; case TK_VARREF: case TK_LETREF: ret = gen_localload(c, ast); break; case TK_IF: ret = gen_if(c, ast); break; case TK_WHILE: ret = gen_while(c, ast); break; case TK_REPEAT: ret = gen_repeat(c, ast); break; case TK_TRY: case TK_TRY_NO_CHECK: ret = gen_try(c, ast); break; case TK_MATCH: ret = gen_match(c, ast); break; case TK_CALL: ret = gen_call(c, ast); break; case TK_CONSUME: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_RECOVER: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_BREAK: ret = gen_break(c, ast); break; case TK_CONTINUE: ret = gen_continue(c, ast); break; case TK_RETURN: ret = gen_return(c, ast); break; case TK_ERROR: ret = gen_error(c, ast); break; case TK_IS: ret = gen_is(c, ast); break; case TK_ISNT: ret = gen_isnt(c, ast); break; case TK_ASSIGN: ret = gen_assign(c, ast); break; case TK_THIS: ret = gen_this(c, ast); break; case TK_TRUE: ret = LLVMConstInt(c->i1, 1, false); break; case TK_FALSE: ret = LLVMConstInt(c->i1, 0, false); break; case TK_INT: ret = gen_int(c, ast); break; case TK_FLOAT: ret = gen_float(c, ast); break; case TK_STRING: ret = gen_string(c, ast); break; case TK_TUPLE: ret = gen_tuple(c, ast); break; case TK_FFICALL: ret = gen_ffi(c, ast); break; case TK_ADDRESS: ret = gen_addressof(c, ast); break; case TK_DIGESTOF: ret = gen_digestof(c, ast); break; case TK_DONTCARE: ret = GEN_NOVALUE; break; case TK_COMPILE_INTRINSIC: ast_error(c->opt->check.errors, ast, "unimplemented compile intrinsic"); return NULL; case TK_COMPILE_ERROR: { ast_t* reason_seq = ast_child(ast); ast_t* reason = ast_child(reason_seq); ast_error(c->opt->check.errors, ast, "compile error: %s", ast_name(reason)); return NULL; } default: ast_error(c->opt->check.errors, ast, "not implemented (codegen unknown)"); return NULL; } if(has_scope) codegen_popscope(c); return ret; }
//translate intercodes translate_Exp(struct Node *node, operand place) { struct Node *child = node->child; assert(child != NULL); intercodes code1 = NULL; intercodes code2 = NULL; intercodes code3 = NULL; intercodes code4 = NULL; intercodes code5 = NULL; //INT if (strcmp(child->type,"INT") == 0) { operand c1 = new_constant(atoi(child->text)); code1 = gen_assign(ASSIGN_K,place,c1); return code1; } //ID if (strcmp(child->type,"ID") == 0 && child->sibling == NULL) { int id = getVarID(child); operand v1 = new_var(id); code1 = gen_assign(ASSIGN_K,place,v1); return code1; } //Exp1 ASSINGOP Exp2 if (strcmp(child->type,"Exp") == 0 && strcmp(child->sibling->type,"ASSIGNOP") == 0) { //Exp1 is ID (ID = Exp2) // printf("%s\n",child->child->type); if (strcmp(child->child->type,"ID") == 0) { operand t1 = new_tmp(); int id = getVarID(child->child); operand v1 = new_var(id); code1 = translate_Exp(child->sibling->sibling,t1); code2 = gen_assign(ASSIGN_K,v1,t1); // code1 = link(code1,code2); if (place != NULL) { code3 = gen_assign(ASSIGN_K,place,v1); code1 = link(code1,code3); } return code1; } //Exp[Exp] = Exp2 } //Exp1 PLUS/MINUS/STAR/DIV Exp2 if (strcmp(child->type,"Exp") == 0 && (strcmp(child->sibling->type,"PLUS") == 0 || strcmp(child->sibling->type,"MINUS") == 0 || strcmp(child->sibling->type,"STAR") == 0 || strcmp(child->sibling->type,"DIV") == 0)) { operand t1 = new_tmp(); operand t2 = new_tmp(); code1 = translate_Exp(child,t1); code2 = translate_Exp(child->sibling->sibling,t2); //printf("%d %d\n", t1->u.tmp_no, t2 -> u.tmp_no); if (strcmp(child->sibling->type,"PLUS") == 0) { code3 = gen_binop(ADD_K,place,t1,t2); } else if (strcmp(child->sibling->type,"MINUS") == 0) code3 = gen_binop(SUB_K,place,t1,t2); else if (strcmp(child->sibling->type,"STAR") == 0) code3 = gen_binop(MUL_K,place,t1,t2); else if (strcmp(child->sibling->type,"DIV") == 0) code3 = gen_binop(DIV_K,place,t1,t2); //code1 = link(code1,code2); //code1 = link(code1,code3); return code1; } //MINUS Exp1 if (strcmp(child->type,"MINUS") == 0) { operand t1 = new_tmp(); code1 = translate_Exp(child,t1); operand c1 = new_constant(0); code2 = gen_binop(SUB_K,place,c1,t1); code1 = link(code1,code2); return code1; } //Exp1 RELOP Exp2 //NOT Exp1 //Exp1 AND Exp2 //Exp1 OR Exp2 if (strcmp(child->type,"NOT") == 0 || strcmp(child->sibling->type,"RELOP") == 0 || strcmp(child->sibling->type,"AND") == 0 || strcmp(child->sibling->type,"OR") == 0) { operand label1 = new_label(); operand label2 = new_label(); operand c1 = new_constant(0); operand c2 = new_constant(1); code1 = gen_assign(ASSIGN_K,place,c1); code2 = translate_Cond(node,label1,label2); code3 = gen_one(LABEL_K,label1); code4 = gen_assign(ASSIGN_K,place,c2); code5 = gen_one(LABEL_K,label2); code1 = link(code1,code2); code1 = link(code1,code3); code1 = link(code1,code4); code1 = link(code1,code5); return code1; } //ID LP RP if (strcmp(child->sibling->sibling->type,"LP") == 0 && strcmp(child->sibling->sibling->type,"RP") == 0) { char *func_name = child->text; if (strcmp(func_name,"read") == 0) { if (place == NULL) { operand t1 = new_tmp(); code1 = gen_one(READ_K,t1); } else code1 = gen_one(READ_K,place); return code1; } struct funMes *func_node = getFunMes(child); assert(func_node != NULL); operand f1 = new_function(func_name); if (place != NULL && place->kind != ADDRESS) code1 = gen_assign(CALL_K,place,f1); else if (place != NULL && place->kind == ADDRESS) { operand t2 = new_tmp(); code1 = gen_assign(CALL_K,t2,f1); code2 = gen_assign(ASSIGN_K,place,t2); code1 = link(code1,code2); } else { operand t2 = new_tmp(); code1 = gen_assign(CALL_K,t2,f1); } return code1; } //ID LP Args RP if (strcmp(child->sibling->type,"LP") == 0 && strcmp(child->sibling->sibling->type,"Args") == 0) { char *func_name = child->text; operand *arg_list = (operand *)malloc(sizeof(operand) * 10); int arg_num = 0; code1 = translate_Args(child->sibling->sibling,arg_list,&arg_num); if (strcmp(func_name,"write") == 0) { assert(arg_num == 1); operand t1; if (arg_list[0]->kind == ADDRESS) { t1 = new_tmp(); code2 = gen_assign(ASSIGN_K,t1,arg_list[0]); code1 = link(code1,code2); } else t1 = arg_list[0]; code3 = gen_one(WRITE_K,t1); code1 = link(code1,code3); return code1; } int i; for (i = 0;i < arg_num;i++) { code2 = gen_one(ARG_K,arg_list[i]); code1 = link(code1,code2); } operand f1 = new_function(func_name); if (place != NULL && place->kind != ADDRESS) code3 = gen_assign(CALL_K,place,f1); else if (place != NULL && place->kind == ADDRESS) { operand t2 = new_tmp(); code1 = gen_assign(CALL_K,t2,f1); code2 = gen_assign(ASSIGN_K,place,t2); code1 = link(code1,code2); } else { operand t2 = new_tmp(); code3 = gen_assign(CALL_K,t2,f1); } code1 = link(code1,code3); return code1; } //LP Exp RP if (strcmp(child->type,"LP") == 0) { return translate_Exp(child->sibling,place); } //Exp1 LB Exp2 RB if (strcmp(child->type,"LB") == 0) { return translate_array(node,place,NULL,NULL); } //Exp DOT ID return NULL; }