blob: 5fbc82dd38305d39252151ca2c1493cf3c0f1625 [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
Russ Cox8c195bd2015-02-13 14:40:36 -05007// case OADD:
8// if(n->right->op == OLITERAL) {
9// v = n->right->vconst;
10// naddr(n->left, a, canemitcode);
11// } else
12// if(n->left->op == OLITERAL) {
13// v = n->left->vconst;
14// naddr(n->right, a, canemitcode);
15// } else
16// goto bad;
17// a->offset += v;
18// break;
19
20/*
21 * a function named init is a special case.
22 * it is called by the initialization before
23 * main is run. to make it unique within a
24 * package and also uncallable, the name,
Russ Coxf6791da2015-02-20 13:54:45 -050025 * normally "pkg.init", is altered to "pkg.init.1".
Russ Cox8c195bd2015-02-13 14:40:36 -050026 */
27
28var renameinit_initgen int
29
30func renameinit() *Sym {
31 renameinit_initgen++
Matthew Dempsky8b3670f2015-03-06 12:02:24 -080032 return Lookupf("init.%d", renameinit_initgen)
Russ Cox8c195bd2015-02-13 14:40:36 -050033}
34
35/*
36 * hand-craft the following initialization code
37 * var initdone· uint8 (1)
38 * func init() (2)
39 * if initdone· != 0 { (3)
40 * if initdone· == 2 (4)
41 * return
42 * throw(); (5)
43 * }
44 * initdone· = 1; (6)
45 * // over all matching imported symbols
46 * <pkg>.init() (7)
47 * { <init stmts> } (8)
Russ Coxf6791da2015-02-20 13:54:45 -050048 * init.<n>() // if any (9)
Russ Cox8c195bd2015-02-13 14:40:36 -050049 * initdone· = 2; (10)
50 * return (11)
51 * }
52 */
Russ Coxdc7b54b2015-02-17 22:13:49 -050053func anyinit(n *NodeList) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -050054 // are there any interesting init statements
Russ Cox382b44e2015-02-23 16:07:24 -050055 for l := n; l != nil; l = l.Next {
Russ Cox8c195bd2015-02-13 14:40:36 -050056 switch l.N.Op {
Josh Bleecher Snyderb09925b2015-04-01 09:38:44 -070057 case ODCLFUNC, ODCLCONST, ODCLTYPE, OEMPTY:
Russ Cox8c195bd2015-02-13 14:40:36 -050058 break
59
Russ Cox0ad4f8b2015-04-17 00:25:10 -040060 case OAS, OASWB:
Russ Coxdc7b54b2015-02-17 22:13:49 -050061 if isblank(l.N.Left) && candiscard(l.N.Right) {
Russ Cox8c195bd2015-02-13 14:40:36 -050062 break
63 }
64 fallthrough
65
66 // fall through
67 default:
Russ Coxdc7b54b2015-02-17 22:13:49 -050068 return true
Russ Cox8c195bd2015-02-13 14:40:36 -050069 }
70 }
71
72 // is this main
73 if localpkg.Name == "main" {
Russ Coxdc7b54b2015-02-17 22:13:49 -050074 return true
Russ Cox8c195bd2015-02-13 14:40:36 -050075 }
76
77 // is there an explicit init function
Russ Cox382b44e2015-02-23 16:07:24 -050078 s := Lookup("init.1")
Russ Cox8c195bd2015-02-13 14:40:36 -050079
Russ Cox8c195bd2015-02-13 14:40:36 -050080 if s.Def != nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -050081 return true
Russ Cox8c195bd2015-02-13 14:40:36 -050082 }
83
84 // are there any imported init functions
Russ Coxd0b59de2015-03-02 16:21:15 -050085 for _, s := range initSyms {
86 if s.Def != nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -050087 return true
Russ Cox8c195bd2015-02-13 14:40:36 -050088 }
89 }
90
91 // then none
Russ Coxdc7b54b2015-02-17 22:13:49 -050092 return false
Russ Cox8c195bd2015-02-13 14:40:36 -050093}
94
95func fninit(n *NodeList) {
Russ Cox8c195bd2015-02-13 14:40:36 -050096 if Debug['A'] != 0 {
97 // sys.go or unsafe.go during compiler build
98 return
99 }
100
101 n = initfix(n)
Russ Coxdc7b54b2015-02-17 22:13:49 -0500102 if !anyinit(n) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500103 return
104 }
105
Russ Cox175929b2015-03-02 14:22:05 -0500106 var r *NodeList
Russ Cox8c195bd2015-02-13 14:40:36 -0500107
108 // (1)
Matthew Dempsky8b3670f2015-03-06 12:02:24 -0800109 gatevar := newname(Lookup("initdone·"))
Russ Cox8c195bd2015-02-13 14:40:36 -0500110 addvar(gatevar, Types[TUINT8], PEXTERN)
111
112 // (2)
113 Maxarg = 0
114
Russ Cox382b44e2015-02-23 16:07:24 -0500115 fn := Nod(ODCLFUNC, nil, nil)
Matthew Dempsky8b3670f2015-03-06 12:02:24 -0800116 initsym := Lookup("init")
Russ Coxbd4fff62015-05-27 10:42:55 -0400117 fn.Func.Nname = newname(initsym)
118 fn.Func.Nname.Name.Defn = fn
119 fn.Func.Nname.Name.Param.Ntype = Nod(OTFUNC, nil, nil)
120 declare(fn.Func.Nname, PFUNC)
Russ Cox8c195bd2015-02-13 14:40:36 -0500121 funchdr(fn)
122
123 // (3)
Russ Cox382b44e2015-02-23 16:07:24 -0500124 a := Nod(OIF, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500125
Russ Cox66be1482015-05-26 21:30:20 -0400126 a.Left = Nod(ONE, gatevar, Nodintconst(0))
Russ Cox8c195bd2015-02-13 14:40:36 -0500127 r = list(r, a)
128
129 // (4)
Russ Cox382b44e2015-02-23 16:07:24 -0500130 b := Nod(OIF, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500131
Russ Cox66be1482015-05-26 21:30:20 -0400132 b.Left = Nod(OEQ, gatevar, Nodintconst(2))
Russ Cox8c195bd2015-02-13 14:40:36 -0500133 b.Nbody = list1(Nod(ORETURN, nil, nil))
134 a.Nbody = list1(b)
135
136 // (5)
137 b = syslook("throwinit", 0)
138
139 b = Nod(OCALL, b, nil)
140 a.Nbody = list(a.Nbody, b)
141
142 // (6)
143 a = Nod(OAS, gatevar, Nodintconst(1))
144
145 r = list(r, a)
146
147 // (7)
Russ Coxd0b59de2015-03-02 16:21:15 -0500148 for _, s := range initSyms {
149 if s.Def != nil && s != initsym {
Russ Cox8c195bd2015-02-13 14:40:36 -0500150 // could check that it is fn of no args/returns
151 a = Nod(OCALL, s.Def, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500152 r = list(r, a)
153 }
154 }
155
156 // (8)
157 r = concat(r, n)
158
159 // (9)
160 // could check that it is fn of no args/returns
Russ Cox382b44e2015-02-23 16:07:24 -0500161 for i := 1; ; i++ {
Matthew Dempsky8b3670f2015-03-06 12:02:24 -0800162 s := Lookupf("init.%d", i)
Russ Cox8c195bd2015-02-13 14:40:36 -0500163 if s.Def == nil {
164 break
165 }
166 a = Nod(OCALL, s.Def, nil)
167 r = list(r, a)
168 }
169
170 // (10)
171 a = Nod(OAS, gatevar, Nodintconst(2))
172
173 r = list(r, a)
174
175 // (11)
176 a = Nod(ORETURN, nil, nil)
177
178 r = list(r, a)
Russ Coxbd4fff62015-05-27 10:42:55 -0400179 exportsym(fn.Func.Nname)
Russ Cox8c195bd2015-02-13 14:40:36 -0500180
181 fn.Nbody = r
182 funcbody(fn)
183
184 Curfn = fn
185 typecheck(&fn, Etop)
186 typechecklist(r, Etop)
187 Curfn = nil
188 funccompile(fn)
189}