1// 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
285				if sysname == "select" {
286					// select is a keyword of Go. Its name is
287					// changed to c_select.
288					cExtern += "#define c_select select\n"
289				}
290				cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
291				cIn := strings.Join(cIn, ", ")
292				cExtern += fmt.Sprintf("(%s);\n", cIn)
293			}
294			// GC Library name
295			if modname == "" {
296				modname = "libc.a/shr_64.o"
297			} else {
298				fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
299				os.Exit(1)
300			}
301			sysvarname := fmt.Sprintf("libc_%s", sysname)
302
303			if !onlyCommon {
304				// GC Runtime import of function to allow cross-platform builds.
305				dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
306				// GC Link symbol to proc address variable.
307				linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
308				// GC Library proc address variable.
309				vars = append(vars, sysvarname)
310			}
311
312			strconvfunc := "BytePtrFromString"
313			strconvtype := "*byte"
314
315			// Go function header.
316			if outps != "" {
317				outps = fmt.Sprintf(" (%s)", outps)
318			}
319			if textcommon != "" {
320				textcommon += "\n"
321			}
322
323			textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
324
325			// Prepare arguments tocall.
326			var argscommon []string // Arguments in the common part
327			var argscall []string   // Arguments for call prototype
328			var argsgc []string     // Arguments for gc call (with syscall6)
329			var argsgccgo []string  // Arguments for gccgo call (with C.name_of_syscall)
330			n := 0
331			argN := 0
332			for _, param := range in {
333				p := parseParam(param)
334				if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
335					argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
336					argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
337					argsgc = append(argsgc, p.Name)
338					argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
339				} else if p.Type == "string" && errvar != "" {
340					textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
341					textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
342					textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
343
344					argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
345					argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
346					argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
347					argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
348					n++
349				} else if p.Type == "string" {
350					fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
351					textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
352					textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
353					textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
354
355					argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
356					argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
357					argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
358					argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
359					n++
360				} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
361					// Convert slice into pointer, length.
362					// Have to be careful not to take address of &a[0] if len == 0:
363					// pass nil in that case.
364					textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
365					textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
366					argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
367					argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
368					argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
369					argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
370					n++
371				} else if p.Type == "int64" && endianness != "" {
372					fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
373				} else if p.Type == "bool" {
374					fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
375				} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
376					argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
377					argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
378					argsgc = append(argsgc, p.Name)
379					argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
380				} else if p.Type == "int" {
381					if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
382						// These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
383						argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
384						argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
385						argsgc = append(argsgc, p.Name)
386						argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
387
388					} else {
389						argscommon = append(argscommon, p.Name)
390						argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
391						argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
392						argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
393					}
394				} else if p.Type == "int32" {
395					argscommon = append(argscommon, p.Name)
396					argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
397					argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
398					argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
399				} else if p.Type == "int64" {
400					argscommon = append(argscommon, p.Name)
401					argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
402					argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
403					argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
404				} else if p.Type == "uint32" {
405					argscommon = append(argscommon, p.Name)
406					argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
407					argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
408					argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
409				} else if p.Type == "uint64" {
410					argscommon = append(argscommon, p.Name)
411					argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
412					argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
413					argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
414				} else if p.Type == "uintptr" {
415					argscommon = append(argscommon, p.Name)
416					argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
417					argsgc = append(argsgc, p.Name)
418					argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
419				} else {
420					argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
421					argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
422					argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
423					argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
424				}
425				argN++
426			}
427			nargs := len(argsgc)
428
429			// COMMON function generation
430			argscommonlist := strings.Join(argscommon, ", ")
431			callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
432			ret := []string{"_", "_"}
433			body := ""
434			doErrno := false
435			for i := 0; i < len(out); i++ {
436				p := parseParam(out[i])
437				reg := ""
438				if p.Name == "err" {
439					reg = "e1"
440					ret[1] = reg
441					doErrno = true
442				} else {
443					reg = "r0"
444					ret[0] = reg
445				}
446				if p.Type == "bool" {
447					reg = fmt.Sprintf("%s != 0", reg)
448				}
449				if reg != "e1" {
450					body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
451				}
452			}
453			if ret[0] == "_" && ret[1] == "_" {
454				textcommon += fmt.Sprintf("\t%s\n", callcommon)
455			} else {
456				textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
457			}
458			textcommon += body
459
460			if doErrno {
461				textcommon += "\tif e1 != 0 {\n"
462				textcommon += "\t\terr = errnoErr(e1)\n"
463				textcommon += "\t}\n"
464			}
465			textcommon += "\treturn\n"
466			textcommon += "}\n"
467
468			if onlyCommon {
469				continue
470			}
471
472			// CALL Prototype
473			callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
474
475			// GC function generation
476			asm := "syscall6"
477			if nonblock != nil {
478				asm = "rawSyscall6"
479			}
480
481			if len(argsgc) <= 6 {
482				for len(argsgc) < 6 {
483					argsgc = append(argsgc, "0")
484				}
485			} else {
486				fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
487				os.Exit(1)
488			}
489			argsgclist := strings.Join(argsgc, ", ")
490			callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
491
492			textgc += callProto
493			textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
494			textgc += "\treturn\n}\n"
495
496			// GCCGO function generation
497			argsgccgolist := strings.Join(argsgccgo, ", ")
498			var callgccgo string
499			if sysname == "select" {
500				// select is a keyword of Go. Its name is
501				// changed to c_select.
502				callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist)
503			} else {
504				callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
505			}
506			textgccgo += callProto
507			textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
508			textgccgo += "\te1 = syscall.GetErrno()\n"
509			textgccgo += "\treturn\n}\n"
510		}
511		if err := s.Err(); err != nil {
512			fmt.Fprintf(os.Stderr, err.Error())
513			os.Exit(1)
514		}
515		file.Close()
516	}
517	imp := ""
518	if pack != "unix" {
519		imp = "import \"golang.org/x/sys/unix\"\n"
520
521	}
522
523	// Print zsyscall_aix_ppc64.go
524	err := ioutil.WriteFile("zsyscall_aix_ppc64.go",
525		[]byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)),
526		0644)
527	if err != nil {
528		fmt.Fprintf(os.Stderr, err.Error())
529		os.Exit(1)
530	}
531
532	// Print zsyscall_aix_ppc64_gc.go
533	vardecls := "\t" + strings.Join(vars, ",\n\t")
534	vardecls += " syscallFunc"
535	err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go",
536		[]byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
537		0644)
538	if err != nil {
539		fmt.Fprintf(os.Stderr, err.Error())
540		os.Exit(1)
541	}
542
543	// Print zsyscall_aix_ppc64_gccgo.go
544	err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go",
545		[]byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)),
546		0644)
547	if err != nil {
548		fmt.Fprintf(os.Stderr, err.Error())
549		os.Exit(1)
550	}
551}
552
553const srcTemplate1 = `// %s
554// Code generated by the command above; see README.md. DO NOT EDIT.
555
556// +build %s
557
558package %s
559
560import (
561	"unsafe"
562)
563
564
565%s
566
567%s
568`
569const srcTemplate2 = `// %s
570// Code generated by the command above; see README.md. DO NOT EDIT.
571
572// +build %s
573// +build !gccgo
574
575package %s
576
577import (
578	"unsafe"
579)
580%s
581%s
582%s
583type syscallFunc uintptr
584
585var (
586%s
587)
588
589// Implemented in runtime/syscall_aix.go.
590func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
591func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
592
593%s
594`
595const srcTemplate3 = `// %s
596// Code generated by the command above; see README.md. DO NOT EDIT.
597
598// +build %s
599// +build gccgo
600
601package %s
602
603%s
604*/
605import "C"
606import (
607	"syscall"
608)
609
610
611%s
612
613%s
614`
615