void common_init_node(node_t * n) { struct fontinfo fi; char *str; ND_width(n) = late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH); ND_height(n) = late_double(n, N_height, DEFAULT_NODEHEIGHT, MIN_NODEHEIGHT); ND_shape(n) = bind_shape(late_nnstring(n, N_shape, DEFAULT_NODESHAPE), n); str = agxget(n, N_label); fi.fontsize = late_double(n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE); fi.fontname = late_nnstring(n, N_fontname, DEFAULT_FONTNAME); fi.fontcolor = late_nnstring(n, N_fontcolor, DEFAULT_COLOR); ND_label(n) = make_label((void*)n, str, ((aghtmlstr(str) ? LT_HTML : LT_NONE) | ( (shapeOf(n) == SH_RECORD) ? LT_RECD : LT_NONE)), fi.fontsize, fi.fontname, fi.fontcolor); if (N_xlabel && (str = agxget(n, N_xlabel)) && (str[0])) { ND_xlabel(n) = make_label((void*)n, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), fi.fontsize, fi.fontname, fi.fontcolor); GD_has_labels(agraphof(n)) |= NODE_XLABEL; } ND_showboxes(n) = late_int(n, N_showboxes, 0, 0); ND_shape(n)->fns->initfn(n); }
/* Build necessary code for a while statement */ void build_while_stmt(environment *env, NODE *node, int while_count, int if_count, int flag, int return_type) { char *s_tmp, *val1, *val2, *temporary; tac_quad *loop_jmp; if (node==NULL || type_of(node)!=WHILE) return; /* Generate label for start of while loop */ s_tmp = malloc(sizeof(char) * 25); sprintf(s_tmp, "__while%d", while_count); append_code(make_label(s_tmp)); /* Generate loop jump */ s_tmp = malloc(sizeof(char) * 25); sprintf(s_tmp, "__while%d", while_count); loop_jmp = make_goto(s_tmp); /* End while loop stmt */ s_tmp = malloc(sizeof(char) * 25); sprintf(s_tmp, "__while%dend", while_count); /* Build IF stmt for condition */ build_if_stmt(env, node, if_count, make_goto(s_tmp), loop_jmp, flag, return_type); append_code(make_label(s_tmp)); }
void bingen(int lower, int avg, int higher, AMODE *ap1, struct cases *cs, int size) { AMODE *ap2 = make_immed(cs->ptrs[avg].id); AMODE *ap3 = make_label(cs->ptrs[avg].label); if (cs->ptrs[avg].binlabel != - 1) gen_label(cs->ptrs[avg].binlabel); gen_coden(op_cmp, size, ap1, ap2); gen_code(op_je, ap3, 0); if (avg == lower) { if (cs->deflab < 0) cs->deflab = nextlabel++; ap3 = make_label(cs->deflab); gen_code(op_jmp, ap3, 0); } else { int avg1 = (lower + avg) / 2; int avg2 = (higher + avg + 1) / 2; if (avg + 1 < higher) ap3 = make_label(cs->ptrs[avg2].binlabel = nextlabel++); else ap3 = make_label(cs->deflab); if (size < 0) gen_code(op_jg, ap3, 0); else gen_code(op_ja, ap3, 0); bingen(lower, avg1, avg, ap1, cs, size); if (avg + 1 < higher) bingen(avg + 1, avg2, higher, ap1, cs, size); } }
void bingen(int lower, int avg, int higher,AMODE *ap1, int deflab, int size,long * switchids,int * switchlabels,int *switchbinlabels) { AMODE *ap2 = make_immed(switchids[avg]); AMODE *ap3 = make_label(switchlabels[avg]); if (switchbinlabels[avg] != -1) gen_label(switchbinlabels[avg]); gen_code(op_cmp,4,ap1,ap2); gen_code(op_je,0,ap3,0); if (avg == lower) { ap3 = make_label(deflab); gen_code(op_jmp,0,ap3,0); } else { int avg1 = (lower + avg)/2; int avg2 = (higher + avg+1)/2; if (avg+1 < higher) ap3 = make_label(switchbinlabels[avg2]=nextlabel++); else ap3 = make_label(deflab); if (size < 0) gen_code(op_jg,0,ap3,0); else gen_code(op_ja,0,ap3,0); bingen(lower,avg1,avg,ap1,deflab,size,switchids,switchlabels,switchbinlabels); if (avg+1 < higher) bingen(avg+1,avg2,higher,ap1,deflab,size,switchids,switchlabels,switchbinlabels); } }
static void emit_literal(Node *node) { SAVE; switch (node->ty->kind) { case KIND_BOOL: case KIND_CHAR: case KIND_SHORT: emit("mov $%u, #rax", node->ival); break; case KIND_INT: emit("mov $%u, #rax", node->ival); break; case KIND_LONG: case KIND_LLONG: { emit("mov $%lu, #rax", node->ival); break; } case KIND_FLOAT: { if (!node->flabel) { node->flabel = make_label(); float fval = node->fval; emit_noindent(".data"); emit_label(node->flabel); emit(".long %d", *(uint32_t *)&fval); emit_noindent(".text"); } emit("movss %s(#rip), #xmm0", node->flabel); break; } case KIND_DOUBLE: case KIND_LDOUBLE: { if (!node->flabel) { node->flabel = make_label(); emit_noindent(".data"); emit_label(node->flabel); emit(".quad %lu", *(uint64_t *)&node->fval); emit_noindent(".text"); } emit("movsd %s(#rip), #xmm0", node->flabel); break; } case KIND_ARRAY: { if (!node->slabel) { node->slabel = make_label(); emit_noindent(".data"); emit_label(node->slabel); emit(".string \"%s\"", quote_cstring_len(node->sval, node->ty->size)); emit_noindent(".text"); } emit("lea %s(#rip), #rax", node->slabel); break; } default: error("internal error"); } }
void gencompactswitch(SNODE *stmt, int deflab) { int tablab,curlab,i, size = natural_size(stmt->exp); AMODE *ap,*ap2; long switchbottom=gswitchbottom, switchcount=gswitchcount; long switchtop=gswitchtop; int *switchlabels=0; tablab = nextlabel++; curlab = nextlabel++; initstack(); ap = gen_expr(stmt->exp,F_DREG | F_VOL,4); initstack(); if (switchbottom) gen_code(op_sub,4,ap,make_immed(switchbottom)); if (size < 0) gen_code(op_jl,0,make_label(deflab),0); else gen_code(op_jb,0,make_label(deflab),0); gen_code(op_cmp,4,ap,make_immed(switchtop-switchbottom)); if (size < 0) gen_code(op_jge,0,make_label(deflab),0); else gen_code(op_jnc,0,make_label(deflab),0); gen_code(op_shl,4,ap,make_immed(2)); ap2 = xalloc(sizeof(AMODE)); ap->mode = am_indisp; ap2->preg = ap->preg; ap->offset = makenode(en_labcon,(char *)tablab,0); gen_code(op_jmp,4,ap,0); initstack(); align(4); gen_label(tablab); switchlabels = xalloc((switchtop-switchbottom) * sizeof(int)); for (i=switchbottom; i < switchtop; i++) { switchlabels[i-switchbottom] = deflab; } stmt = stmt->s1; while (stmt) { if( stmt->s2 ) /* default case ? */ { stmt->label = (SNODE *)deflab; diddef = TRUE; } else { switchlabels[(int)stmt->label-switchbottom] = curlab; stmt->label = (SNODE *)curlab; } if(stmt->next != 0 ) curlab = nextlabel++; stmt = stmt->next; } for (i=0; i < switchtop-switchbottom; i++) gen_code(op_dd,4,make_label(switchlabels[i]),0); }
/* Build necessary code for an if statement */ void build_if_stmt(environment *env, NODE *node, int if_count, tac_quad *false_jump, tac_quad *loop_jump, int flag, int return_type) { char *s_tmp; value *val1, *val2, *temporary; if (node==NULL || (type_of(node)!=IF && type_of(node)!=WHILE)) return; /* LHS is condition */ val1 = make_simple(env, node->left, flag, return_type); /* Generate if statement */ s_tmp = malloc(sizeof(char) * 25); sprintf(s_tmp, "__if%dtrue", if_count); append_code(make_if(val1, s_tmp)); /* Output false branch (i.e. else part) */ if (type_of(node->right)==ELSE) { /* Build code for false part */ build_else_part(env, node->right, 0, flag, return_type); } /* Generate goto end of if statement */ if (false_jump != NULL) { append_code(false_jump); } else { s_tmp = malloc(sizeof(char) * 25); sprintf(s_tmp, "__if%dend", if_count); append_code(make_goto(s_tmp)); } /* Generate label for start of true branch */ s_tmp = malloc(sizeof(char) * 25); sprintf(s_tmp, "__if%dtrue", if_count); append_code(make_label(s_tmp)); /* Output true branch */ if (type_of(node->right)==ELSE) { /* Build code for true part */ build_else_part(env, node->right, 1, flag, return_type); } else { /* True part is whole right branch */ make_simple(env, node->right, flag, return_type); } /* Check if extra loop jump has been specified (for WHILE loops etc) */ if (loop_jump) { append_code(loop_jump); } /* Generate end of IF stmt label */ s_tmp = malloc(sizeof(char) * 25); sprintf(s_tmp, "__if%dend", if_count); append_code(make_label(s_tmp)); }
static void emit_do(Node *node) { SAVE; char *begin = make_label(); char *end = make_label(); SET_JUMP_LABELS(end, begin); emit_label(begin); if (node->forbody) emit_expr(node->forbody); emit_expr(node->forcond); emit_je(end); emit_jmp(begin); emit_label(end); RESTORE_JUMP_LABELS(); }
static void emit_switch(Node *node) { SAVE; char *oswitch = lswitch, *obreak = lbreak; emit_expr(node->switchexpr); lswitch = make_label(); lbreak = make_label(); emit_jmp(lswitch); if (node->switchbody) emit_expr(node->switchbody); emit_label(lswitch); emit_label(lbreak); lswitch = oswitch; lbreak = obreak; }
static void generate_if(struct vec *v,OBJ ast) { char* label1; char* label2; generate_r(v,obj_if_test(ast)); emit(v,JUMP_UNLESS); label1 = declare_label(v); generate_r(v,obj_if_consequent(ast)); emit(v,JUMP); label2 = declare_label(v); make_label(v,label1); generate_r(v,obj_if_alternate(ast)); make_label(v,label2); }
// Generate a function body. // void GenerateFunction(SYM *sym, Statement *stmt) { char buf[20]; char *bl; throwlab = retlab = contlab = breaklab = -1; lastsph = 0; memset(semaphores,0,sizeof(semaphores)); throwlab = nextlabel++; while( lc_auto & 7 ) /* round frame size to word */ ++lc_auto; if (sym->IsInterrupt) { //GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8)); //GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE)); } if (!sym->IsNocall) { GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(24)); // For a leaf routine don't bother to store the link register or exception link register. if (sym->IsLeaf) GenerateDiadic(op_sw,0,makereg(27),make_indirect(30)); else { GenerateDiadic(op_sw, 0, makereg(27), make_indexed(0,30)); GenerateDiadic(op_sw, 0, makereg(28), make_indexed(8,30)); GenerateDiadic(op_sw, 0, makereg(31), make_indexed(16,30)); GenerateDiadic(op_lea,0,makereg(28),make_label(throwlab)); } GenerateDiadic(op_mov,0,makereg(27),makereg(30)); if (lc_auto) GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(lc_auto)); } if (optimize) opt1(stmt); GenerateStatement(stmt); GenerateReturn(sym,0); // Generate code for the hidden default catch GenerateLabel(throwlab); if (sym->IsLeaf){ if (sym->DoesThrow) { GenerateDiadic(op_mov,0,makereg(31),makereg(28)); GenerateDiadic(op_bra,0,make_label(retlab),NULL); // goto regular return cleanup code } } else { GenerateDiadic(op_lw,0,makereg(31),make_indexed(8,27)); // load throw return address from stack into LR GenerateDiadic(op_sw,0,makereg(31),make_indexed(16,27)); // and store it back (so it can be loaded with the lm) GenerateDiadic(op_bra,0,make_label(retlab),NULL); // goto regular return cleanup code } }
static void ptest_initNode(node_t * n) { char *str; ND_width(n) = late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH); ND_height(n) = late_double(n, N_height, DEFAULT_NODEHEIGHT, MIN_NODEWIDTH); if (N_label == NULL) str = NODENAME_ESC; else str = agxget(n, N_label->index); str = strdup_and_subst(str, NODENAME_ESC, n->name); ND_label(n) = make_label(str, late_double(n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE), late_nnstring(n, N_fontname, DEFAULT_FONTNAME), late_nnstring(n, N_fontcolor, DEFAULT_COLOR), n->graph); ND_shape(n) = bind_shape(late_nnstring(n, N_shape, DEFAULT_NODESHAPE)); ND_shape(n)->initfn(n); /* ### need to quantize ? */ ptest_nodesize(n, n->GD_flip(graph)); }
void genwhile(SNODE *stmt) /* * generate code to evaluate a while statement. */ { int lab1, lab2, lab3; initstack(); /* initialize temp registers */ lab1 = contlab; /* save old continue label */ contlab = nextlabel++; /* new continue label */ if( stmt->s1 != 0 ) /* has block */ { lab2 = breaklab; /* save old break label */ breaklab = nextlabel++; gen_code(op_jmp,0,make_label(contlab),0); lab3 = nextlabel++; gen_label(lab3); genstmt(stmt->s1); gen_label(contlab); if (stmt->lst) gen_line(stmt->lst); initstack(); truejp(stmt->exp,lab3); gen_label(breaklab); breaklab = lab2; /* restore old break label */ } else /* no loop code */ { if (stmt->lst) gen_line(stmt->lst); gen_label(contlab); initstack(); truejp(stmt->exp,contlab); } contlab = lab1; /* restore old continue label */ }
static void emit_default(Node *node) { SAVE; if (!lswitch) error("stray case label"); emit_label(lswitch); lswitch = make_label(); }
void do_graph_label(graph_t* g) { char *p, *pos; int pos_ix; /* it would be nice to allow multiple graph labels in the future */ if ((p = agget(g,"label"))) { g->u.label = make_label(p, late_float(g,agfindattr(g,"fontsize"),DEFAULT_FONTSIZE,MIN_FONTSIZE), late_nnstring(g,agfindattr(g,"fontname"),DEFAULT_FONTNAME), late_nnstring(g,agfindattr(g,"fontcolor"),DEFAULT_COLOR),g); pos = agget(g,"labelloc"); if (!g->u.left_to_right) { if (!pos || (pos[0] != 'b')) pos_ix = TOP_IX; else pos_ix = BOTTOM_IX; g->u.border[pos_ix] = cvt2pt(g->u.label->dimen); } else { /* when rotated, the labels will be restored to TOP or BOTTOM */ if (!pos || (pos[0] != 'b')) pos_ix = RIGHT_IX; else pos_ix = LEFT_IX; g->u.border[pos_ix].x = g->u.label->dimen.y; g->u.border[pos_ix].y = g->u.label->dimen.x; } } }
void genif(SNODE *stmt) /* * generate code to evaluate an if statement. */ { int lab1, lab2; int areg, sreg; lab1 = nextlabel++; /* else label */ lab2 = nextlabel++; /* exit label */ InitRegs(); /* clear temps */ ChooseRegs(&areg, &sreg); falsejp(stmt->exp, areg, sreg, lab1); genstmt(stmt->s1); if (stmt->s2 != 0) /* else part exists */ { gen_codes(op_jmp, 0, make_label(lab2), 0); gen_label(lab1); genstmt(stmt->s2); gen_label(lab2); } else /* no else code */ gen_label(lab1); }
static void emit_ternary(Node *node) { SAVE; emit_expr(node->cond); char *ne = make_label(); emit_je(ne); if (node->then) emit_expr(node->then); if (node->els) { char *end = make_label(); emit_jmp(end); emit_label(ne); emit_expr(node->els); emit_label(end); } else { emit_label(ne); } }
static void emit_literal(Node *node) { SAVE; switch (node->ctype->type) { case CTYPE_BOOL: case CTYPE_CHAR: emit("mov $%d, %%rax", node->ival); break; case CTYPE_INT: emit("mov $%d, %%rax", node->ival); break; case CTYPE_LONG: case CTYPE_LLONG: { emit("mov $%lu, %%rax", node->ival); break; } case CTYPE_FLOAT: { if (!node->flabel) { node->flabel = make_label(); float fval = node->fval; int *p = (int *)&fval; emit_noindent(".data"); emit_label(node->flabel); emit(".long %d", *p); emit_noindent(".text"); } emit("movss %s(%%rip), %%xmm0", node->flabel); break; } case CTYPE_DOUBLE: case CTYPE_LDOUBLE: { if (!node->flabel) { node->flabel = make_label(); int *fval = (int *)&node->fval; emit_noindent(".data"); emit_label(node->flabel); emit(".long %d", fval[0]); emit(".long %d", fval[1]); emit_noindent(".text"); } emit("movsd %s(%%rip), %%xmm0", node->flabel); break; } default: error("internal error"); } }
static void emit_data_charptr(char *s, int depth) { char *label = make_label(); emit(".data %d", depth + 1); emit_label(label); emit(".string \"%s\"", quote_cstring(s)); emit(".data %d", depth); emit(".quad %s", label); }
static void emit_builtin_return_address(Node *node) { push("r11"); assert(vec_len(node->args) == 1); emit_expr(vec_head(node->args)); char *loop = make_label(); char *end = make_label(); emit("mov #rbp, #r11"); emit_label(loop); emit("test #rax, #rax"); emit("jz %s", end); emit("mov (#r11), #r11"); emit("sub $1, #rax"); emit_jmp(loop); emit_label(end); emit("mov 8(#r11), #rax"); pop("r11"); }
void gen_for(SNODE *stmt) /* * generate code to evaluate a for loop */ { int old_break, old_cont, exit_label, loop_label, start_label; int areg, sreg; old_break = breaklab; old_cont = contlab; loop_label = nextlabel++; contlab = nextlabel++; start_label = nextlabel++; exit_label = nextlabel++; InitRegs(); if (stmt->label != 0) { gen_void_external(stmt->label); } gen_codes(op_jmp, 0, make_label(start_label), 0); gen_label(loop_label); if (stmt->s1 != 0) { breaklab = exit_label; genstmt(stmt->s1); } if (stmt->lst) gen_line(stmt->lst); gen_label(contlab); InitRegs(); if (stmt->s2 != 0) { gen_void_external(stmt->s2); } gen_label(start_label); InitRegs(); ChooseRegs(&areg, &sreg); if (stmt->exp != 0) truejp(stmt->exp, areg, sreg, loop_label); else gen_codes(op_jmp, 0, make_label(loop_label), 0); gen_label(exit_label); breaklab = old_break; contlab = old_cont; }
static void emit_case(Node *node) { SAVE; if (!lswitch) error("stray case label"); char *skip = make_label(); emit_jmp(skip); emit_label(lswitch); lswitch = make_label(); emit("cmp $%d, %%eax", node->casebeg); if (node->casebeg == node->caseend) { emit("jne %s", lswitch); } else { emit("jl %s", lswitch); emit("cmp $%d, %%eax", node->caseend); emit("jg %s", lswitch); } emit_label(skip); }
static void emit_literal_string(Node *node) { SAVE; if (!node->slabel) { node->slabel = make_label(); emit_noindent(".data"); emit_label(node->slabel); emit(".string \"%s\"", quote_cstring(node->sval)); emit_noindent(".text"); } emit("lea %s(%%rip), %%rax", node->slabel); }
static void emit_for(Node *node) { SAVE; if (node->forinit) emit_expr(node->forinit); char *begin = make_label(); char *step = make_label(); char *end = make_label(); SET_JUMP_LABELS(end, step); emit_label(begin); if (node->forcond) { emit_expr(node->forcond); emit_je(end); } if (node->forbody) emit_expr(node->forbody); emit_label(step); if (node->forstep) emit_expr(node->forstep); emit_jmp(begin); emit_label(end); RESTORE_JUMP_LABELS(); }
static void emit_logor(Node *node) { SAVE; char *end = make_label(); emit_expr(node->left); emit("test %%rax, %%rax"); emit("mov $1, %%rax"); emit("jne %s", end); emit_expr(node->right); emit("test %%rax, %%rax"); emit("mov $1, %%rax"); emit("jne %s", end); emit("mov $0, %%rax"); emit_label(end); }
void gen_open_library(const char * libname, const char * librarybase) { char lab[80],lablabel[80]; gen_pop_addr(1); /* address of library name in a1 */ gen_jsr("_open_library"); make_library_base(libname); gen_save32d(0,librarybase); gen_test(); make_label(lab,lablabel); gen_bne(lab); gen_jmp("_EXIT_PROG"); /* quit program if can't open library */ gen_label(lablabel); enter_XREF("_open_library"); }
static void emit_logand(Node *node) { SAVE; char *end = make_label(); emit_expr(node->left); emit("test #rax, #rax"); emit("mov $0, #rax"); emit("je %s", end); emit_expr(node->right); emit("test #rax, #rax"); emit("mov $0, #rax"); emit("je %s", end); emit("mov $1, #rax"); emit_label(end); }
void directive_print_ppc440s(struct instruction *i) { switch ( i->code ) { case Target: printf("%s:\n",make_label(i->args[0])); break; case CmovTarget: printf("%s:\n",make_label(i->args[0])); break; case Cache_Align: printf(".align 4\n"); break; case Enter_Routine: printf(".text\n.align 3\n"); printf(".globl %s\n",i->mnemonic); printf("%s:\n\n",i->mnemonic); /* printf(".set noreorder\n\n");*/ break; case Exit_Routine: printf("\tblr\n"); /* printf(".size %s\n",i->mnemonic);*/ break; case Pipe_Flush: printf("# Instruction order barrier inserted\n"); break; case NOP: printf(" nop\n"); break; case FNOP: printf(" fnop\n"); break; default: printf("Error: Unknown assembler directive requested\n"); exit(0); break; } }
void gen_for(SNODE *stmt) /* * generate code to evaluate a for loop */ { int old_break, old_cont, exit_label, loop_label; old_break = breaklab; old_cont = contlab; loop_label = nextlabel++; exit_label = nextlabel++; contlab = nextlabel++; initstack(); if( stmt->label != 0 ) gen_expr(stmt->label,F_ALL | F_NOVALUE ,natural_size(stmt->label)); gen_code(op_jmp,0,make_label(contlab),0); gen_label(loop_label); if( stmt->s1 != 0 ) { breaklab = exit_label; genstmt(stmt->s1); } initstack(); if( stmt->s2 != 0 ) gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2)); gen_label(contlab); if (stmt->lst) gen_line(stmt->lst); initstack(); if( stmt->exp != 0 ) truejp(stmt->exp,loop_label); else gen_code(op_jmp,0,make_label(loop_label),0); gen_label(exit_label); breaklab = old_break; contlab = old_cont; }
static void emit_data_addr(Node *operand, int depth) { switch (operand->type) { case AST_LVAR: { char *label = make_label(); emit(".data %d", depth + 1); emit_label(label); emit_data_int(operand->lvarinit, operand->ctype->size, 0, depth + 1); emit(".data %d", depth); emit(".quad %s", label); return; } case AST_GVAR: emit(".quad %s", operand->varname); return; default: error("internal error"); } }