blob: 45b4429088fea0f4e71e4bf7bfccdb71b6c64704 [file] [log] [blame]
Don Newton98fd8812019-09-23 15:15:02 -04001// Copyright 2019 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
5// +build ignore
6
7/*
8This program reads a file containing function prototypes
9(like syscall_aix.go) and generates system call bodies.
10The prototypes are marked by lines beginning with "//sys"
11and read like func declarations if //sys is replaced by func, but:
12 * The parameter lists must give a name for each argument.
13 This includes return parameters.
14 * The parameter lists must give a type for each argument:
15 the (x, y, z int) shorthand is not allowed.
16 * If the return parameter is an error number, it must be named err.
17 * If go func name needs to be different than its libc name,
18 * or the function is not in libc, name could be specified
19 * at the end, after "=" sign, like
20 //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
21
22
23This program will generate three files and handle both gc and gccgo implementation:
24 - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
25 - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
26 - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
27
28 The generated code looks like this
29
30zsyscall_aix_ppc64.go
31func asyscall(...) (n int, err error) {
32 // Pointer Creation
33 r1, e1 := callasyscall(...)
34 // Type Conversion
35 // Error Handler
36 return
37}
38
39zsyscall_aix_ppc64_gc.go
40//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
41//go:linkname libc_asyscall libc_asyscall
42var asyscall syscallFunc
43
44func callasyscall(...) (r1 uintptr, e1 Errno) {
45 r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
46 return
47}
48
49zsyscall_aix_ppc64_ggcgo.go
50
51// int asyscall(...)
52
53import "C"
54
55func callasyscall(...) (r1 uintptr, e1 Errno) {
56 r1 = uintptr(C.asyscall(...))
57 e1 = syscall.GetErrno()
58 return
59}
60*/
61
62package main
63
64import (
65 "bufio"
66 "flag"
67 "fmt"
68 "io/ioutil"
69 "os"
70 "regexp"
71 "strings"
72)
73
74var (
75 b32 = flag.Bool("b32", false, "32bit big-endian")
76 l32 = flag.Bool("l32", false, "32bit little-endian")
77 aix = flag.Bool("aix", false, "aix")
78 tags = flag.String("tags", "", "build tags")
79)
80
81// cmdLine returns this programs's commandline arguments
82func cmdLine() string {
83 return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ")
84}
85
86// buildTags returns build tags
87func buildTags() string {
88 return *tags
89}
90
91// Param is function parameter
92type Param struct {
93 Name string
94 Type string
95}
96
97// usage prints the program usage
98func usage() {
99 fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n")
100 os.Exit(1)
101}
102
103// parseParamList parses parameter list and returns a slice of parameters
104func parseParamList(list string) []string {
105 list = strings.TrimSpace(list)
106 if list == "" {
107 return []string{}
108 }
109 return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
110}
111
112// parseParam splits a parameter into name and type
113func parseParam(p string) Param {
114 ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
115 if ps == nil {
116 fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
117 os.Exit(1)
118 }
119 return Param{ps[1], ps[2]}
120}
121
122func main() {
123 flag.Usage = usage
124 flag.Parse()
125 if len(flag.Args()) <= 0 {
126 fmt.Fprintf(os.Stderr, "no files to parse provided\n")
127 usage()
128 }
129
130 endianness := ""
131 if *b32 {
132 endianness = "big-endian"
133 } else if *l32 {
134 endianness = "little-endian"
135 }
136
137 pack := ""
138 // GCCGO
139 textgccgo := ""
140 cExtern := "/*\n#include <stdint.h>\n"
141 // GC
142 textgc := ""
143 dynimports := ""
144 linknames := ""
145 var vars []string
146 // COMMON
147 textcommon := ""
148 for _, path := range flag.Args() {
149 file, err := os.Open(path)
150 if err != nil {
151 fmt.Fprintf(os.Stderr, err.Error())
152 os.Exit(1)
153 }
154 s := bufio.NewScanner(file)
155 for s.Scan() {
156 t := s.Text()
157 t = strings.TrimSpace(t)
158 t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
159 if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
160 pack = p[1]
161 }
162 nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
163 if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
164 continue
165 }
166
167 // Line must be of the form
168 // func Open(path string, mode int, perm int) (fd int, err error)
169 // Split into name, in params, out params.
170 f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
171 if f == nil {
172 fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
173 os.Exit(1)
174 }
175 funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
176
177 // Split argument lists on comma.
178 in := parseParamList(inps)
179 out := parseParamList(outps)
180
181 inps = strings.Join(in, ", ")
182 outps = strings.Join(out, ", ")
183
184 if sysname == "" {
185 sysname = funct
186 }
187
188 onlyCommon := false
189 if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" {
190 // This function call another syscall which is already implemented.
191 // Therefore, the gc and gccgo part must not be generated.
192 onlyCommon = true
193 }
194
195 // Try in vain to keep people from editing this file.
196 // The theory is that they jump into the middle of the file
197 // without reading the header.
198
199 textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
200 if !onlyCommon {
201 textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
202 textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
203 }
204
205 // Check if value return, err return available
206 errvar := ""
207 rettype := ""
208 for _, param := range out {
209 p := parseParam(param)
210 if p.Type == "error" {
211 errvar = p.Name
212 } else {
213 rettype = p.Type
214 }
215 }
216
217 sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
218 sysname = strings.ToLower(sysname) // All libc functions are lowercase.
219
220 // GCCGO Prototype return type
221 cRettype := ""
222 if rettype == "unsafe.Pointer" {
223 cRettype = "uintptr_t"
224 } else if rettype == "uintptr" {
225 cRettype = "uintptr_t"
226 } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
227 cRettype = "uintptr_t"
228 } else if rettype == "int" {
229 cRettype = "int"
230 } else if rettype == "int32" {
231 cRettype = "int"
232 } else if rettype == "int64" {
233 cRettype = "long long"
234 } else if rettype == "uint32" {
235 cRettype = "unsigned int"
236 } else if rettype == "uint64" {
237 cRettype = "unsigned long long"
238 } else {
239 cRettype = "int"
240 }
241 if sysname == "exit" {
242 cRettype = "void"
243 }
244
245 // GCCGO Prototype arguments type
246 var cIn []string
247 for i, param := range in {
248 p := parseParam(param)
249 if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
250 cIn = append(cIn, "uintptr_t")
251 } else if p.Type == "string" {
252 cIn = append(cIn, "uintptr_t")
253 } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
254 cIn = append(cIn, "uintptr_t", "size_t")
255 } else if p.Type == "unsafe.Pointer" {
256 cIn = append(cIn, "uintptr_t")
257 } else if p.Type == "uintptr" {
258 cIn = append(cIn, "uintptr_t")
259 } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
260 cIn = append(cIn, "uintptr_t")
261 } else if p.Type == "int" {
262 if (i == 0 || i == 2) && funct == "fcntl" {
263 // These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
264 cIn = append(cIn, "uintptr_t")
265 } else {
266 cIn = append(cIn, "int")
267 }
268
269 } else if p.Type == "int32" {
270 cIn = append(cIn, "int")
271 } else if p.Type == "int64" {
272 cIn = append(cIn, "long long")
273 } else if p.Type == "uint32" {
274 cIn = append(cIn, "unsigned int")
275 } else if p.Type == "uint64" {
276 cIn = append(cIn, "unsigned long long")
277 } else {
278 cIn = append(cIn, "int")
279 }
280 }
281
282 if !onlyCommon {
283 // GCCGO Prototype Generation
284 // Imports of system calls from libc
Don Newton98fd8812019-09-23 15:15:02 -0400285 cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
286 cIn := strings.Join(cIn, ", ")
287 cExtern += fmt.Sprintf("(%s);\n", cIn)
288 }
289 // GC Library name
290 if modname == "" {
291 modname = "libc.a/shr_64.o"
292 } else {
293 fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
294 os.Exit(1)
295 }
296 sysvarname := fmt.Sprintf("libc_%s", sysname)
297
298 if !onlyCommon {
299 // GC Runtime import of function to allow cross-platform builds.
300 dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
301 // GC Link symbol to proc address variable.
302 linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
303 // GC Library proc address variable.
304 vars = append(vars, sysvarname)
305 }
306
307 strconvfunc := "BytePtrFromString"
308 strconvtype := "*byte"
309
310 // Go function header.
311 if outps != "" {
312 outps = fmt.Sprintf(" (%s)", outps)
313 }
314 if textcommon != "" {
315 textcommon += "\n"
316 }
317
318 textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
319
320 // Prepare arguments tocall.
321 var argscommon []string // Arguments in the common part
322 var argscall []string // Arguments for call prototype
323 var argsgc []string // Arguments for gc call (with syscall6)
324 var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall)
325 n := 0
326 argN := 0
327 for _, param := range in {
328 p := parseParam(param)
329 if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
330 argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
331 argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
332 argsgc = append(argsgc, p.Name)
333 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
334 } else if p.Type == "string" && errvar != "" {
335 textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
336 textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
337 textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
338
339 argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
340 argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
341 argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
342 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
343 n++
344 } else if p.Type == "string" {
345 fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
346 textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
347 textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
348 textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
349
350 argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
351 argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
352 argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
353 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
354 n++
355 } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
356 // Convert slice into pointer, length.
357 // Have to be careful not to take address of &a[0] if len == 0:
358 // pass nil in that case.
359 textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
360 textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
361 argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
362 argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
363 argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
364 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
365 n++
366 } else if p.Type == "int64" && endianness != "" {
367 fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
368 } else if p.Type == "bool" {
369 fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
370 } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
371 argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
372 argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
373 argsgc = append(argsgc, p.Name)
374 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
375 } else if p.Type == "int" {
376 if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
377 // These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
378 argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
379 argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
380 argsgc = append(argsgc, p.Name)
381 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
382
383 } else {
384 argscommon = append(argscommon, p.Name)
385 argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
386 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
387 argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
388 }
389 } else if p.Type == "int32" {
390 argscommon = append(argscommon, p.Name)
391 argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
392 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
393 argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
394 } else if p.Type == "int64" {
395 argscommon = append(argscommon, p.Name)
396 argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
397 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
398 argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
399 } else if p.Type == "uint32" {
400 argscommon = append(argscommon, p.Name)
401 argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
402 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
403 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
404 } else if p.Type == "uint64" {
405 argscommon = append(argscommon, p.Name)
406 argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
407 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
408 argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
409 } else if p.Type == "uintptr" {
410 argscommon = append(argscommon, p.Name)
411 argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
412 argsgc = append(argsgc, p.Name)
413 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
414 } else {
415 argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
416 argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
417 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
418 argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
419 }
420 argN++
421 }
422 nargs := len(argsgc)
423
424 // COMMON function generation
425 argscommonlist := strings.Join(argscommon, ", ")
426 callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
427 ret := []string{"_", "_"}
428 body := ""
429 doErrno := false
430 for i := 0; i < len(out); i++ {
431 p := parseParam(out[i])
432 reg := ""
433 if p.Name == "err" {
434 reg = "e1"
435 ret[1] = reg
436 doErrno = true
437 } else {
438 reg = "r0"
439 ret[0] = reg
440 }
441 if p.Type == "bool" {
442 reg = fmt.Sprintf("%s != 0", reg)
443 }
444 if reg != "e1" {
445 body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
446 }
447 }
448 if ret[0] == "_" && ret[1] == "_" {
449 textcommon += fmt.Sprintf("\t%s\n", callcommon)
450 } else {
451 textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
452 }
453 textcommon += body
454
455 if doErrno {
456 textcommon += "\tif e1 != 0 {\n"
457 textcommon += "\t\terr = errnoErr(e1)\n"
458 textcommon += "\t}\n"
459 }
460 textcommon += "\treturn\n"
461 textcommon += "}\n"
462
463 if onlyCommon {
464 continue
465 }
466
467 // CALL Prototype
468 callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
469
470 // GC function generation
471 asm := "syscall6"
472 if nonblock != nil {
473 asm = "rawSyscall6"
474 }
475
476 if len(argsgc) <= 6 {
477 for len(argsgc) < 6 {
478 argsgc = append(argsgc, "0")
479 }
480 } else {
481 fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
482 os.Exit(1)
483 }
484 argsgclist := strings.Join(argsgc, ", ")
485 callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
486
487 textgc += callProto
488 textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
489 textgc += "\treturn\n}\n"
490
491 // GCCGO function generation
492 argsgccgolist := strings.Join(argsgccgo, ", ")
Don Newtone0d34a82019-11-14 10:58:06 -0500493 callgccgo := fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
Don Newton98fd8812019-09-23 15:15:02 -0400494 textgccgo += callProto
495 textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
496 textgccgo += "\te1 = syscall.GetErrno()\n"
497 textgccgo += "\treturn\n}\n"
498 }
499 if err := s.Err(); err != nil {
500 fmt.Fprintf(os.Stderr, err.Error())
501 os.Exit(1)
502 }
503 file.Close()
504 }
505 imp := ""
506 if pack != "unix" {
507 imp = "import \"golang.org/x/sys/unix\"\n"
508
509 }
510
511 // Print zsyscall_aix_ppc64.go
512 err := ioutil.WriteFile("zsyscall_aix_ppc64.go",
513 []byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)),
514 0644)
515 if err != nil {
516 fmt.Fprintf(os.Stderr, err.Error())
517 os.Exit(1)
518 }
519
520 // Print zsyscall_aix_ppc64_gc.go
521 vardecls := "\t" + strings.Join(vars, ",\n\t")
522 vardecls += " syscallFunc"
523 err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go",
524 []byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
525 0644)
526 if err != nil {
527 fmt.Fprintf(os.Stderr, err.Error())
528 os.Exit(1)
529 }
530
531 // Print zsyscall_aix_ppc64_gccgo.go
532 err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go",
533 []byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)),
534 0644)
535 if err != nil {
536 fmt.Fprintf(os.Stderr, err.Error())
537 os.Exit(1)
538 }
539}
540
541const srcTemplate1 = `// %s
542// Code generated by the command above; see README.md. DO NOT EDIT.
543
544// +build %s
545
546package %s
547
548import (
549 "unsafe"
550)
551
552
553%s
554
555%s
556`
557const srcTemplate2 = `// %s
558// Code generated by the command above; see README.md. DO NOT EDIT.
559
560// +build %s
561// +build !gccgo
562
563package %s
564
565import (
566 "unsafe"
567)
568%s
569%s
570%s
571type syscallFunc uintptr
572
573var (
574%s
575)
576
577// Implemented in runtime/syscall_aix.go.
578func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
579func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
580
581%s
582`
583const srcTemplate3 = `// %s
584// Code generated by the command above; see README.md. DO NOT EDIT.
585
586// +build %s
587// +build gccgo
588
589package %s
590
591%s
592*/
593import "C"
594import (
595 "syscall"
596)
597
598
599%s
600
601%s
602`