2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
2015-02-24 12:19:01 -05:00
|
|
|
//go:generate go tool yacc go.y
|
2015-03-09 17:40:23 -07:00
|
|
|
//go:generate go run yaccerrors.go
|
2015-02-27 17:40:34 +09:00
|
|
|
//go:generate go run mkbuiltin.go runtime unsafe
|
2015-02-24 12:19:01 -05:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
package gc
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"cmd/internal/obj"
|
|
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"log"
|
|
|
|
|
"os"
|
|
|
|
|
"path"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"unicode"
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var yyprev int
|
|
|
|
|
|
|
|
|
|
var yylast int
|
|
|
|
|
|
|
|
|
|
var imported_unsafe int
|
|
|
|
|
|
|
|
|
|
var goos string
|
|
|
|
|
|
|
|
|
|
var goarch string
|
|
|
|
|
|
|
|
|
|
var goroot string
|
|
|
|
|
|
cmd/internal/gc: optimize append + write barrier
The code generated for x = append(x, v) is roughly:
t := x
if len(t)+1 > cap(t) {
t = grow(t)
}
t[len(t)] = v
len(t)++
x = t
We used to generate this code as Go pseudocode during walk.
Generate it instead as actual instructions during gen.
Doing so lets us apply a few optimizations. The most important
is that when, as in the above example, the source slice and the
destination slice are the same, the code can instead do:
t := x
if len(t)+1 > cap(t) {
t = grow(t)
x = {base(t), len(t)+1, cap(t)}
} else {
len(x)++
}
t[len(t)] = v
That is, in the fast path that does not reallocate the array,
only the updated length needs to be written back to x,
not the array pointer and not the capacity. This is more like
what you'd write by hand in C. It's faster in general, since
the fast path elides two of the three stores, but it's especially
faster when the form of x is such that the base pointer write
would turn into a write barrier. No write, no barrier.
name old mean new mean delta
BinaryTree17 5.68s × (0.97,1.04) 5.81s × (0.98,1.03) +2.35% (p=0.023)
Fannkuch11 4.41s × (0.98,1.03) 4.35s × (1.00,1.00) ~ (p=0.090)
FmtFprintfEmpty 92.7ns × (0.91,1.16) 86.0ns × (0.94,1.11) -7.31% (p=0.038)
FmtFprintfString 281ns × (0.96,1.08) 276ns × (0.98,1.04) ~ (p=0.219)
FmtFprintfInt 288ns × (0.97,1.06) 274ns × (0.98,1.06) -4.94% (p=0.002)
FmtFprintfIntInt 493ns × (0.97,1.04) 506ns × (0.99,1.01) +2.65% (p=0.009)
FmtFprintfPrefixedInt 423ns × (0.97,1.04) 391ns × (0.99,1.01) -7.52% (p=0.000)
FmtFprintfFloat 598ns × (0.99,1.01) 566ns × (0.99,1.01) -5.27% (p=0.000)
FmtManyArgs 1.89µs × (0.98,1.05) 1.91µs × (0.99,1.01) ~ (p=0.231)
GobDecode 14.8ms × (0.98,1.03) 15.3ms × (0.99,1.02) +3.01% (p=0.000)
GobEncode 12.3ms × (0.98,1.01) 11.5ms × (0.97,1.03) -5.93% (p=0.000)
Gzip 656ms × (0.99,1.05) 645ms × (0.99,1.01) ~ (p=0.055)
Gunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) -0.32% (p=0.034)
HTTPClientServer 91.2µs × (0.97,1.04) 90.5µs × (0.97,1.04) ~ (p=0.468)
JSONEncode 32.6ms × (0.97,1.08) 32.0ms × (0.98,1.03) ~ (p=0.190)
JSONDecode 114ms × (0.97,1.05) 114ms × (0.99,1.01) ~ (p=0.887)
Mandelbrot200 6.11ms × (0.98,1.04) 6.04ms × (1.00,1.01) ~ (p=0.167)
GoParse 6.66ms × (0.97,1.04) 6.47ms × (0.97,1.05) -2.81% (p=0.014)
RegexpMatchEasy0_32 159ns × (0.99,1.00) 171ns × (0.93,1.07) +7.19% (p=0.002)
RegexpMatchEasy0_1K 538ns × (1.00,1.01) 550ns × (0.98,1.01) +2.30% (p=0.000)
RegexpMatchEasy1_32 138ns × (1.00,1.00) 135ns × (0.99,1.02) -1.60% (p=0.000)
RegexpMatchEasy1_1K 869ns × (0.99,1.01) 879ns × (1.00,1.01) +1.08% (p=0.000)
RegexpMatchMedium_32 252ns × (0.99,1.01) 243ns × (1.00,1.00) -3.71% (p=0.000)
RegexpMatchMedium_1K 72.7µs × (1.00,1.00) 70.3µs × (1.00,1.00) -3.34% (p=0.000)
RegexpMatchHard_32 3.85µs × (1.00,1.00) 3.82µs × (1.00,1.01) -0.81% (p=0.000)
RegexpMatchHard_1K 118µs × (1.00,1.00) 117µs × (1.00,1.00) -0.56% (p=0.000)
Revcomp 920ms × (0.97,1.07) 917ms × (0.97,1.04) ~ (p=0.808)
Template 129ms × (0.98,1.03) 114ms × (0.99,1.01) -12.06% (p=0.000)
TimeParse 619ns × (0.99,1.01) 622ns × (0.99,1.01) ~ (p=0.062)
TimeFormat 661ns × (0.98,1.04) 665ns × (0.99,1.01) ~ (p=0.524)
See next CL for combination with a similar optimization for slice.
The benchmarks that are slower in this CL are still faster overall
with the combination of the two.
Change-Id: I2a7421658091b2488c64741b4db15ab6c3b4cb7e
Reviewed-on: https://go-review.googlesource.com/9812
Reviewed-by: David Chase <drchase@google.com>
2015-05-06 12:34:30 -04:00
|
|
|
var (
|
|
|
|
|
Debug_wb int
|
|
|
|
|
Debug_append int
|
|
|
|
|
)
|
2015-04-17 00:34:18 -04:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Debug arguments.
|
|
|
|
|
// These can be specified with the -d flag, as in "-d nil"
|
|
|
|
|
// to set the debug_checknil variable. In general the list passed
|
|
|
|
|
// to -d can be comma-separated.
|
|
|
|
|
var debugtab = []struct {
|
|
|
|
|
name string
|
|
|
|
|
val *int
|
2015-03-08 18:46:28 -04:00
|
|
|
}{
|
2015-03-20 00:06:10 -04:00
|
|
|
{"nil", &Debug_checknil}, // print information about nil checks
|
|
|
|
|
{"typeassert", &Debug_typeassert}, // print information about type assertion inlining
|
|
|
|
|
{"disablenil", &Disable_checknil}, // disable nil checks
|
2015-04-17 00:34:18 -04:00
|
|
|
{"wb", &Debug_wb}, // print information about write barriers
|
cmd/internal/gc: optimize append + write barrier
The code generated for x = append(x, v) is roughly:
t := x
if len(t)+1 > cap(t) {
t = grow(t)
}
t[len(t)] = v
len(t)++
x = t
We used to generate this code as Go pseudocode during walk.
Generate it instead as actual instructions during gen.
Doing so lets us apply a few optimizations. The most important
is that when, as in the above example, the source slice and the
destination slice are the same, the code can instead do:
t := x
if len(t)+1 > cap(t) {
t = grow(t)
x = {base(t), len(t)+1, cap(t)}
} else {
len(x)++
}
t[len(t)] = v
That is, in the fast path that does not reallocate the array,
only the updated length needs to be written back to x,
not the array pointer and not the capacity. This is more like
what you'd write by hand in C. It's faster in general, since
the fast path elides two of the three stores, but it's especially
faster when the form of x is such that the base pointer write
would turn into a write barrier. No write, no barrier.
name old mean new mean delta
BinaryTree17 5.68s × (0.97,1.04) 5.81s × (0.98,1.03) +2.35% (p=0.023)
Fannkuch11 4.41s × (0.98,1.03) 4.35s × (1.00,1.00) ~ (p=0.090)
FmtFprintfEmpty 92.7ns × (0.91,1.16) 86.0ns × (0.94,1.11) -7.31% (p=0.038)
FmtFprintfString 281ns × (0.96,1.08) 276ns × (0.98,1.04) ~ (p=0.219)
FmtFprintfInt 288ns × (0.97,1.06) 274ns × (0.98,1.06) -4.94% (p=0.002)
FmtFprintfIntInt 493ns × (0.97,1.04) 506ns × (0.99,1.01) +2.65% (p=0.009)
FmtFprintfPrefixedInt 423ns × (0.97,1.04) 391ns × (0.99,1.01) -7.52% (p=0.000)
FmtFprintfFloat 598ns × (0.99,1.01) 566ns × (0.99,1.01) -5.27% (p=0.000)
FmtManyArgs 1.89µs × (0.98,1.05) 1.91µs × (0.99,1.01) ~ (p=0.231)
GobDecode 14.8ms × (0.98,1.03) 15.3ms × (0.99,1.02) +3.01% (p=0.000)
GobEncode 12.3ms × (0.98,1.01) 11.5ms × (0.97,1.03) -5.93% (p=0.000)
Gzip 656ms × (0.99,1.05) 645ms × (0.99,1.01) ~ (p=0.055)
Gunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) -0.32% (p=0.034)
HTTPClientServer 91.2µs × (0.97,1.04) 90.5µs × (0.97,1.04) ~ (p=0.468)
JSONEncode 32.6ms × (0.97,1.08) 32.0ms × (0.98,1.03) ~ (p=0.190)
JSONDecode 114ms × (0.97,1.05) 114ms × (0.99,1.01) ~ (p=0.887)
Mandelbrot200 6.11ms × (0.98,1.04) 6.04ms × (1.00,1.01) ~ (p=0.167)
GoParse 6.66ms × (0.97,1.04) 6.47ms × (0.97,1.05) -2.81% (p=0.014)
RegexpMatchEasy0_32 159ns × (0.99,1.00) 171ns × (0.93,1.07) +7.19% (p=0.002)
RegexpMatchEasy0_1K 538ns × (1.00,1.01) 550ns × (0.98,1.01) +2.30% (p=0.000)
RegexpMatchEasy1_32 138ns × (1.00,1.00) 135ns × (0.99,1.02) -1.60% (p=0.000)
RegexpMatchEasy1_1K 869ns × (0.99,1.01) 879ns × (1.00,1.01) +1.08% (p=0.000)
RegexpMatchMedium_32 252ns × (0.99,1.01) 243ns × (1.00,1.00) -3.71% (p=0.000)
RegexpMatchMedium_1K 72.7µs × (1.00,1.00) 70.3µs × (1.00,1.00) -3.34% (p=0.000)
RegexpMatchHard_32 3.85µs × (1.00,1.00) 3.82µs × (1.00,1.01) -0.81% (p=0.000)
RegexpMatchHard_1K 118µs × (1.00,1.00) 117µs × (1.00,1.00) -0.56% (p=0.000)
Revcomp 920ms × (0.97,1.07) 917ms × (0.97,1.04) ~ (p=0.808)
Template 129ms × (0.98,1.03) 114ms × (0.99,1.01) -12.06% (p=0.000)
TimeParse 619ns × (0.99,1.01) 622ns × (0.99,1.01) ~ (p=0.062)
TimeFormat 661ns × (0.98,1.04) 665ns × (0.99,1.01) ~ (p=0.524)
See next CL for combination with a similar optimization for slice.
The benchmarks that are slower in this CL are still faster overall
with the combination of the two.
Change-Id: I2a7421658091b2488c64741b4db15ab6c3b4cb7e
Reviewed-on: https://go-review.googlesource.com/9812
Reviewed-by: David Chase <drchase@google.com>
2015-05-06 12:34:30 -04:00
|
|
|
{"append", &Debug_append}, // print information about append compilation
|
2015-03-08 18:46:28 -04:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// Our own isdigit, isspace, isalpha, isalnum that take care
|
|
|
|
|
// of EOF and other out of range arguments.
|
|
|
|
|
func yy_isdigit(c int) bool {
|
|
|
|
|
return c >= 0 && c <= 0xFF && isdigit(c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func yy_isspace(c int) bool {
|
|
|
|
|
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func yy_isalpha(c int) bool {
|
|
|
|
|
return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func yy_isalnum(c int) bool {
|
|
|
|
|
return c >= 0 && c <= 0xFF && isalnum(c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Disallow use of isdigit etc.
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
EOF = -1
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func usage() {
|
|
|
|
|
fmt.Printf("usage: %cg [options] file.go...\n", Thearch.Thechar)
|
|
|
|
|
obj.Flagprint(1)
|
2015-02-23 10:22:26 -05:00
|
|
|
Exit(2)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 14:02:27 -05:00
|
|
|
func hidePanic() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if nsavederrors+nerrors > 0 {
|
2015-02-23 14:02:27 -05:00
|
|
|
// If we've already complained about things
|
|
|
|
|
// in the program, don't bother complaining
|
|
|
|
|
// about a panic too; let the user clean up
|
|
|
|
|
// the code and try again.
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func doversion() {
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Expstring()
|
2015-02-13 14:40:36 -05:00
|
|
|
if p == "X:none" {
|
|
|
|
|
p = ""
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
sep := ""
|
2015-02-23 14:02:27 -05:00
|
|
|
if p != "" {
|
2015-02-13 14:40:36 -05:00
|
|
|
sep = " "
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("%cg version %s%s%s\n", Thearch.Thechar, obj.Getgoversion(), sep, p)
|
|
|
|
|
os.Exit(0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Main() {
|
2015-02-23 14:02:27 -05:00
|
|
|
defer hidePanic()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// Allow GOARCH=thearch.thestring or GOARCH=thearch.thestringsuffix,
|
|
|
|
|
// but not other values.
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Getgoarch()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if !strings.HasPrefix(p, Thearch.Thestring) {
|
|
|
|
|
log.Fatalf("cannot use %cg with GOARCH=%s", Thearch.Thechar, p)
|
|
|
|
|
}
|
|
|
|
|
goarch = p
|
|
|
|
|
|
|
|
|
|
Thearch.Linkarchinit()
|
|
|
|
|
Ctxt = obj.Linknew(Thearch.Thelinkarch)
|
|
|
|
|
Ctxt.Diag = Yyerror
|
|
|
|
|
Ctxt.Bso = &bstdout
|
|
|
|
|
bstdout = *obj.Binitw(os.Stdout)
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
localpkg = mkpkg("")
|
2015-02-13 14:40:36 -05:00
|
|
|
localpkg.Prefix = "\"\""
|
|
|
|
|
|
|
|
|
|
// pseudo-package, for scoping
|
2015-03-02 16:03:26 -05:00
|
|
|
builtinpkg = mkpkg("go.builtin")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin
|
|
|
|
|
|
|
|
|
|
// pseudo-package, accessed by import "unsafe"
|
2015-03-02 16:03:26 -05:00
|
|
|
unsafepkg = mkpkg("unsafe")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
unsafepkg.Name = "unsafe"
|
|
|
|
|
|
|
|
|
|
// real package, referred to by generated runtime calls
|
2015-03-02 16:03:26 -05:00
|
|
|
Runtimepkg = mkpkg("runtime")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
Runtimepkg.Name = "runtime"
|
|
|
|
|
|
|
|
|
|
// pseudo-packages used in symbol tables
|
2015-03-02 16:03:26 -05:00
|
|
|
gostringpkg = mkpkg("go.string")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
gostringpkg.Name = "go.string"
|
|
|
|
|
gostringpkg.Prefix = "go.string" // not go%2estring
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
itabpkg = mkpkg("go.itab")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
itabpkg.Name = "go.itab"
|
|
|
|
|
itabpkg.Prefix = "go.itab" // not go%2eitab
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
weaktypepkg = mkpkg("go.weak.type")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
weaktypepkg.Name = "go.weak.type"
|
|
|
|
|
weaktypepkg.Prefix = "go.weak.type" // not go%2eweak%2etype
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
typelinkpkg = mkpkg("go.typelink")
|
2015-02-13 14:40:36 -05:00
|
|
|
typelinkpkg.Name = "go.typelink"
|
|
|
|
|
typelinkpkg.Prefix = "go.typelink" // not go%2etypelink
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
trackpkg = mkpkg("go.track")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
trackpkg.Name = "go.track"
|
|
|
|
|
trackpkg.Prefix = "go.track" // not go%2etrack
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
typepkg = mkpkg("type")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
typepkg.Name = "type"
|
|
|
|
|
|
|
|
|
|
goroot = obj.Getgoroot()
|
|
|
|
|
goos = obj.Getgoos()
|
|
|
|
|
|
|
|
|
|
Nacl = goos == "nacl"
|
|
|
|
|
if Nacl {
|
|
|
|
|
flag_largemodel = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outfile = ""
|
|
|
|
|
obj.Flagcount("+", "compiling runtime", &compiling_runtime)
|
|
|
|
|
obj.Flagcount("%", "debug non-static initializers", &Debug['%'])
|
|
|
|
|
obj.Flagcount("A", "for bootstrapping, allow 'any' type", &Debug['A'])
|
|
|
|
|
obj.Flagcount("B", "disable bounds checking", &Debug['B'])
|
2015-05-01 16:14:50 -07:00
|
|
|
obj.Flagstr("D", "set relative `path` for local imports", &localimport)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagcount("E", "debug symbol export", &Debug['E'])
|
2015-05-01 16:14:50 -07:00
|
|
|
obj.Flagfn1("I", "add `directory` to import search path", addidir)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagcount("K", "debug missing line numbers", &Debug['K'])
|
|
|
|
|
obj.Flagcount("L", "use full (long) path in error messages", &Debug['L'])
|
|
|
|
|
obj.Flagcount("M", "debug move generation", &Debug['M'])
|
|
|
|
|
obj.Flagcount("N", "disable optimizations", &Debug['N'])
|
|
|
|
|
obj.Flagcount("P", "debug peephole optimizer", &Debug['P'])
|
|
|
|
|
obj.Flagcount("R", "debug register optimizer", &Debug['R'])
|
|
|
|
|
obj.Flagcount("S", "print assembly listing", &Debug['S'])
|
|
|
|
|
obj.Flagfn0("V", "print compiler version", doversion)
|
|
|
|
|
obj.Flagcount("W", "debug parse tree after type checking", &Debug['W'])
|
2015-05-01 16:14:50 -07:00
|
|
|
obj.Flagstr("asmhdr", "write assembly header to `file`", &asmhdr)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagcount("complete", "compiling complete package (no C or assembly)", &pure_go)
|
2015-05-01 16:14:50 -07:00
|
|
|
obj.Flagstr("d", "print debug information about items in `list`", &debugstr)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagcount("e", "no limit on number of errors reported", &Debug['e'])
|
|
|
|
|
obj.Flagcount("f", "debug stack frames", &Debug['f'])
|
|
|
|
|
obj.Flagcount("g", "debug code generation", &Debug['g'])
|
|
|
|
|
obj.Flagcount("h", "halt on error", &Debug['h'])
|
|
|
|
|
obj.Flagcount("i", "debug line number stack", &Debug['i'])
|
2015-05-01 16:14:50 -07:00
|
|
|
obj.Flagstr("installsuffix", "set pkg directory `suffix`", &flag_installsuffix)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
|
|
|
|
|
obj.Flagcount("l", "disable inlining", &Debug['l'])
|
|
|
|
|
obj.Flagcount("live", "debug liveness analysis", &debuglive)
|
|
|
|
|
obj.Flagcount("m", "print optimization decisions", &Debug['m'])
|
|
|
|
|
obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports)
|
2015-05-01 16:14:50 -07:00
|
|
|
obj.Flagstr("o", "write output to `file`", &outfile)
|
|
|
|
|
obj.Flagstr("p", "set expected package import `path`", &myimportpath)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagcount("pack", "write package file instead of object file", &writearchive)
|
|
|
|
|
obj.Flagcount("r", "debug generated wrappers", &Debug['r'])
|
|
|
|
|
obj.Flagcount("race", "enable race detector", &flag_race)
|
|
|
|
|
obj.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s'])
|
2015-05-01 16:14:50 -07:00
|
|
|
obj.Flagstr("trimpath", "remove `prefix` from recorded source file paths", &Ctxt.LineHist.TrimPathPrefix)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagcount("u", "reject unsafe code", &safemode)
|
|
|
|
|
obj.Flagcount("v", "increase debug verbosity", &Debug['v'])
|
|
|
|
|
obj.Flagcount("w", "debug type checking", &Debug['w'])
|
|
|
|
|
use_writebarrier = 1
|
|
|
|
|
obj.Flagcount("wb", "enable write barrier", &use_writebarrier)
|
|
|
|
|
obj.Flagcount("x", "debug lexer", &Debug['x'])
|
|
|
|
|
obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y'])
|
2015-02-10 15:56:32 +13:00
|
|
|
var flag_shared int
|
2015-03-30 00:49:25 +00:00
|
|
|
var flag_dynlink bool
|
2015-02-13 14:40:36 -05:00
|
|
|
if Thearch.Thechar == '6' {
|
|
|
|
|
obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel)
|
2015-02-10 15:56:32 +13:00
|
|
|
obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared)
|
2015-03-30 00:49:25 +00:00
|
|
|
flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-01 16:14:50 -07:00
|
|
|
obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
|
|
|
|
|
obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile)
|
|
|
|
|
obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagparse(usage)
|
2015-03-30 00:49:25 +00:00
|
|
|
|
|
|
|
|
if flag_dynlink {
|
|
|
|
|
flag_shared = 1
|
|
|
|
|
}
|
2015-02-10 15:56:32 +13:00
|
|
|
Ctxt.Flag_shared = int32(flag_shared)
|
2015-03-30 00:49:25 +00:00
|
|
|
Ctxt.Flag_dynlink = flag_dynlink
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
Ctxt.Debugasm = int32(Debug['S'])
|
|
|
|
|
Ctxt.Debugvlog = int32(Debug['v'])
|
|
|
|
|
|
|
|
|
|
if flag.NArg() < 1 {
|
|
|
|
|
usage()
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 10:22:26 -05:00
|
|
|
startProfile()
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
if flag_race != 0 {
|
2015-03-02 16:03:26 -05:00
|
|
|
racepkg = mkpkg("runtime/race")
|
2015-02-13 14:40:36 -05:00
|
|
|
racepkg.Name = "race"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parse -d argument
|
|
|
|
|
if debugstr != "" {
|
cmd/internal/gc: accept comma-separated list of name=value for -d
This should obviously have no performance impact.
Listing numbers just as a sanity check for the benchmark
comparison program: it should (and does) find nothing
to report.
name old new delta
BenchmarkBinaryTree17 18.0s × (0.99,1.01) 17.9s × (0.99,1.00) ~
BenchmarkFannkuch11 4.36s × (1.00,1.00) 4.35s × (1.00,1.00) ~
BenchmarkFmtFprintfEmpty 120ns × (0.99,1.06) 120ns × (0.94,1.05) ~
BenchmarkFmtFprintfString 480ns × (0.99,1.01) 477ns × (1.00,1.00) ~
BenchmarkFmtFprintfInt 451ns × (0.99,1.01) 450ns × (0.99,1.01) ~
BenchmarkFmtFprintfIntInt 766ns × (0.99,1.01) 765ns × (0.99,1.01) ~
BenchmarkFmtFprintfPrefixedInt 569ns × (0.99,1.01) 569ns × (0.99,1.01) ~
BenchmarkFmtFprintfFloat 728ns × (1.00,1.01) 728ns × (1.00,1.00) ~
BenchmarkFmtManyArgs 2.81µs × (1.00,1.01) 2.82µs × (0.99,1.01) ~
BenchmarkGobDecode 39.4ms × (0.99,1.01) 39.1ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (0.99,1.00) 39.4ms × (0.99,1.01) ~
BenchmarkGzip 660ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 143ms × (1.00,1.00) 143ms × (1.00,1.00) ~
BenchmarkHTTPClientServer 132µs × (0.99,1.01) 133µs × (0.99,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 57.3ms × (0.99,1.04) ~
BenchmarkJSONDecode 138ms × (1.00,1.01) 139ms × (0.99,1.00) ~
BenchmarkMandelbrot200 6.02ms × (1.00,1.00) 6.02ms × (1.00,1.00) ~
BenchmarkGoParse 9.79ms × (0.92,1.07) 9.72ms × (0.92,1.11) ~
BenchmarkRegexpMatchEasy0_32 210ns × (1.00,1.01) 209ns × (1.00,1.01) ~
BenchmarkRegexpMatchEasy0_1K 593ns × (0.99,1.01) 592ns × (0.99,1.00) ~
BenchmarkRegexpMatchEasy1_32 182ns × (0.99,1.01) 183ns × (0.98,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.01) 1.01µs × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_32 331ns × (1.00,1.00) 330ns × (1.00,1.00) ~
BenchmarkRegexpMatchMedium_1K 92.6µs × (1.00,1.01) 92.4µs × (1.00,1.00) ~
BenchmarkRegexpMatchHard_32 4.58µs × (0.99,1.05) 4.77µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.01) 136µs × (1.00,1.00) ~
BenchmarkRevcomp 900ms × (0.99,1.06) 906ms × (0.99,1.05) ~
BenchmarkTemplate 171ms × (1.00,1.01) 171ms × (0.99,1.01) ~
BenchmarkTimeParse 637ns × (1.00,1.00) 638ns × (1.00,1.00) ~
BenchmarkTimeFormat 742ns × (1.00,1.00) 745ns × (0.99,1.02) ~
Change-Id: I59ec875715cb176bbffa709546370a6a7fc5a75d
Reviewed-on: https://go-review.googlesource.com/9309
Reviewed-by: Austin Clements <austin@google.com>
2015-04-24 11:45:11 -04:00
|
|
|
Split:
|
|
|
|
|
for _, name := range strings.Split(debugstr, ",") {
|
|
|
|
|
if name == "" {
|
2015-02-13 14:40:36 -05:00
|
|
|
continue
|
|
|
|
|
}
|
cmd/internal/gc: accept comma-separated list of name=value for -d
This should obviously have no performance impact.
Listing numbers just as a sanity check for the benchmark
comparison program: it should (and does) find nothing
to report.
name old new delta
BenchmarkBinaryTree17 18.0s × (0.99,1.01) 17.9s × (0.99,1.00) ~
BenchmarkFannkuch11 4.36s × (1.00,1.00) 4.35s × (1.00,1.00) ~
BenchmarkFmtFprintfEmpty 120ns × (0.99,1.06) 120ns × (0.94,1.05) ~
BenchmarkFmtFprintfString 480ns × (0.99,1.01) 477ns × (1.00,1.00) ~
BenchmarkFmtFprintfInt 451ns × (0.99,1.01) 450ns × (0.99,1.01) ~
BenchmarkFmtFprintfIntInt 766ns × (0.99,1.01) 765ns × (0.99,1.01) ~
BenchmarkFmtFprintfPrefixedInt 569ns × (0.99,1.01) 569ns × (0.99,1.01) ~
BenchmarkFmtFprintfFloat 728ns × (1.00,1.01) 728ns × (1.00,1.00) ~
BenchmarkFmtManyArgs 2.81µs × (1.00,1.01) 2.82µs × (0.99,1.01) ~
BenchmarkGobDecode 39.4ms × (0.99,1.01) 39.1ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (0.99,1.00) 39.4ms × (0.99,1.01) ~
BenchmarkGzip 660ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 143ms × (1.00,1.00) 143ms × (1.00,1.00) ~
BenchmarkHTTPClientServer 132µs × (0.99,1.01) 133µs × (0.99,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 57.3ms × (0.99,1.04) ~
BenchmarkJSONDecode 138ms × (1.00,1.01) 139ms × (0.99,1.00) ~
BenchmarkMandelbrot200 6.02ms × (1.00,1.00) 6.02ms × (1.00,1.00) ~
BenchmarkGoParse 9.79ms × (0.92,1.07) 9.72ms × (0.92,1.11) ~
BenchmarkRegexpMatchEasy0_32 210ns × (1.00,1.01) 209ns × (1.00,1.01) ~
BenchmarkRegexpMatchEasy0_1K 593ns × (0.99,1.01) 592ns × (0.99,1.00) ~
BenchmarkRegexpMatchEasy1_32 182ns × (0.99,1.01) 183ns × (0.98,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.01) 1.01µs × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_32 331ns × (1.00,1.00) 330ns × (1.00,1.00) ~
BenchmarkRegexpMatchMedium_1K 92.6µs × (1.00,1.01) 92.4µs × (1.00,1.00) ~
BenchmarkRegexpMatchHard_32 4.58µs × (0.99,1.05) 4.77µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.01) 136µs × (1.00,1.00) ~
BenchmarkRevcomp 900ms × (0.99,1.06) 906ms × (0.99,1.05) ~
BenchmarkTemplate 171ms × (1.00,1.01) 171ms × (0.99,1.01) ~
BenchmarkTimeParse 637ns × (1.00,1.00) 638ns × (1.00,1.00) ~
BenchmarkTimeFormat 742ns × (1.00,1.00) 745ns × (0.99,1.02) ~
Change-Id: I59ec875715cb176bbffa709546370a6a7fc5a75d
Reviewed-on: https://go-review.googlesource.com/9309
Reviewed-by: Austin Clements <austin@google.com>
2015-04-24 11:45:11 -04:00
|
|
|
val := 1
|
|
|
|
|
if i := strings.Index(name, "="); i >= 0 {
|
|
|
|
|
var err error
|
|
|
|
|
val, err = strconv.Atoi(name[i+1:])
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("invalid debug value %v", name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
cmd/internal/gc: accept comma-separated list of name=value for -d
This should obviously have no performance impact.
Listing numbers just as a sanity check for the benchmark
comparison program: it should (and does) find nothing
to report.
name old new delta
BenchmarkBinaryTree17 18.0s × (0.99,1.01) 17.9s × (0.99,1.00) ~
BenchmarkFannkuch11 4.36s × (1.00,1.00) 4.35s × (1.00,1.00) ~
BenchmarkFmtFprintfEmpty 120ns × (0.99,1.06) 120ns × (0.94,1.05) ~
BenchmarkFmtFprintfString 480ns × (0.99,1.01) 477ns × (1.00,1.00) ~
BenchmarkFmtFprintfInt 451ns × (0.99,1.01) 450ns × (0.99,1.01) ~
BenchmarkFmtFprintfIntInt 766ns × (0.99,1.01) 765ns × (0.99,1.01) ~
BenchmarkFmtFprintfPrefixedInt 569ns × (0.99,1.01) 569ns × (0.99,1.01) ~
BenchmarkFmtFprintfFloat 728ns × (1.00,1.01) 728ns × (1.00,1.00) ~
BenchmarkFmtManyArgs 2.81µs × (1.00,1.01) 2.82µs × (0.99,1.01) ~
BenchmarkGobDecode 39.4ms × (0.99,1.01) 39.1ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (0.99,1.00) 39.4ms × (0.99,1.01) ~
BenchmarkGzip 660ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 143ms × (1.00,1.00) 143ms × (1.00,1.00) ~
BenchmarkHTTPClientServer 132µs × (0.99,1.01) 133µs × (0.99,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 57.3ms × (0.99,1.04) ~
BenchmarkJSONDecode 138ms × (1.00,1.01) 139ms × (0.99,1.00) ~
BenchmarkMandelbrot200 6.02ms × (1.00,1.00) 6.02ms × (1.00,1.00) ~
BenchmarkGoParse 9.79ms × (0.92,1.07) 9.72ms × (0.92,1.11) ~
BenchmarkRegexpMatchEasy0_32 210ns × (1.00,1.01) 209ns × (1.00,1.01) ~
BenchmarkRegexpMatchEasy0_1K 593ns × (0.99,1.01) 592ns × (0.99,1.00) ~
BenchmarkRegexpMatchEasy1_32 182ns × (0.99,1.01) 183ns × (0.98,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.01) 1.01µs × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_32 331ns × (1.00,1.00) 330ns × (1.00,1.00) ~
BenchmarkRegexpMatchMedium_1K 92.6µs × (1.00,1.01) 92.4µs × (1.00,1.00) ~
BenchmarkRegexpMatchHard_32 4.58µs × (0.99,1.05) 4.77µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.01) 136µs × (1.00,1.00) ~
BenchmarkRevcomp 900ms × (0.99,1.06) 906ms × (0.99,1.05) ~
BenchmarkTemplate 171ms × (1.00,1.01) 171ms × (0.99,1.01) ~
BenchmarkTimeParse 637ns × (1.00,1.00) 638ns × (1.00,1.00) ~
BenchmarkTimeFormat 742ns × (1.00,1.00) 745ns × (0.99,1.02) ~
Change-Id: I59ec875715cb176bbffa709546370a6a7fc5a75d
Reviewed-on: https://go-review.googlesource.com/9309
Reviewed-by: Austin Clements <austin@google.com>
2015-04-24 11:45:11 -04:00
|
|
|
name = name[:i]
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
cmd/internal/gc: accept comma-separated list of name=value for -d
This should obviously have no performance impact.
Listing numbers just as a sanity check for the benchmark
comparison program: it should (and does) find nothing
to report.
name old new delta
BenchmarkBinaryTree17 18.0s × (0.99,1.01) 17.9s × (0.99,1.00) ~
BenchmarkFannkuch11 4.36s × (1.00,1.00) 4.35s × (1.00,1.00) ~
BenchmarkFmtFprintfEmpty 120ns × (0.99,1.06) 120ns × (0.94,1.05) ~
BenchmarkFmtFprintfString 480ns × (0.99,1.01) 477ns × (1.00,1.00) ~
BenchmarkFmtFprintfInt 451ns × (0.99,1.01) 450ns × (0.99,1.01) ~
BenchmarkFmtFprintfIntInt 766ns × (0.99,1.01) 765ns × (0.99,1.01) ~
BenchmarkFmtFprintfPrefixedInt 569ns × (0.99,1.01) 569ns × (0.99,1.01) ~
BenchmarkFmtFprintfFloat 728ns × (1.00,1.01) 728ns × (1.00,1.00) ~
BenchmarkFmtManyArgs 2.81µs × (1.00,1.01) 2.82µs × (0.99,1.01) ~
BenchmarkGobDecode 39.4ms × (0.99,1.01) 39.1ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (0.99,1.00) 39.4ms × (0.99,1.01) ~
BenchmarkGzip 660ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 143ms × (1.00,1.00) 143ms × (1.00,1.00) ~
BenchmarkHTTPClientServer 132µs × (0.99,1.01) 133µs × (0.99,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 57.3ms × (0.99,1.04) ~
BenchmarkJSONDecode 138ms × (1.00,1.01) 139ms × (0.99,1.00) ~
BenchmarkMandelbrot200 6.02ms × (1.00,1.00) 6.02ms × (1.00,1.00) ~
BenchmarkGoParse 9.79ms × (0.92,1.07) 9.72ms × (0.92,1.11) ~
BenchmarkRegexpMatchEasy0_32 210ns × (1.00,1.01) 209ns × (1.00,1.01) ~
BenchmarkRegexpMatchEasy0_1K 593ns × (0.99,1.01) 592ns × (0.99,1.00) ~
BenchmarkRegexpMatchEasy1_32 182ns × (0.99,1.01) 183ns × (0.98,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.01) 1.01µs × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_32 331ns × (1.00,1.00) 330ns × (1.00,1.00) ~
BenchmarkRegexpMatchMedium_1K 92.6µs × (1.00,1.01) 92.4µs × (1.00,1.00) ~
BenchmarkRegexpMatchHard_32 4.58µs × (0.99,1.05) 4.77µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.01) 136µs × (1.00,1.00) ~
BenchmarkRevcomp 900ms × (0.99,1.06) 906ms × (0.99,1.05) ~
BenchmarkTemplate 171ms × (1.00,1.01) 171ms × (0.99,1.01) ~
BenchmarkTimeParse 637ns × (1.00,1.00) 638ns × (1.00,1.00) ~
BenchmarkTimeFormat 742ns × (1.00,1.00) 745ns × (0.99,1.02) ~
Change-Id: I59ec875715cb176bbffa709546370a6a7fc5a75d
Reviewed-on: https://go-review.googlesource.com/9309
Reviewed-by: Austin Clements <austin@google.com>
2015-04-24 11:45:11 -04:00
|
|
|
for _, t := range debugtab {
|
|
|
|
|
if t.name == name {
|
|
|
|
|
if t.val != nil {
|
|
|
|
|
*t.val = val
|
|
|
|
|
continue Split
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
cmd/internal/gc: accept comma-separated list of name=value for -d
This should obviously have no performance impact.
Listing numbers just as a sanity check for the benchmark
comparison program: it should (and does) find nothing
to report.
name old new delta
BenchmarkBinaryTree17 18.0s × (0.99,1.01) 17.9s × (0.99,1.00) ~
BenchmarkFannkuch11 4.36s × (1.00,1.00) 4.35s × (1.00,1.00) ~
BenchmarkFmtFprintfEmpty 120ns × (0.99,1.06) 120ns × (0.94,1.05) ~
BenchmarkFmtFprintfString 480ns × (0.99,1.01) 477ns × (1.00,1.00) ~
BenchmarkFmtFprintfInt 451ns × (0.99,1.01) 450ns × (0.99,1.01) ~
BenchmarkFmtFprintfIntInt 766ns × (0.99,1.01) 765ns × (0.99,1.01) ~
BenchmarkFmtFprintfPrefixedInt 569ns × (0.99,1.01) 569ns × (0.99,1.01) ~
BenchmarkFmtFprintfFloat 728ns × (1.00,1.01) 728ns × (1.00,1.00) ~
BenchmarkFmtManyArgs 2.81µs × (1.00,1.01) 2.82µs × (0.99,1.01) ~
BenchmarkGobDecode 39.4ms × (0.99,1.01) 39.1ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (0.99,1.00) 39.4ms × (0.99,1.01) ~
BenchmarkGzip 660ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 143ms × (1.00,1.00) 143ms × (1.00,1.00) ~
BenchmarkHTTPClientServer 132µs × (0.99,1.01) 133µs × (0.99,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 57.3ms × (0.99,1.04) ~
BenchmarkJSONDecode 138ms × (1.00,1.01) 139ms × (0.99,1.00) ~
BenchmarkMandelbrot200 6.02ms × (1.00,1.00) 6.02ms × (1.00,1.00) ~
BenchmarkGoParse 9.79ms × (0.92,1.07) 9.72ms × (0.92,1.11) ~
BenchmarkRegexpMatchEasy0_32 210ns × (1.00,1.01) 209ns × (1.00,1.01) ~
BenchmarkRegexpMatchEasy0_1K 593ns × (0.99,1.01) 592ns × (0.99,1.00) ~
BenchmarkRegexpMatchEasy1_32 182ns × (0.99,1.01) 183ns × (0.98,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.01) 1.01µs × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_32 331ns × (1.00,1.00) 330ns × (1.00,1.00) ~
BenchmarkRegexpMatchMedium_1K 92.6µs × (1.00,1.01) 92.4µs × (1.00,1.00) ~
BenchmarkRegexpMatchHard_32 4.58µs × (0.99,1.05) 4.77µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.01) 136µs × (1.00,1.00) ~
BenchmarkRevcomp 900ms × (0.99,1.06) 906ms × (0.99,1.05) ~
BenchmarkTemplate 171ms × (1.00,1.01) 171ms × (0.99,1.01) ~
BenchmarkTimeParse 637ns × (1.00,1.00) 638ns × (1.00,1.00) ~
BenchmarkTimeFormat 742ns × (1.00,1.00) 745ns × (0.99,1.02) ~
Change-Id: I59ec875715cb176bbffa709546370a6a7fc5a75d
Reviewed-on: https://go-review.googlesource.com/9309
Reviewed-by: Austin Clements <austin@google.com>
2015-04-24 11:45:11 -04:00
|
|
|
log.Fatalf("unknown debug key -d %s\n", name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// enable inlining. for now:
|
|
|
|
|
// default: inlining on. (debug['l'] == 1)
|
|
|
|
|
// -l: inlining off (debug['l'] == 0)
|
|
|
|
|
// -ll, -lll: inlining on again, with extra debugging (debug['l'] > 1)
|
|
|
|
|
if Debug['l'] <= 1 {
|
|
|
|
|
Debug['l'] = 1 - Debug['l']
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Thearch.Betypeinit()
|
|
|
|
|
if Widthptr == 0 {
|
|
|
|
|
Fatal("betypeinit failed")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lexinit()
|
|
|
|
|
typeinit()
|
|
|
|
|
lexinit1()
|
|
|
|
|
// TODO(rsc): Restore yytinit?
|
|
|
|
|
|
|
|
|
|
blockgen = 1
|
|
|
|
|
dclcontext = PEXTERN
|
|
|
|
|
nerrors = 0
|
|
|
|
|
lexlineno = 1
|
|
|
|
|
|
|
|
|
|
for _, infile = range flag.Args() {
|
|
|
|
|
linehist(infile, 0, 0)
|
|
|
|
|
|
|
|
|
|
curio.infile = infile
|
|
|
|
|
var err error
|
|
|
|
|
curio.bin, err = obj.Bopenr(infile)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("open %s: %v\n", infile, err)
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curio.peekc = 0
|
|
|
|
|
curio.peekc1 = 0
|
|
|
|
|
curio.nlsemi = 0
|
|
|
|
|
curio.eofnl = 0
|
|
|
|
|
curio.last = 0
|
|
|
|
|
|
|
|
|
|
// Skip initial BOM if present.
|
|
|
|
|
if obj.Bgetrune(curio.bin) != obj.BOM {
|
|
|
|
|
obj.Bungetrune(curio.bin)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block = 1
|
|
|
|
|
iota_ = -1000000
|
|
|
|
|
|
|
|
|
|
imported_unsafe = 0
|
|
|
|
|
|
|
|
|
|
yyparse()
|
|
|
|
|
if nsyntaxerrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
linehist("<pop>", 0, 0)
|
|
|
|
|
if curio.bin != nil {
|
|
|
|
|
obj.Bterm(curio.bin)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
testdclstack()
|
|
|
|
|
mkpackage(localpkg.Name) // final import not used checks
|
|
|
|
|
lexfini()
|
|
|
|
|
|
|
|
|
|
typecheckok = 1
|
|
|
|
|
if Debug['f'] != 0 {
|
|
|
|
|
frame(1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process top-level declarations in phases.
|
|
|
|
|
|
|
|
|
|
// Phase 1: const, type, and names and types of funcs.
|
|
|
|
|
// This will gather all the information about types
|
|
|
|
|
// and methods but doesn't depend on any of it.
|
|
|
|
|
defercheckwidth()
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op != ODCL && l.N.Op != OAS {
|
|
|
|
|
typecheck(&l.N, Etop)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 2: Variable assignments.
|
|
|
|
|
// To check interface assignments, depends on phase 1.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCL || l.N.Op == OAS {
|
|
|
|
|
typecheck(&l.N, Etop)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
resumecheckwidth()
|
|
|
|
|
|
|
|
|
|
// Phase 3: Type check function bodies.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCLFUNC || l.N.Op == OCLOSURE {
|
|
|
|
|
Curfn = l.N
|
|
|
|
|
decldepth = 1
|
|
|
|
|
saveerrors()
|
|
|
|
|
typechecklist(l.N.Nbody, Etop)
|
|
|
|
|
checkreturn(l.N)
|
|
|
|
|
if nerrors != 0 {
|
|
|
|
|
l.N.Nbody = nil // type errors; do not compile
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 4: Decide how to capture closed variables.
|
|
|
|
|
// This needs to run before escape analysis,
|
|
|
|
|
// because variables captured by value do not escape.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCLFUNC && l.N.Closure != nil {
|
|
|
|
|
Curfn = l.N
|
|
|
|
|
capturevars(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Curfn = nil
|
|
|
|
|
|
|
|
|
|
if nsavederrors+nerrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 5: Inlining
|
|
|
|
|
if Debug['l'] > 1 {
|
|
|
|
|
// Typecheck imported function bodies if debug['l'] > 1,
|
|
|
|
|
// otherwise lazily when used or re-exported.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := importlist; l != nil; l = l.Next {
|
2015-03-25 19:33:01 -07:00
|
|
|
if l.N.Func.Inl != nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
saveerrors()
|
|
|
|
|
typecheckinl(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nsavederrors+nerrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if Debug['l'] != 0 {
|
|
|
|
|
// Find functions that can be inlined and clone them before walk expands them.
|
2015-02-24 12:19:01 -05:00
|
|
|
visitBottomUp(xtop, func(list *NodeList, recursive bool) {
|
|
|
|
|
for l := list; l != nil; l = l.Next {
|
|
|
|
|
if l.N.Op == ODCLFUNC {
|
|
|
|
|
caninl(l.N)
|
|
|
|
|
inlcalls(l.N)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-24 12:19:01 -05:00
|
|
|
})
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 6: Escape analysis.
|
|
|
|
|
// Required for moving heap allocations onto stack,
|
|
|
|
|
// which in turn is required by the closure implementation,
|
|
|
|
|
// which stores the addresses of stack variables into the closure.
|
|
|
|
|
// If the closure does not escape, it needs to be on the stack
|
|
|
|
|
// or else the stack copier will not update it.
|
|
|
|
|
escapes(xtop)
|
|
|
|
|
|
|
|
|
|
// Escape analysis moved escaped values off stack.
|
|
|
|
|
// Move large values off stack too.
|
|
|
|
|
movelarge(xtop)
|
|
|
|
|
|
|
|
|
|
// Phase 7: Transform closure bodies to properly reference captured variables.
|
|
|
|
|
// This needs to happen before walk, because closures must be transformed
|
|
|
|
|
// before walk reaches a call of a closure.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCLFUNC && l.N.Closure != nil {
|
|
|
|
|
Curfn = l.N
|
|
|
|
|
transformclosure(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Curfn = nil
|
|
|
|
|
|
|
|
|
|
// Phase 8: Compile top level functions.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCLFUNC {
|
|
|
|
|
funccompile(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nsavederrors+nerrors == 0 {
|
|
|
|
|
fninit(xtop)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 9: Check external declarations.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := externdcl; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ONAME {
|
|
|
|
|
typecheck(&l.N, Erv)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nerrors+nsavederrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dumpobj()
|
|
|
|
|
|
|
|
|
|
if asmhdr != "" {
|
|
|
|
|
dumpasmhdr()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nerrors+nsavederrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Flusherrors()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func saveerrors() {
|
|
|
|
|
nsavederrors += nerrors
|
|
|
|
|
nerrors = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func arsize(b *obj.Biobuf, name string) int {
|
|
|
|
|
var buf [ArhdrSize]byte
|
|
|
|
|
if _, err := io.ReadFull(b, buf[:]); err != nil {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
aname := strings.Trim(string(buf[0:16]), " ")
|
|
|
|
|
if !strings.HasPrefix(aname, name) {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
asize := strings.Trim(string(buf[48:58]), " ")
|
|
|
|
|
i, _ := strconv.Atoi(asize)
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func skiptopkgdef(b *obj.Biobuf) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
/* archive header */
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Brdline(b, '\n')
|
2015-02-13 14:40:36 -05:00
|
|
|
if p == "" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if obj.Blinelen(b) != 8 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if p != "!<arch>\n" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* symbol table may be first; skip it */
|
2015-02-23 16:07:24 -05:00
|
|
|
sz := arsize(b, "__.GOSYMDEF")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if sz >= 0 {
|
|
|
|
|
obj.Bseek(b, int64(sz), 1)
|
|
|
|
|
} else {
|
|
|
|
|
obj.Bseek(b, 8, 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* package export block is next */
|
|
|
|
|
sz = arsize(b, "__.PKGDEF")
|
|
|
|
|
|
|
|
|
|
if sz <= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func addidir(dir string) {
|
|
|
|
|
if dir == "" {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var pp **Idir
|
2015-02-13 14:40:36 -05:00
|
|
|
for pp = &idirs; *pp != nil; pp = &(*pp).link {
|
|
|
|
|
}
|
|
|
|
|
*pp = new(Idir)
|
|
|
|
|
(*pp).link = nil
|
|
|
|
|
(*pp).dir = dir
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// is this path a local name? begins with ./ or ../ or /
|
2015-03-02 16:03:26 -05:00
|
|
|
func islocalname(name string) bool {
|
|
|
|
|
return strings.HasPrefix(name, "/") ||
|
|
|
|
|
Ctxt.Windows != 0 && len(name) >= 3 && yy_isalpha(int(name[0])) && name[1] == ':' && name[2] == '/' ||
|
|
|
|
|
strings.HasPrefix(name, "./") || name == "." ||
|
|
|
|
|
strings.HasPrefix(name, "../") || name == ".."
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-06 12:02:24 -08:00
|
|
|
func findpkg(name string) (file string, ok bool) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if islocalname(name) {
|
|
|
|
|
if safemode != 0 || nolocalimports != 0 {
|
2015-03-06 12:02:24 -08:00
|
|
|
return "", false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// try .a before .6. important for building libraries:
|
|
|
|
|
// if there is an array.6 in the array.a library,
|
|
|
|
|
// want to find all of array.a, not just array.6.
|
2015-03-06 12:02:24 -08:00
|
|
|
file = fmt.Sprintf("%s.a", name)
|
|
|
|
|
if obj.Access(file, 0) >= 0 {
|
|
|
|
|
return file, true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-06 12:02:24 -08:00
|
|
|
file = fmt.Sprintf("%s.%c", name, Thearch.Thechar)
|
|
|
|
|
if obj.Access(file, 0) >= 0 {
|
|
|
|
|
return file, true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-06 12:02:24 -08:00
|
|
|
return "", false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// local imports should be canonicalized already.
|
|
|
|
|
// don't want to see "encoding/../encoding/base64"
|
|
|
|
|
// as different from "encoding/base64".
|
2015-02-23 16:07:24 -05:00
|
|
|
var q string
|
2015-02-13 14:40:36 -05:00
|
|
|
_ = q
|
2015-03-02 16:03:26 -05:00
|
|
|
if path.Clean(name) != name {
|
|
|
|
|
Yyerror("non-canonical import path %q (should be %q)", name, q)
|
2015-03-06 12:02:24 -08:00
|
|
|
return "", false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
for p := idirs; p != nil; p = p.link {
|
2015-03-06 12:02:24 -08:00
|
|
|
file = fmt.Sprintf("%s/%s.a", p.dir, name)
|
|
|
|
|
if obj.Access(file, 0) >= 0 {
|
|
|
|
|
return file, true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-06 12:02:24 -08:00
|
|
|
file = fmt.Sprintf("%s/%s.%c", p.dir, name, Thearch.Thechar)
|
|
|
|
|
if obj.Access(file, 0) >= 0 {
|
|
|
|
|
return file, true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if goroot != "" {
|
2015-02-23 16:07:24 -05:00
|
|
|
suffix := ""
|
|
|
|
|
suffixsep := ""
|
2015-02-13 14:40:36 -05:00
|
|
|
if flag_installsuffix != "" {
|
|
|
|
|
suffixsep = "_"
|
|
|
|
|
suffix = flag_installsuffix
|
|
|
|
|
} else if flag_race != 0 {
|
|
|
|
|
suffixsep = "_"
|
|
|
|
|
suffix = "race"
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-06 12:02:24 -08:00
|
|
|
file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", goroot, goos, goarch, suffixsep, suffix, name)
|
|
|
|
|
if obj.Access(file, 0) >= 0 {
|
|
|
|
|
return file, true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-06 12:02:24 -08:00
|
|
|
file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.%c", goroot, goos, goarch, suffixsep, suffix, name, Thearch.Thechar)
|
|
|
|
|
if obj.Access(file, 0) >= 0 {
|
|
|
|
|
return file, true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-06 12:02:24 -08:00
|
|
|
return "", false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func fakeimport() {
|
2015-03-02 16:03:26 -05:00
|
|
|
importpkg = mkpkg("fake")
|
2015-02-13 14:40:36 -05:00
|
|
|
cannedimports("fake.6", "$$\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func importfile(f *Val, line int) {
|
|
|
|
|
if f.Ctype != CTSTR {
|
|
|
|
|
Yyerror("import statement not a string")
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
if len(f.U.Sval) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("import path is empty")
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if isbadimport(f.U.Sval) {
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The package name main is no longer reserved,
|
|
|
|
|
// but we reserve the import path "main" to identify
|
|
|
|
|
// the main package, just as we reserve the import
|
|
|
|
|
// path "math" to identify the standard math package.
|
2015-03-02 16:03:26 -05:00
|
|
|
if f.U.Sval == "main" {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("cannot import \"main\"")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
if myimportpath != "" && f.U.Sval == myimportpath {
|
|
|
|
|
Yyerror("import %q while compiling that package (import cycle)", f.U.Sval)
|
2015-02-13 14:40:36 -05:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
if f.U.Sval == "unsafe" {
|
2015-02-13 14:40:36 -05:00
|
|
|
if safemode != 0 {
|
|
|
|
|
Yyerror("cannot import package unsafe")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
importpkg = mkpkg(f.U.Sval)
|
|
|
|
|
cannedimports("unsafe.6", unsafeimport)
|
|
|
|
|
imported_unsafe = 1
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
path_ := f.U.Sval
|
2015-02-13 14:40:36 -05:00
|
|
|
if islocalname(path_) {
|
2015-03-02 16:03:26 -05:00
|
|
|
if path_[0] == '/' {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("import path cannot be absolute path")
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
prefix := Ctxt.Pathname
|
2015-02-13 14:40:36 -05:00
|
|
|
if localimport != "" {
|
|
|
|
|
prefix = localimport
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
cleanbuf := prefix
|
2015-02-13 14:40:36 -05:00
|
|
|
cleanbuf += "/"
|
2015-03-02 16:03:26 -05:00
|
|
|
cleanbuf += path_
|
2015-02-13 14:40:36 -05:00
|
|
|
cleanbuf = path.Clean(cleanbuf)
|
2015-03-02 16:03:26 -05:00
|
|
|
path_ = cleanbuf
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if isbadimport(path_) {
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-06 12:02:24 -08:00
|
|
|
file, found := findpkg(path_)
|
|
|
|
|
if !found {
|
2015-03-02 16:03:26 -05:00
|
|
|
Yyerror("can't find import: %q", f.U.Sval)
|
2015-02-13 14:40:36 -05:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
importpkg = mkpkg(path_)
|
|
|
|
|
|
|
|
|
|
// If we already saw that package, feed a dummy statement
|
|
|
|
|
// to the lexer to avoid parsing export data twice.
|
|
|
|
|
if importpkg.Imported != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
tag := ""
|
2015-02-13 14:40:36 -05:00
|
|
|
if importpkg.Safe {
|
|
|
|
|
tag = "safe"
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
p := fmt.Sprintf("package %s %s\n$$\n", importpkg.Name, tag)
|
2015-02-13 14:40:36 -05:00
|
|
|
cannedimports(file, p)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
importpkg.Imported = 1
|
|
|
|
|
|
|
|
|
|
var err error
|
2015-02-23 16:07:24 -05:00
|
|
|
var imp *obj.Biobuf
|
2015-03-06 12:02:24 -08:00
|
|
|
imp, err = obj.Bopenr(file)
|
2015-02-13 14:40:36 -05:00
|
|
|
if err != nil {
|
2015-03-02 16:03:26 -05:00
|
|
|
Yyerror("can't open import: %q: %v", f.U.Sval, err)
|
2015-02-13 14:40:36 -05:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-06 12:02:24 -08:00
|
|
|
if strings.HasSuffix(file, ".a") {
|
2015-02-17 22:13:49 -05:00
|
|
|
if !skiptopkgdef(imp) {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("import %s: not a package file", file)
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check object header
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Brdstr(imp, '\n', 1)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if p != "empty archive" {
|
|
|
|
|
if !strings.HasPrefix(p, "go object ") {
|
|
|
|
|
Yyerror("import %s: not a go object file", file)
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
q := fmt.Sprintf("%s %s %s %s", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring())
|
2015-02-13 14:40:36 -05:00
|
|
|
if p[10:] != q {
|
|
|
|
|
Yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q)
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// assume files move (get installed)
|
|
|
|
|
// so don't record the full path.
|
2015-03-06 12:02:24 -08:00
|
|
|
linehist(file[len(file)-len(path_)-2:], -1, 1) // acts as #pragma lib
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* position the input right
|
|
|
|
|
* after $$ and return
|
|
|
|
|
*/
|
|
|
|
|
pushedio = curio
|
|
|
|
|
|
|
|
|
|
curio.bin = imp
|
|
|
|
|
curio.peekc = 0
|
|
|
|
|
curio.peekc1 = 0
|
|
|
|
|
curio.infile = file
|
|
|
|
|
curio.nlsemi = 0
|
|
|
|
|
typecheckok = 1
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var c int32
|
2015-02-13 14:40:36 -05:00
|
|
|
for {
|
|
|
|
|
c = int32(getc())
|
|
|
|
|
if c == EOF {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c != '$' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
c = int32(getc())
|
|
|
|
|
if c == EOF {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c != '$' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
Yyerror("no import in %q", f.U.Sval)
|
2015-02-13 14:40:36 -05:00
|
|
|
unimportfile()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func unimportfile() {
|
|
|
|
|
if curio.bin != nil {
|
|
|
|
|
obj.Bterm(curio.bin)
|
|
|
|
|
curio.bin = nil
|
|
|
|
|
} else {
|
|
|
|
|
lexlineno-- // re correct sys.6 line number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curio = pushedio
|
|
|
|
|
|
|
|
|
|
pushedio.bin = nil
|
|
|
|
|
incannedimport = 0
|
|
|
|
|
typecheckok = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func cannedimports(file string, cp string) {
|
|
|
|
|
lexlineno++ // if sys.6 is included on line 1,
|
|
|
|
|
|
|
|
|
|
pushedio = curio
|
|
|
|
|
|
|
|
|
|
curio.bin = nil
|
|
|
|
|
curio.peekc = 0
|
|
|
|
|
curio.peekc1 = 0
|
|
|
|
|
curio.infile = file
|
|
|
|
|
curio.cp = cp
|
|
|
|
|
curio.nlsemi = 0
|
|
|
|
|
curio.importsafe = false
|
|
|
|
|
|
|
|
|
|
typecheckok = 1
|
|
|
|
|
incannedimport = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isfrog(c int) bool {
|
|
|
|
|
// complain about possibly invisible control characters
|
|
|
|
|
if c < ' ' {
|
|
|
|
|
return !yy_isspace(c) // exclude good white space
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if 0x7f <= c && c <= 0xa0 { // DEL, unicode block including unbreakable space.
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Loophack struct {
|
|
|
|
|
v int
|
|
|
|
|
next *Loophack
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _yylex_lstk *Loophack
|
|
|
|
|
|
|
|
|
|
func _yylex(yylval *yySymType) int32 {
|
|
|
|
|
var c1 int
|
|
|
|
|
var escflag int
|
|
|
|
|
var v int64
|
|
|
|
|
var cp *bytes.Buffer
|
|
|
|
|
var rune_ uint
|
|
|
|
|
var s *Sym
|
|
|
|
|
var h *Loophack
|
2015-02-24 20:54:57 +00:00
|
|
|
var str string
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
prevlineno = lineno
|
|
|
|
|
|
|
|
|
|
l0:
|
2015-03-02 12:35:15 -05:00
|
|
|
c := getc()
|
2015-02-13 14:40:36 -05:00
|
|
|
if yy_isspace(c) {
|
|
|
|
|
if c == '\n' && curio.nlsemi != 0 {
|
|
|
|
|
ungetc(c)
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: implicit semi\n")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
return ';'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lineno = lexlineno /* start of token */
|
|
|
|
|
|
|
|
|
|
if c >= utf8.RuneSelf {
|
|
|
|
|
/* all multibyte runes are alpha */
|
|
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
|
|
|
|
|
goto talph
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if yy_isalpha(c) {
|
|
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
goto talph
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if yy_isdigit(c) {
|
2015-03-02 12:35:15 -05:00
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
if c != '0' {
|
|
|
|
|
for {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if yy_isdigit(c) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c == '.' {
|
|
|
|
|
goto casedot
|
|
|
|
|
}
|
|
|
|
|
if c == 'e' || c == 'E' || c == 'p' || c == 'P' {
|
|
|
|
|
goto caseep
|
|
|
|
|
}
|
|
|
|
|
if c == 'i' {
|
|
|
|
|
goto casei
|
|
|
|
|
}
|
|
|
|
|
goto ncu
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if c == 'x' || c == 'X' {
|
|
|
|
|
for {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if yy_isdigit(c) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c >= 'a' && c <= 'f' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c >= 'A' && c <= 'F' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if lexbuf.Len() == 2 {
|
|
|
|
|
Yyerror("malformed hex constant")
|
|
|
|
|
}
|
|
|
|
|
if c == 'p' {
|
|
|
|
|
goto caseep
|
|
|
|
|
}
|
|
|
|
|
goto ncu
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == 'p' { // 0p begins floating point zero
|
|
|
|
|
goto caseep
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c1 = 0
|
|
|
|
|
for {
|
|
|
|
|
if !yy_isdigit(c) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c < '0' || c > '7' {
|
|
|
|
|
c1 = 1 // not octal
|
|
|
|
|
}
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == '.' {
|
|
|
|
|
goto casedot
|
|
|
|
|
}
|
|
|
|
|
if c == 'e' || c == 'E' {
|
|
|
|
|
goto caseep
|
|
|
|
|
}
|
|
|
|
|
if c == 'i' {
|
|
|
|
|
goto casei
|
|
|
|
|
}
|
|
|
|
|
if c1 != 0 {
|
|
|
|
|
Yyerror("malformed octal constant")
|
|
|
|
|
}
|
|
|
|
|
goto ncu
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch c {
|
|
|
|
|
case EOF:
|
|
|
|
|
lineno = prevlineno
|
|
|
|
|
ungetc(EOF)
|
|
|
|
|
return -1
|
|
|
|
|
|
|
|
|
|
case '_':
|
|
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
goto talph
|
|
|
|
|
|
|
|
|
|
case '.':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if yy_isdigit(c1) {
|
|
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = c1
|
|
|
|
|
goto casedot
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '.' {
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '.' {
|
|
|
|
|
c = LDDD
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ungetc(c1)
|
|
|
|
|
c1 = '.'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* "..." */
|
|
|
|
|
case '"':
|
|
|
|
|
lexbuf.Reset()
|
|
|
|
|
lexbuf.WriteString(`"<string>"`)
|
|
|
|
|
|
|
|
|
|
cp = &strbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
|
|
|
|
|
for {
|
2015-02-17 22:13:49 -05:00
|
|
|
if escchar('"', &escflag, &v) {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if v < utf8.RuneSelf || escflag != 0 {
|
|
|
|
|
cp.WriteByte(byte(v))
|
|
|
|
|
} else {
|
|
|
|
|
rune_ = uint(v)
|
|
|
|
|
cp.WriteRune(rune(rune_))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto strlit
|
|
|
|
|
|
|
|
|
|
/* `...` */
|
|
|
|
|
case '`':
|
|
|
|
|
lexbuf.Reset()
|
|
|
|
|
lexbuf.WriteString("`<string>`")
|
|
|
|
|
|
|
|
|
|
cp = &strbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == '\r' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c == EOF {
|
|
|
|
|
Yyerror("eof in string")
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == '`' {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
cp.WriteRune(rune(c))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto strlit
|
|
|
|
|
|
|
|
|
|
/* '.' */
|
|
|
|
|
case '\'':
|
2015-02-17 22:13:49 -05:00
|
|
|
if escchar('\'', &escflag, &v) {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("empty character literal or unescaped ' in character literal")
|
|
|
|
|
v = '\''
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if !escchar('\'', &escflag, &v) {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("missing '")
|
|
|
|
|
ungetc(int(v))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yylval.val.U.Xval = new(Mpint)
|
|
|
|
|
Mpmovecfix(yylval.val.U.Xval, v)
|
|
|
|
|
yylval.val.Ctype = CTRUNE
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: codepoint literal\n")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
litbuf = "string literal"
|
|
|
|
|
return LLITERAL
|
|
|
|
|
|
|
|
|
|
case '/':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '*' {
|
2015-02-23 16:07:24 -05:00
|
|
|
nl := 0
|
2015-02-13 14:40:36 -05:00
|
|
|
for {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == '\n' {
|
|
|
|
|
nl = 1
|
|
|
|
|
}
|
|
|
|
|
for c == '*' {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == '/' {
|
|
|
|
|
if nl != 0 {
|
|
|
|
|
ungetc('\n')
|
|
|
|
|
}
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == '\n' {
|
|
|
|
|
nl = 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == EOF {
|
|
|
|
|
Yyerror("eof in comment")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '/' {
|
|
|
|
|
c = getlinepragma()
|
|
|
|
|
for {
|
|
|
|
|
if c == '\n' || c == EOF {
|
|
|
|
|
ungetc(c)
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = int(getr())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = ODIV
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ':':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LCOLAS
|
|
|
|
|
yylval.i = int(lexlineno)
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OMUL
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '%':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OMOD
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '+':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '+' {
|
|
|
|
|
c = LINC
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OADD
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '-':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '-' {
|
|
|
|
|
c = LDEC
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OSUB
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '>':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '>' {
|
|
|
|
|
c = LRSH
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = ORSH
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LGE
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = LGT
|
|
|
|
|
|
|
|
|
|
case '<':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '<' {
|
|
|
|
|
c = LLSH
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OLSH
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LLE
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '-' {
|
|
|
|
|
c = LCOMM
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = LLT
|
|
|
|
|
|
|
|
|
|
case '=':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LEQ
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '!':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LNE
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '&':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '&' {
|
|
|
|
|
c = LANDAND
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '^' {
|
|
|
|
|
c = LANDNOT
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OANDNOT
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OAND
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '|':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '|' {
|
|
|
|
|
c = LOROR
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OOR
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '^':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OXOR
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* clumsy dance:
|
|
|
|
|
* to implement rule that disallows
|
|
|
|
|
* if T{1}[0] { ... }
|
|
|
|
|
* but allows
|
|
|
|
|
* if (T{1}[0]) { ... }
|
|
|
|
|
* the block bodies for if/for/switch/select
|
|
|
|
|
* begin with an LBODY token, not '{'.
|
|
|
|
|
*
|
|
|
|
|
* when we see the keyword, the next
|
|
|
|
|
* non-parenthesized '{' becomes an LBODY.
|
|
|
|
|
* loophack is normally 0.
|
|
|
|
|
* a keyword makes it go up to 1.
|
|
|
|
|
* parens push loophack onto a stack and go back to 0.
|
|
|
|
|
* a '{' with loophack == 1 becomes LBODY and disables loophack.
|
|
|
|
|
*
|
|
|
|
|
* i said it was clumsy.
|
|
|
|
|
*/
|
2015-04-01 09:38:44 -07:00
|
|
|
case '(', '[':
|
2015-02-13 14:40:36 -05:00
|
|
|
if loophack != 0 || _yylex_lstk != nil {
|
|
|
|
|
h = new(Loophack)
|
|
|
|
|
if h == nil {
|
|
|
|
|
Flusherrors()
|
|
|
|
|
Yyerror("out of memory")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
h.v = loophack
|
|
|
|
|
h.next = _yylex_lstk
|
|
|
|
|
_yylex_lstk = h
|
|
|
|
|
loophack = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto lx
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case ')', ']':
|
2015-02-13 14:40:36 -05:00
|
|
|
if _yylex_lstk != nil {
|
|
|
|
|
h = _yylex_lstk
|
|
|
|
|
loophack = h.v
|
|
|
|
|
_yylex_lstk = h.next
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto lx
|
|
|
|
|
|
|
|
|
|
case '{':
|
|
|
|
|
if loophack == 1 {
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("%v lex: LBODY\n", Ctxt.Line(int(lexlineno)))
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
loophack = 0
|
|
|
|
|
return LBODY
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto lx
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ungetc(c1)
|
|
|
|
|
|
|
|
|
|
lx:
|
|
|
|
|
if c > 0xff {
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lexlineno)), lexname(c))
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lexlineno)), c)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if isfrog(c) {
|
|
|
|
|
Yyerror("illegal character 0x%x", uint(c))
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if importpkg == nil && (c == '#' || c == '$' || c == '?' || c == '@' || c == '\\') {
|
|
|
|
|
Yyerror("%s: unexpected %c", "syntax error", c)
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return int32(c)
|
|
|
|
|
|
|
|
|
|
asop:
|
|
|
|
|
yylval.i = c // rathole to hold which asop
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: TOKEN ASOP %c\n", c)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
return LASOP
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* cp is set to lexbuf and some
|
|
|
|
|
* prefix has been stored
|
|
|
|
|
*/
|
|
|
|
|
talph:
|
|
|
|
|
for {
|
|
|
|
|
if c >= utf8.RuneSelf {
|
|
|
|
|
ungetc(c)
|
|
|
|
|
rune_ = uint(getr())
|
|
|
|
|
|
|
|
|
|
// 0xb7 · is used for internal names
|
|
|
|
|
if !unicode.IsLetter(rune(rune_)) && !unicode.IsDigit(rune(rune_)) && (importpkg == nil || rune_ != 0xb7) {
|
|
|
|
|
Yyerror("invalid identifier character U+%04x", rune_)
|
|
|
|
|
}
|
|
|
|
|
cp.WriteRune(rune(rune_))
|
|
|
|
|
} else if !yy_isalnum(c) && c != '_' {
|
|
|
|
|
break
|
|
|
|
|
} else {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
}
|
|
|
|
|
c = getc()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp = nil
|
|
|
|
|
ungetc(c)
|
|
|
|
|
|
2015-03-02 16:21:15 -05:00
|
|
|
s = LookupBytes(lexbuf.Bytes())
|
2015-02-13 14:40:36 -05:00
|
|
|
switch s.Lexical {
|
|
|
|
|
case LIGNORE:
|
|
|
|
|
goto l0
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case LFOR, LIF, LSWITCH, LSELECT:
|
2015-02-13 14:40:36 -05:00
|
|
|
loophack = 1 // see comment about loophack above
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
fmt.Printf("lex: %s %s\n", s, lexname(int(s.Lexical)))
|
2015-02-23 17:34:49 -05:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.sym = s
|
|
|
|
|
return int32(s.Lexical)
|
|
|
|
|
|
|
|
|
|
ncu:
|
|
|
|
|
cp = nil
|
|
|
|
|
ungetc(c)
|
|
|
|
|
|
2015-02-24 20:54:57 +00:00
|
|
|
str = lexbuf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.val.U.Xval = new(Mpint)
|
2015-02-24 20:54:57 +00:00
|
|
|
mpatofix(yylval.val.U.Xval, str)
|
2015-03-18 14:10:22 -07:00
|
|
|
if yylval.val.U.Xval.Ovf {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("overflow in constant")
|
|
|
|
|
Mpmovecfix(yylval.val.U.Xval, 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yylval.val.Ctype = CTINT
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: integer literal\n")
|
|
|
|
|
}
|
2015-02-24 20:54:57 +00:00
|
|
|
litbuf = "literal " + str
|
2015-02-13 14:40:36 -05:00
|
|
|
return LLITERAL
|
|
|
|
|
|
|
|
|
|
casedot:
|
|
|
|
|
for {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if !yy_isdigit(c) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == 'i' {
|
|
|
|
|
goto casei
|
|
|
|
|
}
|
|
|
|
|
if c != 'e' && c != 'E' {
|
|
|
|
|
goto caseout
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
caseep:
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if c == '+' || c == '-' {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !yy_isdigit(c) {
|
|
|
|
|
Yyerror("malformed fp constant exponent")
|
|
|
|
|
}
|
|
|
|
|
for yy_isdigit(c) {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == 'i' {
|
|
|
|
|
goto casei
|
|
|
|
|
}
|
|
|
|
|
goto caseout
|
|
|
|
|
|
|
|
|
|
// imaginary constant
|
|
|
|
|
casei:
|
|
|
|
|
cp = nil
|
|
|
|
|
|
2015-02-24 20:54:57 +00:00
|
|
|
str = lexbuf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.val.U.Cval = new(Mpcplx)
|
|
|
|
|
Mpmovecflt(&yylval.val.U.Cval.Real, 0.0)
|
2015-02-24 20:54:57 +00:00
|
|
|
mpatoflt(&yylval.val.U.Cval.Imag, str)
|
2015-03-20 16:59:08 -07:00
|
|
|
if yylval.val.U.Cval.Imag.Val.IsInf() {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("overflow in imaginary constant")
|
|
|
|
|
Mpmovecflt(&yylval.val.U.Cval.Real, 0.0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yylval.val.Ctype = CTCPLX
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: imaginary literal\n")
|
|
|
|
|
}
|
2015-02-24 20:54:57 +00:00
|
|
|
litbuf = "literal " + str
|
2015-02-13 14:40:36 -05:00
|
|
|
return LLITERAL
|
|
|
|
|
|
|
|
|
|
caseout:
|
|
|
|
|
cp = nil
|
|
|
|
|
ungetc(c)
|
|
|
|
|
|
2015-02-24 20:54:57 +00:00
|
|
|
str = lexbuf.String()
|
2015-03-20 16:59:08 -07:00
|
|
|
yylval.val.U.Fval = newMpflt()
|
2015-02-24 20:54:57 +00:00
|
|
|
mpatoflt(yylval.val.U.Fval, str)
|
2015-03-20 16:59:08 -07:00
|
|
|
if yylval.val.U.Fval.Val.IsInf() {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("overflow in float constant")
|
|
|
|
|
Mpmovecflt(yylval.val.U.Fval, 0.0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yylval.val.Ctype = CTFLT
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: floating literal\n")
|
|
|
|
|
}
|
2015-02-24 20:54:57 +00:00
|
|
|
litbuf = "literal " + str
|
2015-02-13 14:40:36 -05:00
|
|
|
return LLITERAL
|
|
|
|
|
|
|
|
|
|
strlit:
|
2015-03-02 16:03:26 -05:00
|
|
|
yylval.val.U.Sval = internString(cp.Bytes())
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.val.Ctype = CTSTR
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: string literal\n")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
litbuf = "string literal"
|
|
|
|
|
return LLITERAL
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
var internedStrings = map[string]string{}
|
|
|
|
|
|
|
|
|
|
func internString(b []byte) string {
|
|
|
|
|
s, ok := internedStrings[string(b)] // string(b) here doesn't allocate
|
|
|
|
|
if ok {
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
s = string(b)
|
|
|
|
|
internedStrings[s] = s
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func more(pp *string) bool {
|
|
|
|
|
p := *pp
|
|
|
|
|
for p != "" && yy_isspace(int(p[0])) {
|
|
|
|
|
p = p[1:]
|
|
|
|
|
}
|
|
|
|
|
*pp = p
|
|
|
|
|
return p != ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* read and interpret syntax that looks like
|
|
|
|
|
* //line parse.y:15
|
|
|
|
|
* as a discontinuity in sequential line numbers.
|
|
|
|
|
* the next line of input comes from parse.y:15
|
|
|
|
|
*/
|
|
|
|
|
func getlinepragma() int {
|
|
|
|
|
var cmd, verb, name string
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
c := int(getr())
|
2015-02-13 14:40:36 -05:00
|
|
|
if c == 'g' {
|
2015-03-02 12:35:15 -05:00
|
|
|
cp := &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
cp.WriteByte('g') // already read
|
|
|
|
|
for {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == EOF || c >= utf8.RuneSelf {
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
if c == '\n' {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
}
|
|
|
|
|
cp = nil
|
|
|
|
|
|
2015-03-08 22:41:48 -04:00
|
|
|
text := lexbuf.String()
|
|
|
|
|
|
|
|
|
|
if strings.HasPrefix(text, "go:cgo_") {
|
|
|
|
|
pragcgo(text)
|
2015-03-02 12:35:15 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-08 22:41:48 -04:00
|
|
|
cmd = text
|
2015-03-02 12:35:15 -05:00
|
|
|
verb = cmd
|
|
|
|
|
if i := strings.Index(verb, " "); i >= 0 {
|
|
|
|
|
verb = verb[:i]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:linkname" {
|
|
|
|
|
if imported_unsafe == 0 {
|
|
|
|
|
Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"")
|
|
|
|
|
}
|
|
|
|
|
f := strings.Fields(cmd)
|
|
|
|
|
if len(f) != 3 {
|
|
|
|
|
Yyerror("usage: //go:linkname localname linkname")
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lookup(f[1]).Linkname = f[2]
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:nointerface" && obj.Fieldtrack_enabled != 0 {
|
|
|
|
|
nointerface = true
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:noescape" {
|
|
|
|
|
noescape = true
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:nosplit" {
|
|
|
|
|
nosplit = true
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:nowritebarrier" {
|
|
|
|
|
if compiling_runtime == 0 {
|
|
|
|
|
Yyerror("//go:nowritebarrier only allowed in runtime")
|
|
|
|
|
}
|
|
|
|
|
nowritebarrier = true
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if c != 'l' {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
for i := 1; i < 5; i++ {
|
2015-02-13 14:40:36 -05:00
|
|
|
c = int(getr())
|
|
|
|
|
if c != int("line "[i]) {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
cp := &lexbuf
|
2015-02-13 14:40:36 -05:00
|
|
|
cp.Reset()
|
2015-03-02 12:35:15 -05:00
|
|
|
linep := 0
|
2015-02-13 14:40:36 -05:00
|
|
|
for {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == EOF {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if c == '\n' {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c == ' ' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c == ':' {
|
|
|
|
|
linep = cp.Len() + 1
|
|
|
|
|
}
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp = nil
|
|
|
|
|
|
|
|
|
|
if linep == 0 {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-08 22:41:48 -04:00
|
|
|
text := lexbuf.String()
|
2015-03-02 12:35:15 -05:00
|
|
|
n := 0
|
2015-03-08 22:41:48 -04:00
|
|
|
for _, c := range text[linep:] {
|
2015-02-13 14:40:36 -05:00
|
|
|
if c < '0' || c > '9' {
|
|
|
|
|
goto out
|
|
|
|
|
}
|
|
|
|
|
n = n*10 + int(c) - '0'
|
|
|
|
|
if n > 1e8 {
|
|
|
|
|
Yyerror("line number out of range")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n <= 0 {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-08 22:41:48 -04:00
|
|
|
name = text[:linep-1]
|
2015-02-13 14:40:36 -05:00
|
|
|
linehist(name, int32(n), 0)
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getimpsym(pp *string) string {
|
|
|
|
|
more(pp) // skip spaces
|
|
|
|
|
p := *pp
|
|
|
|
|
if p == "" || p[0] == '"' {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
i := 0
|
|
|
|
|
for i < len(p) && !yy_isspace(int(p[i])) && p[i] != '"' {
|
|
|
|
|
i++
|
|
|
|
|
}
|
|
|
|
|
sym := p[:i]
|
|
|
|
|
*pp = p[i:]
|
|
|
|
|
return sym
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getquoted(pp *string) (string, bool) {
|
|
|
|
|
more(pp) // skip spaces
|
|
|
|
|
p := *pp
|
|
|
|
|
if p == "" || p[0] != '"' {
|
|
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
p = p[1:]
|
|
|
|
|
i := strings.Index(p, `"`)
|
|
|
|
|
if i < 0 {
|
|
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
*pp = p[i+1:]
|
|
|
|
|
return p[:i], true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copied nearly verbatim from the C compiler's #pragma parser.
|
|
|
|
|
// TODO: Rewrite more cleanly once the compiler is written in Go.
|
|
|
|
|
func pragcgo(text string) {
|
|
|
|
|
var q string
|
|
|
|
|
|
|
|
|
|
if i := strings.Index(text, " "); i >= 0 {
|
|
|
|
|
text, q = text[:i], text[i:]
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
verb := text[3:] // skip "go:"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if verb == "cgo_dynamic_linker" || verb == "dynlinker" {
|
|
|
|
|
var ok bool
|
2015-02-23 16:07:24 -05:00
|
|
|
var p string
|
2015-02-13 14:40:36 -05:00
|
|
|
p, ok = getquoted(&q)
|
|
|
|
|
if !ok {
|
2015-03-02 12:35:15 -05:00
|
|
|
Yyerror("usage: //go:cgo_dynamic_linker \"path\"")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_dynamic_linker %v\n", plan9quote(p))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "dynexport" {
|
|
|
|
|
verb = "cgo_export_dynamic"
|
|
|
|
|
}
|
|
|
|
|
if verb == "cgo_export_static" || verb == "cgo_export_dynamic" {
|
2015-02-23 16:07:24 -05:00
|
|
|
local := getimpsym(&q)
|
|
|
|
|
var remote string
|
2015-02-13 14:40:36 -05:00
|
|
|
if local == "" {
|
|
|
|
|
goto err2
|
|
|
|
|
}
|
|
|
|
|
if !more(&q) {
|
|
|
|
|
pragcgobuf += fmt.Sprintf("%s %v\n", verb, plan9quote(local))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remote = getimpsym(&q)
|
|
|
|
|
if remote == "" {
|
|
|
|
|
goto err2
|
|
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("%s %v %v\n", verb, plan9quote(local), plan9quote(remote))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
err2:
|
|
|
|
|
Yyerror("usage: //go:%s local [remote]", verb)
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "cgo_import_dynamic" || verb == "dynimport" {
|
|
|
|
|
var ok bool
|
2015-02-23 16:07:24 -05:00
|
|
|
local := getimpsym(&q)
|
|
|
|
|
var p string
|
|
|
|
|
var remote string
|
2015-02-13 14:40:36 -05:00
|
|
|
if local == "" {
|
|
|
|
|
goto err3
|
|
|
|
|
}
|
|
|
|
|
if !more(&q) {
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v\n", plan9quote(local))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remote = getimpsym(&q)
|
|
|
|
|
if remote == "" {
|
|
|
|
|
goto err3
|
|
|
|
|
}
|
|
|
|
|
if !more(&q) {
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v\n", plan9quote(local), plan9quote(remote))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p, ok = getquoted(&q)
|
|
|
|
|
if !ok {
|
|
|
|
|
goto err3
|
|
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v %v\n", plan9quote(local), plan9quote(remote), plan9quote(p))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
err3:
|
|
|
|
|
Yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]")
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "cgo_import_static" {
|
2015-02-23 16:07:24 -05:00
|
|
|
local := getimpsym(&q)
|
2015-02-13 14:40:36 -05:00
|
|
|
if local == "" || more(&q) {
|
2015-03-02 12:35:15 -05:00
|
|
|
Yyerror("usage: //go:cgo_import_static local")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_import_static %v\n", plan9quote(local))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "cgo_ldflag" {
|
|
|
|
|
var ok bool
|
2015-02-23 16:07:24 -05:00
|
|
|
var p string
|
2015-02-13 14:40:36 -05:00
|
|
|
p, ok = getquoted(&q)
|
|
|
|
|
if !ok {
|
2015-03-02 12:35:15 -05:00
|
|
|
Yyerror("usage: //go:cgo_ldflag \"arg\"")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_ldflag %v\n", plan9quote(p))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type yy struct{}
|
|
|
|
|
|
|
|
|
|
func (yy) Lex(v *yySymType) int {
|
|
|
|
|
return int(yylex(v))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (yy) Error(msg string) {
|
|
|
|
|
Yyerror("%s", msg)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 14:02:27 -05:00
|
|
|
var theparser yyParser
|
|
|
|
|
var parsing bool
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func yyparse() {
|
2015-02-23 14:02:27 -05:00
|
|
|
theparser = yyNewParser()
|
|
|
|
|
parsing = true
|
|
|
|
|
theparser.Parse(yy{})
|
|
|
|
|
parsing = false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func yylex(yylval *yySymType) int32 {
|
2015-02-23 16:07:24 -05:00
|
|
|
lx := int(_yylex(yylval))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if curio.nlsemi != 0 && lx == EOF {
|
|
|
|
|
// Treat EOF as "end of line" for the purposes
|
|
|
|
|
// of inserting a semicolon.
|
|
|
|
|
lx = ';'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch lx {
|
|
|
|
|
case LNAME,
|
|
|
|
|
LLITERAL,
|
|
|
|
|
LBREAK,
|
|
|
|
|
LCONTINUE,
|
|
|
|
|
LFALL,
|
|
|
|
|
LRETURN,
|
|
|
|
|
LINC,
|
|
|
|
|
LDEC,
|
|
|
|
|
')',
|
|
|
|
|
'}',
|
|
|
|
|
']':
|
|
|
|
|
curio.nlsemi = 1
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
curio.nlsemi = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Track last two tokens returned by yylex.
|
|
|
|
|
yyprev = yylast
|
|
|
|
|
|
|
|
|
|
yylast = lx
|
|
|
|
|
return int32(lx)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getc() int {
|
2015-02-23 16:07:24 -05:00
|
|
|
c := curio.peekc
|
2015-02-13 14:40:36 -05:00
|
|
|
if c != 0 {
|
|
|
|
|
curio.peekc = curio.peekc1
|
|
|
|
|
curio.peekc1 = 0
|
|
|
|
|
goto check
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if curio.bin == nil {
|
|
|
|
|
if len(curio.cp) == 0 {
|
|
|
|
|
c = 0
|
|
|
|
|
} else {
|
|
|
|
|
c = int(curio.cp[0])
|
|
|
|
|
curio.cp = curio.cp[1:]
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
loop:
|
|
|
|
|
c = obj.Bgetc(curio.bin)
|
|
|
|
|
if c == 0xef {
|
2015-05-01 15:29:11 +10:00
|
|
|
buf, err := curio.bin.Peek(2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("getc: peeking: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if buf[0] == 0xbb && buf[1] == 0xbf {
|
2015-02-13 14:40:36 -05:00
|
|
|
yyerrorl(int(lexlineno), "Unicode (UTF-8) BOM in middle of file")
|
2015-05-01 15:29:11 +10:00
|
|
|
|
|
|
|
|
// consume BOM bytes
|
|
|
|
|
obj.Bgetc(curio.bin)
|
|
|
|
|
obj.Bgetc(curio.bin)
|
2015-02-13 14:40:36 -05:00
|
|
|
goto loop
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check:
|
|
|
|
|
switch c {
|
|
|
|
|
case 0:
|
|
|
|
|
if curio.bin != nil {
|
|
|
|
|
Yyerror("illegal NUL byte")
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// insert \n at EOF
|
|
|
|
|
case EOF:
|
|
|
|
|
if curio.eofnl != 0 || curio.last == '\n' {
|
|
|
|
|
return EOF
|
|
|
|
|
}
|
|
|
|
|
curio.eofnl = 1
|
|
|
|
|
c = '\n'
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
case '\n':
|
|
|
|
|
if pushedio.bin == nil {
|
|
|
|
|
lexlineno++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curio.last = c
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ungetc(c int) {
|
|
|
|
|
curio.peekc1 = curio.peekc
|
|
|
|
|
curio.peekc = c
|
|
|
|
|
if c == '\n' && pushedio.bin == nil {
|
|
|
|
|
lexlineno--
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getr() int32 {
|
|
|
|
|
var buf [utf8.UTFMax]byte
|
|
|
|
|
|
|
|
|
|
for i := 0; ; i++ {
|
|
|
|
|
c := getc()
|
|
|
|
|
if i == 0 && c < utf8.RuneSelf {
|
|
|
|
|
return int32(c)
|
|
|
|
|
}
|
|
|
|
|
buf[i] = byte(c)
|
|
|
|
|
if i+1 == len(buf) || utf8.FullRune(buf[:i+1]) {
|
|
|
|
|
r, w := utf8.DecodeRune(buf[:i+1])
|
|
|
|
|
if r == utf8.RuneError && w == 1 {
|
|
|
|
|
lineno = lexlineno
|
2015-03-02 15:22:19 -05:00
|
|
|
// The string conversion here makes a copy for passing
|
|
|
|
|
// to fmt.Printf, so that buf itself does not escape and can
|
|
|
|
|
// be allocated on the stack.
|
|
|
|
|
Yyerror("illegal UTF-8 sequence % x", string(buf[:i+1]))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
return int32(r)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func escchar(e int, escflg *int, val *int64) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
*escflg = 0
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
c := int(getr())
|
2015-02-13 14:40:36 -05:00
|
|
|
switch c {
|
|
|
|
|
case EOF:
|
|
|
|
|
Yyerror("eof in string")
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case '\n':
|
|
|
|
|
Yyerror("newline in string")
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case '\\':
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if c == e {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
*val = int64(c)
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
u := 0
|
2015-02-13 14:40:36 -05:00
|
|
|
c = int(getr())
|
2015-02-23 16:07:24 -05:00
|
|
|
var i int
|
2015-02-13 14:40:36 -05:00
|
|
|
switch c {
|
|
|
|
|
case 'x':
|
|
|
|
|
*escflg = 1 // it's a byte
|
|
|
|
|
i = 2
|
|
|
|
|
goto hex
|
|
|
|
|
|
|
|
|
|
case 'u':
|
|
|
|
|
i = 4
|
|
|
|
|
u = 1
|
|
|
|
|
goto hex
|
|
|
|
|
|
|
|
|
|
case 'U':
|
|
|
|
|
i = 8
|
|
|
|
|
u = 1
|
|
|
|
|
goto hex
|
|
|
|
|
|
|
|
|
|
case '0',
|
|
|
|
|
'1',
|
|
|
|
|
'2',
|
|
|
|
|
'3',
|
|
|
|
|
'4',
|
|
|
|
|
'5',
|
|
|
|
|
'6',
|
|
|
|
|
'7':
|
|
|
|
|
*escflg = 1 // it's a byte
|
2015-03-02 12:35:15 -05:00
|
|
|
l := int64(c) - '0'
|
|
|
|
|
for i := 2; i > 0; i-- {
|
|
|
|
|
c = getc()
|
|
|
|
|
if c >= '0' && c <= '7' {
|
|
|
|
|
l = l*8 + int64(c) - '0'
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Yyerror("non-octal character in escape sequence: %c", c)
|
|
|
|
|
ungetc(c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if l > 255 {
|
|
|
|
|
Yyerror("octal escape value > 255: %d", l)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*val = l
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case 'a':
|
|
|
|
|
c = '\a'
|
|
|
|
|
case 'b':
|
|
|
|
|
c = '\b'
|
|
|
|
|
case 'f':
|
|
|
|
|
c = '\f'
|
|
|
|
|
case 'n':
|
|
|
|
|
c = '\n'
|
|
|
|
|
case 'r':
|
|
|
|
|
c = '\r'
|
|
|
|
|
case 't':
|
|
|
|
|
c = '\t'
|
|
|
|
|
case 'v':
|
|
|
|
|
c = '\v'
|
|
|
|
|
case '\\':
|
|
|
|
|
c = '\\'
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if c != e {
|
|
|
|
|
Yyerror("unknown escape sequence: %c", c)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*val = int64(c)
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
hex:
|
2015-03-02 12:35:15 -05:00
|
|
|
l := int64(0)
|
2015-02-13 14:40:36 -05:00
|
|
|
for ; i > 0; i-- {
|
|
|
|
|
c = getc()
|
|
|
|
|
if c >= '0' && c <= '9' {
|
|
|
|
|
l = l*16 + int64(c) - '0'
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c >= 'a' && c <= 'f' {
|
|
|
|
|
l = l*16 + int64(c) - 'a' + 10
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c >= 'A' && c <= 'F' {
|
|
|
|
|
l = l*16 + int64(c) - 'A' + 10
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Yyerror("non-hex character in escape sequence: %c", c)
|
|
|
|
|
ungetc(c)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if u != 0 && (l > utf8.MaxRune || (0xd800 <= l && l < 0xe000)) {
|
|
|
|
|
Yyerror("invalid Unicode code point in escape sequence: %#x", l)
|
|
|
|
|
l = utf8.RuneError
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*val = l
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var syms = []struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{
|
|
|
|
|
/* basic types */
|
2015-04-02 15:19:10 -07:00
|
|
|
{"int8", LNAME, TINT8, OXXX},
|
|
|
|
|
{"int16", LNAME, TINT16, OXXX},
|
|
|
|
|
{"int32", LNAME, TINT32, OXXX},
|
|
|
|
|
{"int64", LNAME, TINT64, OXXX},
|
|
|
|
|
{"uint8", LNAME, TUINT8, OXXX},
|
|
|
|
|
{"uint16", LNAME, TUINT16, OXXX},
|
|
|
|
|
{"uint32", LNAME, TUINT32, OXXX},
|
|
|
|
|
{"uint64", LNAME, TUINT64, OXXX},
|
|
|
|
|
{"float32", LNAME, TFLOAT32, OXXX},
|
|
|
|
|
{"float64", LNAME, TFLOAT64, OXXX},
|
|
|
|
|
{"complex64", LNAME, TCOMPLEX64, OXXX},
|
|
|
|
|
{"complex128", LNAME, TCOMPLEX128, OXXX},
|
|
|
|
|
{"bool", LNAME, TBOOL, OXXX},
|
|
|
|
|
{"string", LNAME, TSTRING, OXXX},
|
|
|
|
|
{"any", LNAME, TANY, OXXX},
|
|
|
|
|
{"break", LBREAK, Txxx, OXXX},
|
|
|
|
|
{"case", LCASE, Txxx, OXXX},
|
|
|
|
|
{"chan", LCHAN, Txxx, OXXX},
|
|
|
|
|
{"const", LCONST, Txxx, OXXX},
|
|
|
|
|
{"continue", LCONTINUE, Txxx, OXXX},
|
|
|
|
|
{"default", LDEFAULT, Txxx, OXXX},
|
|
|
|
|
{"else", LELSE, Txxx, OXXX},
|
|
|
|
|
{"defer", LDEFER, Txxx, OXXX},
|
|
|
|
|
{"fallthrough", LFALL, Txxx, OXXX},
|
|
|
|
|
{"for", LFOR, Txxx, OXXX},
|
|
|
|
|
{"func", LFUNC, Txxx, OXXX},
|
|
|
|
|
{"go", LGO, Txxx, OXXX},
|
|
|
|
|
{"goto", LGOTO, Txxx, OXXX},
|
|
|
|
|
{"if", LIF, Txxx, OXXX},
|
|
|
|
|
{"import", LIMPORT, Txxx, OXXX},
|
|
|
|
|
{"interface", LINTERFACE, Txxx, OXXX},
|
|
|
|
|
{"map", LMAP, Txxx, OXXX},
|
|
|
|
|
{"package", LPACKAGE, Txxx, OXXX},
|
|
|
|
|
{"range", LRANGE, Txxx, OXXX},
|
|
|
|
|
{"return", LRETURN, Txxx, OXXX},
|
|
|
|
|
{"select", LSELECT, Txxx, OXXX},
|
|
|
|
|
{"struct", LSTRUCT, Txxx, OXXX},
|
|
|
|
|
{"switch", LSWITCH, Txxx, OXXX},
|
|
|
|
|
{"type", LTYPE, Txxx, OXXX},
|
|
|
|
|
{"var", LVAR, Txxx, OXXX},
|
|
|
|
|
{"append", LNAME, Txxx, OAPPEND},
|
|
|
|
|
{"cap", LNAME, Txxx, OCAP},
|
|
|
|
|
{"close", LNAME, Txxx, OCLOSE},
|
|
|
|
|
{"complex", LNAME, Txxx, OCOMPLEX},
|
|
|
|
|
{"copy", LNAME, Txxx, OCOPY},
|
|
|
|
|
{"delete", LNAME, Txxx, ODELETE},
|
|
|
|
|
{"imag", LNAME, Txxx, OIMAG},
|
|
|
|
|
{"len", LNAME, Txxx, OLEN},
|
|
|
|
|
{"make", LNAME, Txxx, OMAKE},
|
|
|
|
|
{"new", LNAME, Txxx, ONEW},
|
|
|
|
|
{"panic", LNAME, Txxx, OPANIC},
|
|
|
|
|
{"print", LNAME, Txxx, OPRINT},
|
|
|
|
|
{"println", LNAME, Txxx, OPRINTN},
|
|
|
|
|
{"real", LNAME, Txxx, OREAL},
|
|
|
|
|
{"recover", LNAME, Txxx, ORECOVER},
|
|
|
|
|
{"notwithstanding", LIGNORE, Txxx, OXXX},
|
|
|
|
|
{"thetruthofthematter", LIGNORE, Txxx, OXXX},
|
|
|
|
|
{"despiteallobjections", LIGNORE, Txxx, OXXX},
|
|
|
|
|
{"whereas", LIGNORE, Txxx, OXXX},
|
|
|
|
|
{"insofaras", LIGNORE, Txxx, OXXX},
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func lexinit() {
|
|
|
|
|
var lex int
|
|
|
|
|
var s *Sym
|
|
|
|
|
var s1 *Sym
|
|
|
|
|
var t *Type
|
|
|
|
|
var etype int
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* initialize basic types array
|
|
|
|
|
* initialize known symbols
|
|
|
|
|
*/
|
2015-02-23 16:07:24 -05:00
|
|
|
for i := 0; i < len(syms); i++ {
|
2015-02-13 14:40:36 -05:00
|
|
|
lex = syms[i].lexical
|
|
|
|
|
s = Lookup(syms[i].name)
|
|
|
|
|
s.Lexical = uint16(lex)
|
|
|
|
|
|
|
|
|
|
etype = syms[i].etype
|
|
|
|
|
if etype != Txxx {
|
|
|
|
|
if etype < 0 || etype >= len(Types) {
|
|
|
|
|
Fatal("lexinit: %s bad etype", s.Name)
|
|
|
|
|
}
|
|
|
|
|
s1 = Pkglookup(syms[i].name, builtinpkg)
|
|
|
|
|
t = Types[etype]
|
|
|
|
|
if t == nil {
|
|
|
|
|
t = typ(etype)
|
|
|
|
|
t.Sym = s1
|
|
|
|
|
|
|
|
|
|
if etype != TANY && etype != TSTRING {
|
|
|
|
|
dowidth(t)
|
|
|
|
|
}
|
|
|
|
|
Types[etype] = t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = typenod(t)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
etype = syms[i].op
|
|
|
|
|
if etype != OXXX {
|
|
|
|
|
s1 = Pkglookup(syms[i].name, builtinpkg)
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = Nod(ONAME, nil, nil)
|
|
|
|
|
s1.Def.Sym = s1
|
|
|
|
|
s1.Def.Etype = uint8(etype)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// logically, the type of a string literal.
|
|
|
|
|
// types[TSTRING] is the named type string
|
|
|
|
|
// (the type of x in var x string or var x = "hello").
|
|
|
|
|
// this is the ideal form
|
|
|
|
|
// (the type of x in const x = "hello").
|
|
|
|
|
idealstring = typ(TSTRING)
|
|
|
|
|
|
|
|
|
|
idealbool = typ(TBOOL)
|
|
|
|
|
|
|
|
|
|
s = Pkglookup("true", builtinpkg)
|
2015-02-17 22:13:49 -05:00
|
|
|
s.Def = Nodbool(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
s.Def.Sym = Lookup("true")
|
|
|
|
|
s.Def.Type = idealbool
|
|
|
|
|
|
|
|
|
|
s = Pkglookup("false", builtinpkg)
|
2015-02-17 22:13:49 -05:00
|
|
|
s.Def = Nodbool(false)
|
2015-02-13 14:40:36 -05:00
|
|
|
s.Def.Sym = Lookup("false")
|
|
|
|
|
s.Def.Type = idealbool
|
|
|
|
|
|
|
|
|
|
s = Lookup("_")
|
|
|
|
|
s.Block = -100
|
|
|
|
|
s.Def = Nod(ONAME, nil, nil)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
Types[TBLANK] = typ(TBLANK)
|
|
|
|
|
s.Def.Type = Types[TBLANK]
|
|
|
|
|
nblank = s.Def
|
|
|
|
|
|
|
|
|
|
s = Pkglookup("_", builtinpkg)
|
|
|
|
|
s.Block = -100
|
|
|
|
|
s.Def = Nod(ONAME, nil, nil)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
Types[TBLANK] = typ(TBLANK)
|
|
|
|
|
s.Def.Type = Types[TBLANK]
|
|
|
|
|
|
|
|
|
|
Types[TNIL] = typ(TNIL)
|
|
|
|
|
s = Pkglookup("nil", builtinpkg)
|
2015-02-23 16:07:24 -05:00
|
|
|
var v Val
|
2015-02-13 14:40:36 -05:00
|
|
|
v.Ctype = CTNIL
|
|
|
|
|
s.Def = nodlit(v)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func lexinit1() {
|
|
|
|
|
// t = interface { Error() string }
|
2015-02-23 16:07:24 -05:00
|
|
|
rcvr := typ(TSTRUCT)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
rcvr.Type = typ(TFIELD)
|
|
|
|
|
rcvr.Type.Type = Ptrto(typ(TSTRUCT))
|
|
|
|
|
rcvr.Funarg = 1
|
2015-02-23 16:07:24 -05:00
|
|
|
in := typ(TSTRUCT)
|
2015-02-13 14:40:36 -05:00
|
|
|
in.Funarg = 1
|
2015-02-23 16:07:24 -05:00
|
|
|
out := typ(TSTRUCT)
|
2015-02-13 14:40:36 -05:00
|
|
|
out.Type = typ(TFIELD)
|
|
|
|
|
out.Type.Type = Types[TSTRING]
|
|
|
|
|
out.Funarg = 1
|
2015-02-23 16:07:24 -05:00
|
|
|
f := typ(TFUNC)
|
2015-02-13 14:40:36 -05:00
|
|
|
*getthis(f) = rcvr
|
|
|
|
|
*Getoutarg(f) = out
|
|
|
|
|
*getinarg(f) = in
|
|
|
|
|
f.Thistuple = 1
|
|
|
|
|
f.Intuple = 0
|
|
|
|
|
f.Outnamed = 0
|
|
|
|
|
f.Outtuple = 1
|
2015-02-23 16:07:24 -05:00
|
|
|
t := typ(TINTER)
|
2015-02-13 14:40:36 -05:00
|
|
|
t.Type = typ(TFIELD)
|
|
|
|
|
t.Type.Sym = Lookup("Error")
|
|
|
|
|
t.Type.Type = f
|
|
|
|
|
|
|
|
|
|
// error type
|
2015-02-23 16:07:24 -05:00
|
|
|
s := Lookup("error")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
s.Lexical = LNAME
|
2015-02-23 16:07:24 -05:00
|
|
|
s1 := Pkglookup("error", builtinpkg)
|
2015-02-13 14:40:36 -05:00
|
|
|
errortype = t
|
|
|
|
|
errortype.Sym = s1
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = typenod(errortype)
|
|
|
|
|
|
|
|
|
|
// byte alias
|
|
|
|
|
s = Lookup("byte")
|
|
|
|
|
|
|
|
|
|
s.Lexical = LNAME
|
|
|
|
|
s1 = Pkglookup("byte", builtinpkg)
|
|
|
|
|
bytetype = typ(TUINT8)
|
|
|
|
|
bytetype.Sym = s1
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = typenod(bytetype)
|
|
|
|
|
|
|
|
|
|
// rune alias
|
|
|
|
|
s = Lookup("rune")
|
|
|
|
|
|
|
|
|
|
s.Lexical = LNAME
|
|
|
|
|
s1 = Pkglookup("rune", builtinpkg)
|
|
|
|
|
runetype = typ(TINT32)
|
|
|
|
|
runetype.Sym = s1
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = typenod(runetype)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func lexfini() {
|
|
|
|
|
var s *Sym
|
|
|
|
|
var lex int
|
|
|
|
|
var etype int
|
|
|
|
|
var i int
|
|
|
|
|
|
|
|
|
|
for i = 0; i < len(syms); i++ {
|
|
|
|
|
lex = syms[i].lexical
|
|
|
|
|
if lex != LNAME {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
s = Lookup(syms[i].name)
|
|
|
|
|
s.Lexical = uint16(lex)
|
|
|
|
|
|
|
|
|
|
etype = syms[i].etype
|
|
|
|
|
if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil {
|
|
|
|
|
s.Def = typenod(Types[etype])
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
etype = syms[i].op
|
|
|
|
|
if etype != OXXX && s.Def == nil {
|
|
|
|
|
s.Def = Nod(ONAME, nil, nil)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Def.Etype = uint8(etype)
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// backend-specific builtin types (e.g. int).
|
|
|
|
|
for i = range Thearch.Typedefs {
|
|
|
|
|
s = Lookup(Thearch.Typedefs[i].Name)
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = typenod(Types[Thearch.Typedefs[i].Etype])
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// there's only so much table-driven we can handle.
|
|
|
|
|
// these are special cases.
|
|
|
|
|
s = Lookup("byte")
|
|
|
|
|
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = typenod(bytetype)
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("error")
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = typenod(errortype)
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("rune")
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = typenod(runetype)
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("nil")
|
|
|
|
|
if s.Def == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var v Val
|
2015-02-13 14:40:36 -05:00
|
|
|
v.Ctype = CTNIL
|
|
|
|
|
s.Def = nodlit(v)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("iota")
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = Nod(OIOTA, nil, nil)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("true")
|
|
|
|
|
if s.Def == nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
s.Def = Nodbool(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("false")
|
|
|
|
|
if s.Def == nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
s.Def = Nodbool(false)
|
2015-02-13 14:40:36 -05:00
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nodfp = Nod(ONAME, nil, nil)
|
|
|
|
|
nodfp.Type = Types[TINT32]
|
|
|
|
|
nodfp.Xoffset = 0
|
|
|
|
|
nodfp.Class = PPARAM
|
|
|
|
|
nodfp.Sym = Lookup(".fp")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lexn = []struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{
|
2015-04-02 15:19:10 -07:00
|
|
|
{LANDAND, "ANDAND"},
|
|
|
|
|
{LANDNOT, "ANDNOT"},
|
|
|
|
|
{LASOP, "ASOP"},
|
|
|
|
|
{LBREAK, "BREAK"},
|
|
|
|
|
{LCASE, "CASE"},
|
|
|
|
|
{LCHAN, "CHAN"},
|
|
|
|
|
{LCOLAS, "COLAS"},
|
|
|
|
|
{LCOMM, "<-"},
|
|
|
|
|
{LCONST, "CONST"},
|
|
|
|
|
{LCONTINUE, "CONTINUE"},
|
|
|
|
|
{LDDD, "..."},
|
|
|
|
|
{LDEC, "DEC"},
|
|
|
|
|
{LDEFAULT, "DEFAULT"},
|
|
|
|
|
{LDEFER, "DEFER"},
|
|
|
|
|
{LELSE, "ELSE"},
|
|
|
|
|
{LEQ, "EQ"},
|
|
|
|
|
{LFALL, "FALL"},
|
|
|
|
|
{LFOR, "FOR"},
|
|
|
|
|
{LFUNC, "FUNC"},
|
|
|
|
|
{LGE, "GE"},
|
|
|
|
|
{LGO, "GO"},
|
|
|
|
|
{LGOTO, "GOTO"},
|
|
|
|
|
{LGT, "GT"},
|
|
|
|
|
{LIF, "IF"},
|
|
|
|
|
{LIMPORT, "IMPORT"},
|
|
|
|
|
{LINC, "INC"},
|
|
|
|
|
{LINTERFACE, "INTERFACE"},
|
|
|
|
|
{LLE, "LE"},
|
|
|
|
|
{LLITERAL, "LITERAL"},
|
|
|
|
|
{LLSH, "LSH"},
|
|
|
|
|
{LLT, "LT"},
|
|
|
|
|
{LMAP, "MAP"},
|
|
|
|
|
{LNAME, "NAME"},
|
|
|
|
|
{LNE, "NE"},
|
|
|
|
|
{LOROR, "OROR"},
|
|
|
|
|
{LPACKAGE, "PACKAGE"},
|
|
|
|
|
{LRANGE, "RANGE"},
|
|
|
|
|
{LRETURN, "RETURN"},
|
|
|
|
|
{LRSH, "RSH"},
|
|
|
|
|
{LSELECT, "SELECT"},
|
|
|
|
|
{LSTRUCT, "STRUCT"},
|
|
|
|
|
{LSWITCH, "SWITCH"},
|
|
|
|
|
{LTYPE, "TYPE"},
|
|
|
|
|
{LVAR, "VAR"},
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func lexname(lex int) string {
|
2015-02-23 16:07:24 -05:00
|
|
|
for i := 0; i < len(lexn); i++ {
|
2015-02-13 14:40:36 -05:00
|
|
|
if lexn[i].lex == lex {
|
|
|
|
|
return lexn[i].name
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-20 13:50:46 -07:00
|
|
|
return fmt.Sprintf("LEX-%d", lex)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var yytfix = []struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{
|
2015-04-02 15:19:10 -07:00
|
|
|
{"$end", "EOF"},
|
|
|
|
|
{"LASOP", "op="},
|
|
|
|
|
{"LBREAK", "break"},
|
|
|
|
|
{"LCASE", "case"},
|
|
|
|
|
{"LCHAN", "chan"},
|
|
|
|
|
{"LCOLAS", ":="},
|
|
|
|
|
{"LCONST", "const"},
|
|
|
|
|
{"LCONTINUE", "continue"},
|
|
|
|
|
{"LDDD", "..."},
|
|
|
|
|
{"LDEFAULT", "default"},
|
|
|
|
|
{"LDEFER", "defer"},
|
|
|
|
|
{"LELSE", "else"},
|
|
|
|
|
{"LFALL", "fallthrough"},
|
|
|
|
|
{"LFOR", "for"},
|
|
|
|
|
{"LFUNC", "func"},
|
|
|
|
|
{"LGO", "go"},
|
|
|
|
|
{"LGOTO", "goto"},
|
|
|
|
|
{"LIF", "if"},
|
|
|
|
|
{"LIMPORT", "import"},
|
|
|
|
|
{"LINTERFACE", "interface"},
|
|
|
|
|
{"LMAP", "map"},
|
|
|
|
|
{"LNAME", "name"},
|
|
|
|
|
{"LPACKAGE", "package"},
|
|
|
|
|
{"LRANGE", "range"},
|
|
|
|
|
{"LRETURN", "return"},
|
|
|
|
|
{"LSELECT", "select"},
|
|
|
|
|
{"LSTRUCT", "struct"},
|
|
|
|
|
{"LSWITCH", "switch"},
|
|
|
|
|
{"LTYPE", "type"},
|
|
|
|
|
{"LVAR", "var"},
|
|
|
|
|
{"LANDAND", "&&"},
|
|
|
|
|
{"LANDNOT", "&^"},
|
|
|
|
|
{"LBODY", "{"},
|
|
|
|
|
{"LCOMM", "<-"},
|
|
|
|
|
{"LDEC", "--"},
|
|
|
|
|
{"LINC", "++"},
|
|
|
|
|
{"LEQ", "=="},
|
|
|
|
|
{"LGE", ">="},
|
|
|
|
|
{"LGT", ">"},
|
|
|
|
|
{"LLE", "<="},
|
|
|
|
|
{"LLT", "<"},
|
|
|
|
|
{"LLSH", "<<"},
|
|
|
|
|
{"LRSH", ">>"},
|
|
|
|
|
{"LOROR", "||"},
|
|
|
|
|
{"LNE", "!="},
|
2015-02-13 14:40:36 -05:00
|
|
|
// spell out to avoid confusion with punctuation in error messages
|
2015-04-02 15:19:10 -07:00
|
|
|
{"';'", "semicolon or newline"},
|
|
|
|
|
{"','", "comma"},
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-02 17:01:14 -07:00
|
|
|
func init() {
|
|
|
|
|
yyErrorVerbose = true
|
|
|
|
|
|
|
|
|
|
Outer:
|
|
|
|
|
for i, s := range yyToknames {
|
|
|
|
|
// Apply yytfix if possible.
|
|
|
|
|
for _, fix := range yytfix {
|
|
|
|
|
if s == fix.have {
|
|
|
|
|
yyToknames[i] = fix.want
|
|
|
|
|
continue Outer
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Turn 'x' into x.
|
|
|
|
|
if len(s) == 3 && s[0] == '\'' && s[2] == '\'' {
|
|
|
|
|
yyToknames[i] = s[1:2]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
func pkgnotused(lineno int, path string, name string) {
|
2015-02-13 14:40:36 -05:00
|
|
|
// If the package was imported with a name other than the final
|
|
|
|
|
// import path element, show it explicitly in the error message.
|
|
|
|
|
// Note that this handles both renamed imports and imports of
|
|
|
|
|
// packages containing unconventional package declarations.
|
|
|
|
|
// Note that this uses / always, even on Windows, because Go import
|
|
|
|
|
// paths always use forward slashes.
|
2015-03-02 16:03:26 -05:00
|
|
|
elem := path
|
2015-02-13 14:40:36 -05:00
|
|
|
if i := strings.LastIndex(elem, "/"); i >= 0 {
|
|
|
|
|
elem = elem[i+1:]
|
|
|
|
|
}
|
|
|
|
|
if name == "" || elem == name {
|
2015-03-02 16:03:26 -05:00
|
|
|
yyerrorl(int(lineno), "imported and not used: %q", path)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-03-02 16:03:26 -05:00
|
|
|
yyerrorl(int(lineno), "imported and not used: %q as %s", path, name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func mkpackage(pkgname string) {
|
|
|
|
|
if localpkg.Name == "" {
|
|
|
|
|
if pkgname == "_" {
|
|
|
|
|
Yyerror("invalid package name _")
|
|
|
|
|
}
|
|
|
|
|
localpkg.Name = pkgname
|
|
|
|
|
} else {
|
|
|
|
|
if pkgname != localpkg.Name {
|
|
|
|
|
Yyerror("package %s; expected %s", pkgname, localpkg.Name)
|
|
|
|
|
}
|
2015-03-02 16:21:15 -05:00
|
|
|
for _, s := range localpkg.Syms {
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if s.Def.Op == OPACK {
|
|
|
|
|
// throw away top-level package name leftover
|
|
|
|
|
// from previous file.
|
|
|
|
|
// leave s->block set to cause redeclaration
|
|
|
|
|
// errors if a conflicting top-level name is
|
|
|
|
|
// introduced by a different file.
|
2015-03-06 21:18:41 +11:00
|
|
|
if !s.Def.Used && nsyntaxerrors == 0 {
|
2015-03-02 16:21:15 -05:00
|
|
|
pkgnotused(int(s.Def.Lineno), s.Def.Pkg.Path, s.Name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 16:21:15 -05:00
|
|
|
s.Def = nil
|
|
|
|
|
continue
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-02 16:21:15 -05:00
|
|
|
if s.Def.Sym != s {
|
|
|
|
|
// throw away top-level name left over
|
|
|
|
|
// from previous import . "x"
|
2015-03-06 21:18:41 +11:00
|
|
|
if s.Def.Pack != nil && !s.Def.Pack.Used && nsyntaxerrors == 0 {
|
2015-03-02 16:21:15 -05:00
|
|
|
pkgnotused(int(s.Def.Pack.Lineno), s.Def.Pack.Pkg.Path, "")
|
2015-03-06 21:18:41 +11:00
|
|
|
s.Def.Pack.Used = true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 16:21:15 -05:00
|
|
|
|
|
|
|
|
s.Def = nil
|
|
|
|
|
continue
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if outfile == "" {
|
2015-02-23 16:07:24 -05:00
|
|
|
p := infile
|
2015-02-13 14:40:36 -05:00
|
|
|
if i := strings.LastIndex(p, "/"); i >= 0 {
|
|
|
|
|
p = p[i+1:]
|
|
|
|
|
}
|
|
|
|
|
if Ctxt.Windows != 0 {
|
|
|
|
|
if i := strings.LastIndex(p, `\`); i >= 0 {
|
|
|
|
|
p = p[i+1:]
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-06 12:02:24 -08:00
|
|
|
if i := strings.LastIndex(p, "."); i >= 0 {
|
|
|
|
|
p = p[:i]
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-06 12:02:24 -08:00
|
|
|
outfile = fmt.Sprintf("%s.%c", p, Thearch.Thechar)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|