1// Copyright 2018 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// +build ignore
7
8// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
9//This program must be run after mksyscall.go.
10package main
11
12import (
13	"bytes"
14	"fmt"
15	"io/ioutil"
16	"log"
17	"os"
18	"strings"
19)
20
21const ptrsize = 8 // Pointer size. All supported platforms are 64-bit.
22
23func writeASMFile(in string, fileName string, buildTags string) {
24	trampolines := map[string]bool{}
25
26	var out bytes.Buffer
27
28	fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
29	fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
30	fmt.Fprintf(&out, "\n")
31	fmt.Fprintf(&out, "//go:build %s\n", buildTags)
32	fmt.Fprintf(&out, "// +build %s\n", buildTags)
33	fmt.Fprintf(&out, "\n")
34	fmt.Fprintf(&out, "#include \"textflag.h\"\n")
35	for _, line := range strings.Split(in, "\n") {
36		const prefix = "var "
37		const suffix = "_trampoline_addr uintptr"
38		if !strings.HasPrefix(line, prefix) || !strings.HasSuffix(line, suffix) {
39			continue
40		}
41		fn := strings.TrimSuffix(strings.TrimPrefix(line, prefix), suffix)
42		if !trampolines[fn] {
43			trampolines[fn] = true
44			fmt.Fprintf(&out, "\nTEXT %s_trampoline<>(SB),NOSPLIT,$0-0\n", fn)
45			fmt.Fprintf(&out, "\tJMP\t%s(SB)\n\n", fn)
46			fmt.Fprintf(&out, "GLOBL\t·%s_trampoline_addr(SB), RODATA, $%d\n", fn, ptrsize)
47			fmt.Fprintf(&out, "DATA\t·%s_trampoline_addr(SB)/%d, $%s_trampoline<>(SB)\n", fn, ptrsize, fn)
48		}
49	}
50	err := ioutil.WriteFile(fileName, out.Bytes(), 0644)
51	if err != nil {
52		log.Fatalf("can't write %s: %s", fileName, err)
53	}
54}
55
56func main() {
57	in1, err := ioutil.ReadFile("syscall_darwin.go")
58	if err != nil {
59		log.Fatalf("can't open syscall_darwin.go: %s", err)
60	}
61	arch := os.Args[1]
62	in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
63	if err != nil {
64		log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
65	}
66	in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
67	if err != nil {
68		log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
69	}
70	in := string(in1) + string(in2) + string(in3)
71
72	writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.s", arch), "go1.12")
73
74	in1, err = ioutil.ReadFile("syscall_darwin.1_13.go")
75	if err != nil {
76		log.Fatalf("can't open syscall_darwin.1_13.go: %s", err)
77	}
78	in2, err = ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.1_13.go", arch))
79	if err != nil {
80		log.Fatalf("can't open zsyscall_darwin_%s.1_13.go: %s", arch, err)
81	}
82
83	in = string(in1) + string(in2)
84
85	writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.1_13.s", arch), "go1.13")
86}
87