1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 //go:generate go run mkbuiltin.go
10 "cmd/compile/internal/ssa"
24 var imported_unsafe bool
43 // These can be specified with the -d flag, as in "-d nil"
44 // to set the debug_checknil variable. In general the list passed
45 // to -d can be comma-separated.
46 var debugtab = []struct {
50 {"append", &Debug_append}, // print information about append compilation
51 {"disablenil", &Disable_checknil}, // disable nil checks
52 {"gcprog", &Debug_gcprog}, // print dump of GC programs
53 {"nil", &Debug_checknil}, // print information about nil checks
54 {"panic", &Debug_panic}, // do not hide any compiler panic
55 {"slice", &Debug_slice}, // print information about slice compilation
56 {"typeassert", &Debug_typeassert}, // print information about type assertion inlining
57 {"wb", &Debug_wb}, // print information about write barriers
58 {"export", &Debug_export}, // print export data
66 fmt.Printf("usage: compile [options] file.go...\n")
72 if Debug_panic == 0 && nsavederrors+nerrors > 0 {
73 // If we've already complained about things
74 // in the program, don't bother complaining
75 // about a panic too; let the user clean up
76 // the code and try again.
77 if err := recover(); err != nil {
92 fmt.Printf("compile version %s%s%s\n", obj.Getgoversion(), sep, p)
99 // Allow GOARCH=thearch.thestring or GOARCH=thearch.thestringsuffix,
100 // but not other values.
103 if !strings.HasPrefix(p, Thearch.Thestring) {
104 log.Fatalf("cannot use %cg with GOARCH=%s", Thearch.Thechar, p)
108 Thearch.Linkarchinit()
109 Ctxt = obj.Linknew(Thearch.Thelinkarch)
110 Ctxt.DiagFunc = Yyerror
112 bstdout = *obj.Binitw(os.Stdout)
115 localpkg.Prefix = "\"\""
117 // pseudo-package, for scoping
118 builtinpkg = mkpkg("go.builtin")
120 builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin
122 // pseudo-package, accessed by import "unsafe"
123 unsafepkg = mkpkg("unsafe")
125 unsafepkg.Name = "unsafe"
127 // real package, referred to by generated runtime calls
128 Runtimepkg = mkpkg("runtime")
130 Runtimepkg.Name = "runtime"
132 // pseudo-packages used in symbol tables
133 gostringpkg = mkpkg("go.string")
135 gostringpkg.Name = "go.string"
136 gostringpkg.Prefix = "go.string" // not go%2estring
138 itabpkg = mkpkg("go.itab")
140 itabpkg.Name = "go.itab"
141 itabpkg.Prefix = "go.itab" // not go%2eitab
143 weaktypepkg = mkpkg("go.weak.type")
145 weaktypepkg.Name = "go.weak.type"
146 weaktypepkg.Prefix = "go.weak.type" // not go%2eweak%2etype
148 typelinkpkg = mkpkg("go.typelink")
149 typelinkpkg.Name = "go.typelink"
150 typelinkpkg.Prefix = "go.typelink" // not go%2etypelink
152 trackpkg = mkpkg("go.track")
154 trackpkg.Name = "go.track"
155 trackpkg.Prefix = "go.track" // not go%2etrack
157 typepkg = mkpkg("type")
159 typepkg.Name = "type"
161 goroot = obj.Getgoroot()
164 Nacl = goos == "nacl"
170 obj.Flagcount("+", "compiling runtime", &compiling_runtime)
171 obj.Flagcount("%", "debug non-static initializers", &Debug['%'])
172 obj.Flagcount("A", "for bootstrapping, allow 'any' type", &Debug['A'])
173 obj.Flagcount("B", "disable bounds checking", &Debug['B'])
174 obj.Flagstr("D", "set relative `path` for local imports", &localimport)
175 obj.Flagcount("E", "debug symbol export", &Debug['E'])
176 obj.Flagfn1("I", "add `directory` to import search path", addidir)
177 obj.Flagcount("K", "debug missing line numbers", &Debug['K'])
178 obj.Flagcount("L", "use full (long) path in error messages", &Debug['L'])
179 obj.Flagcount("M", "debug move generation", &Debug['M'])
180 obj.Flagcount("N", "disable optimizations", &Debug['N'])
181 obj.Flagcount("P", "debug peephole optimizer", &Debug['P'])
182 obj.Flagcount("R", "debug register optimizer", &Debug['R'])
183 obj.Flagcount("S", "print assembly listing", &Debug['S'])
184 obj.Flagfn0("V", "print compiler version", doversion)
185 obj.Flagcount("W", "debug parse tree after type checking", &Debug['W'])
186 obj.Flagstr("asmhdr", "write assembly header to `file`", &asmhdr)
187 obj.Flagstr("buildid", "record `id` as the build id in the export metadata", &buildid)
188 obj.Flagcount("complete", "compiling complete package (no C or assembly)", &pure_go)
189 obj.Flagstr("d", "print debug information about items in `list`", &debugstr)
190 obj.Flagcount("e", "no limit on number of errors reported", &Debug['e'])
191 obj.Flagcount("f", "debug stack frames", &Debug['f'])
192 obj.Flagcount("g", "debug code generation", &Debug['g'])
193 obj.Flagcount("h", "halt on error", &Debug['h'])
194 obj.Flagcount("i", "debug line number stack", &Debug['i'])
195 obj.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
196 obj.Flagstr("installsuffix", "set pkg directory `suffix`", &flag_installsuffix)
197 obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
198 obj.Flagcount("l", "disable inlining", &Debug['l'])
199 obj.Flagcount("live", "debug liveness analysis", &debuglive)
200 obj.Flagcount("m", "print optimization decisions", &Debug['m'])
201 obj.Flagcount("msan", "build code compatible with C/C++ memory sanitizer", &flag_msan)
202 obj.Flagcount("newexport", "use new export format", &newexport) // TODO(gri) remove eventually (issue 13241)
203 obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports)
204 obj.Flagstr("o", "write output to `file`", &outfile)
205 obj.Flagstr("p", "set expected package import `path`", &myimportpath)
206 obj.Flagcount("pack", "write package file instead of object file", &writearchive)
207 obj.Flagcount("r", "debug generated wrappers", &Debug['r'])
208 obj.Flagcount("race", "enable race detector", &flag_race)
209 obj.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s'])
210 obj.Flagstr("trimpath", "remove `prefix` from recorded source file paths", &Ctxt.LineHist.TrimPathPrefix)
211 obj.Flagcount("u", "reject unsafe code", &safemode)
212 obj.Flagcount("v", "increase debug verbosity", &Debug['v'])
213 obj.Flagcount("w", "debug type checking", &Debug['w'])
215 obj.Flagcount("wb", "enable write barrier", &use_writebarrier)
216 obj.Flagcount("x", "debug lexer", &Debug['x'])
217 obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y'])
219 var flag_dynlink bool
220 switch Thearch.Thechar {
221 case '5', '6', '7', '8', '9':
222 obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared)
224 if Thearch.Thechar == '6' {
225 obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel)
227 switch Thearch.Thechar {
228 case '5', '6', '7', '8', '9':
229 flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
231 obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
232 obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile)
233 obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate)
239 Ctxt.Flag_shared = int32(flag_shared)
240 Ctxt.Flag_dynlink = flag_dynlink
241 Ctxt.Flag_optimize = Debug['N'] == 0
243 Ctxt.Debugasm = int32(Debug['S'])
244 Ctxt.Debugvlog = int32(Debug['v'])
253 racepkg = mkpkg("runtime/race")
254 racepkg.Name = "race"
257 msanpkg = mkpkg("runtime/msan")
258 msanpkg.Name = "msan"
260 if flag_race != 0 && flag_msan != 0 {
261 log.Fatal("cannot use both -race and -msan")
262 } else if flag_race != 0 || flag_msan != 0 {
269 for _, name := range strings.Split(debugstr, ",") {
274 if i := strings.Index(name, "="); i >= 0 {
276 val, err = strconv.Atoi(name[i+1:])
278 log.Fatalf("invalid debug value %v", name)
282 for _, t := range debugtab {
290 // special case for ssa for now
291 if strings.HasPrefix(name, "ssa/") {
292 // expect form ssa/phase/flag
293 // e.g. -d=ssa/generic_cse/time
294 // _ in phase name also matches space
296 flag := "debug" // default flag is debug
297 if i := strings.Index(phase, "/"); i >= 0 {
301 err := ssa.PhaseOption(phase, flag, val)
307 log.Fatalf("unknown debug key -d %s\n", name)
311 // enable inlining. for now:
312 // default: inlining on. (debug['l'] == 1)
313 // -l: inlining off (debug['l'] == 0)
314 // -ll, -lll: inlining on again, with extra debugging (debug['l'] > 1)
316 Debug['l'] = 1 - Debug['l']
321 Fatalf("betypeinit failed")
335 for _, infile = range flag.Args() {
336 if trace && Debug['x'] != 0 {
337 fmt.Printf("--- %s ---\n", infile)
342 bin, err := obj.Bopenr(infile)
344 fmt.Printf("open %s: %v\n", infile, err)
348 // Skip initial BOM if present.
349 if obj.Bgetrune(bin) != BOM {
356 imported_unsafe = false
359 if nsyntaxerrors != 0 {
363 // Instead of converting EOF into '\n' in getc and count it as an extra line
364 // for the line history to work, and which then has to be corrected elsewhere,
365 // just add a line here.
373 mkpackage(localpkg.Name) // final import not used checks
381 // Process top-level declarations in phases.
383 // Phase 1: const, type, and names and types of funcs.
384 // This will gather all the information about types
385 // and methods but doesn't depend on any of it.
388 for l := xtop; l != nil; l = l.Next {
389 if l.N.Op != ODCL && l.N.Op != OAS && l.N.Op != OAS2 {
390 typecheck(&l.N, Etop)
394 // Phase 2: Variable assignments.
395 // To check interface assignments, depends on phase 1.
396 for l := xtop; l != nil; l = l.Next {
397 if l.N.Op == ODCL || l.N.Op == OAS || l.N.Op == OAS2 {
398 typecheck(&l.N, Etop)
403 // Phase 3: Type check function bodies.
404 for l := xtop; l != nil; l = l.Next {
405 if l.N.Op == ODCLFUNC || l.N.Op == OCLOSURE {
409 typechecklist(l.N.Nbody, Etop)
412 l.N.Nbody = nil // type errors; do not compile
417 // Phase 4: Decide how to capture closed variables.
418 // This needs to run before escape analysis,
419 // because variables captured by value do not escape.
420 for l := xtop; l != nil; l = l.Next {
421 if l.N.Op == ODCLFUNC && l.N.Func.Closure != nil {
429 if nsavederrors+nerrors != 0 {
435 // Typecheck imported function bodies if debug['l'] > 1,
436 // otherwise lazily when used or re-exported.
437 for _, n := range importlist {
438 if n.Func.Inl != nil {
444 if nsavederrors+nerrors != 0 {
450 // Find functions that can be inlined and clone them before walk expands them.
451 visitBottomUp(xtop, func(list []*Node, recursive bool) {
452 // TODO: use a range statement here if the order does not matter
453 for i := len(list) - 1; i >= 0; i-- {
455 if n.Op == ODCLFUNC {
463 // Phase 6: Escape analysis.
464 // Required for moving heap allocations onto stack,
465 // which in turn is required by the closure implementation,
466 // which stores the addresses of stack variables into the closure.
467 // If the closure does not escape, it needs to be on the stack
468 // or else the stack copier will not update it.
469 // Large values are also moved off stack in escape analysis;
470 // because large values may contain pointers, it must happen early.
473 // Phase 7: Transform closure bodies to properly reference captured variables.
474 // This needs to happen before walk, because closures must be transformed
475 // before walk reaches a call of a closure.
476 for l := xtop; l != nil; l = l.Next {
477 if l.N.Op == ODCLFUNC && l.N.Func.Closure != nil {
479 transformclosure(l.N)
485 // Phase 8: Compile top level functions.
486 for l := xtop; l != nil; l = l.Next {
487 if l.N.Op == ODCLFUNC {
492 if nsavederrors+nerrors == 0 {
496 if compiling_runtime != 0 {
497 checknowritebarrierrec()
500 // Phase 9: Check external declarations.
501 for i, n := range externdcl {
503 typecheck(&externdcl[i], Erv)
507 if nerrors+nsavederrors != 0 {
517 if nerrors+nsavederrors != 0 {
524 var importMap = map[string]string{}
526 func addImportMap(s string) {
527 if strings.Count(s, "=") != 1 {
528 log.Fatal("-importmap argument must be of the form source=actual")
530 i := strings.Index(s, "=")
531 source, actual := s[:i], s[i+1:]
532 if source == "" || actual == "" {
533 log.Fatal("-importmap argument must be of the form source=actual; source and actual must be non-empty")
535 importMap[source] = actual
539 nsavederrors += nerrors
543 func arsize(b *obj.Biobuf, name string) int {
544 var buf [ArhdrSize]byte
545 if _, err := io.ReadFull(b, buf[:]); err != nil {
548 aname := strings.Trim(string(buf[0:16]), " ")
549 if !strings.HasPrefix(aname, name) {
552 asize := strings.Trim(string(buf[48:58]), " ")
553 i, _ := strconv.Atoi(asize)
557 func skiptopkgdef(b *obj.Biobuf) bool {
559 p := obj.Brdline(b, '\n')
563 if obj.Blinelen(b) != 8 {
566 if p != "!<arch>\n" {
570 // package export block should be first
571 sz := arsize(b, "__.PKGDEF")
577 func addidir(dir string) {
579 idirs = append(idirs, dir)
583 func isDriveLetter(b byte) bool {
584 return 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z'
587 // is this path a local name? begins with ./ or ../ or /
588 func islocalname(name string) bool {
589 return strings.HasPrefix(name, "/") ||
590 Ctxt.Windows != 0 && len(name) >= 3 && isDriveLetter(name[0]) && name[1] == ':' && name[2] == '/' ||
591 strings.HasPrefix(name, "./") || name == "." ||
592 strings.HasPrefix(name, "../") || name == ".."
595 func findpkg(name string) (file string, ok bool) {
596 if islocalname(name) {
597 if safemode != 0 || nolocalimports != 0 {
601 // try .a before .6. important for building libraries:
602 // if there is an array.6 in the array.a library,
603 // want to find all of array.a, not just array.6.
604 file = fmt.Sprintf("%s.a", name)
605 if _, err := os.Stat(file); err == nil {
608 file = fmt.Sprintf("%s.o", name)
609 if _, err := os.Stat(file); err == nil {
615 // local imports should be canonicalized already.
616 // don't want to see "encoding/../encoding/base64"
617 // as different from "encoding/base64".
618 if q := path.Clean(name); q != name {
619 Yyerror("non-canonical import path %q (should be %q)", name, q)
623 for _, dir := range idirs {
624 file = fmt.Sprintf("%s/%s.a", dir, name)
625 if _, err := os.Stat(file); err == nil {
628 file = fmt.Sprintf("%s/%s.o", dir, name)
629 if _, err := os.Stat(file); err == nil {
637 if flag_installsuffix != "" {
639 suffix = flag_installsuffix
640 } else if flag_race != 0 {
643 } else if flag_msan != 0 {
648 file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", goroot, goos, goarch, suffixsep, suffix, name)
649 if _, err := os.Stat(file); err == nil {
652 file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.o", goroot, goos, goarch, suffixsep, suffix, name)
653 if _, err := os.Stat(file); err == nil {
661 // loadsys loads the definitions for the low-level runtime and unsafe functions,
662 // so that the compiler can generate calls to them,
663 // but does not make the names "runtime" or "unsafe" visible as packages.
673 importpkg = Runtimepkg
674 parse_import(obj.Binitr(strings.NewReader(runtimeimport)), nil)
676 importpkg = unsafepkg
677 parse_import(obj.Binitr(strings.NewReader(unsafeimport)), nil)
683 func importfile(f *Val, indent []byte) {
684 if importpkg != nil {
685 Fatalf("importpkg not nil")
688 path_, ok := f.U.(string)
690 Yyerror("import statement not a string")
695 Yyerror("import path is empty")
699 if isbadimport(path_) {
703 // The package name main is no longer reserved,
704 // but we reserve the import path "main" to identify
705 // the main package, just as we reserve the import
706 // path "math" to identify the standard math package.
708 Yyerror("cannot import \"main\"")
712 if myimportpath != "" && path_ == myimportpath {
713 Yyerror("import %q while compiling that package (import cycle)", path_)
717 if mapped, ok := importMap[path_]; ok {
721 if path_ == "unsafe" {
723 Yyerror("cannot import package unsafe")
727 importpkg = unsafepkg
728 imported_unsafe = true
732 if islocalname(path_) {
734 Yyerror("import path cannot be absolute path")
738 prefix := Ctxt.Pathname
739 if localimport != "" {
742 path_ = path.Join(prefix, path_)
744 if isbadimport(path_) {
749 file, found := findpkg(path_)
751 Yyerror("can't find import: %q", path_)
755 importpkg = mkpkg(path_)
757 if importpkg.Imported {
761 importpkg.Imported = true
763 imp, err := obj.Bopenr(file)
765 Yyerror("can't open import: %q: %v", path_, err)
770 if strings.HasSuffix(file, ".a") {
771 if !skiptopkgdef(imp) {
772 Yyerror("import %s: not a package file", file)
777 // check object header
778 p := obj.Brdstr(imp, '\n', 1)
780 if p != "empty archive" {
781 if !strings.HasPrefix(p, "go object ") {
782 Yyerror("import %s: not a go object file", file)
786 q := fmt.Sprintf("%s %s %s %s", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring())
788 Yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q)
793 // assume files move (get installed)
794 // so don't record the full path.
795 linehistpragma(file[len(file)-len(path_)-2:]) // acts as #pragma lib
797 // In the importfile, if we find:
798 // $$\n (old format): position the input right after $$\n and return
799 // $$B\n (new format): import directly, then feed the lexer a dummy statement
810 if c == '$' || c < 0 {
816 // get character after $$
824 parse_import(imp, indent)
828 obj.Bgetc(imp) // skip \n after $$B
832 Yyerror("no import in %q", path_)
836 if safemode != 0 && !importpkg.Safe {
837 Yyerror("cannot import unsafe package %q", importpkg.Path)
841 func isSpace(c rune) bool {
842 return c == ' ' || c == '\t' || c == '\n' || c == '\r'
845 func isLetter(c rune) bool {
846 return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_'
849 func isDigit(c rune) bool {
850 return '0' <= c && c <= '9'
853 func plan9quote(s string) string {
857 for _, c := range s {
858 if c <= ' ' || c == '\'' {
859 return "'" + strings.Replace(s, "'", "''", -1) + "'"
868 Nointerface Pragma = 1 << iota
869 Noescape // func parameters don't escape
870 Norace // func must not have race detector annotations
871 Nosplit // func should not execute on separate stack
872 Noinline // func should not be inlined
873 Systemstack // func must run on system stack
874 Nowritebarrier // emit compiler error instead of write barrier
875 Nowritebarrierrec // error on write barrier in this or recursive callees
882 peekr2 rune // second peekc for ...
884 nlsemi bool // if set, '\n' and EOF translate to ';'
887 // accumulated by lexer; reset by parser
892 sym_ *Sym // valid if tok == LNAME
893 val Val // valid if tok == LLITERAL
894 op Op // valid if tok == LASOP or LINCOP, or prec > 0
895 prec OpPrec // operator precedence; 0 if not a binary operator
901 // Precedences of binary operators (must be > 0).
902 PCOMM OpPrec = 1 + iota
911 // The value of single-char tokens is just their character's Unicode value.
912 // They are all below utf8.RuneSelf. Shift other tokens up to avoid conflicts.
913 LLITERAL = utf8.RuneSelf + iota
959 func (l *lexer) next() {
968 if c == '\n' && nlsemi {
970 fmt.Printf("lex: implicit semi\n")
972 // Insert implicit semicolon on previous line,
973 // before the newline character.
974 lineno = lexlineno - 1
984 // identifiers and keywords
985 // (for better error messages consume all chars >= utf8.RuneSelf for identifiers)
986 if isLetter(c) || c >= utf8.RuneSelf {
988 if l.tok == LIGNORE {
1001 l.ungetr(EOF) // return EOF again in future next call
1002 // Treat EOF as "end of line" for the purposes
1003 // of inserting a semicolon.
1005 if Debug['x'] != 0 {
1006 fmt.Printf("lex: implicit semi\n")
1014 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
1062 Yyerror("eof in comment")
1068 // A comment containing newlines acts like a newline.
1069 if lexlineno > lineno && nlsemi {
1070 if Debug['x'] != 0 {
1071 fmt.Printf("lex: implicit semi\n")
1080 c = l.getlinepragma()
1082 if c == '\n' || c == EOF {
1149 // Not a binary operator, but parsed as one
1150 // so we can give a good error message when used
1151 // in an expression context.
1222 case '(', '[', '{', ',', ';':
1229 case '#', '$', '?', '@', '\\':
1230 if importpkg != nil {
1236 // anything else is illegal
1237 Yyerror("syntax error: illegal character %#U", c)
1244 if Debug['x'] != 0 {
1245 if c >= utf8.RuneSelf {
1246 fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lineno)), lexname(c))
1248 fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lineno)), c)
1277 if Debug['x'] != 0 {
1278 fmt.Printf("lex: TOKEN ASOP %s=\n", goopnames[op])
1283 func (l *lexer) ident(c rune) {
1287 // accelerate common case (7bit ASCII)
1288 for isLetter(c) || isDigit(c) {
1289 cp.WriteByte(byte(c))
1295 if c >= utf8.RuneSelf {
1296 if unicode.IsLetter(c) || c == '_' || unicode.IsDigit(c) || importpkg != nil && c == 0xb7 {
1297 if cp.Len() == 0 && unicode.IsDigit(c) {
1298 Yyerror("identifier cannot begin with digit %#U", c)
1301 Yyerror("invalid identifier character %#U", c)
1304 } else if isLetter(c) || isDigit(c) {
1305 cp.WriteByte(byte(c))
1315 name := lexbuf.Bytes()
1318 if tok, ok := keywords[string(name)]; ok {
1319 if Debug['x'] != 0 {
1320 fmt.Printf("lex: %s\n", lexname(tok))
1323 case LBREAK, LCONTINUE, LFALL, LRETURN:
1331 s := LookupBytes(name)
1332 if Debug['x'] != 0 {
1333 fmt.Printf("lex: ident %s\n", s)
1340 var keywords = map[string]int32{
1345 "continue": LCONTINUE,
1346 "default": LDEFAULT,
1349 "fallthrough": LFALL,
1356 "interface": LINTERFACE,
1358 "package": LPACKAGE,
1368 "notwithstanding": LIGNORE,
1369 "thetruthofthematter": LIGNORE,
1370 "despiteallobjections": LIGNORE,
1372 "insofaras": LIGNORE,
1375 func (l *lexer) number(c rune) {
1376 // TODO(gri) this can be done nicely with fewer or even without labels
1385 cp.WriteByte(byte(c))
1391 if c == 'e' || c == 'E' || c == 'p' || c == 'P' {
1403 if c == 'x' || c == 'X' {
1404 cp.WriteByte(byte(c))
1406 for isDigit(c) || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
1407 cp.WriteByte(byte(c))
1410 if lexbuf.Len() == 2 {
1411 Yyerror("malformed hex constant")
1419 if c == 'p' { // 0p begins floating point zero
1428 cp.WriteByte(byte(c))
1434 if c == 'e' || c == 'E' {
1441 Yyerror("malformed octal constant")
1452 cp.WriteByte(byte(c))
1458 if c != 'e' && c != 'E' {
1461 // base-2-exponents (p or P) don't appear in numbers
1462 // with fractions - ok to not test for 'p' or 'P'
1467 if importpkg == nil && (c == 'p' || c == 'P') {
1468 // <mantissa>p<base-2-exponent> is allowed in .a/.o imports,
1469 // but not in .go sources. See #9036.
1470 Yyerror("malformed floating point constant")
1472 cp.WriteByte(byte(c))
1474 if c == '+' || c == '-' {
1475 cp.WriteByte(byte(c))
1480 Yyerror("malformed floating point constant exponent")
1483 cp.WriteByte(byte(c))
1492 // imaginary constant
1495 str = lexbuf.String()
1496 l.val.U = new(Mpcplx)
1497 Mpmovecflt(&l.val.U.(*Mpcplx).Real, 0.0)
1498 mpatoflt(&l.val.U.(*Mpcplx).Imag, str)
1499 if l.val.U.(*Mpcplx).Imag.Val.IsInf() {
1500 Yyerror("overflow in imaginary constant")
1501 Mpmovecflt(&l.val.U.(*Mpcplx).Imag, 0.0)
1504 if Debug['x'] != 0 {
1505 fmt.Printf("lex: imaginary literal\n")
1513 str = lexbuf.String()
1514 l.val.U = newMpflt()
1515 mpatoflt(l.val.U.(*Mpflt), str)
1516 if l.val.U.(*Mpflt).Val.IsInf() {
1517 Yyerror("overflow in float constant")
1518 Mpmovecflt(l.val.U.(*Mpflt), 0.0)
1521 if Debug['x'] != 0 {
1522 fmt.Printf("lex: floating literal\n")
1530 str = lexbuf.String()
1531 l.val.U = new(Mpint)
1532 mpatofix(l.val.U.(*Mpint), str)
1533 if l.val.U.(*Mpint).Ovf {
1534 Yyerror("overflow in constant")
1535 Mpmovecfix(l.val.U.(*Mpint), 0)
1538 if Debug['x'] != 0 {
1539 fmt.Printf("lex: integer literal\n")
1543 litbuf = "literal " + str
1548 func (l *lexer) stdString() {
1550 lexbuf.WriteString(`"<string>"`)
1556 r, b, ok := l.onechar('"')
1567 l.val.U = internString(cp.Bytes())
1568 if Debug['x'] != 0 {
1569 fmt.Printf("lex: string literal\n")
1571 litbuf = "string literal"
1576 func (l *lexer) rawString() {
1578 lexbuf.WriteString("`<string>`")
1589 Yyerror("eof in string")
1598 l.val.U = internString(cp.Bytes())
1599 if Debug['x'] != 0 {
1600 fmt.Printf("lex: string literal\n")
1602 litbuf = "string literal"
1607 func (l *lexer) rune() {
1608 r, b, ok := l.onechar('\'')
1610 Yyerror("empty character literal or unescaped ' in character literal")
1617 if c := l.getr(); c != '\'' {
1618 Yyerror("missing '")
1624 Mpmovecfix(x, int64(r))
1626 if Debug['x'] != 0 {
1627 fmt.Printf("lex: codepoint literal\n")
1629 litbuf = "rune literal"
1634 var internedStrings = map[string]string{}
1636 func internString(b []byte) string {
1637 s, ok := internedStrings[string(b)] // string(b) here doesn't allocate
1640 internedStrings[s] = s
1645 func more(pp *string) bool {
1647 for p != "" && isSpace(rune(p[0])) {
1654 // read and interpret syntax that looks like
1655 // //line parse.y:15
1656 // as a discontinuity in sequential line numbers.
1657 // the next line of input comes from parse.y:15
1658 func (l *lexer) getlinepragma() rune {
1660 if c == 'g' { // check for //go: directive
1663 cp.WriteByte('g') // already read
1666 if c == EOF || c >= utf8.RuneSelf {
1672 cp.WriteByte(byte(c))
1676 text := strings.TrimSuffix(lexbuf.String(), "\r")
1678 if strings.HasPrefix(text, "go:cgo_") {
1683 if i := strings.Index(text, " "); i >= 0 {
1689 if !imported_unsafe {
1690 Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"")
1692 f := strings.Fields(text)
1694 Yyerror("usage: //go:linkname localname linkname")
1697 Lookup(f[1]).Linkname = f[2]
1698 case "go:nointerface":
1699 if obj.Fieldtrack_enabled != 0 {
1700 l.pragma |= Nointerface
1703 l.pragma |= Noescape
1709 l.pragma |= Noinline
1710 case "go:systemstack":
1711 if compiling_runtime == 0 {
1712 Yyerror("//go:systemstack only allowed in runtime")
1714 l.pragma |= Systemstack
1715 case "go:nowritebarrier":
1716 if compiling_runtime == 0 {
1717 Yyerror("//go:nowritebarrier only allowed in runtime")
1719 l.pragma |= Nowritebarrier
1720 case "go:nowritebarrierrec":
1721 if compiling_runtime == 0 {
1722 Yyerror("//go:nowritebarrierrec only allowed in runtime")
1724 l.pragma |= Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier
1729 // check for //line directive
1733 for i := 1; i < 5; i++ {
1735 if c != rune("line "[i]) {
1755 linep = cp.Len() + 1
1757 cp.WriteByte(byte(c))
1764 text := strings.TrimSuffix(lexbuf.String(), "\r")
1765 n, err := strconv.Atoi(text[linep:])
1767 return c // todo: make this an error instead? it is almost certainly a bug.
1770 Yyerror("line number out of range")
1777 linehistupdate(text[:linep-1], n)
1781 func getimpsym(pp *string) string {
1782 more(pp) // skip spaces
1784 if p == "" || p[0] == '"' {
1788 for i < len(p) && !isSpace(rune(p[i])) && p[i] != '"' {
1796 func getquoted(pp *string) (string, bool) {
1797 more(pp) // skip spaces
1799 if p == "" || p[0] != '"' {
1803 i := strings.Index(p, `"`)
1811 // Copied nearly verbatim from the C compiler's #pragma parser.
1812 // TODO: Rewrite more cleanly once the compiler is written in Go.
1813 func pragcgo(text string) {
1816 if i := strings.Index(text, " "); i >= 0 {
1817 text, q = text[:i], text[i:]
1820 verb := text[3:] // skip "go:"
1822 if verb == "cgo_dynamic_linker" || verb == "dynlinker" {
1823 p, ok := getquoted(&q)
1825 Yyerror("usage: //go:cgo_dynamic_linker \"path\"")
1828 pragcgobuf += fmt.Sprintf("cgo_dynamic_linker %v\n", plan9quote(p))
1833 if verb == "dynexport" {
1834 verb = "cgo_export_dynamic"
1836 if verb == "cgo_export_static" || verb == "cgo_export_dynamic" {
1837 local := getimpsym(&q)
1843 pragcgobuf += fmt.Sprintf("%s %v\n", verb, plan9quote(local))
1847 remote = getimpsym(&q)
1851 pragcgobuf += fmt.Sprintf("%s %v %v\n", verb, plan9quote(local), plan9quote(remote))
1855 Yyerror("usage: //go:%s local [remote]", verb)
1859 if verb == "cgo_import_dynamic" || verb == "dynimport" {
1861 local := getimpsym(&q)
1868 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v\n", plan9quote(local))
1872 remote = getimpsym(&q)
1877 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v\n", plan9quote(local), plan9quote(remote))
1881 p, ok = getquoted(&q)
1885 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v %v\n", plan9quote(local), plan9quote(remote), plan9quote(p))
1889 Yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]")
1893 if verb == "cgo_import_static" {
1894 local := getimpsym(&q)
1895 if local == "" || more(&q) {
1896 Yyerror("usage: //go:cgo_import_static local")
1899 pragcgobuf += fmt.Sprintf("cgo_import_static %v\n", plan9quote(local))
1904 if verb == "cgo_ldflag" {
1905 p, ok := getquoted(&q)
1907 Yyerror("usage: //go:cgo_ldflag \"arg\"")
1910 pragcgobuf += fmt.Sprintf("cgo_ldflag %v\n", plan9quote(p))
1916 func (l *lexer) getr() rune {
1917 // unread rune != 0 available
1918 if r := l.peekr1; r != 0 {
1921 if r == '\n' && importpkg == nil {
1928 // common case: 7bit ASCII
1929 c := obj.Bgetc(l.bin)
1930 if c < utf8.RuneSelf {
1932 yyerrorl(int(lexlineno), "illegal NUL byte")
1935 if c == '\n' && importpkg == nil {
1940 // c >= utf8.RuneSelf
1942 // uncommon case: non-ASCII
1943 var buf [utf8.UTFMax]byte
1945 buf[1] = byte(obj.Bgetc(l.bin))
1947 for ; i < len(buf) && !utf8.FullRune(buf[:i]); i++ {
1948 buf[i] = byte(obj.Bgetc(l.bin))
1951 r, w := utf8.DecodeRune(buf[:i])
1952 if r == utf8.RuneError && w == 1 {
1953 // The string conversion here makes a copy for passing
1954 // to fmt.Printf, so that buf itself does not escape and
1955 // can be allocated on the stack.
1956 yyerrorl(int(lexlineno), "illegal UTF-8 sequence % x", string(buf[:i]))
1960 yyerrorl(int(lexlineno), "Unicode (UTF-8) BOM in middle of file")
1967 func (l *lexer) ungetr(r rune) {
1970 if r == '\n' && importpkg == nil {
1975 // onechar lexes a single character within a rune or interpreted string literal,
1976 // handling escape sequences as necessary.
1977 func (l *lexer) onechar(quote rune) (r rune, b byte, ok bool) {
1981 Yyerror("eof in string")
1986 Yyerror("newline in string")
2003 return 0, byte(l.hexchar(2)), true
2006 return l.unichar(4), 0, true
2009 return l.unichar(8), 0, true
2011 case '0', '1', '2', '3', '4', '5', '6', '7':
2013 for i := 2; i > 0; i-- {
2015 if c >= '0' && c <= '7' {
2020 Yyerror("non-octal character in escape sequence: %c", c)
2025 Yyerror("octal escape value > 255: %d", x)
2028 return 0, byte(x), true
2049 Yyerror("unknown escape sequence: %c", c)
2056 func (l *lexer) unichar(n int) rune {
2058 if x > utf8.MaxRune || 0xd800 <= x && x < 0xe000 {
2059 Yyerror("invalid Unicode code point in escape sequence: %#x", x)
2065 func (l *lexer) hexchar(n int) uint32 {
2070 switch c := l.getr(); {
2073 case 'a' <= c && c <= 'f':
2074 d = uint32(c - 'a' + 10)
2075 case 'A' <= c && c <= 'F':
2076 d = uint32(c - 'A' + 10)
2078 Yyerror("non-hex character in escape sequence: %c", c)
2088 var basicTypes = [...]struct {
2097 {"uint16", TUINT16},
2098 {"uint32", TUINT32},
2099 {"uint64", TUINT64},
2100 {"float32", TFLOAT32},
2101 {"float64", TFLOAT64},
2102 {"complex64", TCOMPLEX64},
2103 {"complex128", TCOMPLEX128},
2105 {"string", TSTRING},
2109 var builtinFuncs = [...]struct {
2113 {"append", OAPPEND},
2116 {"complex", OCOMPLEX},
2118 {"delete", ODELETE},
2125 {"println", OPRINTN},
2127 {"recover", ORECOVER},
2130 // lexinit initializes known symbols and the basic types.
2132 for _, s := range basicTypes {
2134 if int(etype) >= len(Types) {
2135 Fatalf("lexinit: %s bad etype", s.name)
2137 s2 := Pkglookup(s.name, builtinpkg)
2142 if etype != TANY && etype != TSTRING {
2148 s2.Def.Name = new(Name)
2151 for _, s := range builtinFuncs {
2152 // TODO(marvin): Fix Node.EType type union.
2153 s2 := Pkglookup(s.name, builtinpkg)
2154 s2.Def = Nod(ONAME, nil, nil)
2156 s2.Def.Etype = EType(s.op)
2159 // logically, the type of a string literal.
2160 // types[TSTRING] is the named type string
2161 // (the type of x in var x string or var x = "hello").
2162 // this is the ideal form
2163 // (the type of x in const x = "hello").
2164 idealstring = typ(TSTRING)
2166 idealbool = typ(TBOOL)
2168 s := Pkglookup("true", builtinpkg)
2169 s.Def = Nodbool(true)
2170 s.Def.Sym = Lookup("true")
2171 s.Def.Name = new(Name)
2172 s.Def.Type = idealbool
2174 s = Pkglookup("false", builtinpkg)
2175 s.Def = Nodbool(false)
2176 s.Def.Sym = Lookup("false")
2177 s.Def.Name = new(Name)
2178 s.Def.Type = idealbool
2182 s.Def = Nod(ONAME, nil, nil)
2184 Types[TBLANK] = typ(TBLANK)
2185 s.Def.Type = Types[TBLANK]
2188 s = Pkglookup("_", builtinpkg)
2190 s.Def = Nod(ONAME, nil, nil)
2192 Types[TBLANK] = typ(TBLANK)
2193 s.Def.Type = Types[TBLANK]
2195 Types[TNIL] = typ(TNIL)
2196 s = Pkglookup("nil", builtinpkg)
2201 s.Def.Name = new(Name)
2203 s = Pkglookup("iota", builtinpkg)
2204 s.Def = Nod(OIOTA, nil, nil)
2206 s.Def.Name = new(Name)
2210 // t = interface { Error() string }
2211 rcvr := typ(TSTRUCT)
2213 rcvr.Type = typ(TFIELD)
2214 rcvr.Type.Type = Ptrto(typ(TSTRUCT))
2219 out.Type = typ(TFIELD)
2220 out.Type.Type = Types[TSTRING]
2231 t.Type = typ(TFIELD)
2232 t.Type.Sym = Lookup("Error")
2236 s := Pkglookup("error", builtinpkg)
2239 s.Def = typenod(errortype)
2242 s = Pkglookup("byte", builtinpkg)
2243 bytetype = typ(TUINT8)
2245 s.Def = typenod(bytetype)
2246 s.Def.Name = new(Name)
2249 s = Pkglookup("rune", builtinpkg)
2250 runetype = typ(TINT32)
2252 s.Def = typenod(runetype)
2253 s.Def.Name = new(Name)
2255 // backend-specific builtin types (e.g. int).
2256 for i := range Thearch.Typedefs {
2257 s := Pkglookup(Thearch.Typedefs[i].Name, builtinpkg)
2258 s.Def = typenod(Types[Thearch.Typedefs[i].Etype])
2259 s.Def.Name = new(Name)
2260 s.Origpkg = builtinpkg
2265 for _, s := range builtinpkg.Syms {
2269 s1 := Lookup(s.Name)
2278 nodfp = Nod(ONAME, nil, nil)
2279 nodfp.Type = Types[TINT32]
2281 nodfp.Class = PPARAM
2282 nodfp.Sym = Lookup(".fp")
2285 var lexn = map[rune]string{
2295 LCONTINUE: "CONTINUE",
2297 LDEFAULT: "DEFAULT",
2311 LINTERFACE: "INTERFACE",
2313 LLITERAL: "LITERAL",
2320 LPACKAGE: "PACKAGE",
2331 func lexname(lex rune) string {
2332 if s, ok := lexn[lex]; ok {
2335 return fmt.Sprintf("LEX-%d", lex)
2338 func pkgnotused(lineno int, path string, name string) {
2339 // If the package was imported with a name other than the final
2340 // import path element, show it explicitly in the error message.
2341 // Note that this handles both renamed imports and imports of
2342 // packages containing unconventional package declarations.
2343 // Note that this uses / always, even on Windows, because Go import
2344 // paths always use forward slashes.
2346 if i := strings.LastIndex(elem, "/"); i >= 0 {
2349 if name == "" || elem == name {
2350 yyerrorl(int(lineno), "imported and not used: %q", path)
2352 yyerrorl(int(lineno), "imported and not used: %q as %s", path, name)
2356 func mkpackage(pkgname string) {
2357 if localpkg.Name == "" {
2359 Yyerror("invalid package name _")
2361 localpkg.Name = pkgname
2363 if pkgname != localpkg.Name {
2364 Yyerror("package %s; expected %s", pkgname, localpkg.Name)
2366 for _, s := range localpkg.Syms {
2370 if s.Def.Op == OPACK {
2371 // throw away top-level package name leftover
2372 // from previous file.
2373 // leave s->block set to cause redeclaration
2374 // errors if a conflicting top-level name is
2375 // introduced by a different file.
2376 if !s.Def.Used && nsyntaxerrors == 0 {
2377 pkgnotused(int(s.Def.Lineno), s.Def.Name.Pkg.Path, s.Name)
2384 // throw away top-level name left over
2385 // from previous import . "x"
2386 if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {
2387 pkgnotused(int(s.Def.Name.Pack.Lineno), s.Def.Name.Pack.Name.Pkg.Path, "")
2388 s.Def.Name.Pack.Used = true
2399 if i := strings.LastIndex(p, "/"); i >= 0 {
2402 if Ctxt.Windows != 0 {
2403 if i := strings.LastIndex(p, `\`); i >= 0 {
2407 if i := strings.LastIndex(p, "."); i >= 0 {
2411 if writearchive > 0 {
2414 outfile = p + suffix