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.
|
|
|
|
|
|
|
|
package gc
|
|
|
|
|
|
|
|
import "fmt"
|
|
|
|
|
|
|
|
// case OADD:
|
|
|
|
// if(n->right->op == OLITERAL) {
|
|
|
|
// v = n->right->vconst;
|
|
|
|
// naddr(n->left, a, canemitcode);
|
|
|
|
// } else
|
|
|
|
// if(n->left->op == OLITERAL) {
|
|
|
|
// v = n->left->vconst;
|
|
|
|
// naddr(n->right, a, canemitcode);
|
|
|
|
// } else
|
|
|
|
// goto bad;
|
|
|
|
// a->offset += v;
|
|
|
|
// break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* a function named init is a special case.
|
|
|
|
* it is called by the initialization before
|
|
|
|
* main is run. to make it unique within a
|
|
|
|
* package and also uncallable, the name,
|
2015-02-20 13:54:45 -05:00
|
|
|
* normally "pkg.init", is altered to "pkg.init.1".
|
2015-02-13 14:40:36 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
var renameinit_initgen int
|
|
|
|
|
|
|
|
func renameinit() *Sym {
|
|
|
|
renameinit_initgen++
|
2015-02-20 13:54:45 -05:00
|
|
|
namebuf = fmt.Sprintf("init.%d", renameinit_initgen)
|
2015-02-13 14:40:36 -05:00
|
|
|
return Lookup(namebuf)
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* hand-craft the following initialization code
|
|
|
|
* var initdone· uint8 (1)
|
|
|
|
* func init() (2)
|
|
|
|
* if initdone· != 0 { (3)
|
|
|
|
* if initdone· == 2 (4)
|
|
|
|
* return
|
|
|
|
* throw(); (5)
|
|
|
|
* }
|
|
|
|
* initdone· = 1; (6)
|
|
|
|
* // over all matching imported symbols
|
|
|
|
* <pkg>.init() (7)
|
|
|
|
* { <init stmts> } (8)
|
2015-02-20 13:54:45 -05:00
|
|
|
* init.<n>() // if any (9)
|
2015-02-13 14:40:36 -05:00
|
|
|
* initdone· = 2; (10)
|
|
|
|
* return (11)
|
|
|
|
* }
|
|
|
|
*/
|
2015-02-17 22:13:49 -05:00
|
|
|
func anyinit(n *NodeList) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
// are there any interesting init statements
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := n; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch l.N.Op {
|
|
|
|
case ODCLFUNC,
|
|
|
|
ODCLCONST,
|
|
|
|
ODCLTYPE,
|
|
|
|
OEMPTY:
|
|
|
|
break
|
|
|
|
|
|
|
|
case OAS:
|
2015-02-17 22:13:49 -05:00
|
|
|
if isblank(l.N.Left) && candiscard(l.N.Right) {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
}
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
// fall through
|
|
|
|
default:
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// is this main
|
|
|
|
if localpkg.Name == "main" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// is there an explicit init function
|
2015-02-23 16:07:24 -05:00
|
|
|
s := Lookup("init.1")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
if s.Def != nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// are there any imported init functions
|
2015-02-23 16:07:24 -05:00
|
|
|
for h := uint32(0); h < NHASH; h++ {
|
2015-02-13 14:40:36 -05:00
|
|
|
for s = hash[h]; s != nil; s = s.Link {
|
|
|
|
if s.Name[0] != 'i' || s.Name != "init" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if s.Def == nil {
|
|
|
|
continue
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// then none
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func fninit(n *NodeList) {
|
|
|
|
if Debug['A'] != 0 {
|
|
|
|
// sys.go or unsafe.go during compiler build
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
n = initfix(n)
|
2015-02-17 22:13:49 -05:00
|
|
|
if !anyinit(n) {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-03-02 14:22:05 -05:00
|
|
|
var r *NodeList
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
// (1)
|
2015-02-28 20:31:32 +00:00
|
|
|
namebuf = "initdone·"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
gatevar := newname(Lookup(namebuf))
|
2015-02-13 14:40:36 -05:00
|
|
|
addvar(gatevar, Types[TUINT8], PEXTERN)
|
|
|
|
|
|
|
|
// (2)
|
|
|
|
Maxarg = 0
|
|
|
|
|
2015-02-28 20:31:32 +00:00
|
|
|
namebuf = "init"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
fn := Nod(ODCLFUNC, nil, nil)
|
|
|
|
initsym := Lookup(namebuf)
|
2015-02-13 14:40:36 -05:00
|
|
|
fn.Nname = newname(initsym)
|
|
|
|
fn.Nname.Defn = fn
|
|
|
|
fn.Nname.Ntype = Nod(OTFUNC, nil, nil)
|
|
|
|
declare(fn.Nname, PFUNC)
|
|
|
|
funchdr(fn)
|
|
|
|
|
|
|
|
// (3)
|
2015-02-23 16:07:24 -05:00
|
|
|
a := Nod(OIF, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
a.Ntest = Nod(ONE, gatevar, Nodintconst(0))
|
|
|
|
r = list(r, a)
|
|
|
|
|
|
|
|
// (4)
|
2015-02-23 16:07:24 -05:00
|
|
|
b := Nod(OIF, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
b.Ntest = Nod(OEQ, gatevar, Nodintconst(2))
|
|
|
|
b.Nbody = list1(Nod(ORETURN, nil, nil))
|
|
|
|
a.Nbody = list1(b)
|
|
|
|
|
|
|
|
// (5)
|
|
|
|
b = syslook("throwinit", 0)
|
|
|
|
|
|
|
|
b = Nod(OCALL, b, nil)
|
|
|
|
a.Nbody = list(a.Nbody, b)
|
|
|
|
|
|
|
|
// (6)
|
|
|
|
a = Nod(OAS, gatevar, Nodintconst(1))
|
|
|
|
|
|
|
|
r = list(r, a)
|
|
|
|
|
|
|
|
// (7)
|
2015-02-23 16:07:24 -05:00
|
|
|
var s *Sym
|
|
|
|
for h := uint32(0); h < NHASH; h++ {
|
2015-02-13 14:40:36 -05:00
|
|
|
for s = hash[h]; s != nil; s = s.Link {
|
|
|
|
if s.Name[0] != 'i' || s.Name != "init" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if s.Def == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if s == initsym {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// could check that it is fn of no args/returns
|
|
|
|
a = Nod(OCALL, s.Def, nil)
|
|
|
|
|
|
|
|
r = list(r, a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// (8)
|
|
|
|
r = concat(r, n)
|
|
|
|
|
|
|
|
// (9)
|
|
|
|
// could check that it is fn of no args/returns
|
2015-02-23 16:07:24 -05:00
|
|
|
for i := 1; ; i++ {
|
2015-02-20 13:54:45 -05:00
|
|
|
namebuf = fmt.Sprintf("init.%d", i)
|
2015-02-13 14:40:36 -05:00
|
|
|
s = Lookup(namebuf)
|
|
|
|
if s.Def == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
a = Nod(OCALL, s.Def, nil)
|
|
|
|
r = list(r, a)
|
|
|
|
}
|
|
|
|
|
|
|
|
// (10)
|
|
|
|
a = Nod(OAS, gatevar, Nodintconst(2))
|
|
|
|
|
|
|
|
r = list(r, a)
|
|
|
|
|
|
|
|
// (11)
|
|
|
|
a = Nod(ORETURN, nil, nil)
|
|
|
|
|
|
|
|
r = list(r, a)
|
|
|
|
exportsym(fn.Nname)
|
|
|
|
|
|
|
|
fn.Nbody = r
|
|
|
|
funcbody(fn)
|
|
|
|
|
|
|
|
Curfn = fn
|
|
|
|
typecheck(&fn, Etop)
|
|
|
|
typechecklist(r, Etop)
|
|
|
|
Curfn = nil
|
|
|
|
funccompile(fn)
|
|
|
|
}
|