/* assign input vector */ void assign_input_affix () { int nr = popi (); affix_node affx = popa (); value new_val = my_ivals[nr]; if (affx -> val != value_nil) { if (equal_value (new_val, affx -> val)) callq (); } else { affx -> val = rdup_value (new_val); if (affx -> mfunc != NULL) { /* check metadefinition */ pushv (new_val); pushq (affx -> mfunc); callq (); pop (2); } else callq (); rfre_value (new_val); affx -> val = value_nil; }; pusha (affx); pushi (nr); pushq (assign_input_affix); };
static void assign(Node *n) { Node *l, *r; int op; op = n->Assign.op; l = n->Assign.l; r = n->Assign.r; if(op == '=') { expr(r); pushq("rax"); addr(l); popq("rcx"); if(!isptr(l->type) && !isitype(l->type) && !isstruct(l->type)) errorf("unimplemented assign\n"); store(l->type); outi("movq %%rcx, %%rax\n"); return; } addr(l); pushq("rax"); load(l->type); pushq("rax"); expr(r); outi("movq %%rax, %%rcx\n"); popq("rax"); /* XXX this type is not correct for comparison ops works anyway, but should be changed*/ obinop(op, n->type); outi("movq %%rax, %%rcx\n"); popq("rax"); store(l->type); outi("movq %%rcx, %%rax\n"); }
int main(int argc, const char *argv[]) { queue_t* a; int data; int i; a = (queue_t*)malloc(sizeof(queue_t)); new_queue(a, 10); print_queue(a); pushq(a, 2); print_queue(a); popq(a, &data); print_queue(a); pushq(a, 3); print_queue(a); for(i = 0; i < a->size + 3; i++) { pushq(a, i); print_queue(a); } for(i = 0; i < a->size + 3; i++) { popq(a, &data); print_queue(a); printf("data: %d\n", data); } del_queue(a); free(a); return 0; }
static void incdec(Node *n) { if(!isitype(n->type) && !isptr(n->type)) panic("unimplemented incdec"); addr(n->Incdec.operand); pushq("rax"); load(n->type); if(isptr(n->type)) { if(n->Incdec.op == TOKINC) outi("add $%d, %%rax\n", n->type->Ptr.subty->size); else outi("add $%d, %%rax\n", -n->type->Ptr.subty->size); } else { if(n->Incdec.op == TOKINC) outi("inc %%rax\n"); else outi("dec %%rax\n"); } outi("movq %%rax, %%rcx\n"); popq("rax"); store(n->type); outi("movq %%rcx, %%rax\n"); if(n->Incdec.post == 1) { if(n->Incdec.op == TOKINC) outi("dec %%rax\n"); else outi("inc %%rax\n"); } }
static void call(Node *n) { int i, nargs, nintargs, cleanup; Vec *args; Node *arg; args = n->Call.args; i = nargs = args->len; /* Push args in reverse order */ while(i-- != 0) { arg = vecget(args, i); if(!isitype(arg->type) && !isptr(arg->type) && !isarray(arg->type) && !isfunc(arg->type)) errorposf(&arg->pos, "unimplemented arg type\n"); expr(arg); pushq("rax"); } nintargs = nargs; if(nintargs > 6) nintargs = 6; for(i = 0; i < nintargs; i++) popq(intargregs[i]); expr(n->Call.funclike); outi("call *%%rax\n"); cleanup = 8 * (nargs - nintargs); if(cleanup) { outi("add $%d, %%rsp\n", cleanup); stackoffset -= cleanup; } }
void emitsym(Sym *sym) { out("# emit sym %s\n", sym->name); switch(sym->k){ case SYMGLOBAL: if(sym->Global.sclass == SCEXTERN) break; if(isfunc(sym->type)) { func(sym->init, sym->Global.label, sym->Global.sclass == SCGLOBAL); break; } penddata(sym->Global.label, sym->type, sym->init, sym->Global.sclass == SCGLOBAL); break; case SYMLOCAL: if(sym->init) { expr(sym->init); pushq("rax"); outi("leaq %d(%%rbp), %%rax\n", sym->Local.slot->offset); popq("rcx"); if(!isptr(sym->type) && !isitype(sym->type) && !isstruct(sym->type)) errorf("unimplemented init\n"); store(sym->type); } break; case SYMENUM: case SYMTYPE: panic("internal error"); } out("\n"); }
void semipred_showfield () { int i,j; fprintf (stderr, "Field:\n"); for (i = 0; i < height; i++) { for (j = 0; j < width; j++) fputc ((field [i*width +j])?'X':' ', stderr); fputc ('\n', stderr); }; fputc ('\n', stderr); pushi (0); pushi (0); pushi (mk_nodenr (alib_modnr, 3)); pushq (make_semipredicate_node); callq (); pop (4); pushq (semipred_showfield); };
/* Reserve space to collect output affixes */ void reserve_collection_space () { my_nrps = popi (); my_cvals = (value **) ckcalloc (1, sizeof (value *)); room = 1; allocated = 0; callq (); pushi (my_nrps); pushq (reserve_collection_space); };
void collect_output_affix () { int nr = popi (); affix_node affx = popa (); value new_val = affx -> val; check_for_space (); my_cvals[nrofparses][nr] = rdup_value (new_val); callq (); pusha (affx); pushi (nr); pushq (collect_output_affix); };
void pred_makeemptyfield () { affix_node af1 = new_affix_node ("makeemptyfield_af1"); affix_node af2 = new_affix_node ("makeemptyfield_af2"); pushq (delayed_makeemptyfield); pushq (make_node_delayed); pusha (af2); pushi (tag_single); pusha (af1); pushi (tag_single); pushi (2); pushi (0); pushi (mk_nodenr (alib_modnr, 0)); pushq (make_predicate_node); callq (); pop (10); rfre_value (af1 -> val); free_affix_node (af1); rfre_value (af2 -> val); free_affix_node (af2); pushq (pred_makeemptyfield); };
static void addr(Node *n) { int sz; int offset; Sym *sym; switch(n->t) { case NUNOP: expr(n->Unop.operand); break; case NSEL: expr(n->Sel.operand); if(isptr(n->Sel.operand->type)) offset = structoffsetfromname(n->Sel.operand->type->Ptr.subty, n->Sel.name); else if(isstruct(n->Sel.operand->type)) offset = structoffsetfromname(n->Sel.operand->type, n->Sel.name); else panic("internal error"); if(offset < 0) panic("internal error"); outi("addq $%d, %%rax\n", offset); break; case NIDENT: sym = n->Ident.sym; switch(sym->k) { case SYMGLOBAL: outi("leaq %s(%%rip), %%rax\n", sym->Global.label); break; case SYMLOCAL: outi("leaq %d(%%rbp), %%rax\n", sym->Local.slot->offset); break; default: panic("internal error"); } break; case NIDX: expr(n->Idx.idx); sz = n->type->size; if(sz != 1) { outi("imul $%d, %%rax\n", sz); } pushq("rax"); expr(n->Idx.operand); popq("rcx"); outi("addq %%rcx, %%rax\n"); break; default: errorf("unimplemented addr\n"); } }
static void binop(Node *n) { if(n->Binop.op == TOKLAND || n->Binop.op == TOKLOR) { shortcircuit(n); return; } expr(n->Binop.l); pushq("rax"); expr(n->Binop.r); outi("movq %%rax, %%rcx\n"); popq("rax"); obinop(n->Binop.op, n->type); }
static void store(CTy *t) { if(isitype(t) || isptr(t)) { switch(t->size) { case 8: outi("movq %%rcx, (%%rax)\n"); break; case 4: outi("movl %%ecx, (%%rax)\n"); break; case 2: outi("movw %%cx, (%%rax)\n"); break; case 1: outi("movb %%cl, (%%rax)\n"); break; default: panic("internal error\n"); } return; } if(isstruct(t)) { pushq("rdi"); pushq("rsi"); pushq("rcx"); outi("movq %%rcx, %%rsi\n"); outi("movq %%rax, %%rdi\n"); outi("movq $%d, %%rcx\n", t->size); outi("rep movsb\n"); popq("rcx"); popq("rsi"); popq("rdi"); return; } errorf("unimplemented store\n"); }
static void vastart(Node *n) { int argend; expr(n->Builtin.Vastart.valist); /* XXX currently only support int args */ argend = (n->Builtin.Vastart.param->Ident.sym->Local.paramidx + 1) * 8; pushq("rcx"); outi("movl $%d, (%%rax)\n", argend); outi("movl $%d, 4(%%rax)\n", 48 + 0 * 16); outi("leaq %d(%%rbp), %%rcx\n", -176); outi("movq %%rcx, 16(%%rax)\n"); popq("rcx"); }
static void func(Node *f, char *label, int isglobal) { Vec *v; Sym *sym; int i; calcslotoffsets(f); out("\n"); out(".text\n"); out("# function %s\n", f->Func.name); if(isglobal) out(".globl %s\n", label); out("%s:\n", label); pushq("rbp"); outi("movq %%rsp, %%rbp\n"); if(f->type->Func.isvararg) { stackoffset += 176; outi("sub $176, %%rsp\n"); outi("movq %%rdi, (%%rsp)\n"); outi("movq %%rsi, 8(%%rsp)\n"); outi("movq %%rdx, 16(%%rsp)\n"); outi("movq %%rcx, 24(%%rsp)\n"); outi("movq %%r8, 32(%%rsp)\n"); outi("movq %%r9, 40(%%rsp)\n"); } if(f->Func.localsz) { outi("sub $%d, %%rsp\n", f->Func.localsz); stackoffset += f->Func.localsz; } v = f->Func.params; for(i = 0; i < v->len; i++) { sym = vecget(v, i); if(!isitype(sym->type) && !isptr(sym->type) && !isarray(sym->type)) errorposf(&f->pos, "unimplemented arg type"); if(i < 6) { outi("movq %%%s, %d(%%rbp)\n", intargregs[i], sym->Local.slot->offset); } else { outi("movq %d(%%rbp), %%rcx\n", 16 + 8 * (i - 6)); outi("leaq %d(%%rbp), %%rax\n", sym->Local.slot->offset); store(sym->type); } } block(f->Func.body); outi("leave\n"); outi("ret\n"); }
// void getPsrInfo(VM_Version::CpuidInfo* cpuid_info); address generate_getPsrInfo() { StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub"); # define __ _masm-> address start = __ pc(); // rbx is callee-save on both unix and windows // rcx and rdx are first and second argument registers on windows __ pushq(rbx); __ movq(r8, rarg0); __ xorl(rax, rax); __ cpuid(); __ leaq(r9, Address(r8, in_bytes(VM_Version::std_cpuid0_offset()))); __ movl(Address(r9, 0), rax); __ movl(Address(r9, 4), rbx); __ movl(Address(r9, 8), rcx); __ movl(Address(r9, 12), rdx); __ movl(rax, 1); __ cpuid(); __ leaq(r9, Address(r8, in_bytes(VM_Version::std_cpuid1_offset()))); __ movl(Address(r9, 0), rax); __ movl(Address(r9, 4), rbx); __ movl(Address(r9, 8), rcx); __ movl(Address(r9, 12), rdx); __ movl(rax, 0x80000001); __ cpuid(); __ leaq(r9, Address(r8, in_bytes(VM_Version::ext_cpuid1_offset()))); __ movl(Address(r9, 0), rax); __ movl(Address(r9, 4), rbx); __ movl(Address(r9, 8), rcx); __ movl(Address(r9, 12), rdx); __ popq(rbx); __ ret(0); return start; }