golang.org/x/sys@v0.20.1-0.20240517151509-673e0f94c16d/unix/mksyscall_aix_ppc64.go (about)

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