1
2
3
4
5 package asmgen
6
7 import (
8 "fmt"
9 "slices"
10 "strings"
11 )
12
13
14
15
16
17
18 type Func struct {
19 Name string
20 Asm *Asm
21 inputs []string
22 outputs []string
23 args map[string]int
24 }
25
26
27 func (a *Asm) Func(decl string) *Func {
28 d, ok := strings.CutPrefix(decl, "func ")
29 if !ok {
30 a.Fatalf("func decl does not begin with 'func '")
31 }
32 name, d, ok := strings.Cut(d, "(")
33 if !ok {
34 a.Fatalf("func decl does not have func arg list")
35 }
36 f := &Func{
37 Name: name,
38 Asm: a,
39 args: make(map[string]int),
40 }
41 a.FreeAll()
42
43
44
45 d = strings.ReplaceAll(d, ") (", ", ")
46 d = strings.TrimSuffix(d, ")")
47 args := strings.Split(d, ",")
48
49
50 typ := ""
51 for i, arg := range slices.Backward(args) {
52 arg = strings.TrimSpace(arg)
53 if !strings.Contains(arg, " ") {
54 if typ == "" {
55 a.Fatalf("missing argument type")
56 }
57 arg += " " + typ
58 } else {
59 _, typ, _ = strings.Cut(arg, " ")
60 }
61 args[i] = arg
62 }
63
64
65 off := 0
66 for _, arg := range args {
67 name, typ, _ := strings.Cut(arg, " ")
68 switch typ {
69 default:
70 a.Fatalf("unknown type %s", typ)
71 case "Word", "uint", "int":
72 f.args[name] = off
73 off += a.Arch.WordBytes
74 case "[]Word":
75 if strings.HasPrefix(name, "z") {
76 f.outputs = append(f.outputs, name)
77 } else {
78 f.inputs = append(f.inputs, name)
79 }
80 f.args[name+"_base"] = off
81 f.args[name+"_len"] = off + a.Arch.WordBytes
82 f.args[name+"_cap"] = off + 2*a.Arch.WordBytes
83 off += 3 * a.Arch.WordBytes
84 }
85 }
86
87 a.Printf("\n")
88 a.Printf("// %s\n", decl)
89 a.Printf("TEXT ยท%s(SB), NOSPLIT, $0\n", name)
90 if a.Arch.setup != nil {
91 a.Arch.setup(f)
92 }
93 return f
94 }
95
96
97
98 func (f *Func) Arg(name string) Reg {
99 return f.ArgHint(name, HintNone)
100 }
101
102
103 func (f *Func) ArgHint(name string, hint Hint) Reg {
104 off, ok := f.args[name]
105 if !ok {
106 f.Asm.Fatalf("unknown argument %s", name)
107 }
108 mem := Reg{fmt.Sprintf("%s+%d(FP)", name, off)}
109 if hint == HintMemOK && f.Asm.Arch.memOK {
110 return mem
111 }
112 r := f.Asm.RegHint(hint)
113 f.Asm.Mov(mem, r)
114 return r
115 }
116
117
118 func (f *Func) ArgPtr(name string) RegPtr {
119 return RegPtr(f.Arg(name))
120 }
121
122
123 func (f *Func) StoreArg(src Reg, name string) {
124 off, ok := f.args[name]
125 if !ok {
126 f.Asm.Fatalf("unknown argument %s", name)
127 }
128 a := f.Asm
129 mem := Reg{fmt.Sprintf("%s+%d(FP)", name, off)}
130 if src.IsImm() && !a.Arch.memOK {
131 r := a.Reg()
132 a.Mov(src, r)
133 a.Mov(r, mem)
134 a.Free(r)
135 return
136 }
137 a.Mov(src, mem)
138 }
139
View as plain text