blob: 5b1dca08e0eb5138f42b23153c9436aec0cc3ba0 [file] [log] [blame]
Russ Cox8c195bd2015-02-13 14:40:36 -05001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package gc
6
7import "fmt"
8
9// case OADD:
10// if(n->right->op == OLITERAL) {
11// v = n->right->vconst;
12// naddr(n->left, a, canemitcode);
13// } else
14// if(n->left->op == OLITERAL) {
15// v = n->left->vconst;
16// naddr(n->right, a, canemitcode);
17// } else
18// goto bad;
19// a->offset += v;
20// break;
21
22/*
23 * a function named init is a special case.
24 * it is called by the initialization before
25 * main is run. to make it unique within a
26 * package and also uncallable, the name,
Russ Coxf6791da2015-02-20 13:54:45 -050027 * normally "pkg.init", is altered to "pkg.init.1".
Russ Cox8c195bd2015-02-13 14:40:36 -050028 */
29
30var renameinit_initgen int
31
32func renameinit() *Sym {
33 renameinit_initgen++
Russ Coxf6791da2015-02-20 13:54:45 -050034 namebuf = fmt.Sprintf("init.%d", renameinit_initgen)
Russ Cox8c195bd2015-02-13 14:40:36 -050035 return Lookup(namebuf)
36}
37
38/*
39 * hand-craft the following initialization code
40 * var initdone· uint8 (1)
41 * func init() (2)
42 * if initdone· != 0 { (3)
43 * if initdone· == 2 (4)
44 * return
45 * throw(); (5)
46 * }
47 * initdone· = 1; (6)
48 * // over all matching imported symbols
49 * <pkg>.init() (7)
50 * { <init stmts> } (8)
Russ Coxf6791da2015-02-20 13:54:45 -050051 * init.<n>() // if any (9)
Russ Cox8c195bd2015-02-13 14:40:36 -050052 * initdone· = 2; (10)
53 * return (11)
54 * }
55 */
Russ Coxdc7b54b2015-02-17 22:13:49 -050056func anyinit(n *NodeList) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -050057 // are there any interesting init statements
Russ Cox382b44e2015-02-23 16:07:24 -050058 for l := n; l != nil; l = l.Next {
Russ Cox8c195bd2015-02-13 14:40:36 -050059 switch l.N.Op {
60 case ODCLFUNC,
61 ODCLCONST,
62 ODCLTYPE,
63 OEMPTY:
64 break
65
66 case OAS:
Russ Coxdc7b54b2015-02-17 22:13:49 -050067 if isblank(l.N.Left) && candiscard(l.N.Right) {
Russ Cox8c195bd2015-02-13 14:40:36 -050068 break
69 }
70 fallthrough
71
72 // fall through
73 default:
Russ Coxdc7b54b2015-02-17 22:13:49 -050074 return true
Russ Cox8c195bd2015-02-13 14:40:36 -050075 }
76 }
77
78 // is this main
79 if localpkg.Name == "main" {
Russ Coxdc7b54b2015-02-17 22:13:49 -050080 return true
Russ Cox8c195bd2015-02-13 14:40:36 -050081 }
82
83 // is there an explicit init function
Russ Cox382b44e2015-02-23 16:07:24 -050084 s := Lookup("init.1")
Russ Cox8c195bd2015-02-13 14:40:36 -050085
Russ Cox8c195bd2015-02-13 14:40:36 -050086 if s.Def != nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -050087 return true
Russ Cox8c195bd2015-02-13 14:40:36 -050088 }
89
90 // are there any imported init functions
Russ Cox382b44e2015-02-23 16:07:24 -050091 for h := uint32(0); h < NHASH; h++ {
Russ Cox8c195bd2015-02-13 14:40:36 -050092 for s = hash[h]; s != nil; s = s.Link {
93 if s.Name[0] != 'i' || s.Name != "init" {
94 continue
95 }
96 if s.Def == nil {
97 continue
98 }
Russ Coxdc7b54b2015-02-17 22:13:49 -050099 return true
Russ Cox8c195bd2015-02-13 14:40:36 -0500100 }
101 }
102
103 // then none
Russ Coxdc7b54b2015-02-17 22:13:49 -0500104 return false
Russ Cox8c195bd2015-02-13 14:40:36 -0500105}
106
107func fninit(n *NodeList) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500108 if Debug['A'] != 0 {
109 // sys.go or unsafe.go during compiler build
110 return
111 }
112
113 n = initfix(n)
Russ Coxdc7b54b2015-02-17 22:13:49 -0500114 if !anyinit(n) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500115 return
116 }
117
Russ Cox175929b2015-03-02 14:22:05 -0500118 var r *NodeList
Russ Cox8c195bd2015-02-13 14:40:36 -0500119
120 // (1)
Josh Bleecher Snyder05ca0f32015-02-28 20:31:32 +0000121 namebuf = "initdone·"
Russ Cox8c195bd2015-02-13 14:40:36 -0500122
Russ Cox382b44e2015-02-23 16:07:24 -0500123 gatevar := newname(Lookup(namebuf))
Russ Cox8c195bd2015-02-13 14:40:36 -0500124 addvar(gatevar, Types[TUINT8], PEXTERN)
125
126 // (2)
127 Maxarg = 0
128
Josh Bleecher Snyder05ca0f32015-02-28 20:31:32 +0000129 namebuf = "init"
Russ Cox8c195bd2015-02-13 14:40:36 -0500130
Russ Cox382b44e2015-02-23 16:07:24 -0500131 fn := Nod(ODCLFUNC, nil, nil)
132 initsym := Lookup(namebuf)
Russ Cox8c195bd2015-02-13 14:40:36 -0500133 fn.Nname = newname(initsym)
134 fn.Nname.Defn = fn
135 fn.Nname.Ntype = Nod(OTFUNC, nil, nil)
136 declare(fn.Nname, PFUNC)
137 funchdr(fn)
138
139 // (3)
Russ Cox382b44e2015-02-23 16:07:24 -0500140 a := Nod(OIF, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500141
142 a.Ntest = Nod(ONE, gatevar, Nodintconst(0))
143 r = list(r, a)
144
145 // (4)
Russ Cox382b44e2015-02-23 16:07:24 -0500146 b := Nod(OIF, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500147
148 b.Ntest = Nod(OEQ, gatevar, Nodintconst(2))
149 b.Nbody = list1(Nod(ORETURN, nil, nil))
150 a.Nbody = list1(b)
151
152 // (5)
153 b = syslook("throwinit", 0)
154
155 b = Nod(OCALL, b, nil)
156 a.Nbody = list(a.Nbody, b)
157
158 // (6)
159 a = Nod(OAS, gatevar, Nodintconst(1))
160
161 r = list(r, a)
162
163 // (7)
Russ Cox382b44e2015-02-23 16:07:24 -0500164 var s *Sym
165 for h := uint32(0); h < NHASH; h++ {
Russ Cox8c195bd2015-02-13 14:40:36 -0500166 for s = hash[h]; s != nil; s = s.Link {
167 if s.Name[0] != 'i' || s.Name != "init" {
168 continue
169 }
170 if s.Def == nil {
171 continue
172 }
173 if s == initsym {
174 continue
175 }
176
177 // could check that it is fn of no args/returns
178 a = Nod(OCALL, s.Def, nil)
179
180 r = list(r, a)
181 }
182 }
183
184 // (8)
185 r = concat(r, n)
186
187 // (9)
188 // could check that it is fn of no args/returns
Russ Cox382b44e2015-02-23 16:07:24 -0500189 for i := 1; ; i++ {
Russ Coxf6791da2015-02-20 13:54:45 -0500190 namebuf = fmt.Sprintf("init.%d", i)
Russ Cox8c195bd2015-02-13 14:40:36 -0500191 s = Lookup(namebuf)
192 if s.Def == nil {
193 break
194 }
195 a = Nod(OCALL, s.Def, nil)
196 r = list(r, a)
197 }
198
199 // (10)
200 a = Nod(OAS, gatevar, Nodintconst(2))
201
202 r = list(r, a)
203
204 // (11)
205 a = Nod(ORETURN, nil, nil)
206
207 r = list(r, a)
208 exportsym(fn.Nname)
209
210 fn.Nbody = r
211 funcbody(fn)
212
213 Curfn = fn
214 typecheck(&fn, Etop)
215 typechecklist(r, Etop)
216 Curfn = nil
217 funccompile(fn)
218}