github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/lex.go (about) 1 // Copyright 2009 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 package gc 6 7 import ( 8 "github.com/gagliardetto/golang-go/cmd/compile/internal/syntax" 9 "github.com/gagliardetto/golang-go/cmd/internal/objabi" 10 "github.com/gagliardetto/golang-go/cmd/internal/src" 11 "fmt" 12 "strings" 13 ) 14 15 // lineno is the source position at the start of the most recently lexed token. 16 // TODO(gri) rename and eventually remove 17 var lineno src.XPos 18 19 func makePos(base *src.PosBase, line, col uint) src.XPos { 20 return Ctxt.PosTable.XPos(src.MakePos(base, line, col)) 21 } 22 23 func isSpace(c rune) bool { 24 return c == ' ' || c == '\t' || c == '\n' || c == '\r' 25 } 26 27 func isQuoted(s string) bool { 28 return len(s) >= 2 && s[0] == '"' && s[len(s)-1] == '"' 29 } 30 31 const ( 32 // Func pragmas. 33 Nointerface syntax.Pragma = 1 << iota 34 Noescape // func parameters don't escape 35 Norace // func must not have race detector annotations 36 Nosplit // func should not execute on separate stack 37 Noinline // func should not be inlined 38 NoCheckPtr // func should not be instrumented by checkptr 39 CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all 40 UintptrEscapes // pointers converted to uintptr escape 41 42 // Runtime-only func pragmas. 43 // See ../../../../runtime/README.md for detailed descriptions. 44 Systemstack // func must run on system stack 45 Nowritebarrier // emit compiler error instead of write barrier 46 Nowritebarrierrec // error on write barrier in this or recursive callees 47 Yeswritebarrierrec // cancels Nowritebarrierrec in this function and callees 48 49 // Runtime-only type pragmas 50 NotInHeap // values of this type must not be heap allocated 51 ) 52 53 func pragmaValue(verb string) syntax.Pragma { 54 switch verb { 55 case "go:nointerface": 56 if objabi.Fieldtrack_enabled != 0 { 57 return Nointerface 58 } 59 case "go:noescape": 60 return Noescape 61 case "go:norace": 62 return Norace 63 case "go:nosplit": 64 return Nosplit | NoCheckPtr // implies NoCheckPtr (see #34972) 65 case "go:noinline": 66 return Noinline 67 case "go:nocheckptr": 68 return NoCheckPtr 69 case "go:systemstack": 70 return Systemstack 71 case "go:nowritebarrier": 72 return Nowritebarrier 73 case "go:nowritebarrierrec": 74 return Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier 75 case "go:yeswritebarrierrec": 76 return Yeswritebarrierrec 77 case "go:cgo_unsafe_args": 78 return CgoUnsafeArgs | NoCheckPtr // implies NoCheckPtr (see #34968) 79 case "go:uintptrescapes": 80 // For the next function declared in the file 81 // any uintptr arguments may be pointer values 82 // converted to uintptr. This directive 83 // ensures that the referenced allocated 84 // object, if any, is retained and not moved 85 // until the call completes, even though from 86 // the types alone it would appear that the 87 // object is no longer needed during the 88 // call. The conversion to uintptr must appear 89 // in the argument list. 90 // Used in syscall/dll_windows.go. 91 return UintptrEscapes 92 case "go:notinheap": 93 return NotInHeap 94 } 95 return 0 96 } 97 98 // pragcgo is called concurrently if files are parsed concurrently. 99 func (p *noder) pragcgo(pos syntax.Pos, text string) { 100 f := pragmaFields(text) 101 102 verb := strings.TrimPrefix(f[0], "go:") 103 f[0] = verb 104 105 switch verb { 106 case "cgo_export_static", "cgo_export_dynamic": 107 switch { 108 case len(f) == 2 && !isQuoted(f[1]): 109 case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]): 110 default: 111 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf(`usage: //go:%s local [remote]`, verb)}) 112 return 113 } 114 case "cgo_import_dynamic": 115 switch { 116 case len(f) == 2 && !isQuoted(f[1]): 117 case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]): 118 case len(f) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(f[3]): 119 f[3] = strings.Trim(f[3], `"`) 120 if objabi.GOOS == "aix" && f[3] != "" { 121 // On Aix, library pattern must be "lib.a/object.o" 122 // or "lib.a/libname.so.X" 123 n := strings.Split(f[3], "/") 124 if len(n) != 2 || !strings.HasSuffix(n[0], ".a") || (!strings.HasSuffix(n[1], ".o") && !strings.Contains(n[1], ".so.")) { 125 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["lib.a/object.o"]]`}) 126 return 127 } 128 } 129 default: 130 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`}) 131 return 132 } 133 case "cgo_import_static": 134 switch { 135 case len(f) == 2 && !isQuoted(f[1]): 136 default: 137 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_static local`}) 138 return 139 } 140 case "cgo_dynamic_linker": 141 switch { 142 case len(f) == 2 && isQuoted(f[1]): 143 f[1] = strings.Trim(f[1], `"`) 144 default: 145 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_dynamic_linker "path"`}) 146 return 147 } 148 case "cgo_ldflag": 149 switch { 150 case len(f) == 2 && isQuoted(f[1]): 151 f[1] = strings.Trim(f[1], `"`) 152 default: 153 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_ldflag "arg"`}) 154 return 155 } 156 default: 157 return 158 } 159 p.pragcgobuf = append(p.pragcgobuf, f) 160 } 161 162 // pragmaFields is similar to strings.FieldsFunc(s, isSpace) 163 // but does not split when inside double quoted regions and always 164 // splits before the start and after the end of a double quoted region. 165 // pragmaFields does not recognize escaped quotes. If a quote in s is not 166 // closed the part after the opening quote will not be returned as a field. 167 func pragmaFields(s string) []string { 168 var a []string 169 inQuote := false 170 fieldStart := -1 // Set to -1 when looking for start of field. 171 for i, c := range s { 172 switch { 173 case c == '"': 174 if inQuote { 175 inQuote = false 176 a = append(a, s[fieldStart:i+1]) 177 fieldStart = -1 178 } else { 179 inQuote = true 180 if fieldStart >= 0 { 181 a = append(a, s[fieldStart:i]) 182 } 183 fieldStart = i 184 } 185 case !inQuote && isSpace(c): 186 if fieldStart >= 0 { 187 a = append(a, s[fieldStart:i]) 188 fieldStart = -1 189 } 190 default: 191 if fieldStart == -1 { 192 fieldStart = i 193 } 194 } 195 } 196 if !inQuote && fieldStart >= 0 { // Last field might end at the end of the string. 197 a = append(a, s[fieldStart:]) 198 } 199 return a 200 }