mksys.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. package main
  10. import (
  11. "encoding/json"
  12. "flag"
  13. "fmt"
  14. "io/ioutil"
  15. "log"
  16. "os"
  17. "path"
  18. "strings"
  19. "text/template"
  20. )
  21. type Syscall struct {
  22. Ret []string
  23. Args []string
  24. Name string
  25. Id uint32
  26. Define string
  27. Sysname string
  28. Libname string
  29. Fudge string `json:"-"`
  30. GoArgs []string `json:"-"`
  31. Ret0 string `json:"-"`
  32. }
  33. type Syserror struct {
  34. Name string
  35. String string
  36. Id uint32
  37. }
  38. type Sysconf struct {
  39. Syscalls []Syscall
  40. Syserrors []Syserror
  41. }
  42. var mode = flag.String("mode", "", "must be one of: sys.h, sysdecl.h, syscallfiles, systab.c, error.h, errstr.h, sys_harvey.s, sysnum.go")
  43. var outpath = flag.String("o", "", "path/to/output.c")
  44. func usage(msg string) {
  45. fmt.Fprint(os.Stderr, msg)
  46. fmt.Fprint(os.Stderr, "Usage: mksys [-o outpath] -mode=MODE path/to/sysconf.json\n")
  47. flag.PrintDefaults()
  48. os.Exit(1)
  49. }
  50. func main() {
  51. flag.Parse()
  52. if flag.NArg() != 1 {
  53. usage("no path to sysconf.json")
  54. }
  55. outfile := os.Stdout
  56. if *mode != "syscallfiles" && *outpath != "" {
  57. of, err := os.Create(*outpath)
  58. if err != nil {
  59. log.Fatal(err)
  60. }
  61. outfile = of
  62. }
  63. buf, err := ioutil.ReadFile(flag.Arg(0))
  64. if err != nil {
  65. log.Fatal(err)
  66. }
  67. var sysconf Sysconf
  68. err = json.Unmarshal(buf, &sysconf)
  69. if err != nil {
  70. log.Fatal(err)
  71. }
  72. syscalls := sysconf.Syscalls
  73. syserrors := sysconf.Syserrors
  74. for i := range syscalls {
  75. if syscalls[i].Define == "" {
  76. syscalls[i].Define = strings.ToUpper(syscalls[i].Name)
  77. }
  78. if syscalls[i].Sysname == "" {
  79. syscalls[i].Sysname = "sys" + syscalls[i].Name
  80. }
  81. if syscalls[i].Libname == "" {
  82. syscalls[i].Libname = syscalls[i].Name
  83. }
  84. }
  85. switch *mode {
  86. case "sys_harvey.s":
  87. if os.Getenv("ARCH") != "amd64" {
  88. usage("ARCH unsupported or not set")
  89. }
  90. syscallargs := []string{ "DI", "SI", "DX", "R10", "R8", "R9" };
  91. //funcallregs := []string{ "DI", "SI", "DX", "CX", "R8", "R9" };
  92. for i := range syscalls {
  93. goargs := []string{}
  94. fpoff := 0
  95. for k := range syscalls[i].Args {
  96. switch syscalls[i].Args[k] {
  97. case "int32_t", "uint32_t":
  98. goargs = append(goargs, fmt.Sprintf("MOVL arg%d+%d(FP), %s", k, fpoff, syscallargs[k]))
  99. fpoff += 4
  100. case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*", "int64_t":
  101. fpoff = (fpoff + 7) & ^7
  102. goargs = append(goargs, fmt.Sprintf("MOVQ arg%d+%d(FP), %s", k, fpoff, syscallargs[k]))
  103. fpoff += 8
  104. default:
  105. log.Fatalf("unsupported arg %s in syscall: %v", syscalls[i].Args[k], syscalls[i])
  106. }
  107. }
  108. syscalls[i].GoArgs = goargs
  109. switch syscalls[i].Ret[0] {
  110. case "int32_t", "uint32_t":
  111. syscalls[i].Ret0 = fmt.Sprintf("MOVL AX, ret+%d(FP)", fpoff)
  112. fpoff += 4
  113. case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*", "int64_t":
  114. fpoff = (fpoff + 7) & ^7
  115. syscalls[i].Ret0 = fmt.Sprintf("MOVQ AX, ret+%d(FP)", fpoff)
  116. fpoff += 8
  117. default:
  118. log.Fatalf("unsupported Ret[0] in syscall: %v", syscalls[i])
  119. }
  120. }
  121. tmpl, err := template.New("sys_harvey.s").Parse(`/* automatically generated by mksys */
  122. /* System calls for AMD64, Harvey */
  123. #include "go_asm.h"
  124. #include "go_tls.h"
  125. #include "textflag.h"
  126. {{ range . }}
  127. TEXT runtime·{{ .Libname }}(SB),NOSPLIT,$0
  128. {{ range .GoArgs }} {{ . }}
  129. {{ end }} MOVQ ${{ .Id }}, AX
  130. SYSCALL
  131. {{ .Ret0 }}
  132. RET
  133. {{ end }}
  134. `)
  135. if err != nil {
  136. log.Fatal(err)
  137. }
  138. err = tmpl.Execute(outfile, syscalls)
  139. if err != nil {
  140. log.Fatal(err)
  141. }
  142. case "syscallfiles":
  143. if os.Getenv("ARCH") != "amd64" {
  144. usage("ARCH unsupported or not set")
  145. }
  146. tmpl, err := template.New("syscall.s").Parse(`/* automatically generated by mksys */
  147. .globl {{ .Libname }}
  148. {{ .Libname }}:
  149. movq %rcx, %r10 /* rcx gets smashed by systenter. Use r10.*/
  150. movq ${{ .Id }},%rax /* Put the system call into rax, just like linux. */
  151. syscall
  152. ret
  153. `)
  154. if err != nil {
  155. log.Fatal(err)
  156. }
  157. for i := range syscalls {
  158. path := path.Join(*outpath, syscalls[i].Libname+".s")
  159. file, err := os.Create(path)
  160. if err != nil {
  161. log.Fatal(err)
  162. }
  163. err = tmpl.Execute(file, syscalls[i])
  164. if err != nil {
  165. log.Fatal(err)
  166. }
  167. err = file.Close()
  168. if err != nil {
  169. log.Fatal(err)
  170. }
  171. }
  172. case "sysnum.go":
  173. tmpl, err := template.New("sysnum.go").Parse(`// automatically generated by mksys
  174. package syscall
  175. const(
  176. {{ range . }} SYS_{{ .Define }} = {{ .Id }}
  177. {{ end }}
  178. )
  179. `)
  180. err = tmpl.Execute(outfile, syscalls)
  181. if err != nil {
  182. log.Fatal(err)
  183. }
  184. case "sys.h":
  185. tmpl, err := template.New("sys.h").Parse(`/* automatically generated by mksys */
  186. {{ range . }}#define {{ .Define }} {{ .Id }}
  187. {{ end }}
  188. `)
  189. err = tmpl.Execute(outfile, syscalls)
  190. if err != nil {
  191. log.Fatal(err)
  192. }
  193. case "sysdecl.h":
  194. tmpl, err := template.New("sysdecl.h").Parse(`/* automatically generated by mksys */
  195. {{ range . }}extern {{ .Ret0 }} {{ .Libname }}({{ range $i, $e := .Args }}{{ if $i }}, {{ end }}{{ $e }}{{ end }});
  196. {{ end }}
  197. `)
  198. err = tmpl.Execute(outfile, syscalls)
  199. if err != nil {
  200. log.Fatal(err)
  201. }
  202. case "systab.c":
  203. for i := range syscalls {
  204. var fudge string
  205. switch syscalls[i].Ret[0] {
  206. case "int32_t":
  207. fudge = "{ .i = -1 }"
  208. case "int64_t":
  209. fudge = "{ .vl = -1ll }"
  210. case "void*", "char*":
  211. fudge = "{ .v = (void*)-1ll }"
  212. default:
  213. log.Fatalf("unsupported Ret[0] in syscall: %v", syscalls[i])
  214. }
  215. if syscalls[i].Fudge == "" {
  216. syscalls[i].Fudge = fudge
  217. }
  218. syscalls[i].Ret0 = syscalls[i].Ret[0]
  219. }
  220. tmpl, err := template.New("systab.c").Parse(`/* automatically generated by mksys */
  221. #include "u.h"
  222. #include "../port/lib.h"
  223. #include "mem.h"
  224. #include "dat.h"
  225. #include "fns.h"
  226. #include "../../libc/9syscall/sys.h"
  227. {{ range . }}extern void {{ .Sysname }}(Ar0*, ...);
  228. {{ end }}
  229. Systab systab[] = {
  230. {{ range . }}[{{ .Define }}] { "{{ .Name }}", {{ .Sysname }}, {{ .Fudge }} },
  231. {{ end }}
  232. };
  233. int nsyscall = nelem(systab);
  234. `)
  235. err = tmpl.Execute(outfile, syscalls)
  236. if err != nil {
  237. log.Fatal(err)
  238. }
  239. case "error.h":
  240. tmpl, err := template.New("error.h").Parse(`/* automatically generated by mksys */
  241. {{ range . }}extern char {{ .Name }}[]; /* {{ .String }} */
  242. {{ end }}
  243. `)
  244. err = tmpl.Execute(outfile, syserrors)
  245. if err != nil {
  246. log.Fatal(err)
  247. }
  248. case "errstr.h":
  249. tmpl, err := template.New("errstr.h").Parse(`/* automatically generated by mksys */
  250. {{ range . }}char {{ .Name }}[] = "{{ .String }}";
  251. {{ end }}
  252. `)
  253. err = tmpl.Execute(outfile, syserrors)
  254. if err != nil {
  255. log.Fatal(err)
  256. }
  257. }
  258. }