1
2
3
4
5 package pkginit
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/objw"
11 "cmd/compile/internal/staticinit"
12 "cmd/compile/internal/typecheck"
13 "cmd/compile/internal/types"
14 "cmd/internal/obj"
15 "cmd/internal/src"
16 )
17
18
19
20
21
22
23 func MakeInit() {
24 nf := initOrder(typecheck.Target.Decls)
25 if len(nf) == 0 {
26 return
27 }
28
29
30 base.Pos = nf[0].Pos()
31 initializers := typecheck.Lookup("init")
32 fn := typecheck.DeclFunc(initializers, ir.NewFuncType(base.Pos, nil, nil, nil))
33 for _, dcl := range typecheck.InitTodoFunc.Dcl {
34 dcl.Curfn = fn
35 }
36 fn.Dcl = append(fn.Dcl, typecheck.InitTodoFunc.Dcl...)
37 typecheck.InitTodoFunc.Dcl = nil
38
39
40
41 fn.SetInlinabilityChecked(true)
42
43 fn.Body = nf
44 typecheck.FinishFuncBody()
45
46 typecheck.Func(fn)
47 ir.WithFunc(fn, func() {
48 typecheck.Stmts(nf)
49 })
50 typecheck.Target.Decls = append(typecheck.Target.Decls, fn)
51
52
53
54 typecheck.Target.Inits = append([]*ir.Func{fn}, typecheck.Target.Inits...)
55
56 if typecheck.InitTodoFunc.Dcl != nil {
57
58
59
60 base.Fatalf("InitTodoFunc still has declarations")
61 }
62 typecheck.InitTodoFunc = nil
63 }
64
65
66
67
68
69
70
71 func Task() *ir.Name {
72 var deps []*obj.LSym
73 var fns []*obj.LSym
74
75
76 for _, pkg := range typecheck.Target.Imports {
77 n := typecheck.Resolve(ir.NewIdent(base.Pos, pkg.Lookup(".inittask")))
78 if n.Op() == ir.ONONAME {
79 continue
80 }
81 if n.Op() != ir.ONAME || n.(*ir.Name).Class != ir.PEXTERN {
82 base.Fatalf("bad inittask: %v", n)
83 }
84 deps = append(deps, n.(*ir.Name).Linksym())
85 }
86
87
88 for _, fn := range typecheck.Target.Inits {
89 if fn.Sym().Name == "init" {
90
91
92
93 s := staticinit.Schedule{
94 Plans: make(map[ir.Node]*staticinit.Plan),
95 Temps: make(map[ir.Node]*ir.Name),
96 }
97 for _, n := range fn.Body {
98 s.StaticInit(n)
99 }
100 fn.Body = s.Out
101 ir.WithFunc(fn, func() {
102 typecheck.Stmts(fn.Body)
103 })
104
105 if len(fn.Body) == 0 {
106 fn.Body = []ir.Node{ir.NewBlockStmt(src.NoXPos, nil)}
107 }
108 }
109
110
111 if len(fn.Body) == 1 {
112 if stmt := fn.Body[0]; stmt.Op() == ir.OBLOCK && len(stmt.(*ir.BlockStmt).List) == 0 {
113 continue
114 }
115 }
116 fns = append(fns, fn.Nname.Linksym())
117 }
118
119 if len(deps) == 0 && len(fns) == 0 && types.LocalPkg.Name != "main" && types.LocalPkg.Name != "runtime" {
120 return nil
121 }
122
123
124 sym := typecheck.Lookup(".inittask")
125 task := typecheck.NewName(sym)
126 task.SetType(types.Types[types.TUINT8])
127 task.Class = ir.PEXTERN
128 sym.Def = task
129 lsym := task.Linksym()
130 ot := 0
131 ot = objw.Uintptr(lsym, ot, 0)
132 ot = objw.Uintptr(lsym, ot, uint64(len(deps)))
133 ot = objw.Uintptr(lsym, ot, uint64(len(fns)))
134 for _, d := range deps {
135 ot = objw.SymPtr(lsym, ot, d, 0)
136 }
137 for _, f := range fns {
138 ot = objw.SymPtr(lsym, ot, f, 0)
139 }
140
141
142 objw.Global(lsym, int32(ot), obj.NOPTR)
143 return task
144 }
145
View as plain text