1
2
3
4
5 package noder
6
7 import (
8 "fmt"
9 "internal/buildcfg"
10 "strings"
11
12 "cmd/compile/internal/ir"
13 "cmd/compile/internal/syntax"
14 )
15
16 func isSpace(c rune) bool {
17 return c == ' ' || c == '\t' || c == '\n' || c == '\r'
18 }
19
20 func isQuoted(s string) bool {
21 return len(s) >= 2 && s[0] == '"' && s[len(s)-1] == '"'
22 }
23
24 const (
25 funcPragmas = ir.Nointerface |
26 ir.Noescape |
27 ir.Norace |
28 ir.Nosplit |
29 ir.Noinline |
30 ir.NoCheckPtr |
31 ir.RegisterParams |
32 ir.CgoUnsafeArgs |
33 ir.UintptrKeepAlive |
34 ir.UintptrEscapes |
35 ir.Systemstack |
36 ir.Nowritebarrier |
37 ir.Nowritebarrierrec |
38 ir.Yeswritebarrierrec
39 )
40
41 func pragmaFlag(verb string) ir.PragmaFlag {
42 switch verb {
43 case "go:build":
44 return ir.GoBuildPragma
45 case "go:nointerface":
46 if buildcfg.Experiment.FieldTrack {
47 return ir.Nointerface
48 }
49 case "go:noescape":
50 return ir.Noescape
51 case "go:norace":
52 return ir.Norace
53 case "go:nosplit":
54 return ir.Nosplit | ir.NoCheckPtr
55 case "go:noinline":
56 return ir.Noinline
57 case "go:nocheckptr":
58 return ir.NoCheckPtr
59 case "go:systemstack":
60 return ir.Systemstack
61 case "go:nowritebarrier":
62 return ir.Nowritebarrier
63 case "go:nowritebarrierrec":
64 return ir.Nowritebarrierrec | ir.Nowritebarrier
65 case "go:yeswritebarrierrec":
66 return ir.Yeswritebarrierrec
67 case "go:cgo_unsafe_args":
68 return ir.CgoUnsafeArgs | ir.NoCheckPtr
69 case "go:uintptrkeepalive":
70 return ir.UintptrKeepAlive
71 case "go:uintptrescapes":
72
73
74
75 return ir.UintptrEscapes | ir.UintptrKeepAlive
76 case "go:registerparams":
77 return ir.RegisterParams
78 }
79 return 0
80 }
81
82
83 func (p *noder) pragcgo(pos syntax.Pos, text string) {
84 f := pragmaFields(text)
85
86 verb := strings.TrimPrefix(f[0], "go:")
87 f[0] = verb
88
89 switch verb {
90 case "cgo_export_static", "cgo_export_dynamic":
91 switch {
92 case len(f) == 2 && !isQuoted(f[1]):
93 case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]):
94 default:
95 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf(`usage: //go:%s local [remote]`, verb)})
96 return
97 }
98 case "cgo_import_dynamic":
99 switch {
100 case len(f) == 2 && !isQuoted(f[1]):
101 case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]):
102 case len(f) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(f[3]):
103 f[3] = strings.Trim(f[3], `"`)
104 if buildcfg.GOOS == "aix" && f[3] != "" {
105
106
107 n := strings.Split(f[3], "/")
108 if len(n) != 2 || !strings.HasSuffix(n[0], ".a") || (!strings.HasSuffix(n[1], ".o") && !strings.Contains(n[1], ".so.")) {
109 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["lib.a/object.o"]]`})
110 return
111 }
112 }
113 default:
114 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`})
115 return
116 }
117 case "cgo_import_static":
118 switch {
119 case len(f) == 2 && !isQuoted(f[1]):
120 default:
121 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_static local`})
122 return
123 }
124 case "cgo_dynamic_linker":
125 switch {
126 case len(f) == 2 && isQuoted(f[1]):
127 f[1] = strings.Trim(f[1], `"`)
128 default:
129 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_dynamic_linker "path"`})
130 return
131 }
132 case "cgo_ldflag":
133 switch {
134 case len(f) == 2 && isQuoted(f[1]):
135 f[1] = strings.Trim(f[1], `"`)
136 default:
137 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_ldflag "arg"`})
138 return
139 }
140 default:
141 return
142 }
143 p.pragcgobuf = append(p.pragcgobuf, f)
144 }
145
146
147
148
149
150
151 func pragmaFields(s string) []string {
152 var a []string
153 inQuote := false
154 fieldStart := -1
155 for i, c := range s {
156 switch {
157 case c == '"':
158 if inQuote {
159 inQuote = false
160 a = append(a, s[fieldStart:i+1])
161 fieldStart = -1
162 } else {
163 inQuote = true
164 if fieldStart >= 0 {
165 a = append(a, s[fieldStart:i])
166 }
167 fieldStart = i
168 }
169 case !inQuote && isSpace(c):
170 if fieldStart >= 0 {
171 a = append(a, s[fieldStart:i])
172 fieldStart = -1
173 }
174 default:
175 if fieldStart == -1 {
176 fieldStart = i
177 }
178 }
179 }
180 if !inQuote && fieldStart >= 0 {
181 a = append(a, s[fieldStart:])
182 }
183 return a
184 }
185
View as plain text