// cmd/9a/lex.c from Vita Nuova. // // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) // Portions Copyright © 1997-1999 Vita Nuova Limited // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com) // Portions Copyright © 2004,2006 Bruce Ellis // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others // Portions Copyright © 2009 The Go Authors. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define EXTERN #include #include #include "a.h" #include "y.tab.h" enum { Plan9 = 1<<0, Unix = 1<<1, Windows = 1<<2, }; int systemtype(int sys) { #ifdef _WIN32 return sys&Windows; #else return sys&Plan9; #endif } int pathchar(void) { return '/'; } int Lconv(Fmt *fp) { return linklinefmt(ctxt, fp); } void dodef(char *p) { if(nDlist%8 == 0) Dlist = allocn(Dlist, nDlist*sizeof(char *), 8*sizeof(char *)); Dlist[nDlist++] = p; } LinkArch* thelinkarch = &linkpower64; void usage(void) { print("usage: %ca [options] file.c...\n", thechar); flagprint(1); errorexit(); } void main(int argc, char *argv[]) { char *p; thechar = '9'; thestring = "power64"; // Allow GOARCH=thestring or GOARCH=thestringsuffix, // but not other values. p = getgoarch(); if(strncmp(p, thestring, strlen(thestring)) != 0) sysfatal("cannot use %cc with GOARCH=%s", thechar, p); if(strcmp(p, "power64le") == 0) thelinkarch = &linkpower64le; ctxt = linknew(thelinkarch); ctxt->diag = yyerror; ctxt->bso = &bstdout; ctxt->enforce_data_order = 1; Binit(&bstdout, 1, OWRITE); listinit9(); fmtinstall('L', Lconv); ensuresymb(NSYMB); memset(debug, 0, sizeof(debug)); cinit(); outfile = 0; setinclude("."); flagfn1("D", "name[=value]: add #define", dodef); flagfn1("I", "dir: add dir to include path", setinclude); flagcount("S", "print assembly and machine code", &debug['S']); flagcount("m", "debug preprocessor macros", &debug['m']); flagstr("o", "file: set output file", &outfile); flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath); flagparse(&argc, &argv, usage); ctxt->debugasm = debug['S']; if(argc < 1) usage(); if(argc > 1){ print("can't assemble multiple files\n"); errorexit(); } if(assemble(argv[0])) errorexit(); Bflush(&bstdout); exits(0); } int assemble(char *file) { char *ofile, *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(outfile){ p = utfrrune(outfile, '.'); if(p) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } else outfile = "/dev/null"; } of = create(outfile, OWRITE, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion()); Bprint(&obuf, "!\n"); for(pass = 1; pass <= 2; pass++) { nosched = 0; pinit(file); for(i=0; itype = itab[i].type; s->value = itab[i].value; } } void syminit(Sym *s) { s->type = LNAME; s->value = 0; } void cclean(void) { outcode(AEND, &nullgen, NREG, &nullgen); } static Prog *lastpc; void outcode(int a, Addr *g1, int reg, Addr *g2) { Prog *p; Plist *pl; if(pass == 1) goto out; if(g1->scale != NREG) { if(reg != NREG || g2->scale != NREG) yyerror("bad addressing modes"); reg = g1->scale; } else if(g2->scale != NREG) { if(reg != NREG) yyerror("bad addressing modes"); reg = g2->scale; } p = ctxt->arch->prg(); p->as = a; p->lineno = lineno; if(nosched) p->mark |= NOSCHED; p->from = *g1; p->reg = reg; p->to = *g2; p->pc = pc; if(lastpc == nil) { pl = linknewplist(ctxt); pl->firstpc = p; } else lastpc->link = p; lastpc = p; out: if(a != AGLOBL && a != ADATA) pc++; } void outgcode(int a, Addr *g1, int reg, Addr *g2, Addr *g3) { Prog *p; Plist *pl; if(pass == 1) goto out; p = ctxt->arch->prg(); p->as = a; p->lineno = lineno; if(nosched) p->mark |= NOSCHED; p->from = *g1; p->reg = reg; p->from3 = *g2; p->to = *g3; p->pc = pc; if(lastpc == nil) { pl = linknewplist(ctxt); pl->firstpc = p; } else lastpc->link = p; lastpc = p; out: if(a != AGLOBL && a != ADATA) pc++; } #include "../cc/lexbody" #include "../cc/macbody"