Commit 3c0fae53 authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: track pragmas in lexer rather than global variables

By using a Pragma bit set (8 bits) rather than 8 booleans, also
reduce Func type size by 8 bytes (208B -> 200B on 64bit platforms,
116B -> 108B on 32bit platforms).

Change-Id: Ibb7e1f8c418a0b5bc6ff813cbdde7bc6f0013b5a
Reviewed-on: https://go-review.googlesource.com/19966Reviewed-by: default avatarDave Cheney <dave@cheney.net>
parent 071e43a9
...@@ -240,10 +240,9 @@ func (p *importer) typ() *Type { ...@@ -240,10 +240,9 @@ func (p *importer) typ() *Type {
{ {
saved := structpkg saved := structpkg
structpkg = tsym.Pkg structpkg = tsym.Pkg
addmethod(sym, n.Type, false, nointerface) addmethod(sym, n.Type, false, false)
structpkg = saved structpkg = saved
} }
nointerface = false
funchdr(n) funchdr(n)
// (comment from go.y) // (comment from go.y)
......
...@@ -781,7 +781,7 @@ var sys_wbptr *Node ...@@ -781,7 +781,7 @@ var sys_wbptr *Node
func cgen_wbptr(n, res *Node) { func cgen_wbptr(n, res *Node) {
if Curfn != nil { if Curfn != nil {
if Curfn.Func.Nowritebarrier { if Curfn.Func.Pragma&Nowritebarrier != 0 {
Yyerror("write barrier prohibited") Yyerror("write barrier prohibited")
} }
if Curfn.Func.WBLineno == 0 { if Curfn.Func.WBLineno == 0 {
...@@ -831,7 +831,7 @@ func cgen_wbptr(n, res *Node) { ...@@ -831,7 +831,7 @@ func cgen_wbptr(n, res *Node) {
func cgen_wbfat(n, res *Node) { func cgen_wbfat(n, res *Node) {
if Curfn != nil { if Curfn != nil {
if Curfn.Func.Nowritebarrier { if Curfn.Func.Pragma&Nowritebarrier != 0 {
Yyerror("write barrier prohibited") Yyerror("write barrier prohibited")
} }
if Curfn.Func.WBLineno == 0 { if Curfn.Func.WBLineno == 0 {
......
...@@ -1530,7 +1530,7 @@ func checknowritebarrierrec() { ...@@ -1530,7 +1530,7 @@ func checknowritebarrierrec() {
// Check nowritebarrierrec functions. // Check nowritebarrierrec functions.
for _, n := range list { for _, n := range list {
if !n.Func.Nowritebarrierrec { if n.Func.Pragma&Nowritebarrierrec == 0 {
continue continue
} }
call, hasWB := c.best[n] call, hasWB := c.best[n]
......
...@@ -616,23 +616,10 @@ var flag_largemodel int ...@@ -616,23 +616,10 @@ var flag_largemodel int
// when the race detector is enabled. // when the race detector is enabled.
var instrumenting bool var instrumenting bool
// Pending annotations for next func declaration.
var (
noescape bool
noinline bool
norace bool
nosplit bool
nowritebarrier bool
nowritebarrierrec bool
systemstack bool
)
var debuglive int var debuglive int
var Ctxt *obj.Link var Ctxt *obj.Link
var nointerface bool
var writearchive int var writearchive int
var bstdout obj.Biobuf var bstdout obj.Biobuf
......
...@@ -107,7 +107,7 @@ func caninl(fn *Node) { ...@@ -107,7 +107,7 @@ func caninl(fn *Node) {
} }
// If marked "go:noinline", don't inline // If marked "go:noinline", don't inline
if fn.Func.Noinline { if fn.Func.Pragma&Noinline != 0 {
return return
} }
......
...@@ -844,6 +844,19 @@ func plan9quote(s string) string { ...@@ -844,6 +844,19 @@ func plan9quote(s string) string {
return s return s
} }
type Pragma uint8
const (
Nointerface Pragma = 1 << iota
Noescape // func parameters don't escape
Norace // func must not have race detector annotations
Nosplit // func should not execute on separate stack
Noinline // func should not be inlined
Systemstack // func must run on system stack
Nowritebarrier // emit compiler error instead of write barrier
Nowritebarrierrec // error on write barrier in this or recursive callees
)
type lexer struct { type lexer struct {
// source // source
bin *obj.Biobuf bin *obj.Biobuf
...@@ -852,6 +865,10 @@ type lexer struct { ...@@ -852,6 +865,10 @@ type lexer struct {
nlsemi bool // if set, '\n' and EOF translate to ';' nlsemi bool // if set, '\n' and EOF translate to ';'
// pragma flags
// accumulated by lexer; reset by parser
pragma Pragma
// current token // current token
tok int32 tok int32
sym_ *Sym // valid if tok == LNAME sym_ *Sym // valid if tok == LNAME
...@@ -1650,32 +1667,31 @@ func (l *lexer) getlinepragma() rune { ...@@ -1650,32 +1667,31 @@ func (l *lexer) getlinepragma() rune {
Lookup(f[1]).Linkname = f[2] Lookup(f[1]).Linkname = f[2]
case "go:nointerface": case "go:nointerface":
if obj.Fieldtrack_enabled != 0 { if obj.Fieldtrack_enabled != 0 {
nointerface = true l.pragma |= Nointerface
} }
case "go:noescape": case "go:noescape":
noescape = true l.pragma |= Noescape
case "go:norace": case "go:norace":
norace = true l.pragma |= Norace
case "go:nosplit": case "go:nosplit":
nosplit = true l.pragma |= Nosplit
case "go:noinline": case "go:noinline":
noinline = true l.pragma |= Noinline
case "go:systemstack": case "go:systemstack":
if compiling_runtime == 0 { if compiling_runtime == 0 {
Yyerror("//go:systemstack only allowed in runtime") Yyerror("//go:systemstack only allowed in runtime")
} }
systemstack = true l.pragma |= Systemstack
case "go:nowritebarrier": case "go:nowritebarrier":
if compiling_runtime == 0 { if compiling_runtime == 0 {
Yyerror("//go:nowritebarrier only allowed in runtime") Yyerror("//go:nowritebarrier only allowed in runtime")
} }
nowritebarrier = true l.pragma |= Nowritebarrier
case "go:nowritebarrierrec": case "go:nowritebarrierrec":
if compiling_runtime == 0 { if compiling_runtime == 0 {
Yyerror("//go:nowritebarrierrec only allowed in runtime") Yyerror("//go:nowritebarrierrec only allowed in runtime")
} }
nowritebarrierrec = true l.pragma |= Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier
nowritebarrier = true // Implies nowritebarrier
} }
return c return c
} }
......
...@@ -1893,25 +1893,21 @@ func (p *parser) xfndcl() *Node { ...@@ -1893,25 +1893,21 @@ func (p *parser) xfndcl() *Node {
} }
p.want(LFUNC) p.want(LFUNC)
f := p.fndcl() f := p.fndcl(p.pragma&Nointerface != 0)
body := p.fnbody() body := p.fnbody()
if f == nil { if f == nil {
return nil return nil
} }
if noescape && body != nil {
Yyerror("can only use //go:noescape with external func implementations")
}
f.Nbody = body f.Nbody = body
f.Noescape = p.pragma&Noescape != 0
if f.Noescape && body != nil {
Yyerror("can only use //go:noescape with external func implementations")
}
f.Func.Pragma = p.pragma
f.Func.Endlineno = lineno f.Func.Endlineno = lineno
f.Noescape = noescape
f.Func.Norace = norace
f.Func.Nosplit = nosplit
f.Func.Noinline = noinline
f.Func.Nowritebarrier = nowritebarrier
f.Func.Nowritebarrierrec = nowritebarrierrec
f.Func.Systemstack = systemstack
funcbody(f) funcbody(f)
return f return f
...@@ -1922,7 +1918,7 @@ func (p *parser) xfndcl() *Node { ...@@ -1922,7 +1918,7 @@ func (p *parser) xfndcl() *Node {
// Function = Signature FunctionBody . // Function = Signature FunctionBody .
// MethodDecl = "func" Receiver MethodName ( Function | Signature ) . // MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
// Receiver = Parameters . // Receiver = Parameters .
func (p *parser) fndcl() *Node { func (p *parser) fndcl(nointerface bool) *Node {
if trace && Debug['x'] != 0 { if trace && Debug['x'] != 0 {
defer p.trace("fndcl")() defer p.trace("fndcl")()
} }
...@@ -2058,8 +2054,7 @@ func (p *parser) hidden_fndcl() *Node { ...@@ -2058,8 +2054,7 @@ func (p *parser) hidden_fndcl() *Node {
ss.Type = functype(s2.N, s6, s8) ss.Type = functype(s2.N, s6, s8)
checkwidth(ss.Type) checkwidth(ss.Type)
addmethod(s4, ss.Type, false, nointerface) addmethod(s4, ss.Type, false, false)
nointerface = false
funchdr(ss) funchdr(ss)
// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
...@@ -2140,18 +2135,10 @@ loop: ...@@ -2140,18 +2135,10 @@ loop:
testdclstack() testdclstack()
} }
noescape = false // Reset p.pragma BEFORE advancing to the next token (consuming ';')
noinline = false // since comments before may set pragmas for the next function decl.
nointerface = false p.pragma = 0
norace = false
nosplit = false
nowritebarrier = false
nowritebarrierrec = false
systemstack = false
// Consume ';' AFTER resetting the above flags since
// it may read the subsequent comment line which may
// set the flags for the next function declaration.
if p.tok != EOF && !p.got(';') { if p.tok != EOF && !p.got(';') {
p.syntax_error("after top level declaration") p.syntax_error("after top level declaration")
p.advance(LVAR, LCONST, LTYPE, LFUNC) p.advance(LVAR, LCONST, LTYPE, LFUNC)
......
...@@ -434,10 +434,10 @@ func compile(fn *Node) { ...@@ -434,10 +434,10 @@ func compile(fn *Node) {
if fn.Func.Needctxt { if fn.Func.Needctxt {
ptxt.From3.Offset |= obj.NEEDCTXT ptxt.From3.Offset |= obj.NEEDCTXT
} }
if fn.Func.Nosplit { if fn.Func.Pragma&Nosplit != 0 {
ptxt.From3.Offset |= obj.NOSPLIT ptxt.From3.Offset |= obj.NOSPLIT
} }
if fn.Func.Systemstack { if fn.Func.Pragma&Systemstack != 0 {
ptxt.From.Sym.Cfunc = 1 ptxt.From.Sym.Cfunc = 1
} }
......
...@@ -50,7 +50,7 @@ func ispkgin(pkgs []string) bool { ...@@ -50,7 +50,7 @@ func ispkgin(pkgs []string) bool {
} }
func instrument(fn *Node) { func instrument(fn *Node) {
if ispkgin(omit_pkgs) || fn.Func.Norace { if ispkgin(omit_pkgs) || fn.Func.Pragma&Norace != 0 {
return return
} }
......
...@@ -169,18 +169,12 @@ type Func struct { ...@@ -169,18 +169,12 @@ type Func struct {
Depth int32 Depth int32
Endlineno int32 Endlineno int32
WBLineno int32 // line number of first write barrier
Norace bool // func must not have race detector annotations Pragma Pragma // go:xxx function annotations
Nosplit bool // func should not execute on separate stack Dupok bool // duplicate definitions ok
Noinline bool // func should not be inlined Wrapper bool // is method wrapper
Nowritebarrier bool // emit compiler error instead of write barrier Needctxt bool // function uses context register (has closure variables)
Nowritebarrierrec bool // error on write barrier in this or recursive callees
Dupok bool // duplicate definitions ok
Wrapper bool // is method wrapper
Needctxt bool // function uses context register (has closure variables)
Systemstack bool // must run on system stack
WBLineno int32 // line number of first write barrier
} }
type Op uint8 type Op uint8
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment