1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 package main
72
73
74
75
76
77
78
79
80
81
82
83 import (
84 "cmp"
85 "flag"
86 "fmt"
87 "log"
88 "maps"
89 "os"
90 "path/filepath"
91 "runtime/pprof"
92 "slices"
93 "strings"
94
95 "simd/_gen/unify"
96
97 "gopkg.in/yaml.v3"
98 )
99
100 var (
101 xedPath = flag.String("xedPath", "", "load XED datafiles from `path`")
102 flagQ = flag.String("q", "", "query: read `def` as another input (skips final validation)")
103 flagO = flag.String("o", "yaml", "output type: yaml, godefs (generate definitions into a Go source tree")
104 flagGoDefRoot = flag.String("goroot", ".", "the path to the Go dev directory that will receive the generated files")
105 FlagNoDedup = flag.Bool("nodedup", false, "disable deduplicating godefs of 2 qualifying operations from different extensions")
106 FlagNoConstImmPorting = flag.Bool("noconstimmporting", false, "disable const immediate porting from op to imm operand")
107 FlagArch = flag.String("arch", "amd64", "the target architecture")
108
109 Verbose = flag.Bool("v", false, "verbose")
110
111 flagDebugXED = flag.Bool("debug-xed", false, "show XED instructions")
112 flagDebugUnify = flag.Bool("debug-unify", false, "print unification trace")
113 flagDebugHTML = flag.String("debug-html", "", "write unification trace to `file.html`")
114 FlagReportDup = flag.Bool("reportdup", false, "report the duplicate godefs")
115
116 flagCPUProfile = flag.String("cpuprofile", "", "write CPU profile to `file`")
117 flagMemProfile = flag.String("memprofile", "", "write memory profile to `file`")
118 )
119
120 const simdPackage = "simd"
121
122 func main() {
123 flag.Parse()
124
125 if *flagCPUProfile != "" {
126 f, err := os.Create(*flagCPUProfile)
127 if err != nil {
128 log.Fatalf("-cpuprofile: %s", err)
129 }
130 defer f.Close()
131 pprof.StartCPUProfile(f)
132 defer pprof.StopCPUProfile()
133 }
134 if *flagMemProfile != "" {
135 f, err := os.Create(*flagMemProfile)
136 if err != nil {
137 log.Fatalf("-memprofile: %s", err)
138 }
139 defer func() {
140 pprof.WriteHeapProfile(f)
141 f.Close()
142 }()
143 }
144
145 var inputs []unify.Closure
146
147 if *FlagArch != "amd64" {
148 log.Fatalf("simdgen only supports amd64")
149 }
150
151
152 if *xedPath != "" {
153 xedDefs := loadXED(*xedPath)
154 inputs = append(inputs, unify.NewSum(xedDefs...))
155 }
156
157
158 if *flagQ != "" {
159 r := strings.NewReader(*flagQ)
160 def, err := unify.Read(r, "<query>", unify.ReadOpts{})
161 if err != nil {
162 log.Fatalf("parsing -q: %s", err)
163 }
164 inputs = append(inputs, def)
165 }
166
167
168 must := make(map[*unify.Value]struct{})
169 for _, path := range flag.Args() {
170 defs, err := unify.ReadFile(path, unify.ReadOpts{})
171 if err != nil {
172 log.Fatal(err)
173 }
174 inputs = append(inputs, defs)
175
176 if filepath.Base(path) == "go.yaml" {
177
178 for def := range defs.Summands() {
179 must[def] = struct{}{}
180 }
181 }
182 }
183
184
185 if *flagDebugUnify {
186 unify.Debug.UnifyLog = os.Stderr
187 }
188 if *flagDebugHTML != "" {
189 f, err := os.Create(*flagDebugHTML)
190 if err != nil {
191 log.Fatal(err)
192 }
193 unify.Debug.HTML = f
194 defer f.Close()
195 }
196
197
198 unified, err := unify.Unify(inputs...)
199 if err != nil {
200 log.Fatal(err)
201 }
202
203
204
205
206
207
208 if *flagQ == "" && len(must) > 0 {
209 validate(unified, must)
210 }
211
212
213 switch *flagO {
214 case "yaml":
215
216 fmt.Println("!sum")
217 var val1 [1]*unify.Value
218 for val := range unified.All() {
219 val1[0] = val
220
221
222 enc := yaml.NewEncoder(os.Stdout)
223 if err := enc.Encode(val1); err != nil {
224 log.Fatal(err)
225 }
226 enc.Close()
227 }
228 case "godefs":
229 if err := writeGoDefs(*flagGoDefRoot, unified); err != nil {
230 log.Fatalf("Failed writing godefs: %+v", err)
231 }
232 }
233
234 if !*Verbose && *xedPath != "" {
235 if operandRemarks == 0 {
236 fmt.Fprintf(os.Stderr, "XED decoding generated no errors, which is unusual.\n")
237 } else {
238 fmt.Fprintf(os.Stderr, "XED decoding generated %d \"errors\" which is not cause for alarm, use -v for details.\n", operandRemarks)
239 }
240 }
241 }
242
243 func validate(cl unify.Closure, required map[*unify.Value]struct{}) {
244
245
246
247 for def := range cl.All() {
248 if _, ok := def.Domain.(unify.Def); !ok {
249 fmt.Fprintf(os.Stderr, "%s: expected Def, got %T\n", def.PosString(), def.Domain)
250 continue
251 }
252
253 if !def.Exact() {
254 fmt.Fprintf(os.Stderr, "%s: def not reduced to an exact value, why is %s:\n", def.PosString(), def.WhyNotExact())
255 fmt.Fprintf(os.Stderr, "\t%s\n", strings.ReplaceAll(def.String(), "\n", "\n\t"))
256 }
257
258 for root := range def.Provenance() {
259 delete(required, root)
260 }
261 }
262
263 unused := slices.SortedFunc(maps.Keys(required),
264 func(a, b *unify.Value) int {
265 return cmp.Or(
266 cmp.Compare(a.Pos().Path, b.Pos().Path),
267 cmp.Compare(a.Pos().Line, b.Pos().Line),
268 )
269 })
270 for _, def := range unused {
271
272
273
274
275
276
277
278 fmt.Fprintf(os.Stderr, "%s: def required, but did not unify (%v)\n",
279 def.PosString(), def)
280 }
281 }
282
View as plain text