static s32 get_fixup (s32 reloc, s32 code_end) { s32 old_bufpos; s32 next; static s32 reloc_pos; old_bufpos = buf_pos; if (reloc == 0) { buf_pos = code_end; reloc = rdlong (buf_pos); buf_pos += 4; reloc_pos = buf_pos; buf_pos = old_bufpos; if (reloc == 0) return 0; else return reloc+0x1c+LOAD_BASE; } else { buf_pos = reloc_pos; again: next = (u8)rdbyte (buf_pos); buf_pos++; if (next == 0) { buf_pos = old_bufpos; return 0; } else if (next == 1) { reloc += 254; goto again; } else reloc += next; reloc_pos = buf_pos; buf_pos = old_bufpos; return reloc; } }
/* Unpickles a node from a file. Minimal checking * is done. Specifically, no checks are done for * sane arities, a bad file can crash the compiler */ static Node *unpickle(FILE *fd) { size_t i; Ntype type; Node *n; type = rdbyte(fd); if (type == Nnone) return NULL; n = mknode(Zloc, type); n->loc.line = rdint(fd); n->loc.file = file->file.nfiles - 1; switch (n->type) { case Nfile: lappend(&n->file.files, &n->file.nfiles, rdstr(fd)); n->file.nuses = rdint(fd); n->file.uses = zalloc(sizeof(Node*)*n->file.nuses); for (i = 0; i < n->file.nuses; i++) n->file.uses[i] = unpickle(fd); n->file.nstmts = rdint(fd); n->file.stmts = zalloc(sizeof(Node*)*n->file.nstmts); for (i = 0; i < n->file.nstmts; i++) n->file.stmts[i] = unpickle(fd); n->file.globls = rdstab(fd, 0); break; case Nexpr: n->expr.op = rdbyte(fd); rdtype(fd, &n->expr.type); n->expr.isconst = rdbool(fd); n->expr.idx = unpickle(fd); n->expr.nargs = rdint(fd); n->expr.args = zalloc(sizeof(Node *)*n->expr.nargs); for (i = 0; i < n->expr.nargs; i++) n->expr.args[i] = unpickle(fd); break; case Nname: if (rdbool(fd)) n->name.ns = rdstr(fd); n->name.name = rdstr(fd); break; case Nuse: n->use.islocal = rdbool(fd); n->use.name = rdstr(fd); break; case Nlit: n->lit.littype = rdbyte(fd); rdtype(fd, &n->lit.type); n->lit.nelt = rdint(fd); switch (n->lit.littype) { case Lchr: n->lit.chrval = rdint(fd); break; case Lint: n->lit.intval = rdint(fd); break; case Lflt: n->lit.fltval = rdflt(fd); break; case Lstr: rdlenstr(fd, &n->lit.strval); break; case Llbl: n->lit.lblval = rdstr(fd); break; case Lbool: n->lit.boolval = rdbool(fd); break; case Lfunc: n->lit.fnval = unpickle(fd); break; } break; case Nloopstmt: n->loopstmt.init = unpickle(fd); n->loopstmt.cond = unpickle(fd); n->loopstmt.step = unpickle(fd); n->loopstmt.body = unpickle(fd); break; case Niterstmt: n->iterstmt.elt = unpickle(fd); n->iterstmt.seq = unpickle(fd); n->iterstmt.body = unpickle(fd); break; case Nmatchstmt: n->matchstmt.val = unpickle(fd); n->matchstmt.nmatches = rdint(fd); n->matchstmt.matches = zalloc(sizeof(Node *)*n->matchstmt.nmatches); for (i = 0; i < n->matchstmt.nmatches; i++) n->matchstmt.matches[i] = unpickle(fd); break; case Nmatch: n->match.pat = unpickle(fd); n->match.block = unpickle(fd); break; case Nifstmt: n->ifstmt.cond = unpickle(fd); n->ifstmt.iftrue = unpickle(fd); n->ifstmt.iffalse = unpickle(fd); break; case Nblock: n->block.scope = rdstab(fd, 0); n->block.nstmts = rdint(fd); n->block.stmts = zalloc(sizeof(Node *)*n->block.nstmts); n->block.scope->super = curstab(); pushstab(n->func.scope->super); for (i = 0; i < n->block.nstmts; i++) n->block.stmts[i] = unpickle(fd); popstab(); break; case Ndecl: n->decl.did = ndecls; /* unique within file */ /* sym */ n->decl.name = unpickle(fd); rdtype(fd, &n->decl.type); /* symflags */ n->decl.isconst = rdbool(fd); n->decl.isgeneric = rdbool(fd); n->decl.isextern = rdbool(fd); n->decl.isnoret = rdbool(fd); n->decl.ispkglocal = rdbool(fd); /* init */ n->decl.init = unpickle(fd); lappend(&decls, &ndecls, n); break; case Nfunc: rdtype(fd, &n->func.type); n->func.scope = rdstab(fd, 1); n->func.nargs = rdint(fd); n->func.args = zalloc(sizeof(Node *)*n->func.nargs); n->func.scope->super = curstab(); pushstab(n->func.scope->super); for (i = 0; i < n->func.nargs; i++) n->func.args[i] = unpickle(fd); n->func.body = unpickle(fd); popstab(); break; case Nimpl: n->impl.traitname = unpickle(fd); i = rdint(fd); rdtrait(fd, &n->impl.trait, NULL); rdtype(fd, &n->impl.type); n->impl.ndecls = rdint(fd); n->impl.decls = zalloc(sizeof(Node *)*n->impl.ndecls); for (i = 0; i < n->impl.ndecls; i++) n->impl.decls[i] = rdsym(fd, n->impl.trait); break; case Nnone: die("Nnone should not be seen as node type!"); break; } return n; }
/* Writes types to a file. Errors on * internal only types like Tyvar that * will not be meaningful in another file */ static Type *tyunpickle(FILE *fd) { size_t i, n; Type *ty; Ty t; t = rdbyte(fd); ty = mktype(Zloc, t); ty->isimport = 1; if (rdbyte(fd) == Vishidden) ty->ishidden = 1; /* tid is generated; don't write */ n = rdint(fd); for (i = 0; i < n; i++) rdtrait(fd, NULL, ty); ty->nsub = rdint(fd); if (ty->nsub > 0) ty->sub = zalloc(ty->nsub * sizeof(Type*)); switch (ty->type) { case Tyunres: ty->name = unpickle(fd); break; case Typaram: ty->pname = rdstr(fd); break; case Tystruct: ty->nmemb = rdint(fd); ty->sdecls = zalloc(ty->nmemb * sizeof(Node*)); for (i = 0; i < ty->nmemb; i++) ty->sdecls[i] = unpickle(fd); break; case Tyunion: ty->nmemb = rdint(fd); ty->udecls = zalloc(ty->nmemb * sizeof(Node*)); for (i = 0; i < ty->nmemb; i++) ty->udecls[i] = rducon(fd, ty); break; case Tyarray: rdtype(fd, &ty->sub[0]); ty->asize = unpickle(fd); break; case Tyslice: rdtype(fd, &ty->sub[0]); break; case Tyname: ty->name = unpickle(fd); ty->issynth = rdbool(fd); ty->narg = rdint(fd); ty->arg = zalloc(ty->narg * sizeof(Type *)); for (i = 0; i < ty->narg; i++) rdtype(fd, &ty->arg[i]); rdtype(fd, &ty->sub[0]); break; case Tygeneric: ty->name = unpickle(fd); ty->issynth = rdbool(fd); ty->ngparam = rdint(fd); ty->gparam = zalloc(ty->ngparam * sizeof(Type *)); for (i = 0; i < ty->ngparam; i++) rdtype(fd, &ty->gparam[i]); rdtype(fd, &ty->sub[0]); break; default: for (i = 0; i < ty->nsub; i++) rdtype(fd, &ty->sub[i]); break; } return ty; }