mirror of
https://github.com/golang/go
synced 2024-10-14 11:53:56 +00:00
[dev.boringcrypto] all: merge master into dev.boringcrypto
Add a couple of skips for slow js/wasm tests. Change-Id: Ic95256b1d3c6e5e2f0cc536fad51e914d31cda9e
This commit is contained in:
commit
77db076129
2
.github/SUPPORT.md
vendored
2
.github/SUPPORT.md
vendored
|
@ -9,6 +9,6 @@ For asking questions, see:
|
|||
|
||||
* [Gophers Slack](https://gophers.slack.com), use the [invite app](https://invite.slack.golangbridge.org/) for access
|
||||
|
||||
* [Stack Overflow](http://stackoverflow.com/questions/tagged/go) with questions tagged "go"
|
||||
* [Stack Overflow](https://stackoverflow.com/questions/tagged/go) with questions tagged "go"
|
||||
|
||||
* **IRC** channel #go-nuts on Freenode
|
||||
|
|
|
@ -362,24 +362,17 @@ pkg syscall (openbsd-386-cgo), const SYS_KILL = 37
|
|||
pkg syscall (openbsd-amd64), const SYS_KILL = 37
|
||||
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37
|
||||
pkg unicode, const Version = "9.0.0"
|
||||
pkg text/template/parse, method (*VariableNode) Copy() Node
|
||||
pkg text/template/parse, method (*VariableNode) String() string
|
||||
pkg text/template/parse, method (VariableNode) Position() Pos
|
||||
pkg text/template/parse, method (VariableNode) Type() NodeType
|
||||
pkg text/template/parse, type PipeNode struct, Decl []*VariableNode
|
||||
pkg text/template/parse, type VariableNode struct
|
||||
pkg text/template/parse, type VariableNode struct, Ident []string
|
||||
pkg text/template/parse, type VariableNode struct, embedded NodeType
|
||||
pkg text/template/parse, type VariableNode struct, embedded Pos
|
||||
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
||||
pkg syscall (windows-386), type CertChainPolicyStatus struct, ExtraPolicyStatus uintptr
|
||||
pkg syscall (windows-386), type CertContext struct, CertInfo uintptr
|
||||
pkg syscall (windows-386), type CertRevocationInfo struct, CrlInfo uintptr
|
||||
pkg syscall (windows-386), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
||||
pkg syscall (windows-386), type CertSimpleChain struct, TrustListInfo uintptr
|
||||
pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983295
|
||||
pkg syscall (windows-amd64), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
||||
pkg syscall (windows-amd64), type CertChainPolicyStatus struct, ExtraPolicyStatus uintptr
|
||||
pkg syscall (windows-amd64), type CertContext struct, CertInfo uintptr
|
||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr
|
||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
||||
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr
|
||||
pkg syscall (windows-amd64), const TOKEN_ALL_ACCESS = 983295
|
||||
|
|
546
api/go1.11.txt
Normal file
546
api/go1.11.txt
Normal file
|
@ -0,0 +1,546 @@
|
|||
pkg crypto/cipher, func NewGCMWithTagSize(Block, int) (AEAD, error)
|
||||
pkg crypto/rsa, method (*PrivateKey) Size() int
|
||||
pkg crypto/rsa, method (*PublicKey) Size() int
|
||||
pkg crypto/tls, type ConnectionState struct, ExportKeyingMaterial func(string, []uint8, int) ([]uint8, bool)
|
||||
pkg database/sql, method (IsolationLevel) String() string
|
||||
pkg database/sql, type DBStats struct, Idle int
|
||||
pkg database/sql, type DBStats struct, InUse int
|
||||
pkg database/sql, type DBStats struct, MaxIdleClosed int64
|
||||
pkg database/sql, type DBStats struct, MaxLifetimeClosed int64
|
||||
pkg database/sql, type DBStats struct, MaxOpenConnections int
|
||||
pkg database/sql, type DBStats struct, WaitCount int64
|
||||
pkg database/sql, type DBStats struct, WaitDuration time.Duration
|
||||
pkg debug/elf, const ELFOSABI_AROS = 15
|
||||
pkg debug/elf, const ELFOSABI_AROS OSABI
|
||||
pkg debug/elf, const ELFOSABI_CLOUDABI = 17
|
||||
pkg debug/elf, const ELFOSABI_CLOUDABI OSABI
|
||||
pkg debug/elf, const ELFOSABI_FENIXOS = 16
|
||||
pkg debug/elf, const ELFOSABI_FENIXOS OSABI
|
||||
pkg debug/elf, const EM_56800EX = 200
|
||||
pkg debug/elf, const EM_56800EX Machine
|
||||
pkg debug/elf, const EM_68HC05 = 72
|
||||
pkg debug/elf, const EM_68HC05 Machine
|
||||
pkg debug/elf, const EM_68HC08 = 71
|
||||
pkg debug/elf, const EM_68HC08 Machine
|
||||
pkg debug/elf, const EM_68HC11 = 70
|
||||
pkg debug/elf, const EM_68HC11 Machine
|
||||
pkg debug/elf, const EM_68HC16 = 69
|
||||
pkg debug/elf, const EM_68HC16 Machine
|
||||
pkg debug/elf, const EM_78KOR = 199
|
||||
pkg debug/elf, const EM_78KOR Machine
|
||||
pkg debug/elf, const EM_8051 = 165
|
||||
pkg debug/elf, const EM_8051 Machine
|
||||
pkg debug/elf, const EM_ALTERA_NIOS2 = 113
|
||||
pkg debug/elf, const EM_ALTERA_NIOS2 Machine
|
||||
pkg debug/elf, const EM_AMDGPU = 224
|
||||
pkg debug/elf, const EM_AMDGPU Machine
|
||||
pkg debug/elf, const EM_ARCA = 109
|
||||
pkg debug/elf, const EM_ARCA Machine
|
||||
pkg debug/elf, const EM_ARC_COMPACT = 93
|
||||
pkg debug/elf, const EM_ARC_COMPACT Machine
|
||||
pkg debug/elf, const EM_ARC_COMPACT2 = 195
|
||||
pkg debug/elf, const EM_ARC_COMPACT2 Machine
|
||||
pkg debug/elf, const EM_AVR = 83
|
||||
pkg debug/elf, const EM_AVR Machine
|
||||
pkg debug/elf, const EM_AVR32 = 185
|
||||
pkg debug/elf, const EM_AVR32 Machine
|
||||
pkg debug/elf, const EM_BA1 = 201
|
||||
pkg debug/elf, const EM_BA1 Machine
|
||||
pkg debug/elf, const EM_BA2 = 202
|
||||
pkg debug/elf, const EM_BA2 Machine
|
||||
pkg debug/elf, const EM_BLACKFIN = 106
|
||||
pkg debug/elf, const EM_BLACKFIN Machine
|
||||
pkg debug/elf, const EM_BPF = 247
|
||||
pkg debug/elf, const EM_BPF Machine
|
||||
pkg debug/elf, const EM_C166 = 116
|
||||
pkg debug/elf, const EM_C166 Machine
|
||||
pkg debug/elf, const EM_CDP = 215
|
||||
pkg debug/elf, const EM_CDP Machine
|
||||
pkg debug/elf, const EM_CE = 119
|
||||
pkg debug/elf, const EM_CE Machine
|
||||
pkg debug/elf, const EM_CLOUDSHIELD = 192
|
||||
pkg debug/elf, const EM_CLOUDSHIELD Machine
|
||||
pkg debug/elf, const EM_COGE = 216
|
||||
pkg debug/elf, const EM_COGE Machine
|
||||
pkg debug/elf, const EM_COOL = 217
|
||||
pkg debug/elf, const EM_COOL Machine
|
||||
pkg debug/elf, const EM_COREA_1ST = 193
|
||||
pkg debug/elf, const EM_COREA_1ST Machine
|
||||
pkg debug/elf, const EM_COREA_2ND = 194
|
||||
pkg debug/elf, const EM_COREA_2ND Machine
|
||||
pkg debug/elf, const EM_CR = 103
|
||||
pkg debug/elf, const EM_CR Machine
|
||||
pkg debug/elf, const EM_CR16 = 177
|
||||
pkg debug/elf, const EM_CR16 Machine
|
||||
pkg debug/elf, const EM_CRAYNV2 = 172
|
||||
pkg debug/elf, const EM_CRAYNV2 Machine
|
||||
pkg debug/elf, const EM_CRIS = 76
|
||||
pkg debug/elf, const EM_CRIS Machine
|
||||
pkg debug/elf, const EM_CRX = 114
|
||||
pkg debug/elf, const EM_CRX Machine
|
||||
pkg debug/elf, const EM_CSR_KALIMBA = 219
|
||||
pkg debug/elf, const EM_CSR_KALIMBA Machine
|
||||
pkg debug/elf, const EM_CUDA = 190
|
||||
pkg debug/elf, const EM_CUDA Machine
|
||||
pkg debug/elf, const EM_CYPRESS_M8C = 161
|
||||
pkg debug/elf, const EM_CYPRESS_M8C Machine
|
||||
pkg debug/elf, const EM_D10V = 85
|
||||
pkg debug/elf, const EM_D10V Machine
|
||||
pkg debug/elf, const EM_D30V = 86
|
||||
pkg debug/elf, const EM_D30V Machine
|
||||
pkg debug/elf, const EM_DSP24 = 136
|
||||
pkg debug/elf, const EM_DSP24 Machine
|
||||
pkg debug/elf, const EM_DSPIC30F = 118
|
||||
pkg debug/elf, const EM_DSPIC30F Machine
|
||||
pkg debug/elf, const EM_DXP = 112
|
||||
pkg debug/elf, const EM_DXP Machine
|
||||
pkg debug/elf, const EM_ECOG1 = 168
|
||||
pkg debug/elf, const EM_ECOG1 Machine
|
||||
pkg debug/elf, const EM_ECOG16 = 176
|
||||
pkg debug/elf, const EM_ECOG16 Machine
|
||||
pkg debug/elf, const EM_ECOG1X = 168
|
||||
pkg debug/elf, const EM_ECOG1X Machine
|
||||
pkg debug/elf, const EM_ECOG2 = 134
|
||||
pkg debug/elf, const EM_ECOG2 Machine
|
||||
pkg debug/elf, const EM_ETPU = 178
|
||||
pkg debug/elf, const EM_ETPU Machine
|
||||
pkg debug/elf, const EM_EXCESS = 111
|
||||
pkg debug/elf, const EM_EXCESS Machine
|
||||
pkg debug/elf, const EM_F2MC16 = 104
|
||||
pkg debug/elf, const EM_F2MC16 Machine
|
||||
pkg debug/elf, const EM_FIREPATH = 78
|
||||
pkg debug/elf, const EM_FIREPATH Machine
|
||||
pkg debug/elf, const EM_FR30 = 84
|
||||
pkg debug/elf, const EM_FR30 Machine
|
||||
pkg debug/elf, const EM_FT32 = 222
|
||||
pkg debug/elf, const EM_FT32 Machine
|
||||
pkg debug/elf, const EM_FX66 = 66
|
||||
pkg debug/elf, const EM_FX66 Machine
|
||||
pkg debug/elf, const EM_HUANY = 81
|
||||
pkg debug/elf, const EM_HUANY Machine
|
||||
pkg debug/elf, const EM_INTEL205 = 205
|
||||
pkg debug/elf, const EM_INTEL205 Machine
|
||||
pkg debug/elf, const EM_INTEL206 = 206
|
||||
pkg debug/elf, const EM_INTEL206 Machine
|
||||
pkg debug/elf, const EM_INTEL207 = 207
|
||||
pkg debug/elf, const EM_INTEL207 Machine
|
||||
pkg debug/elf, const EM_INTEL208 = 208
|
||||
pkg debug/elf, const EM_INTEL208 Machine
|
||||
pkg debug/elf, const EM_INTEL209 = 209
|
||||
pkg debug/elf, const EM_INTEL209 Machine
|
||||
pkg debug/elf, const EM_IP2K = 101
|
||||
pkg debug/elf, const EM_IP2K Machine
|
||||
pkg debug/elf, const EM_JAVELIN = 77
|
||||
pkg debug/elf, const EM_JAVELIN Machine
|
||||
pkg debug/elf, const EM_K10M = 181
|
||||
pkg debug/elf, const EM_K10M Machine
|
||||
pkg debug/elf, const EM_KM32 = 210
|
||||
pkg debug/elf, const EM_KM32 Machine
|
||||
pkg debug/elf, const EM_KMX16 = 212
|
||||
pkg debug/elf, const EM_KMX16 Machine
|
||||
pkg debug/elf, const EM_KMX32 = 211
|
||||
pkg debug/elf, const EM_KMX32 Machine
|
||||
pkg debug/elf, const EM_KMX8 = 213
|
||||
pkg debug/elf, const EM_KMX8 Machine
|
||||
pkg debug/elf, const EM_KVARC = 214
|
||||
pkg debug/elf, const EM_KVARC Machine
|
||||
pkg debug/elf, const EM_L10M = 180
|
||||
pkg debug/elf, const EM_L10M Machine
|
||||
pkg debug/elf, const EM_LANAI = 244
|
||||
pkg debug/elf, const EM_LANAI Machine
|
||||
pkg debug/elf, const EM_LATTICEMICO32 = 138
|
||||
pkg debug/elf, const EM_LATTICEMICO32 Machine
|
||||
pkg debug/elf, const EM_M16C = 117
|
||||
pkg debug/elf, const EM_M16C Machine
|
||||
pkg debug/elf, const EM_M32C = 120
|
||||
pkg debug/elf, const EM_M32C Machine
|
||||
pkg debug/elf, const EM_M32R = 88
|
||||
pkg debug/elf, const EM_M32R Machine
|
||||
pkg debug/elf, const EM_MANIK = 171
|
||||
pkg debug/elf, const EM_MANIK Machine
|
||||
pkg debug/elf, const EM_MAX = 102
|
||||
pkg debug/elf, const EM_MAX Machine
|
||||
pkg debug/elf, const EM_MAXQ30 = 169
|
||||
pkg debug/elf, const EM_MAXQ30 Machine
|
||||
pkg debug/elf, const EM_MCHP_PIC = 204
|
||||
pkg debug/elf, const EM_MCHP_PIC Machine
|
||||
pkg debug/elf, const EM_MCST_ELBRUS = 175
|
||||
pkg debug/elf, const EM_MCST_ELBRUS Machine
|
||||
pkg debug/elf, const EM_METAG = 174
|
||||
pkg debug/elf, const EM_METAG Machine
|
||||
pkg debug/elf, const EM_MICROBLAZE = 189
|
||||
pkg debug/elf, const EM_MICROBLAZE Machine
|
||||
pkg debug/elf, const EM_MMDSP_PLUS = 160
|
||||
pkg debug/elf, const EM_MMDSP_PLUS Machine
|
||||
pkg debug/elf, const EM_MMIX = 80
|
||||
pkg debug/elf, const EM_MMIX Machine
|
||||
pkg debug/elf, const EM_MN10200 = 90
|
||||
pkg debug/elf, const EM_MN10200 Machine
|
||||
pkg debug/elf, const EM_MN10300 = 89
|
||||
pkg debug/elf, const EM_MN10300 Machine
|
||||
pkg debug/elf, const EM_MOXIE = 223
|
||||
pkg debug/elf, const EM_MOXIE Machine
|
||||
pkg debug/elf, const EM_MSP430 = 105
|
||||
pkg debug/elf, const EM_MSP430 Machine
|
||||
pkg debug/elf, const EM_NDS32 = 167
|
||||
pkg debug/elf, const EM_NDS32 Machine
|
||||
pkg debug/elf, const EM_NORC = 218
|
||||
pkg debug/elf, const EM_NORC Machine
|
||||
pkg debug/elf, const EM_NS32K = 97
|
||||
pkg debug/elf, const EM_NS32K Machine
|
||||
pkg debug/elf, const EM_OPEN8 = 196
|
||||
pkg debug/elf, const EM_OPEN8 Machine
|
||||
pkg debug/elf, const EM_OPENRISC = 92
|
||||
pkg debug/elf, const EM_OPENRISC Machine
|
||||
pkg debug/elf, const EM_PDP10 = 64
|
||||
pkg debug/elf, const EM_PDP10 Machine
|
||||
pkg debug/elf, const EM_PDP11 = 65
|
||||
pkg debug/elf, const EM_PDP11 Machine
|
||||
pkg debug/elf, const EM_PDSP = 63
|
||||
pkg debug/elf, const EM_PDSP Machine
|
||||
pkg debug/elf, const EM_PJ = 91
|
||||
pkg debug/elf, const EM_PJ Machine
|
||||
pkg debug/elf, const EM_PRISM = 82
|
||||
pkg debug/elf, const EM_PRISM Machine
|
||||
pkg debug/elf, const EM_QDSP6 = 164
|
||||
pkg debug/elf, const EM_QDSP6 Machine
|
||||
pkg debug/elf, const EM_R32C = 162
|
||||
pkg debug/elf, const EM_R32C Machine
|
||||
pkg debug/elf, const EM_RISCV = 243
|
||||
pkg debug/elf, const EM_RISCV Machine
|
||||
pkg debug/elf, const EM_RL78 = 197
|
||||
pkg debug/elf, const EM_RL78 Machine
|
||||
pkg debug/elf, const EM_RS08 = 132
|
||||
pkg debug/elf, const EM_RS08 Machine
|
||||
pkg debug/elf, const EM_RX = 173
|
||||
pkg debug/elf, const EM_RX Machine
|
||||
pkg debug/elf, const EM_SCORE7 = 135
|
||||
pkg debug/elf, const EM_SCORE7 Machine
|
||||
pkg debug/elf, const EM_SEP = 108
|
||||
pkg debug/elf, const EM_SEP Machine
|
||||
pkg debug/elf, const EM_SE_C17 = 139
|
||||
pkg debug/elf, const EM_SE_C17 Machine
|
||||
pkg debug/elf, const EM_SE_C33 = 107
|
||||
pkg debug/elf, const EM_SE_C33 Machine
|
||||
pkg debug/elf, const EM_SHARC = 133
|
||||
pkg debug/elf, const EM_SHARC Machine
|
||||
pkg debug/elf, const EM_SLE9X = 179
|
||||
pkg debug/elf, const EM_SLE9X Machine
|
||||
pkg debug/elf, const EM_SNP1K = 99
|
||||
pkg debug/elf, const EM_SNP1K Machine
|
||||
pkg debug/elf, const EM_ST19 = 74
|
||||
pkg debug/elf, const EM_ST19 Machine
|
||||
pkg debug/elf, const EM_ST200 = 100
|
||||
pkg debug/elf, const EM_ST200 Machine
|
||||
pkg debug/elf, const EM_ST7 = 68
|
||||
pkg debug/elf, const EM_ST7 Machine
|
||||
pkg debug/elf, const EM_ST9PLUS = 67
|
||||
pkg debug/elf, const EM_ST9PLUS Machine
|
||||
pkg debug/elf, const EM_STM8 = 186
|
||||
pkg debug/elf, const EM_STM8 Machine
|
||||
pkg debug/elf, const EM_STXP7X = 166
|
||||
pkg debug/elf, const EM_STXP7X Machine
|
||||
pkg debug/elf, const EM_SVX = 73
|
||||
pkg debug/elf, const EM_SVX Machine
|
||||
pkg debug/elf, const EM_TILE64 = 187
|
||||
pkg debug/elf, const EM_TILE64 Machine
|
||||
pkg debug/elf, const EM_TILEGX = 191
|
||||
pkg debug/elf, const EM_TILEGX Machine
|
||||
pkg debug/elf, const EM_TILEPRO = 188
|
||||
pkg debug/elf, const EM_TILEPRO Machine
|
||||
pkg debug/elf, const EM_TI_ARP32 = 143
|
||||
pkg debug/elf, const EM_TI_ARP32 Machine
|
||||
pkg debug/elf, const EM_TI_C2000 = 141
|
||||
pkg debug/elf, const EM_TI_C2000 Machine
|
||||
pkg debug/elf, const EM_TI_C5500 = 142
|
||||
pkg debug/elf, const EM_TI_C5500 Machine
|
||||
pkg debug/elf, const EM_TI_C6000 = 140
|
||||
pkg debug/elf, const EM_TI_C6000 Machine
|
||||
pkg debug/elf, const EM_TI_PRU = 144
|
||||
pkg debug/elf, const EM_TI_PRU Machine
|
||||
pkg debug/elf, const EM_TMM_GPP = 96
|
||||
pkg debug/elf, const EM_TMM_GPP Machine
|
||||
pkg debug/elf, const EM_TPC = 98
|
||||
pkg debug/elf, const EM_TPC Machine
|
||||
pkg debug/elf, const EM_TRIMEDIA = 163
|
||||
pkg debug/elf, const EM_TRIMEDIA Machine
|
||||
pkg debug/elf, const EM_TSK3000 = 131
|
||||
pkg debug/elf, const EM_TSK3000 Machine
|
||||
pkg debug/elf, const EM_UNICORE = 110
|
||||
pkg debug/elf, const EM_UNICORE Machine
|
||||
pkg debug/elf, const EM_V850 = 87
|
||||
pkg debug/elf, const EM_V850 Machine
|
||||
pkg debug/elf, const EM_VAX = 75
|
||||
pkg debug/elf, const EM_VAX Machine
|
||||
pkg debug/elf, const EM_VIDEOCORE = 95
|
||||
pkg debug/elf, const EM_VIDEOCORE Machine
|
||||
pkg debug/elf, const EM_VIDEOCORE3 = 137
|
||||
pkg debug/elf, const EM_VIDEOCORE3 Machine
|
||||
pkg debug/elf, const EM_VIDEOCORE5 = 198
|
||||
pkg debug/elf, const EM_VIDEOCORE5 Machine
|
||||
pkg debug/elf, const EM_VISIUM = 221
|
||||
pkg debug/elf, const EM_VISIUM Machine
|
||||
pkg debug/elf, const EM_XCORE = 203
|
||||
pkg debug/elf, const EM_XCORE Machine
|
||||
pkg debug/elf, const EM_XGATE = 115
|
||||
pkg debug/elf, const EM_XGATE Machine
|
||||
pkg debug/elf, const EM_XIMO16 = 170
|
||||
pkg debug/elf, const EM_XIMO16 Machine
|
||||
pkg debug/elf, const EM_XTENSA = 94
|
||||
pkg debug/elf, const EM_XTENSA Machine
|
||||
pkg debug/elf, const EM_Z80 = 220
|
||||
pkg debug/elf, const EM_Z80 Machine
|
||||
pkg debug/elf, const EM_ZSP = 79
|
||||
pkg debug/elf, const EM_ZSP Machine
|
||||
pkg debug/elf, const R_RISCV_32 = 1
|
||||
pkg debug/elf, const R_RISCV_32 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_64 = 2
|
||||
pkg debug/elf, const R_RISCV_64 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_ADD16 = 34
|
||||
pkg debug/elf, const R_RISCV_ADD16 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_ADD32 = 35
|
||||
pkg debug/elf, const R_RISCV_ADD32 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_ADD64 = 36
|
||||
pkg debug/elf, const R_RISCV_ADD64 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_ADD8 = 33
|
||||
pkg debug/elf, const R_RISCV_ADD8 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_ALIGN = 43
|
||||
pkg debug/elf, const R_RISCV_ALIGN R_RISCV
|
||||
pkg debug/elf, const R_RISCV_BRANCH = 16
|
||||
pkg debug/elf, const R_RISCV_BRANCH R_RISCV
|
||||
pkg debug/elf, const R_RISCV_CALL = 18
|
||||
pkg debug/elf, const R_RISCV_CALL R_RISCV
|
||||
pkg debug/elf, const R_RISCV_CALL_PLT = 19
|
||||
pkg debug/elf, const R_RISCV_CALL_PLT R_RISCV
|
||||
pkg debug/elf, const R_RISCV_COPY = 4
|
||||
pkg debug/elf, const R_RISCV_COPY R_RISCV
|
||||
pkg debug/elf, const R_RISCV_GNU_VTENTRY = 42
|
||||
pkg debug/elf, const R_RISCV_GNU_VTENTRY R_RISCV
|
||||
pkg debug/elf, const R_RISCV_GNU_VTINHERIT = 41
|
||||
pkg debug/elf, const R_RISCV_GNU_VTINHERIT R_RISCV
|
||||
pkg debug/elf, const R_RISCV_GOT_HI20 = 20
|
||||
pkg debug/elf, const R_RISCV_GOT_HI20 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_GPREL_I = 47
|
||||
pkg debug/elf, const R_RISCV_GPREL_I R_RISCV
|
||||
pkg debug/elf, const R_RISCV_GPREL_S = 48
|
||||
pkg debug/elf, const R_RISCV_GPREL_S R_RISCV
|
||||
pkg debug/elf, const R_RISCV_HI20 = 26
|
||||
pkg debug/elf, const R_RISCV_HI20 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_JAL = 17
|
||||
pkg debug/elf, const R_RISCV_JAL R_RISCV
|
||||
pkg debug/elf, const R_RISCV_JUMP_SLOT = 5
|
||||
pkg debug/elf, const R_RISCV_JUMP_SLOT R_RISCV
|
||||
pkg debug/elf, const R_RISCV_LO12_I = 27
|
||||
pkg debug/elf, const R_RISCV_LO12_I R_RISCV
|
||||
pkg debug/elf, const R_RISCV_LO12_S = 28
|
||||
pkg debug/elf, const R_RISCV_LO12_S R_RISCV
|
||||
pkg debug/elf, const R_RISCV_NONE = 0
|
||||
pkg debug/elf, const R_RISCV_NONE R_RISCV
|
||||
pkg debug/elf, const R_RISCV_PCREL_HI20 = 23
|
||||
pkg debug/elf, const R_RISCV_PCREL_HI20 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_PCREL_LO12_I = 24
|
||||
pkg debug/elf, const R_RISCV_PCREL_LO12_I R_RISCV
|
||||
pkg debug/elf, const R_RISCV_PCREL_LO12_S = 25
|
||||
pkg debug/elf, const R_RISCV_PCREL_LO12_S R_RISCV
|
||||
pkg debug/elf, const R_RISCV_RELATIVE = 3
|
||||
pkg debug/elf, const R_RISCV_RELATIVE R_RISCV
|
||||
pkg debug/elf, const R_RISCV_RELAX = 51
|
||||
pkg debug/elf, const R_RISCV_RELAX R_RISCV
|
||||
pkg debug/elf, const R_RISCV_RVC_BRANCH = 44
|
||||
pkg debug/elf, const R_RISCV_RVC_BRANCH R_RISCV
|
||||
pkg debug/elf, const R_RISCV_RVC_JUMP = 45
|
||||
pkg debug/elf, const R_RISCV_RVC_JUMP R_RISCV
|
||||
pkg debug/elf, const R_RISCV_RVC_LUI = 46
|
||||
pkg debug/elf, const R_RISCV_RVC_LUI R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SET16 = 55
|
||||
pkg debug/elf, const R_RISCV_SET16 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SET32 = 56
|
||||
pkg debug/elf, const R_RISCV_SET32 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SET6 = 53
|
||||
pkg debug/elf, const R_RISCV_SET6 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SET8 = 54
|
||||
pkg debug/elf, const R_RISCV_SET8 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SUB16 = 38
|
||||
pkg debug/elf, const R_RISCV_SUB16 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SUB32 = 39
|
||||
pkg debug/elf, const R_RISCV_SUB32 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SUB6 = 52
|
||||
pkg debug/elf, const R_RISCV_SUB6 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SUB64 = 40
|
||||
pkg debug/elf, const R_RISCV_SUB64 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_SUB8 = 37
|
||||
pkg debug/elf, const R_RISCV_SUB8 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TLS_DTPMOD32 = 6
|
||||
pkg debug/elf, const R_RISCV_TLS_DTPMOD32 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TLS_DTPMOD64 = 7
|
||||
pkg debug/elf, const R_RISCV_TLS_DTPMOD64 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TLS_DTPREL32 = 8
|
||||
pkg debug/elf, const R_RISCV_TLS_DTPREL32 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TLS_DTPREL64 = 9
|
||||
pkg debug/elf, const R_RISCV_TLS_DTPREL64 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TLS_GD_HI20 = 22
|
||||
pkg debug/elf, const R_RISCV_TLS_GD_HI20 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TLS_GOT_HI20 = 21
|
||||
pkg debug/elf, const R_RISCV_TLS_GOT_HI20 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TLS_TPREL32 = 10
|
||||
pkg debug/elf, const R_RISCV_TLS_TPREL32 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TLS_TPREL64 = 11
|
||||
pkg debug/elf, const R_RISCV_TLS_TPREL64 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TPREL_ADD = 32
|
||||
pkg debug/elf, const R_RISCV_TPREL_ADD R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TPREL_HI20 = 29
|
||||
pkg debug/elf, const R_RISCV_TPREL_HI20 R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TPREL_I = 49
|
||||
pkg debug/elf, const R_RISCV_TPREL_I R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TPREL_LO12_I = 30
|
||||
pkg debug/elf, const R_RISCV_TPREL_LO12_I R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TPREL_LO12_S = 31
|
||||
pkg debug/elf, const R_RISCV_TPREL_LO12_S R_RISCV
|
||||
pkg debug/elf, const R_RISCV_TPREL_S = 50
|
||||
pkg debug/elf, const R_RISCV_TPREL_S R_RISCV
|
||||
pkg debug/elf, method (R_RISCV) GoString() string
|
||||
pkg debug/elf, method (R_RISCV) String() string
|
||||
pkg debug/elf, type R_RISCV int
|
||||
pkg debug/macho, const CpuArm64 = 16777228
|
||||
pkg debug/macho, const CpuArm64 Cpu
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_ARCHITECTURE ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_BASERELOC = 5
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_BASERELOC ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_DEBUG = 6
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_DEBUG ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_EXCEPTION ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_EXPORT = 0
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_EXPORT ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_GLOBALPTR ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_IAT = 12
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_IAT ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_IMPORT = 1
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_IMPORT ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_RESOURCE = 2
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_RESOURCE ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_SECURITY = 4
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_SECURITY ideal-int
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_TLS = 9
|
||||
pkg debug/pe, const IMAGE_DIRECTORY_ENTRY_TLS ideal-int
|
||||
pkg debug/pe, const IMAGE_FILE_MACHINE_ARM64 = 43620
|
||||
pkg debug/pe, const IMAGE_FILE_MACHINE_ARM64 ideal-int
|
||||
pkg go/ast, type CompositeLit struct, Incomplete bool
|
||||
pkg go/token, method (*File) AddLineColumnInfo(int, string, int, int)
|
||||
pkg go/types, func NewInterfaceType([]*Func, []Type) *Interface
|
||||
pkg go/types, method (*Interface) EmbeddedType(int) Type
|
||||
pkg go/types, method (*Var) Embedded() bool
|
||||
pkg net, method (*ListenConfig) Listen(context.Context, string, string) (Listener, error)
|
||||
pkg net, method (*ListenConfig) ListenPacket(context.Context, string, string) (PacketConn, error)
|
||||
pkg net, type Dialer struct, Control func(string, string, syscall.RawConn) error
|
||||
pkg net, type ListenConfig struct
|
||||
pkg net, type ListenConfig struct, Control func(string, string, syscall.RawConn) error
|
||||
pkg net/http, const StatusMisdirectedRequest = 421
|
||||
pkg net/http, const StatusMisdirectedRequest ideal-int
|
||||
pkg net/http/httptrace, type ClientTrace struct, Got1xxResponse func(int, textproto.MIMEHeader) error
|
||||
pkg os, const ModeIrregular = 524288
|
||||
pkg os, const ModeIrregular FileMode
|
||||
pkg os, const ModeType = 2399666176
|
||||
pkg os, func UserCacheDir() (string, error)
|
||||
pkg os/signal, func Ignored(os.Signal) bool
|
||||
pkg regexp/syntax, method (Op) String() string
|
||||
pkg runtime/trace, func IsEnabled() bool
|
||||
pkg runtime/trace, func Log(context.Context, string, string)
|
||||
pkg runtime/trace, func Logf(context.Context, string, string, ...interface{})
|
||||
pkg runtime/trace, func NewTask(context.Context, string) (context.Context, *Task)
|
||||
pkg runtime/trace, func StartRegion(context.Context, string) *Region
|
||||
pkg runtime/trace, func WithRegion(context.Context, string, func())
|
||||
pkg runtime/trace, method (*Region) End()
|
||||
pkg runtime/trace, method (*Task) End()
|
||||
pkg runtime/trace, type Region struct
|
||||
pkg runtime/trace, type Task struct
|
||||
pkg syscall (netbsd-386), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (netbsd-386), func Pipe2([]int, int) error
|
||||
pkg syscall (netbsd-386-cgo), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (netbsd-386-cgo), func Pipe2([]int, int) error
|
||||
pkg syscall (netbsd-amd64), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (netbsd-amd64), func Pipe2([]int, int) error
|
||||
pkg syscall (netbsd-amd64-cgo), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (netbsd-amd64-cgo), func Pipe2([]int, int) error
|
||||
pkg syscall (netbsd-arm), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (netbsd-arm), func Pipe2([]int, int) error
|
||||
pkg syscall (netbsd-arm-cgo), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (netbsd-arm-cgo), func Pipe2([]int, int) error
|
||||
pkg syscall (openbsd-386), const SOCK_CLOEXEC = 32768
|
||||
pkg syscall (openbsd-386), const SOCK_CLOEXEC ideal-int
|
||||
pkg syscall (openbsd-386), const SOCK_NONBLOCK = 16384
|
||||
pkg syscall (openbsd-386), const SOCK_NONBLOCK ideal-int
|
||||
pkg syscall (openbsd-386), const SYS_ACCEPT4 = 93
|
||||
pkg syscall (openbsd-386), const SYS_ACCEPT4 ideal-int
|
||||
pkg syscall (openbsd-386), const SYS_PIPE2 = 101
|
||||
pkg syscall (openbsd-386), const SYS_PIPE2 ideal-int
|
||||
pkg syscall (openbsd-386), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (openbsd-386), func Pipe2([]int, int) error
|
||||
pkg syscall (openbsd-386-cgo), const SOCK_CLOEXEC = 32768
|
||||
pkg syscall (openbsd-386-cgo), const SOCK_CLOEXEC ideal-int
|
||||
pkg syscall (openbsd-386-cgo), const SOCK_NONBLOCK = 16384
|
||||
pkg syscall (openbsd-386-cgo), const SOCK_NONBLOCK ideal-int
|
||||
pkg syscall (openbsd-386-cgo), const SYS_ACCEPT4 = 93
|
||||
pkg syscall (openbsd-386-cgo), const SYS_ACCEPT4 ideal-int
|
||||
pkg syscall (openbsd-386-cgo), const SYS_PIPE2 = 101
|
||||
pkg syscall (openbsd-386-cgo), const SYS_PIPE2 ideal-int
|
||||
pkg syscall (openbsd-386-cgo), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (openbsd-386-cgo), func Pipe2([]int, int) error
|
||||
pkg syscall (openbsd-amd64), const SOCK_CLOEXEC = 32768
|
||||
pkg syscall (openbsd-amd64), const SOCK_CLOEXEC ideal-int
|
||||
pkg syscall (openbsd-amd64), const SOCK_NONBLOCK = 16384
|
||||
pkg syscall (openbsd-amd64), const SOCK_NONBLOCK ideal-int
|
||||
pkg syscall (openbsd-amd64), const SYS_ACCEPT4 = 93
|
||||
pkg syscall (openbsd-amd64), const SYS_ACCEPT4 ideal-int
|
||||
pkg syscall (openbsd-amd64), const SYS_PIPE2 = 101
|
||||
pkg syscall (openbsd-amd64), const SYS_PIPE2 ideal-int
|
||||
pkg syscall (openbsd-amd64), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (openbsd-amd64), func Pipe2([]int, int) error
|
||||
pkg syscall (openbsd-amd64-cgo), const SOCK_CLOEXEC = 32768
|
||||
pkg syscall (openbsd-amd64-cgo), const SOCK_CLOEXEC ideal-int
|
||||
pkg syscall (openbsd-amd64-cgo), const SOCK_NONBLOCK = 16384
|
||||
pkg syscall (openbsd-amd64-cgo), const SOCK_NONBLOCK ideal-int
|
||||
pkg syscall (openbsd-amd64-cgo), const SYS_ACCEPT4 = 93
|
||||
pkg syscall (openbsd-amd64-cgo), const SYS_ACCEPT4 ideal-int
|
||||
pkg syscall (openbsd-amd64-cgo), const SYS_PIPE2 = 101
|
||||
pkg syscall (openbsd-amd64-cgo), const SYS_PIPE2 ideal-int
|
||||
pkg syscall (openbsd-amd64-cgo), func Accept4(int, int) (int, Sockaddr, error)
|
||||
pkg syscall (openbsd-amd64-cgo), func Pipe2([]int, int) error
|
||||
pkg syscall (windows-386), const TOKEN_ADJUST_SESSIONID = 256
|
||||
pkg syscall (windows-386), const TOKEN_ADJUST_SESSIONID ideal-int
|
||||
pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983551
|
||||
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara Pointer
|
||||
pkg syscall (windows-386), type CertChainPolicyStatus struct, ExtraPolicyStatus Pointer
|
||||
pkg syscall (windows-386), type CertContext struct, CertInfo *CertInfo
|
||||
pkg syscall (windows-386), type CertInfo struct
|
||||
pkg syscall (windows-386), type CertRevocationCrlInfo struct
|
||||
pkg syscall (windows-386), type CertRevocationInfo struct, CrlInfo *CertRevocationCrlInfo
|
||||
pkg syscall (windows-386), type CertRevocationInfo struct, OidSpecificInfo Pointer
|
||||
pkg syscall (windows-386), type CertSimpleChain struct, TrustListInfo *CertTrustListInfo
|
||||
pkg syscall (windows-386), type CertTrustListInfo struct
|
||||
pkg syscall (windows-386), type Pointer *struct
|
||||
pkg syscall (windows-amd64), const TOKEN_ADJUST_SESSIONID = 256
|
||||
pkg syscall (windows-amd64), const TOKEN_ADJUST_SESSIONID ideal-int
|
||||
pkg syscall (windows-amd64), const TOKEN_ALL_ACCESS = 983551
|
||||
pkg syscall (windows-amd64), type CertChainPolicyPara struct, ExtraPolicyPara Pointer
|
||||
pkg syscall (windows-amd64), type CertChainPolicyStatus struct, ExtraPolicyStatus Pointer
|
||||
pkg syscall (windows-amd64), type CertContext struct, CertInfo *CertInfo
|
||||
pkg syscall (windows-amd64), type CertInfo struct
|
||||
pkg syscall (windows-amd64), type CertRevocationCrlInfo struct
|
||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo *CertRevocationCrlInfo
|
||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo Pointer
|
||||
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo *CertTrustListInfo
|
||||
pkg syscall (windows-amd64), type CertTrustListInfo struct
|
||||
pkg syscall (windows-amd64), type Pointer *struct
|
||||
pkg syscall, const ImplementsGetwd = true
|
||||
pkg text/template/parse, type PipeNode struct, IsAssign bool
|
|
@ -110,6 +110,10 @@ packages and commands. Most Go programmers keep <i>all</i> their Go source code
|
|||
and dependencies in a single workspace.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that symbolic links should <b>not</b> be used to link files or directories into your workspace.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Commands and libraries are built from different kinds of source packages.
|
||||
We will discuss the distinction <a href="#PackageNames">later</a>.
|
||||
|
@ -236,7 +240,7 @@ package main
|
|||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Hello, world.\n")
|
||||
fmt.Println("Hello, world.")
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
@ -391,7 +395,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf(stringutil.Reverse("!oG ,olleH"))
|
||||
fmt.Println(stringutil.Reverse("!oG ,olleH"))
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
@ -669,7 +673,7 @@ articles about the Go language and its libraries and tools.
|
|||
|
||||
<p>
|
||||
For real-time help, ask the helpful gophers in <code>#go-nuts</code> on the
|
||||
<a href="http://freenode.net/">Freenode</a> IRC server.
|
||||
<a href="https://freenode.net/">Freenode</a> IRC server.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -92,10 +92,10 @@ account to use.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Google accounts can either be Gmail e-mail accounts, G-Suite organization accounts, or
|
||||
Google accounts can either be Gmail e-mail accounts, G Suite organization accounts, or
|
||||
accounts associated with an external e-mail address.
|
||||
For instance, if you need to use
|
||||
an existing corporate e-mail that is not managed through G-Suite, you can create
|
||||
an existing corporate e-mail that is not managed through G Suite, you can create
|
||||
an account associated
|
||||
<a href="https://accounts.google.com/SignUpWithoutGmail">with your existing
|
||||
e-mail address</a>.
|
||||
|
@ -168,7 +168,7 @@ completed and update the <code>AUTHORS</code> file.
|
|||
<h3 id="config_git_auth">Step 2: Configure git authentication</h3>
|
||||
|
||||
<p>
|
||||
Go development happens on
|
||||
The main Go repository is located at
|
||||
<a href="https://go.googlesource.com">go.googlesource.com</a>,
|
||||
a Git server hosted by Google.
|
||||
Authentication on the web server is made through your Google account, but
|
||||
|
@ -190,8 +190,8 @@ This key is paired with one that is generated and stored on the server,
|
|||
analogous to how SSH keys work.
|
||||
</li>
|
||||
<li>
|
||||
Copy and run this script locally in your command line terminal to store your
|
||||
secret authentication token in a <code>.gitcookies</code> file.
|
||||
Copy and run this script locally in your terminal to store your secret
|
||||
authentication token in a <code>.gitcookies</code> file.
|
||||
If you are using a Windows computer and running <code>cmd</code>,
|
||||
you should instead follow the instructions in the yellow box to run the command;
|
||||
otherwise run the regular script.
|
||||
|
@ -251,12 +251,13 @@ symbolic link or just copy the executable from $GOPATH/bin to this directory.
|
|||
<h2 id="before_contributing">Before contributing code</h2>
|
||||
|
||||
<p>
|
||||
The project welcomes submissions but to make sure things are well
|
||||
coordinated we ask that everyone to discuss any significant changes to the
|
||||
Go repositories before starting work.
|
||||
Best practice is to connect your work to the issue tracker,
|
||||
either by <a href="https://golang.org/issue/new">filing a new issue</a>
|
||||
or by claiming an <a href="https://golang.org/issues">existing issue</a>.
|
||||
The project welcomes code patches, but to make sure things are well
|
||||
coordinated you should discuss any significant change before starting
|
||||
the work.
|
||||
It's recommended that you signal your intention to contribute in the
|
||||
issue tracker, either by <a href="https://golang.org/issue/new">filing
|
||||
a new issue</a> or by claiming
|
||||
an <a href="https://golang.org/issues">existing one</a>.
|
||||
</p>
|
||||
|
||||
<h3>Check the issue tracker</h3>
|
||||
|
@ -309,13 +310,13 @@ When planning work, please note that the Go project follows a <a
|
|||
href="https://golang.org/wiki/Go-Release-Cycle">six-month development cycle</a>.
|
||||
The latter half of each cycle is a three-month feature freeze during
|
||||
which only bug fixes and documentation updates are accepted.
|
||||
New contributions can be
|
||||
sent during a feature freeze but will not be accepted until the freeze is over.
|
||||
New contributions can be sent during a feature freeze, but they will
|
||||
not be merged until the freeze is over.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Changes in general other than bug and documentation fixes
|
||||
must go through the
|
||||
Significant changes to the language, libraries, or tools must go
|
||||
through the
|
||||
<a href="https://golang.org/s/proposal-process">change proposal process</a>
|
||||
before they can be accepted.
|
||||
</p>
|
||||
|
@ -337,10 +338,11 @@ GitHub pull requests to Gerrit.
|
|||
|
||||
<p>
|
||||
Open a pull request as you normally would.
|
||||
Gopherbot will automatically
|
||||
sync the code and post a link to Gerrit.
|
||||
When somebody comments on the
|
||||
change, it will be posted in the pull request, so you will also get a notification.
|
||||
Gopherbot will create a corresponding Gerrit change and post a link to
|
||||
it on your GitHub pull request; updates to the pull request will also
|
||||
get reflected in the Gerrit change.
|
||||
When somebody comments on the change, their comment will be also
|
||||
posted in your pull request, so you will get a notification.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -384,10 +386,10 @@ This is an overview of the overall process:
|
|||
|
||||
<ul>
|
||||
<li>
|
||||
<b>Step 1:</b> Clone the Go source code from GitHub or go.googlesource.com
|
||||
<b>Step 1:</b> Clone the Go source code from go.googlesource.com
|
||||
and make sure it's stable by compiling and testing it once:
|
||||
<pre>
|
||||
$ git clone https://github.com/golang/go # or https://go.googlesource.com/go
|
||||
$ git clone https://go.googlesource.com/go
|
||||
$ cd go/src
|
||||
$ ./all.bash # compile and test
|
||||
</pre>
|
||||
|
@ -418,7 +420,7 @@ $ ./all.bash # recompile and test
|
|||
|
||||
<li>
|
||||
<b>Step 4:</b> Send the changes for review to Gerrit using <code>git</code>
|
||||
<code>codereview</code> <code>mail</code>(which doesn't use e-mail, despite the name).
|
||||
<code>codereview</code> <code>mail</code> (which doesn't use e-mail, despite the name).
|
||||
<pre>
|
||||
$ git codereview mail # send changes to Gerrit
|
||||
</pre>
|
||||
|
@ -545,7 +547,7 @@ ALL TESTS PASSED
|
|||
|
||||
<p>
|
||||
You can use <code>make.bash</code> instead of <code>all.bash</code>
|
||||
to just build the compiler and standard packages without running the test suite.
|
||||
to just build the compiler and the standard library without running the test suite.
|
||||
Once the <code>go</code> tool is built, it will be installed as <code>bin/go</code>
|
||||
under the directory in which you cloned the Go repository, and you can
|
||||
run it directly from there.
|
||||
|
@ -597,8 +599,9 @@ if you prefer.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
If you need to revise your change after the review, edit the files in correct branch,
|
||||
add them to the Git staging area, and then amend the commit with
|
||||
If you need to revise your change after the review, edit the files in
|
||||
the same branch you previously created, add them to the Git staging
|
||||
area, and then amend the commit with
|
||||
<code>git</code> <code>codereview</code> <code>change</code>:
|
||||
</p>
|
||||
|
||||
|
@ -639,7 +642,7 @@ The existing implementation has poor numerical properties for
|
|||
large arguments, so use the McGillicutty algorithm to improve
|
||||
accuracy above 1e10.
|
||||
|
||||
The algorithm is described at http://wikipedia.org/wiki/McGillicutty_Algorithm
|
||||
The algorithm is described at https://wikipedia.org/wiki/McGillicutty_Algorithm
|
||||
|
||||
Fixes #159
|
||||
</pre>
|
||||
|
@ -674,7 +677,7 @@ Don't use HTML, Markdown, or any other markup language.
|
|||
|
||||
<p>
|
||||
Add any relevant information, such as benchmark data if the change
|
||||
afects performance.
|
||||
affects performance.
|
||||
The <a href="https://godoc.org/golang.org/x/tools/cmd/benchcmp">benchcmp</a>
|
||||
tool is conventionally used to format
|
||||
benchmark data for change descriptions.
|
||||
|
@ -937,7 +940,7 @@ remote: ERROR: does not match your user account.
|
|||
<p>
|
||||
you need to configure Git for this repository to use the
|
||||
e-mail address that you registered with.
|
||||
To change the e-mail address for this doesn't happen again, run:
|
||||
To change the e-mail address to ensure this doesn't happen again, run:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -984,8 +987,8 @@ followed by <code>run.bash</code>.
|
|||
|
||||
<li>
|
||||
In this section, we'll call the directory into which you cloned the Go repository <code>$GODIR</code>.
|
||||
The <code>go</code> tool built by <code>$GODIR/make.bash</code>will be installed
|
||||
in <code>$GODIR/bin/go</code>and you
|
||||
The <code>go</code> tool built by <code>$GODIR/make.bash</code> will be installed
|
||||
in <code>$GODIR/bin/go</code> and you
|
||||
can invoke it to test your code.
|
||||
For instance, if you
|
||||
have modified the compiler and you want to test how it affects the
|
||||
|
|
|
@ -47,7 +47,7 @@ In short, the instructions below should be taken only as a guide to how
|
|||
to use GDB when it works, not as a guarantee of success.
|
||||
|
||||
Besides this overview you might want to consult the
|
||||
<a href="http://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>.
|
||||
<a href="https://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -57,7 +57,7 @@ Besides this overview you might want to consult the
|
|||
|
||||
<p>
|
||||
When you compile and link your Go programs with the <code>gc</code> toolchain
|
||||
on Linux, Mac OS X, FreeBSD or NetBSD, the resulting binaries contain DWARFv4
|
||||
on Linux, macOS, FreeBSD or NetBSD, the resulting binaries contain DWARFv4
|
||||
debugging information that recent versions (≥7.5) of the GDB debugger can
|
||||
use to inspect a live process or a core dump.
|
||||
</p>
|
||||
|
|
|
@ -50,7 +50,7 @@ trace. Use tools in isolation to get more precise info.
|
|||
Profiling is useful for identifying expensive or frequently called sections
|
||||
of code. The Go runtime provides <a href="https://golang.org/pkg/runtime/pprof/">
|
||||
profiling data</a> in the format expected by the
|
||||
<a href="https://github.com/google/pprof/blob/master/doc/pprof.md">pprof visualization tool</a>.
|
||||
<a href="https://github.com/google/pprof/blob/master/doc/README.md">pprof visualization tool</a>.
|
||||
The profiling data can be collected during testing
|
||||
via <code>go</code> <code>test</code> or endpoints made available from the <a href="/pkg/net/http/pprof/">
|
||||
net/http/pprof</a> package. Users need to collect the profiling data and use pprof tools to filter
|
||||
|
@ -127,7 +127,7 @@ so it is recommended to collect only a single profile at a time.
|
|||
<p>
|
||||
The Go tools provide text, graph, and <a href="http://valgrind.org/docs/manual/cl-manual.html">callgrind</a>
|
||||
visualization of the profile data using
|
||||
<code><a href="https://github.com/google/pprof/blob/master/doc/pprof.md">go tool pprof</a></code>.
|
||||
<code><a href="https://github.com/google/pprof/blob/master/doc/README.md">go tool pprof</a></code>.
|
||||
Read <a href="https://blog.golang.org/profiling-go-programs">Profiling Go programs</a>
|
||||
to see them in action.
|
||||
</p>
|
||||
|
|
|
@ -195,7 +195,7 @@ See the <a href="/wiki/Articles">Articles page</a> at the
|
|||
|
||||
<img class="gopher" src="/doc/gopher/talks.png"/>
|
||||
|
||||
<h3 id="video_tour_of_go"><a href="http://research.swtch.com/gotour">A Video Tour of Go</a></h3>
|
||||
<h3 id="video_tour_of_go"><a href="https://research.swtch.com/gotour">A Video Tour of Go</a></h3>
|
||||
<p>
|
||||
Three things that make Go fast, fun, and productive:
|
||||
interfaces, reflection, and concurrency. Builds a toy web crawler to
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
This document lists commonly used editor plugins and IDEs from the Go ecosystem
|
||||
that make Go development more productive and seamless.
|
||||
A comprehensive list of editor support and IDEs for Go development is available at
|
||||
<a href="http://golang.org/wiki/IDEsAndTextEditorPlugins">the wiki</a>.
|
||||
<a href="https://golang.org/wiki/IDEsAndTextEditorPlugins">the wiki</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="options">Options</h2>
|
||||
|
|
|
@ -22,7 +22,7 @@ file HACKING</a> in the gofrontend repository.
|
|||
You must follow the <a href="/doc/contribute.html#copyright">Go copyright
|
||||
rules</a> for all changes to the gccgo frontend and the associated
|
||||
libgo library. Code that is part of GCC rather than gccgo must follow
|
||||
the general <a href="http://gcc.gnu.org/contribute.html">GCC
|
||||
the general <a href="https://gcc.gnu.org/contribute.html">GCC
|
||||
contribution rules</a>.
|
||||
</p>
|
||||
|
||||
|
@ -30,9 +30,9 @@ contribution rules</a>.
|
|||
|
||||
<p>
|
||||
The master sources for the gccgo frontend may be found at
|
||||
<a href="http://go.googlesource.com/gofrontend">http://go.googlesource.com/gofrontend</a>.
|
||||
<a href="https://go.googlesource.com/gofrontend">https://go.googlesource.com/gofrontend</a>.
|
||||
They are mirrored
|
||||
at <a href="http://github.com/golang/gofrontend">http://github.com/golang/gofrontend</a>.
|
||||
at <a href="https://github.com/golang/gofrontend">https://github.com/golang/gofrontend</a>.
|
||||
The master sources are not buildable by themselves, but only in
|
||||
conjunction with GCC (in the future, other compilers may be
|
||||
supported). Changes made to the gccgo frontend are also applied to
|
||||
|
|
|
@ -9,7 +9,7 @@ the Go language. The gccgo compiler is a new frontend
|
|||
for GCC, the widely used GNU compiler. Although the
|
||||
frontend itself is under a BSD-style license, gccgo is
|
||||
normally used as part of GCC and is then covered by
|
||||
the <a href="http://www.gnu.org/licenses/gpl.html">GNU General Public
|
||||
the <a href="https://www.gnu.org/licenses/gpl.html">GNU General Public
|
||||
License</a> (the license covers gccgo itself as part of GCC; it
|
||||
does not cover code generated by gccgo).
|
||||
</p>
|
||||
|
@ -25,7 +25,7 @@ compiler.
|
|||
<p>
|
||||
The simplest way to install gccgo is to install a GCC binary release
|
||||
built to include Go support. GCC binary releases are available from
|
||||
<a href="http://gcc.gnu.org/install/binaries.html">various
|
||||
<a href="https://gcc.gnu.org/install/binaries.html">various
|
||||
websites</a> and are typically included as part of GNU/Linux
|
||||
distributions. We expect that most people who build these binaries
|
||||
will include Go support.
|
||||
|
@ -79,7 +79,7 @@ If you cannot use a release, or prefer to build gccgo for
|
|||
yourself,
|
||||
the gccgo source code is accessible via Subversion. The
|
||||
GCC web site
|
||||
has <a href="http://gcc.gnu.org/svn.html">instructions for getting the
|
||||
has <a href="https://gcc.gnu.org/svn.html">instructions for getting the
|
||||
GCC source code</a>. The gccgo source code is included. As a
|
||||
convenience, a stable version of the Go support is available in
|
||||
a branch of the main GCC code
|
||||
|
@ -101,7 +101,7 @@ gccgo</a>.
|
|||
<p>
|
||||
Building gccgo is just like building GCC
|
||||
with one or two additional options. See
|
||||
the <a href="http://gcc.gnu.org/install/">instructions on the gcc web
|
||||
the <a href="https://gcc.gnu.org/install/">instructions on the gcc web
|
||||
site</a>. When you run <code>configure</code>, add the
|
||||
option <code>--enable-languages=c,c++,go</code> (along with other
|
||||
languages you may want to build). If you are targeting a 32-bit x86,
|
||||
|
@ -156,7 +156,7 @@ option <code>--with-ld=<var>GOLD_BINARY</var></code>.
|
|||
<p>
|
||||
A number of prerequisites are required to build GCC, as
|
||||
described on
|
||||
the <a href="http://gcc.gnu.org/install/prerequisites.html">gcc web
|
||||
the <a href="https://gcc.gnu.org/install/prerequisites.html">gcc web
|
||||
site</a>. It is important to install all the prerequisites before
|
||||
running the gcc <code>configure</code> script.
|
||||
The prerequisite libraries can be conveniently downloaded using the
|
||||
|
|
346
doc/go1.11.html
Normal file
346
doc/go1.11.html
Normal file
|
@ -0,0 +1,346 @@
|
|||
<!--{
|
||||
"Title": "Go 1.11 Release Notes",
|
||||
"Path": "/doc/go1.11",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<!--
|
||||
NOTE: In this document and others in this directory, the convention is to
|
||||
set fixed-width phrases with non-fixed-width spaces, as in
|
||||
<code>hello</code> <code>world</code>.
|
||||
Do not send CLs removing the interior tags from such phrases.
|
||||
-->
|
||||
|
||||
<style>
|
||||
ul li { margin: 0.5em 0; }
|
||||
</style>
|
||||
|
||||
<h2 id="introduction">DRAFT RELEASE NOTES - Introduction to Go 1.11</h2>
|
||||
|
||||
<p>
|
||||
<strong>
|
||||
Go 1.11 is not yet released. These are work-in-progress
|
||||
release notes. Go 1.11 is expected to be released in August 2018.
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The latest Go release, version 1.11, arrives six months after <a href="go1.10">Go 1.10</a>.
|
||||
Most of its changes are in the implementation of the toolchain, runtime, and libraries.
|
||||
As always, the release maintains the Go 1 <a href="/doc/go1compat.html">promise of compatibility</a>.
|
||||
We expect almost all Go programs to continue to compile and run as before.
|
||||
</p>
|
||||
|
||||
<h2 id="language">Changes to the language</h2>
|
||||
|
||||
<p>
|
||||
There are no changes to the language specification.
|
||||
</p>
|
||||
|
||||
<h2 id="ports">Ports</h2>
|
||||
|
||||
<p>
|
||||
As <a href="go1.10#ports">announced in the Go 1.10 release notes</a>, Go 1.11 now requires
|
||||
OpenBSD 6.2 or later, macOS 10.10 Yosemite or later, or Windows 7 or later;
|
||||
Support for previous versions of these operating systems has been removed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are <a href="https://golang.org/issue/25206">known issues</a> with NetBSD on i386 hardware.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 107935 -->
|
||||
TODO: PPC64LE race detector support
|
||||
</p>
|
||||
|
||||
<h3 id="package-versioning">Package Versioning (vgo)</h3>
|
||||
<p>
|
||||
<strong>
|
||||
NOTE: This is not present in go1.11beta1 but will be available in future
|
||||
betas and subsequent releases.
|
||||
</strong>
|
||||
Go 1.11 adds experimental, integrated support for package versioning.
|
||||
</p>
|
||||
|
||||
<h3 id="wasm">WebAssembly</h3>
|
||||
<p>
|
||||
Go 1.11 adds an experimental port to WebAssembly (<code>js/wasm</code>).
|
||||
</p>
|
||||
|
||||
<h2 id="library">Core library</h2>
|
||||
|
||||
<p>
|
||||
All of the changes to the standard library are minor.
|
||||
</p>
|
||||
|
||||
<h3 id="minor_library_changes">Minor changes to the library</h3>
|
||||
|
||||
<p>
|
||||
As always, there are various minor changes and updates to the library,
|
||||
made with the Go 1 <a href="/doc/go1compat">promise of compatibility</a>
|
||||
in mind.
|
||||
</p>
|
||||
|
||||
<!-- CL 113315: https://golang.org/cl/113315: cmd/asm: enable AVX512 -->
|
||||
<!-- CL 100459: https://golang.org/cl/100459: cmd/compile: reject type switch with guarded declaration and no cases -->
|
||||
<!-- CL 106797: https://golang.org/cl/106797: cmd/compile: enable indexed export format by default -->
|
||||
<!-- CL 108475: https://golang.org/cl/108475: cmd/compile: add softfloat support to mips64{,le} -->
|
||||
<!-- CL 97375: https://golang.org/cl/97375: cmd/compile, cmd/compile/internal/syntax: print relative column info -->
|
||||
<!-- CL 110395: https://golang.org/cl/110395: cmd/go, cmd/compile: use Windows response files to avoid arg length limits -->
|
||||
<!-- CL 107475: https://golang.org/cl/107475: cmd/internal/obj/arm, runtime: delete old ARM softfloat code -->
|
||||
<!-- CL 112436: https://golang.org/cl/112436: cmd/pprof: add readline support similar to upstream -->
|
||||
<dl id="all"><dt><a href="/pkg/all/">all</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 93875 -->
|
||||
TODO: <a href="https://golang.org/cl/93875">https://golang.org/cl/93875</a>: enable c-shared/c-archive support for freebsd/amd64
|
||||
</p>
|
||||
|
||||
<p><!-- CL 94255 -->
|
||||
TODO: <a href="https://golang.org/cl/94255">https://golang.org/cl/94255</a>: drop support for Windows Vista or below (Windows XP)
|
||||
</p>
|
||||
|
||||
<p><!-- CL 115038 -->
|
||||
TODO: <a href="https://golang.org/cl/115038">https://golang.org/cl/115038</a>: remove support for macOS 10.9 and earlier
|
||||
</p>
|
||||
|
||||
</dl><!-- all -->
|
||||
|
||||
<dl id="crypto"><dt><a href="/pkg/crypto/">crypto</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 64451 -->
|
||||
TODO: <a href="https://golang.org/cl/64451">https://golang.org/cl/64451</a>: randomly read an extra byte of randomness in some places.
|
||||
</p>
|
||||
|
||||
</dl><!-- crypto -->
|
||||
|
||||
<dl id="crypto/cipher"><dt><a href="/pkg/crypto/cipher/">crypto/cipher</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 48510, CL 116435 -->
|
||||
TODO: <a href="https://golang.org/cl/48510">https://golang.org/cl/48510</a>: add NewGCMWithTagSize for custom tag sizes.
|
||||
</p>
|
||||
|
||||
</dl><!-- crypto/cipher -->
|
||||
|
||||
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 103876 -->
|
||||
TODO: <a href="https://golang.org/cl/103876">https://golang.org/cl/103876</a>: add PublicKey.Size accessor
|
||||
</p>
|
||||
|
||||
</dl><!-- crypto/rsa -->
|
||||
|
||||
<dl id="debug/elf"><dt><a href="/pkg/debug/elf/">debug/elf</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 112115 -->
|
||||
TODO: <a href="https://golang.org/cl/112115">https://golang.org/cl/112115</a>: add machine and OSABI constants
|
||||
</p>
|
||||
|
||||
</dl><!-- debug/elf -->
|
||||
|
||||
<dl id="encoding/asn1"><dt><a href="/pkg/encoding/asn1/">encoding/asn1</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 110561 -->
|
||||
TODO: <a href="https://golang.org/cl/110561">https://golang.org/cl/110561</a>: allow Marshaling and Unmarshaling private tag class
|
||||
</p>
|
||||
|
||||
</dl><!-- encoding/asn1 -->
|
||||
|
||||
<dl id="encoding/base32"><dt><a href="/pkg/encoding/base32/">encoding/base32</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 112516 -->
|
||||
TODO: <a href="https://golang.org/cl/112516">https://golang.org/cl/112516</a>: handle surplus padding consistently
|
||||
</p>
|
||||
|
||||
</dl><!-- encoding/base32 -->
|
||||
|
||||
<dl id="encoding/csv"><dt><a href="/pkg/encoding/csv/">encoding/csv</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 99696 -->
|
||||
TODO: <a href="https://golang.org/cl/99696">https://golang.org/cl/99696</a>: disallow quote for use as Comma
|
||||
</p>
|
||||
|
||||
</dl><!-- encoding/csv -->
|
||||
|
||||
<dl id="go/build, runtime/internal/sys"><dt><a href="/pkg/go/build, runtime/internal/sys/">go/build, runtime/internal/sys</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 106256 -->
|
||||
TODO: <a href="https://golang.org/cl/106256">https://golang.org/cl/106256</a>: reserve RISC-V arch names
|
||||
</p>
|
||||
|
||||
</dl><!-- go/build, runtime/internal/sys -->
|
||||
|
||||
<dl id="image/gif"><dt><a href="/pkg/image/gif/">image/gif</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 93076 -->
|
||||
TODO: <a href="https://golang.org/cl/93076">https://golang.org/cl/93076</a>: support non-looping animated gifs (LoopCount=-1)
|
||||
</p>
|
||||
|
||||
</dl><!-- image/gif -->
|
||||
|
||||
<dl id="io/ioutil"><dt><a href="/pkg/io/ioutil/">io/ioutil</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 105675 -->
|
||||
TODO: <a href="https://golang.org/cl/105675">https://golang.org/cl/105675</a>: change TempFile prefix to a pattern
|
||||
</p>
|
||||
|
||||
</dl><!-- io/ioutil -->
|
||||
|
||||
<dl id="math/big"><dt><a href="/pkg/math/big/">math/big</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 74851 -->
|
||||
TODO: <a href="https://golang.org/cl/74851">https://golang.org/cl/74851</a>: speed-up addMulVVW on amd64
|
||||
</p>
|
||||
|
||||
</dl><!-- math/big -->
|
||||
|
||||
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 72810 -->
|
||||
TODO: <a href="https://golang.org/cl/72810">https://golang.org/cl/72810</a>: add ListenConfig, Dialer.Control to permit socket opts before listen/dial
|
||||
</p>
|
||||
|
||||
<p><!-- CL 76391 -->
|
||||
TODO: <a href="https://golang.org/cl/76391">https://golang.org/cl/76391</a>: implement (*syscall.RawConn).Read/Write on Windows
|
||||
</p>
|
||||
|
||||
<p><!-- CL 107715 -->
|
||||
TODO: <a href="https://golang.org/cl/107715">https://golang.org/cl/107715</a>: add support for splice(2) in (*TCPConn).ReadFrom on Linux
|
||||
</p>
|
||||
|
||||
<p><!-- CL 108297 -->
|
||||
TODO: <a href="https://golang.org/cl/108297">https://golang.org/cl/108297</a>: calling File leaves the socket in nonblocking mode
|
||||
</p>
|
||||
|
||||
</dl><!-- net -->
|
||||
|
||||
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 89275 -->
|
||||
TODO: <a href="https://golang.org/cl/89275">https://golang.org/cl/89275</a>: don't sniff Content-type in Server when X-Content-Type-Options:nosniff
|
||||
</p>
|
||||
|
||||
<p><!-- CL 93296 -->
|
||||
TODO: <a href="https://golang.org/cl/93296">https://golang.org/cl/93296</a>: add StatusMisdirectedRequest (421)
|
||||
</p>
|
||||
|
||||
</dl><!-- net/http -->
|
||||
|
||||
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 78835 -->
|
||||
TODO: <a href="https://golang.org/cl/78835">https://golang.org/cl/78835</a>: add UserCacheDir
|
||||
</p>
|
||||
|
||||
<p><!-- CL 94856 -->
|
||||
TODO: <a href="https://golang.org/cl/94856">https://golang.org/cl/94856</a>: add ModeIrregular flag
|
||||
</p>
|
||||
|
||||
<p><!-- CL 99337 -->
|
||||
TODO: <a href="https://golang.org/cl/99337">https://golang.org/cl/99337</a>: enable symlink creation on Windows 10
|
||||
</p>
|
||||
|
||||
<p><!-- CL 100077 -->
|
||||
TODO: <a href="https://golang.org/cl/100077">https://golang.org/cl/100077</a>: use poller when NewFile is called with a blocking descriptor.
|
||||
</p>
|
||||
|
||||
</dl><!-- os -->
|
||||
|
||||
<dl id="os/signal"><dt><a href="/pkg/os/signal/">os/signal</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 108376 -->
|
||||
TODO: <a href="https://golang.org/cl/108376">https://golang.org/cl/108376</a>: add func Ignored(sig Signal) bool
|
||||
</p>
|
||||
|
||||
</dl><!-- os/signal -->
|
||||
|
||||
<dl id="os/user"><dt><a href="/pkg/os/user/">os/user</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 92456 -->
|
||||
TODO: <a href="https://golang.org/cl/92456">https://golang.org/cl/92456</a>: add a way to enforce pure Go implementation
|
||||
</p>
|
||||
|
||||
</dl><!-- os/user -->
|
||||
|
||||
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 85887 -->
|
||||
TODO: <a href="https://golang.org/cl/85887">https://golang.org/cl/85887</a>: use sparse mappings for the heap
|
||||
</p>
|
||||
|
||||
<p><!-- CL 94076 -->
|
||||
TODO: <a href="https://golang.org/cl/94076">https://golang.org/cl/94076</a>: use native CAS and memory barrier on ARMv7
|
||||
</p>
|
||||
|
||||
<p><!-- CL 106156 -->
|
||||
TODO: <a href="https://golang.org/cl/106156">https://golang.org/cl/106156</a>: use fixed TLS offsets on darwin/amd64 and darwin/386
|
||||
</p>
|
||||
|
||||
<p><!-- CL 109255 -->
|
||||
TODO: <a href="https://golang.org/cl/109255">https://golang.org/cl/109255</a>: enable memory sanitizer on arm64
|
||||
</p>
|
||||
|
||||
</dl><!-- runtime -->
|
||||
|
||||
<dl id="runtime,cmd/ld"><dt><a href="/pkg/runtime,cmd/ld/">runtime,cmd/ld</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 108679 -->
|
||||
TODO: <a href="https://golang.org/cl/108679">https://golang.org/cl/108679</a>: on darwin, create theads using libc
|
||||
</p>
|
||||
|
||||
</dl><!-- runtime,cmd/ld -->
|
||||
|
||||
<dl id="runtime/pprof"><dt><a href="/pkg/runtime/pprof/">runtime/pprof</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 102696 -->
|
||||
TODO: <a href="https://golang.org/cl/102696">https://golang.org/cl/102696</a>: introduce "allocs" profile
|
||||
</p>
|
||||
|
||||
</dl><!-- runtime/pprof -->
|
||||
|
||||
<dl id="runtime/traceback"><dt><a href="/pkg/runtime/traceback/">runtime/traceback</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 70993 -->
|
||||
TODO: <a href="https://golang.org/cl/70993">https://golang.org/cl/70993</a>: support tracking goroutine ancestor tracebacks with GODEBUG="tracebackancestors=N"
|
||||
</p>
|
||||
|
||||
</dl><!-- runtime/traceback -->
|
||||
|
||||
<dl id="sync"><dt><a href="/pkg/sync/">sync</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 87095 -->
|
||||
TODO: <a href="https://golang.org/cl/87095">https://golang.org/cl/87095</a>: enable profiling of RWMutex
|
||||
</p>
|
||||
|
||||
</dl><!-- sync -->
|
||||
|
||||
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 106275 -->
|
||||
TODO: <a href="https://golang.org/cl/106275">https://golang.org/cl/106275</a>: introduce Pointer type and use it instead of uintptr
|
||||
</p>
|
||||
|
||||
</dl><!-- syscall -->
|
||||
|
||||
<dl id="text/scanner"><dt><a href="/pkg/text/scanner/">text/scanner</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 112037 -->
|
||||
TODO: <a href="https://golang.org/cl/112037">https://golang.org/cl/112037</a>: return RawString token rather than String for raw string literals
|
||||
</p>
|
||||
|
||||
</dl><!-- text/scanner -->
|
||||
|
||||
<dl id="text/template"><dt><a href="/pkg/text/template/">text/template</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 84480 -->
|
||||
TODO: <a href="https://golang.org/cl/84480">https://golang.org/cl/84480</a>: add variable assignments
|
||||
</p>
|
||||
|
||||
</dl><!-- text/template -->
|
||||
|
||||
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 98157 -->
|
||||
TODO: <a href="https://golang.org/cl/98157">https://golang.org/cl/98157</a>: add support for parsing timezones denoted by sign and offset
|
||||
</p>
|
||||
|
||||
</dl><!-- time -->
|
|
@ -860,13 +860,13 @@ The new build tag <code>netgo</code> (off by default) allows the construction of
|
|||
The <a href="/pkg/net/"><code>net</code></a> package adds a new field
|
||||
<code>DualStack</code> to the <a href="/pkg/net/#Dialer"><code>Dialer</code></a>
|
||||
struct for TCP connection setup using a dual IP stack as described in
|
||||
<a href="http://tools.ietf.org/html/rfc6555">RFC 6555</a>.
|
||||
<a href="https://tools.ietf.org/html/rfc6555">RFC 6555</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/net/http/"><code>net/http</code></a> package will no longer
|
||||
transmit cookies that are incorrect according to
|
||||
<a href="http://tools.ietf.org/html/rfc6265">RFC 6265</a>.
|
||||
<a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a>.
|
||||
It just logs an error and sends nothing.
|
||||
Also,
|
||||
the <a href="/pkg/net/http/"><code>net/http</code></a> package's
|
||||
|
|
|
@ -420,7 +420,7 @@ to automate the running of tools to generate source code before compilation.
|
|||
For example, it can be used to run the <a href="/cmd/yacc"><code>yacc</code></a>
|
||||
compiler-compiler on a <code>.y</code> file to produce the Go source file implementing the grammar,
|
||||
or to automate the generation of <code>String</code> methods for typed constants using the new
|
||||
<a href="http://godoc.org/golang.org/x/tools/cmd/stringer">stringer</a>
|
||||
<a href="https://godoc.org/golang.org/x/tools/cmd/stringer">stringer</a>
|
||||
tool in the <code>golang.org/x/tools</code> subrepository.
|
||||
</p>
|
||||
|
||||
|
@ -619,9 +619,9 @@ has been created to serve as the location for new developments to support system
|
|||
calls on all kernels.
|
||||
It has a nicer structure, with three packages that each hold the implementation of
|
||||
system calls for one of
|
||||
<a href="http://godoc.org/golang.org/x/sys/unix">Unix</a>,
|
||||
<a href="http://godoc.org/golang.org/x/sys/windows">Windows</a> and
|
||||
<a href="http://godoc.org/golang.org/x/sys/plan9">Plan 9</a>.
|
||||
<a href="https://godoc.org/golang.org/x/sys/unix">Unix</a>,
|
||||
<a href="https://godoc.org/golang.org/x/sys/windows">Windows</a> and
|
||||
<a href="https://godoc.org/golang.org/x/sys/plan9">Plan 9</a>.
|
||||
These packages will be curated more generously, accepting all reasonable changes
|
||||
that reflect kernel interfaces in those operating systems.
|
||||
See the documentation and the article mentioned above for more information.
|
||||
|
@ -670,7 +670,7 @@ The <a href="/pkg/crypto/"><code>crypto</code></a> package now has a
|
|||
|
||||
<li>
|
||||
The <a href="/pkg/crypto/tls/"><code>crypto/tls</code></a> package
|
||||
now supports ALPN as defined in <a href="http://tools.ietf.org/html/rfc7301">RFC 7301</a>.
|
||||
now supports ALPN as defined in <a href="https://tools.ietf.org/html/rfc7301">RFC 7301</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
|
|
@ -116,7 +116,7 @@ instead of generated from <a href="/cmd/yacc/">yacc</a>.
|
|||
<p>
|
||||
The compiler, linker, and <code>go</code> command have a new flag <code>-msan</code>,
|
||||
analogous to <code>-race</code> and only available on linux/amd64,
|
||||
that enables interoperation with the <a href="http://clang.llvm.org/docs/MemorySanitizer.html">Clang MemorySanitizer</a>.
|
||||
that enables interoperation with the <a href="https://clang.llvm.org/docs/MemorySanitizer.html">Clang MemorySanitizer</a>.
|
||||
Such interoperation is useful mainly for testing a program containing suspect C or C++ code.
|
||||
</p>
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ POWER5 architecture.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
The OpenBSD port now requires OpenBSD 5.6 or later, for access to the <a href="http://man.openbsd.org/getentropy.2"><i>getentropy</i>(2)</a> system call.
|
||||
The OpenBSD port now requires OpenBSD 5.6 or later, for access to the <a href="https://man.openbsd.org/getentropy.2"><i>getentropy</i>(2)</a> system call.
|
||||
</p>
|
||||
|
||||
<h3 id="known_issues">Known Issues</h3>
|
||||
|
|
|
@ -97,14 +97,14 @@ What's the origin of the mascot?</h3>
|
|||
|
||||
<p>
|
||||
The mascot and logo were designed by
|
||||
<a href="http://reneefrench.blogspot.com">Renée French</a>, who also designed
|
||||
<a href="https://reneefrench.blogspot.com">Renée French</a>, who also designed
|
||||
<a href="https://9p.io/plan9/glenda.html">Glenda</a>,
|
||||
the Plan 9 bunny.
|
||||
The <a href="https://blog.golang.org/gopher">gopher</a>
|
||||
is derived from one she used for an <a href="http://wfmu.org/">WFMU</a>
|
||||
is derived from one she used for an <a href="https://wfmu.org/">WFMU</a>
|
||||
T-shirt design some years ago.
|
||||
The logo and mascot are covered by the
|
||||
<a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0</a>
|
||||
<a href="https://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0</a>
|
||||
license.
|
||||
</p>
|
||||
|
||||
|
@ -1396,7 +1396,7 @@ reservation does not deprive other processes of memory.
|
|||
<p>
|
||||
To find the amount of actual memory allocated to a Go process, use the Unix
|
||||
<code>top</code> command and consult the <code>RES</code> (Linux) or
|
||||
<code>RSIZE</code> (Mac OS X) columns.
|
||||
<code>RSIZE</code> (macOS) columns.
|
||||
<!-- TODO(adg): find out how this works on Windows -->
|
||||
</p>
|
||||
|
||||
|
@ -1929,7 +1929,7 @@ func main() {
|
|||
|
||||
<p>
|
||||
Nowadays, most Go programmers use a tool,
|
||||
<a href="http://godoc.org/golang.org/x/tools/cmd/goimports">goimports</a>,
|
||||
<a href="https://godoc.org/golang.org/x/tools/cmd/goimports">goimports</a>,
|
||||
which automatically rewrites a Go source file to have the correct imports,
|
||||
eliminating the unused imports issue in practice.
|
||||
This program is easily connected to most editors to run automatically when a Go source file is written.
|
||||
|
@ -1968,7 +1968,7 @@ The slowest depend on libraries for which versions of comparable performance
|
|||
are not available in Go.
|
||||
For instance, <a href="https://go.googlesource.com/exp/+/master/shootout/pidigits.go">pidigits.go</a>
|
||||
depends on a multi-precision math package, and the C
|
||||
versions, unlike Go's, use <a href="http://gmplib.org/">GMP</a> (which is
|
||||
versions, unlike Go's, use <a href="https://gmplib.org/">GMP</a> (which is
|
||||
written in optimized assembler).
|
||||
Benchmarks that depend on regular expressions
|
||||
(<a href="https://go.googlesource.com/exp/+/master/shootout/regex-dna.go">regex-dna.go</a>,
|
||||
|
|
|
@ -69,7 +69,7 @@ language.
|
|||
|
||||
<p>
|
||||
Source code is Unicode text encoded in
|
||||
<a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a>. The text is not
|
||||
<a href="https://en.wikipedia.org/wiki/UTF-8">UTF-8</a>. The text is not
|
||||
canonicalized, so a single accented code point is distinct from the
|
||||
same character constructed from combining an accent and a letter;
|
||||
those are treated as two code points. For simplicity, this document
|
||||
|
@ -104,7 +104,7 @@ unicode_digit = /* a Unicode code point classified as "Number, decimal digit" *
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
In <a href="http://www.unicode.org/versions/Unicode8.0.0/">The Unicode Standard 8.0</a>,
|
||||
In <a href="https://www.unicode.org/versions/Unicode8.0.0/">The Unicode Standard 8.0</a>,
|
||||
Section 4.5 "General Category" defines a set of character categories.
|
||||
Go treats all characters in any of the Letter categories Lu, Ll, Lt, Lm, or Lo
|
||||
as Unicode letters, and those in the Number category Nd as Unicode digits.
|
||||
|
@ -793,7 +793,7 @@ rune alias for int32
|
|||
|
||||
<p>
|
||||
The value of an <i>n</i>-bit integer is <i>n</i> bits wide and represented using
|
||||
<a href="http://en.wikipedia.org/wiki/Two's_complement">two's complement arithmetic</a>.
|
||||
<a href="https://en.wikipedia.org/wiki/Two's_complement">two's complement arithmetic</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -3543,7 +3543,7 @@ x = q*y + r and |r| < |y|
|
|||
|
||||
<p>
|
||||
with <code>x / y</code> truncated towards zero
|
||||
(<a href="http://en.wikipedia.org/wiki/Modulo_operation">"truncated division"</a>).
|
||||
(<a href="https://en.wikipedia.org/wiki/Modulo_operation">"truncated division"</a>).
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -6109,7 +6109,7 @@ package and may be relative to a repository of installed packages.
|
|||
<p>
|
||||
Implementation restriction: A compiler may restrict ImportPaths to
|
||||
non-empty strings using only characters belonging to
|
||||
<a href="http://www.unicode.org/versions/Unicode6.3.0/">Unicode's</a>
|
||||
<a href="https://www.unicode.org/versions/Unicode6.3.0/">Unicode's</a>
|
||||
L, M, N, P, and S general categories (the Graphic characters without
|
||||
spaces) and may also exclude the characters
|
||||
<code>!"#$%&'()*,:;<=>?[\]^`{|}</code>
|
||||
|
|
|
@ -98,7 +98,7 @@ goroutines, such as stacks that grow and shrink on demand.
|
|||
|
||||
<p>
|
||||
The compilers can target the DragonFly BSD, FreeBSD, Linux, NetBSD, OpenBSD,
|
||||
OS X (Darwin), Plan 9, Solaris and Windows operating systems.
|
||||
macOS (Darwin), Plan 9, Solaris and Windows operating systems.
|
||||
The full set of supported combinations is listed in the discussion of
|
||||
<a href="#environment">environment variables</a> below.
|
||||
</p>
|
||||
|
@ -197,7 +197,7 @@ have a <code>git</code> command before proceeding.)
|
|||
<p>
|
||||
If you do not have a working Git installation,
|
||||
follow the instructions on the
|
||||
<a href="http://git-scm.com/downloads">Git downloads</a> page.
|
||||
<a href="https://git-scm.com/downloads">Git downloads</a> page.
|
||||
</p>
|
||||
|
||||
<h2 id="ccompiler">(Optional) Install a C compiler</h2>
|
||||
|
@ -388,7 +388,7 @@ You can access the latter commands with
|
|||
|
||||
<p>
|
||||
The usual community resources such as
|
||||
<code>#go-nuts</code> on the <a href="http://freenode.net/">Freenode</a> IRC server
|
||||
<code>#go-nuts</code> on the <a href="https://freenode.net/">Freenode</a> IRC server
|
||||
and the
|
||||
<a href="//groups.google.com/group/golang-nuts">Go Nuts</a>
|
||||
mailing list have active developers that can help you with problems
|
||||
|
@ -468,7 +468,7 @@ These default to the values of <code>$GOHOSTOS</code> and
|
|||
|
||||
<p>
|
||||
Choices for <code>$GOOS</code> are
|
||||
<code>darwin</code> (Mac OS X 10.8 and above and iOS), <code>dragonfly</code>, <code>freebsd</code>,
|
||||
<code>darwin</code> (macOS 10.10 and above and iOS), <code>dragonfly</code>, <code>freebsd</code>,
|
||||
<code>linux</code>, <code>netbsd</code>, <code>openbsd</code>,
|
||||
<code>plan9</code>, <code>solaris</code> and <code>windows</code>.
|
||||
Choices for <code>$GOARCH</code> are
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<p>
|
||||
<a href="/dl/" target="_blank">Official binary
|
||||
distributions</a> are available for the FreeBSD (release 10-STABLE and above),
|
||||
Linux, Mac OS X (10.8 and above), and Windows operating systems and
|
||||
Linux, macOS (10.10 and above), and Windows operating systems and
|
||||
the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor
|
||||
architectures.
|
||||
</p>
|
||||
|
@ -49,7 +49,7 @@ If your OS or architecture is not on the list, you may be able to
|
|||
<tr><td colspan="3"><hr></td></tr>
|
||||
<tr><td>FreeBSD 10.3 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
||||
<tr valign='top'><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm, arm64,<br>s390x, ppc64le</td> <td>CentOS/RHEL 5.x not supported.<br>Install from source for other libc.</td></tr>
|
||||
<tr><td>macOS 10.8 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
||||
<tr><td>macOS 10.10 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
||||
<tr><td>Windows XP SP2 or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
||||
</table>
|
||||
|
||||
|
@ -57,7 +57,7 @@ If your OS or architecture is not on the list, you may be able to
|
|||
<sup>†</sup>A C compiler is required only if you plan to use
|
||||
<a href="/cmd/cgo">cgo</a>.<br/>
|
||||
<sup>‡</sup>You only need to install the command line tools for
|
||||
<a href="http://developer.apple.com/Xcode/">Xcode</a>. If you have already
|
||||
<a href="https://developer.apple.com/Xcode/">Xcode</a>. If you have already
|
||||
installed Xcode 4.3+, you can install it from the Components tab of the
|
||||
Downloads preferences panel.
|
||||
</p>
|
||||
|
@ -74,7 +74,7 @@ first <a href="#uninstall">remove the existing version</a>.
|
|||
|
||||
<div id="tarballInstructions">
|
||||
|
||||
<h3 id="tarball">Linux, Mac OS X, and FreeBSD tarballs</h3>
|
||||
<h3 id="tarball">Linux, macOS, and FreeBSD tarballs</h3>
|
||||
|
||||
<p>
|
||||
<a href="/dl/">Download the archive</a>
|
||||
|
@ -114,36 +114,11 @@ or execute them from the profile using a command such as
|
|||
<code>source $HOME/.profile</code>.
|
||||
</p>
|
||||
|
||||
<h4 id="tarball_non_standard">Installing to a custom location</h4>
|
||||
|
||||
<p>
|
||||
The Go binary distributions assume they will be installed in
|
||||
<code>/usr/local/go</code> (or <code>c:\Go</code> under Windows),
|
||||
but it is possible to install the Go tools to a different location.
|
||||
In this case you must set the <code>GOROOT</code> environment variable
|
||||
to point to the directory in which it was installed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, if you installed Go to your home directory you should add
|
||||
commands like the following to <code>$HOME/.profile</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
export GOROOT=$HOME/go1.X
|
||||
export PATH=$PATH:$GOROOT/bin
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<b>Note</b>: <code>GOROOT</code> must be set only when installing to a custom
|
||||
location.
|
||||
</p>
|
||||
|
||||
</div><!-- tarballInstructions -->
|
||||
|
||||
<div id="darwinPackageInstructions">
|
||||
|
||||
<h3 id="osx">Mac OS X package installer</h3>
|
||||
<h3 id="macos"><div id="osx"></div>macOS package installer</h3>
|
||||
|
||||
<p>
|
||||
<a href="/dl/">Download the package file</a>,
|
||||
|
@ -301,7 +276,7 @@ which describes some essential concepts about using the Go tools.
|
|||
<p>
|
||||
To remove an existing Go installation from your system delete the
|
||||
<code>go</code> directory. This is usually <code>/usr/local/go</code>
|
||||
under Linux, Mac OS X, and FreeBSD or <code>c:\Go</code>
|
||||
under Linux, macOS, and FreeBSD or <code>c:\Go</code>
|
||||
under Windows.
|
||||
</p>
|
||||
|
||||
|
@ -310,7 +285,7 @@ You should also remove the Go <code>bin</code> directory from your
|
|||
<code>PATH</code> environment variable.
|
||||
Under Linux and FreeBSD you should edit <code>/etc/profile</code> or
|
||||
<code>$HOME/.profile</code>.
|
||||
If you installed Go with the <a href="#osx">Mac OS X package</a> then you
|
||||
If you installed Go with the <a href="#macos">macOS package</a> then you
|
||||
should remove the <code>/etc/paths.d/go</code> file.
|
||||
Windows users should read the section about <a href="#windows_env">setting
|
||||
environment variables under Windows</a>.
|
||||
|
|
|
@ -62,7 +62,7 @@ simple, reliable, and efficient software.
|
|||
<span class="big">Download Go</span>
|
||||
<span class="desc">
|
||||
Binary distributions available for<br>
|
||||
Linux, Mac OS X, Windows, and more.
|
||||
Linux, macOS, Windows, and more.
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
# Consult https://www.iana.org/time-zones for the latest versions.
|
||||
|
||||
# Versions to use.
|
||||
CODE=2017c
|
||||
DATA=2017c
|
||||
CODE=2018e
|
||||
DATA=2018e
|
||||
|
||||
set -e
|
||||
rm -rf work
|
||||
|
|
Binary file not shown.
|
@ -89,6 +89,7 @@ func Test21897(t *testing.T) { test21897(t) }
|
|||
func Test22906(t *testing.T) { test22906(t) }
|
||||
func Test24206(t *testing.T) { test24206(t) }
|
||||
func Test25143(t *testing.T) { test25143(t) }
|
||||
func Test23356(t *testing.T) { test23356(t) }
|
||||
|
||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
|
||||
|
|
|
@ -22,6 +22,10 @@ import (
|
|||
)
|
||||
|
||||
func test18146(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping in short mode")
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skipf("skipping flaky test on %s; see golang.org/issue/18202", runtime.GOOS)
|
||||
}
|
||||
|
@ -33,10 +37,6 @@ func test18146(t *testing.T) {
|
|||
attempts := 1000
|
||||
threads := 4
|
||||
|
||||
if testing.Short() {
|
||||
attempts = 100
|
||||
}
|
||||
|
||||
// Restrict the number of attempts based on RLIMIT_NPROC.
|
||||
// Tediously, RLIMIT_NPROC was left out of the syscall package,
|
||||
// probably because it is not in POSIX.1, so we define it here.
|
||||
|
|
19
misc/cgo/test/issue23356.go
Normal file
19
misc/cgo/test/issue23356.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
// int a(void) { return 5; };
|
||||
// int r(void) { return 3; };
|
||||
import "C"
|
||||
import "testing"
|
||||
|
||||
func test23356(t *testing.T) {
|
||||
if got, want := C.a(), C.int(5); got != want {
|
||||
t.Errorf("C.a() == %v, expected %v", got, want)
|
||||
}
|
||||
if got, want := C.r(), C.int(3); got != want {
|
||||
t.Errorf("C.r() == %v, expected %v", got, want)
|
||||
}
|
||||
}
|
11
misc/cgo/test/issue23555.go
Normal file
11
misc/cgo/test/issue23555.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Test that we can have two identical cgo packages in a single binary.
|
||||
// No runtime test; just make sure it compiles.
|
||||
|
||||
package cgotest
|
||||
|
||||
import _ "./issue23555a"
|
||||
import _ "./issue23555b"
|
|
@ -2,10 +2,11 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
package issue23555
|
||||
|
||||
TEXT ·startTimer(SB),NOSPLIT,$0
|
||||
JMP time·startTimer(SB)
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
TEXT ·stopTimer(SB),NOSPLIT,$0
|
||||
JMP time·stopTimer(SB)
|
||||
func X() {
|
||||
C.free(C.malloc(10))
|
||||
}
|
12
misc/cgo/test/issue23555b/a.go
Normal file
12
misc/cgo/test/issue23555b/a.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue23555
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
func X() {
|
||||
C.free(C.malloc(10))
|
||||
}
|
22
misc/cgo/test/issue23720.go
Normal file
22
misc/cgo/test/issue23720.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Test that we can pass compatible typedefs.
|
||||
// No runtime test; just make sure it compiles.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
typedef int *issue23720A;
|
||||
|
||||
typedef const int *issue23720B;
|
||||
|
||||
void issue23720F(issue23720B a) {}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func Issue23720F() {
|
||||
var x C.issue23720A
|
||||
C.issue23720F(x)
|
||||
}
|
|
@ -16,6 +16,8 @@ import (
|
|||
// without writing more assembly code, which we haven't bothered to
|
||||
// do. So this is not much of a test.
|
||||
|
||||
var Baton int32
|
||||
|
||||
func RewindAndSetgid() {
|
||||
atomic.StoreInt32(&Baton, 1)
|
||||
for atomic.LoadInt32(&Baton) != 0 {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build gc
|
||||
|
||||
package issue9400
|
||||
|
||||
var Baton int32
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
// +build !windows
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern void IntoGoAndBack();
|
||||
|
@ -28,11 +30,22 @@ static void* sigthreadfunc(void* unused) {
|
|||
}
|
||||
|
||||
int RunSigThread() {
|
||||
int tries;
|
||||
pthread_t thread;
|
||||
int r;
|
||||
struct timespec ts;
|
||||
|
||||
r = pthread_create(&thread, NULL, &sigthreadfunc, NULL);
|
||||
if (r != 0)
|
||||
return r;
|
||||
return pthread_join(thread, NULL);
|
||||
for (tries = 0; tries < 20; tries++) {
|
||||
r = pthread_create(&thread, NULL, &sigthreadfunc, NULL);
|
||||
if (r == 0) {
|
||||
return pthread_join(thread, NULL);
|
||||
}
|
||||
if (r != EAGAIN) {
|
||||
return r;
|
||||
}
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = (tries + 1) * 1000 * 1000; // Milliseconds.
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
return EAGAIN;
|
||||
}
|
||||
|
|
52
misc/cgo/testplugin/src/issue25756/main.go
Normal file
52
misc/cgo/testplugin/src/issue25756/main.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Run the game of life in C using Go for parallelization.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"plugin"
|
||||
)
|
||||
|
||||
const MAXDIM = 100
|
||||
|
||||
var dim = flag.Int("dim", 16, "board dimensions")
|
||||
var gen = flag.Int("gen", 10, "generations")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var a [MAXDIM * MAXDIM]int32
|
||||
for i := 2; i < *dim; i += 8 {
|
||||
for j := 2; j < *dim-3; j += 8 {
|
||||
for y := 0; y < 3; y++ {
|
||||
a[i**dim+j+y] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p, err := plugin.Open("life.so")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f, err := p.Lookup("Run")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f.(func(int, int, int, []int32))(*gen, *dim, *dim, a[:])
|
||||
|
||||
for i := 0; i < *dim; i++ {
|
||||
for j := 0; j < *dim; j++ {
|
||||
if a[i**dim+j] == 0 {
|
||||
fmt.Print(" ")
|
||||
} else {
|
||||
fmt.Print("X")
|
||||
}
|
||||
}
|
||||
fmt.Print("\n")
|
||||
}
|
||||
}
|
56
misc/cgo/testplugin/src/issue25756/plugin/c-life.c
Normal file
56
misc/cgo/testplugin/src/issue25756/plugin/c-life.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include <assert.h>
|
||||
#include "life.h"
|
||||
#include "_cgo_export.h"
|
||||
|
||||
const int MYCONST = 0;
|
||||
|
||||
// Do the actual manipulation of the life board in C. This could be
|
||||
// done easily in Go, we are just using C for demonstration
|
||||
// purposes.
|
||||
void
|
||||
Step(int x, int y, int *a, int *n)
|
||||
{
|
||||
struct GoStart_return r;
|
||||
|
||||
// Use Go to start 4 goroutines each of which handles 1/4 of the
|
||||
// board.
|
||||
r = GoStart(0, x, y, 0, x / 2, 0, y / 2, a, n);
|
||||
assert(r.r0 == 0 && r.r1 == 100); // test multiple returns
|
||||
r = GoStart(1, x, y, x / 2, x, 0, y / 2, a, n);
|
||||
assert(r.r0 == 1 && r.r1 == 101); // test multiple returns
|
||||
GoStart(2, x, y, 0, x / 2, y / 2, y, a, n);
|
||||
GoStart(3, x, y, x / 2, x, y / 2, y, a, n);
|
||||
GoWait(0);
|
||||
GoWait(1);
|
||||
GoWait(2);
|
||||
GoWait(3);
|
||||
}
|
||||
|
||||
// The actual computation. This is called in parallel.
|
||||
void
|
||||
DoStep(int xdim, int ydim, int xstart, int xend, int ystart, int yend, int *a, int *n)
|
||||
{
|
||||
int x, y, c, i, j;
|
||||
|
||||
for(x = xstart; x < xend; x++) {
|
||||
for(y = ystart; y < yend; y++) {
|
||||
c = 0;
|
||||
for(i = -1; i <= 1; i++) {
|
||||
for(j = -1; j <= 1; j++) {
|
||||
if(x+i >= 0 && x+i < xdim &&
|
||||
y+j >= 0 && y+j < ydim &&
|
||||
(i != 0 || j != 0))
|
||||
c += a[(x+i)*xdim + (y+j)] != 0;
|
||||
}
|
||||
}
|
||||
if(c == 3 || (c == 2 && a[x*xdim + y] != 0))
|
||||
n[x*xdim + y] = 1;
|
||||
else
|
||||
n[x*xdim + y] = 0;
|
||||
}
|
||||
}
|
||||
}
|
39
misc/cgo/testplugin/src/issue25756/plugin/life.go
Normal file
39
misc/cgo/testplugin/src/issue25756/plugin/life.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// #include "life.h"
|
||||
import "C"
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func Run(gen, x, y int, a []int32) {
|
||||
n := make([]int32, x*y)
|
||||
for i := 0; i < gen; i++ {
|
||||
C.Step(C.int(x), C.int(y), (*C.int)(unsafe.Pointer(&a[0])), (*C.int)(unsafe.Pointer(&n[0])))
|
||||
copy(a, n)
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the channels visible from Go.
|
||||
var chans [4]chan bool
|
||||
|
||||
//export GoStart
|
||||
// Double return value is just for testing.
|
||||
func GoStart(i, xdim, ydim, xstart, xend, ystart, yend C.int, a *C.int, n *C.int) (int, int) {
|
||||
c := make(chan bool, int(C.MYCONST))
|
||||
go func() {
|
||||
C.DoStep(xdim, ydim, xstart, xend, ystart, yend, a, n)
|
||||
c <- true
|
||||
}()
|
||||
chans[i] = c
|
||||
return int(i), int(i + 100)
|
||||
}
|
||||
|
||||
//export GoWait
|
||||
func GoWait(i C.int) {
|
||||
<-chans[i]
|
||||
chans[i] = nil
|
||||
}
|
7
misc/cgo/testplugin/src/issue25756/plugin/life.h
Normal file
7
misc/cgo/testplugin/src/issue25756/plugin/life.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
extern void Step(int, int, int *, int *);
|
||||
extern void DoStep(int, int, int, int, int, int, int *, int *);
|
||||
extern const int MYCONST;
|
|
@ -15,7 +15,7 @@ goos=$(go env GOOS)
|
|||
goarch=$(go env GOARCH)
|
||||
|
||||
function cleanup() {
|
||||
rm -f plugin*.so unnamed*.so iface*.so issue*
|
||||
rm -f plugin*.so unnamed*.so iface*.so life.so issue*
|
||||
rm -rf host pkg sub iface
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
@ -90,3 +90,12 @@ GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue22295 src/issue22295.pkg/m
|
|||
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue24351.so src/issue24351/plugin.go
|
||||
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue24351 src/issue24351/main.go
|
||||
./issue24351
|
||||
|
||||
# Test for issue 25756
|
||||
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o life.so issue25756/plugin
|
||||
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue25756 src/issue25756/main.go
|
||||
# Fails intermittently, but 20 runs should cause the failure
|
||||
for i in `seq 1 20`;
|
||||
do
|
||||
./issue25756 > /dev/null
|
||||
done
|
||||
|
|
|
@ -7,9 +7,13 @@ package sanitizers_test
|
|||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func TestTSAN(t *testing.T) {
|
||||
if runtime.GOARCH == "arm64" {
|
||||
t.Skip("skipping test; see https://golang.org/issue/25682")
|
||||
}
|
||||
t.Parallel()
|
||||
requireOvercommit(t)
|
||||
config := configure("thread")
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
package main
|
||||
|
||||
func main() {
|
||||
// This is enough to make sure that the executable references
|
||||
// a type descriptor, which was the cause of
|
||||
// https://golang.org/issue/25970.
|
||||
c := make(chan int)
|
||||
_ = c
|
||||
}
|
||||
|
|
234
misc/wasm/wasm_exec.js
Executable file → Normal file
234
misc/wasm/wasm_exec.js
Executable file → Normal file
|
@ -16,13 +16,11 @@
|
|||
},
|
||||
};
|
||||
|
||||
const now = () => {
|
||||
const [sec, nsec] = process.hrtime();
|
||||
return sec * 1000 + nsec / 1000000;
|
||||
};
|
||||
global.performance = {
|
||||
timeOrigin: Date.now() - now(),
|
||||
now: now,
|
||||
now() {
|
||||
const [sec, nsec] = process.hrtime();
|
||||
return sec * 1000 + nsec / 1000000;
|
||||
},
|
||||
};
|
||||
|
||||
const util = require("util");
|
||||
|
@ -33,7 +31,7 @@
|
|||
|
||||
let outputBuf = "";
|
||||
global.fs = {
|
||||
constants: {},
|
||||
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_NONBLOCK: -1, O_SYNC: -1 }, // unused
|
||||
writeSync(fd, buf) {
|
||||
outputBuf += decoder.decode(buf);
|
||||
const nl = outputBuf.lastIndexOf("\n");
|
||||
|
@ -43,6 +41,11 @@
|
|||
}
|
||||
return buf.length;
|
||||
},
|
||||
openSync(path, flags, mode) {
|
||||
const err = new Error("not implemented");
|
||||
err.code = "ENOSYS";
|
||||
throw err;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -58,6 +61,8 @@
|
|||
console.warn("exit code:", code);
|
||||
}
|
||||
};
|
||||
this._callbackTimeouts = new Map();
|
||||
this._nextCallbackTimeoutID = 1;
|
||||
|
||||
const mem = () => {
|
||||
// The buffer may change when requesting more memory.
|
||||
|
@ -76,21 +81,72 @@
|
|||
}
|
||||
|
||||
const loadValue = (addr) => {
|
||||
const f = mem().getFloat64(addr, true);
|
||||
if (!isNaN(f)) {
|
||||
return f;
|
||||
}
|
||||
|
||||
const id = mem().getUint32(addr, true);
|
||||
return this._values[id];
|
||||
}
|
||||
|
||||
const storeValue = (addr, v) => {
|
||||
if (v === undefined) {
|
||||
mem().setUint32(addr, 0, true);
|
||||
if (typeof v === "number") {
|
||||
if (isNaN(v)) {
|
||||
mem().setUint32(addr + 4, 0x7FF80000, true); // NaN
|
||||
mem().setUint32(addr, 0, true);
|
||||
return;
|
||||
}
|
||||
mem().setFloat64(addr, v, true);
|
||||
return;
|
||||
}
|
||||
if (v === null) {
|
||||
mem().setUint32(addr, 1, true);
|
||||
|
||||
mem().setUint32(addr + 4, 0x7FF80000, true); // NaN
|
||||
|
||||
switch (v) {
|
||||
case undefined:
|
||||
mem().setUint32(addr, 1, true);
|
||||
return;
|
||||
case null:
|
||||
mem().setUint32(addr, 2, true);
|
||||
return;
|
||||
case true:
|
||||
mem().setUint32(addr, 3, true);
|
||||
return;
|
||||
case false:
|
||||
mem().setUint32(addr, 4, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof v === "string") {
|
||||
let ref = this._stringRefs.get(v);
|
||||
if (ref === undefined) {
|
||||
ref = this._values.length;
|
||||
this._values.push(v);
|
||||
this._stringRefs.set(v, ref);
|
||||
}
|
||||
mem().setUint32(addr, ref, true);
|
||||
return;
|
||||
}
|
||||
this._values.push(v);
|
||||
mem().setUint32(addr, this._values.length - 1, true);
|
||||
|
||||
if (typeof v === "symbol") {
|
||||
let ref = this._symbolRefs.get(v);
|
||||
if (ref === undefined) {
|
||||
ref = this._values.length;
|
||||
this._values.push(v);
|
||||
this._symbolRefs.set(v, ref);
|
||||
}
|
||||
mem().setUint32(addr, ref, true);
|
||||
return;
|
||||
}
|
||||
|
||||
let ref = v[this._refProp];
|
||||
if (ref === undefined) {
|
||||
ref = this._values.length;
|
||||
this._values.push(v);
|
||||
v[this._refProp] = ref;
|
||||
}
|
||||
mem().setUint32(addr, ref, true);
|
||||
}
|
||||
|
||||
const loadSlice = (addr) => {
|
||||
|
@ -104,8 +160,7 @@
|
|||
const len = getInt64(addr + 8);
|
||||
const a = new Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
const id = mem().getUint32(array + i * 4, true);
|
||||
a[i] = this._values[id];
|
||||
a[i] = loadValue(array + i * 8);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
@ -116,10 +171,12 @@
|
|||
return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
|
||||
}
|
||||
|
||||
const timeOrigin = Date.now() - performance.now();
|
||||
this.importObject = {
|
||||
go: {
|
||||
// func wasmExit(code int32)
|
||||
"runtime.wasmExit": (sp) => {
|
||||
this.exited = true;
|
||||
this.exit(mem().getInt32(sp + 8, true));
|
||||
},
|
||||
|
||||
|
@ -133,7 +190,7 @@
|
|||
|
||||
// func nanotime() int64
|
||||
"runtime.nanotime": (sp) => {
|
||||
setInt64(sp + 8, (performance.timeOrigin + performance.now()) * 1000000);
|
||||
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
|
||||
},
|
||||
|
||||
// func walltime() (sec int64, nsec int32)
|
||||
|
@ -143,124 +200,117 @@
|
|||
mem().setInt32(sp + 16, (msec % 1000) * 1000000, true);
|
||||
},
|
||||
|
||||
// func scheduleCallback(delay int64) int32
|
||||
"runtime.scheduleCallback": (sp) => {
|
||||
const id = this._nextCallbackTimeoutID;
|
||||
this._nextCallbackTimeoutID++;
|
||||
this._callbackTimeouts.set(id, setTimeout(
|
||||
() => { this._resolveCallbackPromise(); },
|
||||
getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
|
||||
));
|
||||
mem().setInt32(sp + 16, id, true);
|
||||
},
|
||||
|
||||
// func clearScheduledCallback(id int32)
|
||||
"runtime.clearScheduledCallback": (sp) => {
|
||||
const id = mem().getInt32(sp + 8, true);
|
||||
clearTimeout(this._callbackTimeouts.get(id));
|
||||
this._callbackTimeouts.delete(id);
|
||||
},
|
||||
|
||||
// func getRandomData(r []byte)
|
||||
"runtime.getRandomData": (sp) => {
|
||||
crypto.getRandomValues(loadSlice(sp + 8));
|
||||
},
|
||||
|
||||
// func boolVal(value bool) Value
|
||||
"syscall/js.boolVal": (sp) => {
|
||||
storeValue(sp + 16, mem().getUint8(sp + 8) !== 0);
|
||||
},
|
||||
|
||||
// func intVal(value int) Value
|
||||
"syscall/js.intVal": (sp) => {
|
||||
storeValue(sp + 16, getInt64(sp + 8));
|
||||
},
|
||||
|
||||
// func floatVal(value float64) Value
|
||||
"syscall/js.floatVal": (sp) => {
|
||||
storeValue(sp + 16, mem().getFloat64(sp + 8, true));
|
||||
},
|
||||
|
||||
// func stringVal(value string) Value
|
||||
// func stringVal(value string) ref
|
||||
"syscall/js.stringVal": (sp) => {
|
||||
storeValue(sp + 24, loadString(sp + 8));
|
||||
},
|
||||
|
||||
// func (v Value) Get(key string) Value
|
||||
"syscall/js.Value.Get": (sp) => {
|
||||
// func valueGet(v ref, p string) ref
|
||||
"syscall/js.valueGet": (sp) => {
|
||||
storeValue(sp + 32, Reflect.get(loadValue(sp + 8), loadString(sp + 16)));
|
||||
},
|
||||
|
||||
// func (v Value) set(key string, value Value)
|
||||
"syscall/js.Value.set": (sp) => {
|
||||
// func valueSet(v ref, p string, x ref)
|
||||
"syscall/js.valueSet": (sp) => {
|
||||
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
|
||||
},
|
||||
|
||||
// func (v Value) Index(i int) Value
|
||||
"syscall/js.Value.Index": (sp) => {
|
||||
// func valueIndex(v ref, i int) ref
|
||||
"syscall/js.valueIndex": (sp) => {
|
||||
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
|
||||
},
|
||||
|
||||
// func (v Value) setIndex(i int, value Value)
|
||||
"syscall/js.Value.setIndex": (sp) => {
|
||||
// valueSetIndex(v ref, i int, x ref)
|
||||
"syscall/js.valueSetIndex": (sp) => {
|
||||
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
|
||||
},
|
||||
|
||||
// func (v Value) call(name string, args []Value) (Value, bool)
|
||||
"syscall/js.Value.call": (sp) => {
|
||||
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
||||
"syscall/js.valueCall": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const m = Reflect.get(v, loadString(sp + 16));
|
||||
const args = loadSliceOfValues(sp + 32);
|
||||
storeValue(sp + 56, Reflect.apply(m, v, args));
|
||||
mem().setUint8(sp + 60, 1);
|
||||
mem().setUint8(sp + 64, 1);
|
||||
} catch (err) {
|
||||
storeValue(sp + 56, err);
|
||||
mem().setUint8(sp + 60, 0);
|
||||
mem().setUint8(sp + 64, 0);
|
||||
}
|
||||
},
|
||||
|
||||
// func (v Value) invoke(args []Value) (Value, bool)
|
||||
"syscall/js.Value.invoke": (sp) => {
|
||||
// func valueInvoke(v ref, args []ref) (ref, bool)
|
||||
"syscall/js.valueInvoke": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const args = loadSliceOfValues(sp + 16);
|
||||
storeValue(sp + 40, Reflect.apply(v, undefined, args));
|
||||
mem().setUint8(sp + 44, 1);
|
||||
mem().setUint8(sp + 48, 1);
|
||||
} catch (err) {
|
||||
storeValue(sp + 40, err);
|
||||
mem().setUint8(sp + 44, 0);
|
||||
mem().setUint8(sp + 48, 0);
|
||||
}
|
||||
},
|
||||
|
||||
// func (v Value) new(args []Value) (Value, bool)
|
||||
"syscall/js.Value.new": (sp) => {
|
||||
// func valueNew(v ref, args []ref) (ref, bool)
|
||||
"syscall/js.valueNew": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const args = loadSliceOfValues(sp + 16);
|
||||
storeValue(sp + 40, Reflect.construct(v, args));
|
||||
mem().setUint8(sp + 44, 1);
|
||||
mem().setUint8(sp + 48, 1);
|
||||
} catch (err) {
|
||||
storeValue(sp + 40, err);
|
||||
mem().setUint8(sp + 44, 0);
|
||||
mem().setUint8(sp + 48, 0);
|
||||
}
|
||||
},
|
||||
|
||||
// func (v Value) Float() float64
|
||||
"syscall/js.Value.Float": (sp) => {
|
||||
mem().setFloat64(sp + 16, parseFloat(loadValue(sp + 8)), true);
|
||||
},
|
||||
|
||||
// func (v Value) Int() int
|
||||
"syscall/js.Value.Int": (sp) => {
|
||||
setInt64(sp + 16, parseInt(loadValue(sp + 8)));
|
||||
},
|
||||
|
||||
// func (v Value) Bool() bool
|
||||
"syscall/js.Value.Bool": (sp) => {
|
||||
mem().setUint8(sp + 16, !!loadValue(sp + 8));
|
||||
},
|
||||
|
||||
// func (v Value) Length() int
|
||||
"syscall/js.Value.Length": (sp) => {
|
||||
// func valueLength(v ref) int
|
||||
"syscall/js.valueLength": (sp) => {
|
||||
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
|
||||
},
|
||||
|
||||
// func (v Value) prepareString() (Value, int)
|
||||
"syscall/js.Value.prepareString": (sp) => {
|
||||
// valuePrepareString(v ref) (ref, int)
|
||||
"syscall/js.valuePrepareString": (sp) => {
|
||||
const str = encoder.encode(String(loadValue(sp + 8)));
|
||||
storeValue(sp + 16, str);
|
||||
setInt64(sp + 24, str.length);
|
||||
},
|
||||
|
||||
// func (v Value) loadString(b []byte)
|
||||
"syscall/js.Value.loadString": (sp) => {
|
||||
// valueLoadString(v ref, b []byte)
|
||||
"syscall/js.valueLoadString": (sp) => {
|
||||
const str = loadValue(sp + 8);
|
||||
loadSlice(sp + 16).set(str);
|
||||
},
|
||||
|
||||
// func valueInstanceOf(v ref, t ref) bool
|
||||
"syscall/js.valueInstanceOf": (sp) => {
|
||||
mem().setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16));
|
||||
},
|
||||
|
||||
"debug": (value) => {
|
||||
console.log(value);
|
||||
},
|
||||
|
@ -270,7 +320,25 @@
|
|||
|
||||
async run(instance) {
|
||||
this._inst = instance;
|
||||
this._values = [undefined, null, global, this._inst.exports.mem]; // TODO: garbage collection
|
||||
this._values = [ // TODO: garbage collection
|
||||
NaN,
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
global,
|
||||
this._inst.exports.mem,
|
||||
() => { // resolveCallbackPromise
|
||||
if (this.exited) {
|
||||
throw new Error("bad callback: Go program has already exited");
|
||||
}
|
||||
setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous
|
||||
},
|
||||
];
|
||||
this._stringRefs = new Map();
|
||||
this._symbolRefs = new Map();
|
||||
this._refProp = Symbol();
|
||||
this.exited = false;
|
||||
|
||||
const mem = new DataView(this._inst.exports.mem.buffer)
|
||||
|
||||
|
@ -304,7 +372,16 @@
|
|||
offset += 8;
|
||||
});
|
||||
|
||||
this._inst.exports.run(argc, argv);
|
||||
while (true) {
|
||||
const callbackPromise = new Promise((resolve) => {
|
||||
this._resolveCallbackPromise = resolve;
|
||||
});
|
||||
this._inst.exports.run(argc, argv);
|
||||
if (this.exited) {
|
||||
break;
|
||||
}
|
||||
await callbackPromise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,9 +396,16 @@
|
|||
go.env = process.env;
|
||||
go.exit = process.exit;
|
||||
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
|
||||
process.on("exit", () => { // Node.js exits if no callback is pending
|
||||
if (!go.exited) {
|
||||
console.error("error: all goroutines asleep and no JavaScript callback pending - deadlock!");
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
return go.run(result.instance);
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
go.exited = true;
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -81,9 +81,17 @@ const (
|
|||
// See the zip spec for details.
|
||||
type FileHeader struct {
|
||||
// Name is the name of the file.
|
||||
// It must be a relative path, not start with a drive letter (e.g. C:),
|
||||
//
|
||||
// It must be a relative path, not start with a drive letter (such as "C:"),
|
||||
// and must use forward slashes instead of back slashes. A trailing slash
|
||||
// indicates that this file is a directory and should have no data.
|
||||
//
|
||||
// When reading zip files, the Name field is populated from
|
||||
// the zip file directly and is not validated for correctness.
|
||||
// It is the caller's responsibility to sanitize it as
|
||||
// appropriate, including canonicalizing slash directions,
|
||||
// validating that paths are relative, and preventing path
|
||||
// traversal through filenames ("../../../").
|
||||
Name string
|
||||
|
||||
// Comment is any arbitrary user-defined string shorter than 64KiB.
|
||||
|
|
|
@ -45,14 +45,19 @@ type Scanner struct {
|
|||
// input. The arguments are an initial substring of the remaining unprocessed
|
||||
// data and a flag, atEOF, that reports whether the Reader has no more data
|
||||
// to give. The return values are the number of bytes to advance the input
|
||||
// and the next token to return to the user, plus an error, if any. If the
|
||||
// data does not yet hold a complete token, for instance if it has no newline
|
||||
// while scanning lines, SplitFunc can return (0, nil, nil) to signal the
|
||||
// Scanner to read more data into the slice and try again with a longer slice
|
||||
// starting at the same point in the input.
|
||||
// and the next token to return to the user, if any, plus an error, if any.
|
||||
//
|
||||
// If the returned error is non-nil, scanning stops and the error
|
||||
// is returned to the client.
|
||||
// Scanning stops if the function returns an error, in which case some of
|
||||
// the input may be discarded.
|
||||
//
|
||||
// Otherwise, the Scanner advances the input. If the token is not nil,
|
||||
// the Scanner returns it to the user. If the token is nil, the
|
||||
// Scanner reads more data and continues scanning; if there is no more
|
||||
// data--if atEOF was true--the Scanner returns. If the data does not
|
||||
// yet hold a complete token, for instance if it has no newline while
|
||||
// scanning lines, a SplitFunc can return (0, nil, nil) to signal the
|
||||
// Scanner to read more data into the slice and try again with a
|
||||
// longer slice starting at the same point in the input.
|
||||
//
|
||||
// The function is never called with an empty data slice unless atEOF
|
||||
// is true. If atEOF is true, however, data may be non-empty and,
|
||||
|
|
|
@ -77,7 +77,8 @@ func IsARM64STLXR(op obj.As) bool {
|
|||
arm64.ALDADDB, arm64.ALDADDH, arm64.ALDADDW, arm64.ALDADDD,
|
||||
arm64.ALDANDB, arm64.ALDANDH, arm64.ALDANDW, arm64.ALDANDD,
|
||||
arm64.ALDEORB, arm64.ALDEORH, arm64.ALDEORW, arm64.ALDEORD,
|
||||
arm64.ALDORB, arm64.ALDORH, arm64.ALDORW, arm64.ALDORD:
|
||||
arm64.ALDORB, arm64.ALDORH, arm64.ALDORW, arm64.ALDORD,
|
||||
arm64.ALDADDALD, arm64.ALDADDALW:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
2
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
2
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
@ -604,6 +604,8 @@ again:
|
|||
LDORH R5, (RSP), R7 // e7332578
|
||||
LDORB R5, (R6), R7 // c7302538
|
||||
LDORB R5, (RSP), R7 // e7332538
|
||||
LDADDALD R2, (R1), R3 // 2300e2f8
|
||||
LDADDALW R5, (R4), R6 // 8600e5b8
|
||||
|
||||
// RET
|
||||
//
|
||||
|
|
|
@ -64,6 +64,11 @@ a full argument: to allow -mfoo=bar, use CGO_CFLAGS_ALLOW='-mfoo.*',
|
|||
not just CGO_CFLAGS_ALLOW='-mfoo'. Similarly named variables control
|
||||
the allowed CPPFLAGS, CXXFLAGS, FFLAGS, and LDFLAGS.
|
||||
|
||||
Also for security reasons, only a limited set of characters are
|
||||
permitted, notably alphanumeric characters and a few symbols, such as
|
||||
'.', that will not be interpreted in unexpected ways. Attempts to use
|
||||
forbidden characters will get a "malformed #cgo argument" error.
|
||||
|
||||
When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and
|
||||
CGO_LDFLAGS environment variables are added to the flags derived from
|
||||
these directives. Package-specific flags should be set using the
|
||||
|
@ -223,6 +228,26 @@ C compilers are aware of this calling convention and adjust
|
|||
the call accordingly, but Go cannot. In Go, you must pass
|
||||
the pointer to the first element explicitly: C.f(&C.x[0]).
|
||||
|
||||
Calling variadic C functions is not supported. It is possible to
|
||||
circumvent this by using a C function wrapper. For example:
|
||||
|
||||
package main
|
||||
|
||||
// #include <stdio.h>
|
||||
// #include <stdlib.h>
|
||||
//
|
||||
// static void myprint(char* s) {
|
||||
// printf("%s\n", s);
|
||||
// }
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func main() {
|
||||
cs := C.CString("Hello from stdio")
|
||||
C.myprint(cs)
|
||||
C.free(unsafe.Pointer(cs))
|
||||
}
|
||||
|
||||
A few special functions convert between Go and C types
|
||||
by making copies of the data. In pseudo-Go definitions:
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"go/ast"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -279,6 +280,7 @@ func main() {
|
|||
// concern is other cgo wrappers for the same functions.
|
||||
// Use the beginning of the md5 of the input to disambiguate.
|
||||
h := md5.New()
|
||||
io.WriteString(h, *importPath)
|
||||
fs := make([]*File, len(goFiles))
|
||||
for i, input := range goFiles {
|
||||
if *srcDir != "" {
|
||||
|
|
|
@ -609,14 +609,14 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
|||
// We're trying to write a gcc struct that matches gc's layout.
|
||||
// Use packed attribute to force no padding in this struct in case
|
||||
// gcc has different packing requirements.
|
||||
fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
|
||||
fmt.Fprintf(fgcc, "\t%s %v *_cgo_a = v;\n", ctype, p.packedAttribute())
|
||||
if n.FuncType.Result != nil {
|
||||
// Save the stack top for use below.
|
||||
fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n")
|
||||
fmt.Fprintf(fgcc, "\tchar *_cgo_stktop = _cgo_topofstack();\n")
|
||||
}
|
||||
tr := n.FuncType.Result
|
||||
if tr != nil {
|
||||
fmt.Fprintf(fgcc, "\t__typeof__(a->r) r;\n")
|
||||
fmt.Fprintf(fgcc, "\t__typeof__(_cgo_a->r) _cgo_r;\n")
|
||||
}
|
||||
fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
|
||||
if n.AddError {
|
||||
|
@ -624,9 +624,9 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
|||
}
|
||||
fmt.Fprintf(fgcc, "\t")
|
||||
if tr != nil {
|
||||
fmt.Fprintf(fgcc, "r = ")
|
||||
fmt.Fprintf(fgcc, "_cgo_r = ")
|
||||
if c := tr.C.String(); c[len(c)-1] == '*' {
|
||||
fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
|
||||
fmt.Fprint(fgcc, "(__typeof__(_cgo_a->r)) ")
|
||||
}
|
||||
}
|
||||
if n.Kind == "macro" {
|
||||
|
@ -637,7 +637,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
|||
if i > 0 {
|
||||
fmt.Fprintf(fgcc, ", ")
|
||||
}
|
||||
fmt.Fprintf(fgcc, "a->p%d", i)
|
||||
fmt.Fprintf(fgcc, "_cgo_a->p%d", i)
|
||||
}
|
||||
fmt.Fprintf(fgcc, ");\n")
|
||||
}
|
||||
|
@ -648,9 +648,9 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
|
|||
if n.FuncType.Result != nil {
|
||||
// The cgo call may have caused a stack copy (via a callback).
|
||||
// Adjust the return value pointer appropriately.
|
||||
fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n")
|
||||
fmt.Fprintf(fgcc, "\t_cgo_a = (void*)((char*)_cgo_a + (_cgo_topofstack() - _cgo_stktop));\n")
|
||||
// Save the return value.
|
||||
fmt.Fprintf(fgcc, "\ta->r = r;\n")
|
||||
fmt.Fprintf(fgcc, "\t_cgo_a->r = _cgo_r;\n")
|
||||
}
|
||||
if n.AddError {
|
||||
fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n")
|
||||
|
@ -685,12 +685,12 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
|
|||
fmt.Fprintf(fgcc, ")\n")
|
||||
fmt.Fprintf(fgcc, "{\n")
|
||||
if t := n.FuncType.Result; t != nil {
|
||||
fmt.Fprintf(fgcc, "\t%s r;\n", t.C.String())
|
||||
fmt.Fprintf(fgcc, "\t%s _cgo_r;\n", t.C.String())
|
||||
}
|
||||
fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
|
||||
fmt.Fprintf(fgcc, "\t")
|
||||
if t := n.FuncType.Result; t != nil {
|
||||
fmt.Fprintf(fgcc, "r = ")
|
||||
fmt.Fprintf(fgcc, "_cgo_r = ")
|
||||
// Cast to void* to avoid warnings due to omitted qualifiers.
|
||||
if c := t.C.String(); c[len(c)-1] == '*' {
|
||||
fmt.Fprintf(fgcc, "(void*)")
|
||||
|
@ -716,7 +716,7 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
|
|||
if c := t.C.String(); c[len(c)-1] == '*' {
|
||||
fmt.Fprintf(fgcc, "(void*)")
|
||||
}
|
||||
fmt.Fprintf(fgcc, "r;\n")
|
||||
fmt.Fprintf(fgcc, "_cgo_r;\n")
|
||||
}
|
||||
fmt.Fprintf(fgcc, "}\n")
|
||||
fmt.Fprintf(fgcc, "\n")
|
||||
|
|
|
@ -26,7 +26,7 @@ little to do with uppercase GC, which stands for garbage collection.
|
|||
* `cmd/compile/internal/syntax` (lexer, parser, syntax tree)
|
||||
|
||||
In the first phase of compilation, source code is tokenized (lexical analysis),
|
||||
parsed (syntactic analyses), and a syntax tree is constructed for each source
|
||||
parsed (syntax analysis), and a syntax tree is constructed for each source
|
||||
file.
|
||||
|
||||
Each syntax tree is an exact representation of the respective source file, with
|
||||
|
|
|
@ -553,6 +553,28 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
p3.From.Reg = arm64.REGTMP
|
||||
p3.To.Type = obj.TYPE_BRANCH
|
||||
gc.Patch(p3, p)
|
||||
case ssa.OpARM64LoweredAtomicAdd64Variant,
|
||||
ssa.OpARM64LoweredAtomicAdd32Variant:
|
||||
// LDADDAL Rarg1, (Rarg0), Rout
|
||||
// ADD Rarg1, Rout
|
||||
op := arm64.ALDADDALD
|
||||
if v.Op == ssa.OpARM64LoweredAtomicAdd32Variant {
|
||||
op = arm64.ALDADDALW
|
||||
}
|
||||
r0 := v.Args[0].Reg()
|
||||
r1 := v.Args[1].Reg()
|
||||
out := v.Reg0()
|
||||
p := s.Prog(op)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = r1
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = r0
|
||||
p.RegTo2 = out
|
||||
p1 := s.Prog(arm64.AADD)
|
||||
p1.From.Type = obj.TYPE_REG
|
||||
p1.From.Reg = r1
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = out
|
||||
case ssa.OpARM64LoweredAtomicCas64,
|
||||
ssa.OpARM64LoweredAtomicCas32:
|
||||
// LDAXR (Rarg0), Rtmp
|
||||
|
@ -603,25 +625,26 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
gc.Patch(p2, p5)
|
||||
case ssa.OpARM64LoweredAtomicAnd8,
|
||||
ssa.OpARM64LoweredAtomicOr8:
|
||||
// LDAXRB (Rarg0), Rtmp
|
||||
// AND/OR Rarg1, Rtmp
|
||||
// STLXRB Rtmp, (Rarg0), Rtmp
|
||||
// LDAXRB (Rarg0), Rout
|
||||
// AND/OR Rarg1, Rout
|
||||
// STLXRB Rout, (Rarg0), Rtmp
|
||||
// CBNZ Rtmp, -3(PC)
|
||||
r0 := v.Args[0].Reg()
|
||||
r1 := v.Args[1].Reg()
|
||||
out := v.Reg0()
|
||||
p := s.Prog(arm64.ALDAXRB)
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = r0
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = arm64.REGTMP
|
||||
p.To.Reg = out
|
||||
p1 := s.Prog(v.Op.Asm())
|
||||
p1.From.Type = obj.TYPE_REG
|
||||
p1.From.Reg = r1
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = arm64.REGTMP
|
||||
p1.To.Reg = out
|
||||
p2 := s.Prog(arm64.ASTLXRB)
|
||||
p2.From.Type = obj.TYPE_REG
|
||||
p2.From.Reg = arm64.REGTMP
|
||||
p2.From.Reg = out
|
||||
p2.To.Type = obj.TYPE_MEM
|
||||
p2.To.Reg = r0
|
||||
p2.RegTo2 = arm64.REGTMP
|
||||
|
|
|
@ -1128,16 +1128,20 @@ func (p *exporter) stmtList(list Nodes) {
|
|||
}
|
||||
// TODO inlining produces expressions with ninits. we can't export these yet.
|
||||
// (from fmt.go:1461ff)
|
||||
if opprec[n.Op] < 0 {
|
||||
p.stmt(n)
|
||||
} else {
|
||||
p.expr(n)
|
||||
}
|
||||
p.node(n)
|
||||
}
|
||||
|
||||
p.op(OEND)
|
||||
}
|
||||
|
||||
func (p *exporter) node(n *Node) {
|
||||
if opprec[n.Op] < 0 {
|
||||
p.stmt(n)
|
||||
} else {
|
||||
p.expr(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) exprList(list Nodes) {
|
||||
if p.trace {
|
||||
if list.Len() == 0 {
|
||||
|
@ -1552,7 +1556,7 @@ func (p *exporter) exprsOrNil(a, b *Node) {
|
|||
p.expr(a)
|
||||
}
|
||||
if ab&2 != 0 {
|
||||
p.expr(b)
|
||||
p.node(b)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1209,7 +1209,7 @@ func (p *importer) exprsOrNil() (a, b *Node) {
|
|||
a = p.expr()
|
||||
}
|
||||
if ab&2 != 0 {
|
||||
b = p.expr()
|
||||
b = p.node()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -141,6 +141,7 @@ var runtimeDecls = [...]struct {
|
|||
{"uint32tofloat64", funcTag, 109},
|
||||
{"complex128div", funcTag, 110},
|
||||
{"racefuncenter", funcTag, 111},
|
||||
{"racefuncenterfp", funcTag, 5},
|
||||
{"racefuncexit", funcTag, 5},
|
||||
{"raceread", funcTag, 111},
|
||||
{"racewrite", funcTag, 111},
|
||||
|
|
|
@ -183,6 +183,7 @@ func complex128div(num complex128, den complex128) (quo complex128)
|
|||
|
||||
// race detection
|
||||
func racefuncenter(uintptr)
|
||||
func racefuncenterfp()
|
||||
func racefuncexit()
|
||||
func raceread(uintptr)
|
||||
func racewrite(uintptr)
|
||||
|
|
|
@ -243,15 +243,20 @@ func convlit1(n *Node, t *types.Type, explicit bool, reuse canReuseNode) *Node {
|
|||
n.Type = t
|
||||
}
|
||||
|
||||
if n.Type.Etype == TIDEAL {
|
||||
n.Left = convlit(n.Left, t)
|
||||
n.Right = convlit(n.Right, t)
|
||||
n.Type = t
|
||||
if n.Type.IsUntyped() {
|
||||
if t.IsInterface() {
|
||||
n.Left, n.Right = defaultlit2(n.Left, n.Right, true)
|
||||
n.Type = n.Left.Type // same as n.Right.Type per defaultlit2
|
||||
} else {
|
||||
n.Left = convlit(n.Left, t)
|
||||
n.Right = convlit(n.Right, t)
|
||||
n.Type = t
|
||||
}
|
||||
}
|
||||
|
||||
return n
|
||||
|
||||
// target is invalid type for a constant? leave alone.
|
||||
// target is invalid type for a constant? leave alone.
|
||||
case OLITERAL:
|
||||
if !okforconst[t.Etype] && n.Type.Etype != TNIL {
|
||||
return defaultlitreuse(n, nil, reuse)
|
||||
|
@ -294,7 +299,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, reuse canReuseNode) *Node {
|
|||
return n
|
||||
}
|
||||
|
||||
// avoided repeated calculations, errors
|
||||
// avoid repeated calculations, errors
|
||||
if eqtype(n.Type, t) {
|
||||
return n
|
||||
}
|
||||
|
@ -1266,7 +1271,6 @@ func idealkind(n *Node) Ctype {
|
|||
OOR,
|
||||
OPLUS:
|
||||
k1 := idealkind(n.Left)
|
||||
|
||||
k2 := idealkind(n.Right)
|
||||
if k1 > k2 {
|
||||
return k1
|
||||
|
|
|
@ -151,22 +151,27 @@ func (v *bottomUpVisitor) visitcode(n *Node, min uint32) uint32 {
|
|||
|
||||
// Escape analysis.
|
||||
|
||||
// An escape analysis pass for a set of functions.
|
||||
// The analysis assumes that closures and the functions in which they
|
||||
// appear are analyzed together, so that the aliasing between their
|
||||
// variables can be modeled more precisely.
|
||||
// An escape analysis pass for a set of functions. The
|
||||
// analysis assumes that closures and the functions in which
|
||||
// they appear are analyzed together, so that the aliasing
|
||||
// between their variables can be modeled more precisely.
|
||||
//
|
||||
// First escfunc, esc and escassign recurse over the ast of each
|
||||
// function to dig out flow(dst,src) edges between any
|
||||
// pointer-containing nodes and store them in e.nodeEscState(dst).Flowsrc. For
|
||||
// variables assigned to a variable in an outer scope or used as a
|
||||
// return value, they store a flow(theSink, src) edge to a fake node
|
||||
// 'the Sink'. For variables referenced in closures, an edge
|
||||
// flow(closure, &var) is recorded and the flow of a closure itself to
|
||||
// an outer scope is tracked the same way as other variables.
|
||||
// First escfunc, esc and escassign recurse over the ast of
|
||||
// each function to dig out flow(dst,src) edges between any
|
||||
// pointer-containing nodes and store those edges in
|
||||
// e.nodeEscState(dst).Flowsrc. For values assigned to a
|
||||
// variable in an outer scope or used as a return value,
|
||||
// they store a flow(theSink, src) edge to a fake node 'the
|
||||
// Sink'. For variables referenced in closures, an edge
|
||||
// flow(closure, &var) is recorded and the flow of a closure
|
||||
// itself to an outer scope is tracked the same way as other
|
||||
// variables.
|
||||
//
|
||||
// Then escflood walks the graph starting at theSink and tags all
|
||||
// variables of it can reach an & node as escaping and all function
|
||||
// Then escflood walks the graph in destination-to-source
|
||||
// order, starting at theSink, propagating a computed
|
||||
// "escape level", and tags as escaping values it can
|
||||
// reach that are either & (address-taken) nodes or new(T),
|
||||
// and tags pointer-typed or pointer-containing function
|
||||
// parameters it can reach as leaking.
|
||||
//
|
||||
// If a value's address is taken but the address does not escape,
|
||||
|
@ -185,19 +190,6 @@ const (
|
|||
EscFuncTagged
|
||||
)
|
||||
|
||||
// There appear to be some loops in the escape graph, causing
|
||||
// arbitrary recursion into deeper and deeper levels.
|
||||
// Cut this off safely by making minLevel sticky: once you
|
||||
// get that deep, you cannot go down any further but you also
|
||||
// cannot go up any further. This is a conservative fix.
|
||||
// Making minLevel smaller (more negative) would handle more
|
||||
// complex chains of indirections followed by address-of operations,
|
||||
// at the cost of repeating the traversal once for each additional
|
||||
// allowed level when a loop is encountered. Using -2 suffices to
|
||||
// pass all the tests we have written so far, which we assume matches
|
||||
// the level of complexity we want the escape analysis code to handle.
|
||||
const MinLevel = -2
|
||||
|
||||
// A Level encodes the reference state and context applied to
|
||||
// (stack, heap) allocated memory.
|
||||
//
|
||||
|
@ -205,21 +197,49 @@ const MinLevel = -2
|
|||
// along a path from a destination (sink, return value) to a source
|
||||
// (allocation, parameter).
|
||||
//
|
||||
// suffixValue is the maximum-copy-started-suffix-level applied to a sink.
|
||||
// For example:
|
||||
// sink = x.left.left --> level=2, x is dereferenced twice and does not escape to sink.
|
||||
// sink = &Node{x} --> level=-1, x is accessible from sink via one "address of"
|
||||
// sink = &Node{&Node{x}} --> level=-2, x is accessible from sink via two "address of"
|
||||
// sink = &Node{&Node{x.left}} --> level=-1, but x is NOT accessible from sink because it was indirected and then copied.
|
||||
// (The copy operations are sometimes implicit in the source code; in this case,
|
||||
// value of x.left was copied into a field of a newly allocated Node)
|
||||
// suffixValue is the maximum-copy-started-suffix-level on
|
||||
// a flow path from a sink/destination. That is, a value
|
||||
// with suffixValue N is guaranteed to be dereferenced at least
|
||||
// N deep (chained applications of DOTPTR or IND or INDEX)
|
||||
// before the result is assigned to a sink.
|
||||
//
|
||||
// For example, suppose x is a pointer to T, declared type T struct { left, right *T }
|
||||
// sink = x.left.left --> level(x)=2, x is reached via two dereferences (DOTPTR) and does not escape to sink.
|
||||
// sink = &T{right:x} --> level(x)=-1, x is accessible from sink via one "address of"
|
||||
// sink = &T{right:&T{right:x}} --> level(x)=-2, x is accessible from sink via two "address of"
|
||||
//
|
||||
// However, in the next example x's level value and suffixValue differ:
|
||||
// sink = &T{right:&T{right:x.left}} --> level(x).value=-1, level(x).suffixValue=1
|
||||
// The positive suffixValue indicates that x is NOT accessible
|
||||
// from sink. Without a separate suffixValue to capture this, x would
|
||||
// appear to escape because its "value" would be -1. (The copy
|
||||
// operations are sometimes implicit in the source code; in this case,
|
||||
// the value of x.left was copied into a field of an newly allocated T).
|
||||
//
|
||||
// Each node's level (value and suffixValue) is the maximum for
|
||||
// all flow paths from (any) sink to that node.
|
||||
|
||||
// There's one of these for each Node, and the integer values
|
||||
// rarely exceed even what can be stored in 4 bits, never mind 8.
|
||||
type Level struct {
|
||||
value, suffixValue int8
|
||||
}
|
||||
|
||||
// There are loops in the escape graph,
|
||||
// causing arbitrary recursion into deeper and deeper
|
||||
// levels. Cut this off safely by making minLevel sticky:
|
||||
// once you get that deep, you cannot go down any further
|
||||
// but you also cannot go up any further. This is a
|
||||
// conservative fix. Making minLevel smaller (more negative)
|
||||
// would handle more complex chains of indirections followed
|
||||
// by address-of operations, at the cost of repeating the
|
||||
// traversal once for each additional allowed level when a
|
||||
// loop is encountered. Using -2 suffices to pass all the
|
||||
// tests we have written so far, which we assume matches the
|
||||
// level of complexity we want the escape analysis code to
|
||||
// handle.
|
||||
const MinLevel = -2
|
||||
|
||||
func (l Level) int() int {
|
||||
return int(l.value)
|
||||
}
|
||||
|
@ -269,6 +289,7 @@ func (l Level) dec() Level {
|
|||
}
|
||||
|
||||
// copy returns the level for a copy of a value with level l.
|
||||
// The resulting suffixValue is at least zero, or larger if it was already larger.
|
||||
func (l Level) copy() Level {
|
||||
return Level{value: l.value, suffixValue: max8(l.suffixValue, 0)}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ func dumpexport(bout *bio.Writer) {
|
|||
}
|
||||
|
||||
func importsym(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op) *Node {
|
||||
n := asNode(s.Def)
|
||||
n := asNode(s.PkgDef())
|
||||
if n == nil {
|
||||
// iimport should have created a stub ONONAME
|
||||
// declaration for all imported symbols. The exception
|
||||
|
@ -100,7 +100,7 @@ func importsym(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op) *Node {
|
|||
}
|
||||
|
||||
n = dclname(s)
|
||||
s.Def = asTypesNode(n)
|
||||
s.SetPkgDef(asTypesNode(n))
|
||||
s.Importdef = ipkg
|
||||
}
|
||||
if n.Op != ONONAME && n.Op != op {
|
||||
|
|
|
@ -303,6 +303,7 @@ var (
|
|||
racewriterange,
|
||||
supportPopcnt,
|
||||
supportSSE41,
|
||||
arm64SupportAtomics,
|
||||
typedmemclr,
|
||||
typedmemmove,
|
||||
Udiv,
|
||||
|
|
|
@ -970,15 +970,19 @@ func (w *exportWriter) linkname(s *types.Sym) {
|
|||
|
||||
func (w *exportWriter) stmtList(list Nodes) {
|
||||
for _, n := range list.Slice() {
|
||||
if opprec[n.Op] < 0 {
|
||||
w.stmt(n)
|
||||
} else {
|
||||
w.expr(n)
|
||||
}
|
||||
w.node(n)
|
||||
}
|
||||
w.op(OEND)
|
||||
}
|
||||
|
||||
func (w *exportWriter) node(n *Node) {
|
||||
if opprec[n.Op] < 0 {
|
||||
w.stmt(n)
|
||||
} else {
|
||||
w.expr(n)
|
||||
}
|
||||
}
|
||||
|
||||
// Caution: stmt will emit more than one node for statement nodes n that have a non-empty
|
||||
// n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.).
|
||||
func (w *exportWriter) stmt(n *Node) {
|
||||
|
@ -1338,7 +1342,7 @@ func (w *exportWriter) exprsOrNil(a, b *Node) {
|
|||
w.expr(a)
|
||||
}
|
||||
if ab&2 != 0 {
|
||||
w.expr(b)
|
||||
w.node(b)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,9 +46,7 @@ func expandDecl(n *Node) {
|
|||
return
|
||||
}
|
||||
|
||||
inimport = true
|
||||
r.doDecl(n)
|
||||
inimport = false
|
||||
}
|
||||
|
||||
func expandInline(fn *Node) {
|
||||
|
@ -1060,7 +1058,7 @@ func (r *importReader) exprsOrNil() (a, b *Node) {
|
|||
a = r.expr()
|
||||
}
|
||||
if ab&2 != 0 {
|
||||
b = r.expr()
|
||||
b = r.node()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -132,6 +132,12 @@ func caninl(fn *Node) {
|
|||
return
|
||||
}
|
||||
|
||||
// If marked "go:norace" and -race compilation, don't inline.
|
||||
if flag_race && fn.Func.Pragma&Norace != 0 {
|
||||
reason = "marked go:norace with -race compilation"
|
||||
return
|
||||
}
|
||||
|
||||
// If marked "go:cgo_unsafe_args", don't inline, since the
|
||||
// function makes assumptions about its argument frame layout.
|
||||
if fn.Func.Pragma&CgoUnsafeArgs != 0 {
|
||||
|
|
|
@ -481,15 +481,13 @@ func Main(archInit func(*Arch)) {
|
|||
// Phase 1: const, type, and names and types of funcs.
|
||||
// This will gather all the information about types
|
||||
// and methods but doesn't depend on any of it.
|
||||
// We also defer type alias declarations until phase 2
|
||||
// to avoid cycles like #18640.
|
||||
defercheckwidth()
|
||||
|
||||
// Don't use range--typecheck can add closures to xtop.
|
||||
timings.Start("fe", "typecheck", "top1")
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
n := xtop[i]
|
||||
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
|
||||
if op := n.Op; op != ODCL && op != OAS && op != OAS2 {
|
||||
xtop[i] = typecheck(n, Etop)
|
||||
}
|
||||
}
|
||||
|
@ -501,7 +499,7 @@ func Main(archInit func(*Arch)) {
|
|||
timings.Start("fe", "typecheck", "top2")
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
n := xtop[i]
|
||||
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
|
||||
if op := n.Op; op == ODCL || op == OAS || op == OAS2 {
|
||||
xtop[i] = typecheck(n, Etop)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,10 @@ import (
|
|||
"cmd/internal/src"
|
||||
)
|
||||
|
||||
// parseFiles concurrently parses files into *syntax.File structures.
|
||||
// Each declaration in every *syntax.File is converted to a syntax tree
|
||||
// and its root represented by *Node is appended to xtop.
|
||||
// Returns the total count of parsed lines.
|
||||
func parseFiles(filenames []string) uint {
|
||||
var noders []*noder
|
||||
// Limit the number of simultaneously open files.
|
||||
|
|
|
@ -7,6 +7,7 @@ package gc
|
|||
import (
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
"cmd/internal/sys"
|
||||
)
|
||||
|
||||
// The racewalk pass is currently handled in two parts.
|
||||
|
@ -58,17 +59,23 @@ func instrument(fn *Node) {
|
|||
lno := lineno
|
||||
lineno = src.NoXPos
|
||||
|
||||
// nodpc is the PC of the caller as extracted by
|
||||
// getcallerpc. We use -widthptr(FP) for x86.
|
||||
// BUG: this will not work on arm.
|
||||
nodpc := nodfp.copy()
|
||||
nodpc.Type = types.Types[TUINTPTR]
|
||||
nodpc.Xoffset = int64(-Widthptr)
|
||||
fn.Func.Dcl = append(fn.Func.Dcl, nodpc)
|
||||
|
||||
fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
|
||||
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
|
||||
if thearch.LinkArch.Arch == sys.ArchPPC64LE {
|
||||
fn.Func.Enter.Prepend(mkcall("racefuncenterfp", nil, nil))
|
||||
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
|
||||
} else {
|
||||
|
||||
// nodpc is the PC of the caller as extracted by
|
||||
// getcallerpc. We use -widthptr(FP) for x86.
|
||||
// BUG: This only works for amd64. This will not
|
||||
// work on arm or others that might support
|
||||
// race in the future.
|
||||
nodpc := nodfp.copy()
|
||||
nodpc.Type = types.Types[TUINTPTR]
|
||||
nodpc.Xoffset = int64(-Widthptr)
|
||||
fn.Func.Dcl = append(fn.Func.Dcl, nodpc)
|
||||
fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
|
||||
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
|
||||
}
|
||||
lineno = lno
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,15 @@ func typecheckselect(sel *Node) {
|
|||
ncase.List.Set(nil)
|
||||
switch n.Op {
|
||||
default:
|
||||
yyerrorl(n.Pos, "select case must be receive, send or assign recv")
|
||||
pos := n.Pos
|
||||
if n.Op == ONAME {
|
||||
// We don't have the right position for ONAME nodes (see #15459 and
|
||||
// others). Using ncase.Pos for now as it will provide the correct
|
||||
// line number (assuming the expression follows the "case" keyword
|
||||
// on the same line). This matches the approach before 1.10.
|
||||
pos = ncase.Pos
|
||||
}
|
||||
yyerrorl(pos, "select case must be receive, send or assign recv")
|
||||
|
||||
// convert x = <-c into OSELRECV(x, <-c).
|
||||
// remove implicit conversions; the eventual assignment
|
||||
|
|
|
@ -78,6 +78,7 @@ func initssaconfig() {
|
|||
racewriterange = sysfunc("racewriterange")
|
||||
supportPopcnt = sysfunc("support_popcnt")
|
||||
supportSSE41 = sysfunc("support_sse41")
|
||||
arm64SupportAtomics = sysfunc("arm64_support_atomics")
|
||||
typedmemclr = sysfunc("typedmemclr")
|
||||
typedmemmove = sysfunc("typedmemmove")
|
||||
Udiv = sysfunc("udiv")
|
||||
|
@ -2169,8 +2170,9 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||
p := s.addr(n, false)
|
||||
return s.load(n.Left.Type.Elem(), p)
|
||||
case n.Left.Type.IsArray():
|
||||
if bound := n.Left.Type.NumElem(); bound <= 1 {
|
||||
if canSSAType(n.Left.Type) {
|
||||
// SSA can handle arrays of length at most 1.
|
||||
bound := n.Left.Type.NumElem()
|
||||
a := s.expr(n.Left)
|
||||
i := s.expr(n.Right)
|
||||
if bound == 0 {
|
||||
|
@ -2935,14 +2937,56 @@ func init() {
|
|||
s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
|
||||
return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v)
|
||||
},
|
||||
sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS, sys.MIPS64, sys.PPC64)
|
||||
sys.AMD64, sys.S390X, sys.MIPS, sys.MIPS64, sys.PPC64)
|
||||
addF("runtime/internal/atomic", "Xadd64",
|
||||
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||
v := s.newValue3(ssa.OpAtomicAdd64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], args[1], s.mem())
|
||||
s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
|
||||
return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v)
|
||||
},
|
||||
sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS64, sys.PPC64)
|
||||
sys.AMD64, sys.S390X, sys.MIPS64, sys.PPC64)
|
||||
|
||||
makeXaddARM64 := func(op0 ssa.Op, op1 ssa.Op, ty types.EType) func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||
return func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||
// Target Atomic feature is identified by dynamic detection
|
||||
addr := s.entryNewValue1A(ssa.OpAddr, types.Types[TBOOL].PtrTo(), arm64SupportAtomics, s.sb)
|
||||
v := s.load(types.Types[TBOOL], addr)
|
||||
b := s.endBlock()
|
||||
b.Kind = ssa.BlockIf
|
||||
b.SetControl(v)
|
||||
bTrue := s.f.NewBlock(ssa.BlockPlain)
|
||||
bFalse := s.f.NewBlock(ssa.BlockPlain)
|
||||
bEnd := s.f.NewBlock(ssa.BlockPlain)
|
||||
b.AddEdgeTo(bTrue)
|
||||
b.AddEdgeTo(bFalse)
|
||||
b.Likely = ssa.BranchUnlikely // most machines don't have Atomics nowadays
|
||||
|
||||
// We have atomic instructions - use it directly.
|
||||
s.startBlock(bTrue)
|
||||
v0 := s.newValue3(op1, types.NewTuple(types.Types[ty], types.TypeMem), args[0], args[1], s.mem())
|
||||
s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v0)
|
||||
s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[ty], v0)
|
||||
s.endBlock().AddEdgeTo(bEnd)
|
||||
|
||||
// Use original instruction sequence.
|
||||
s.startBlock(bFalse)
|
||||
v1 := s.newValue3(op0, types.NewTuple(types.Types[ty], types.TypeMem), args[0], args[1], s.mem())
|
||||
s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v1)
|
||||
s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[ty], v1)
|
||||
s.endBlock().AddEdgeTo(bEnd)
|
||||
|
||||
// Merge results.
|
||||
s.startBlock(bEnd)
|
||||
return s.variable(n, types.Types[ty])
|
||||
}
|
||||
}
|
||||
|
||||
addF("runtime/internal/atomic", "Xadd",
|
||||
makeXaddARM64(ssa.OpAtomicAdd32, ssa.OpAtomicAdd32Variant, TUINT32),
|
||||
sys.ARM64)
|
||||
addF("runtime/internal/atomic", "Xadd64",
|
||||
makeXaddARM64(ssa.OpAtomicAdd64, ssa.OpAtomicAdd64Variant, TUINT64),
|
||||
sys.ARM64)
|
||||
|
||||
addF("runtime/internal/atomic", "Cas",
|
||||
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||
|
@ -4985,7 +5029,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||
}
|
||||
buf.WriteString("</dl>")
|
||||
buf.WriteString("</code>")
|
||||
f.HTMLWriter.WriteColumn("genssa", "ssa-prog", buf.String())
|
||||
f.HTMLWriter.WriteColumn("genssa", "genssa", "ssa-prog", buf.String())
|
||||
// pp.Text.Ctxt.LineHist.PrintFilenameOnly = saved
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,6 +241,11 @@ func walkswitch(sw *Node) {
|
|||
// search using if..goto, although binary search
|
||||
// is used with long runs of constants.
|
||||
func (s *exprSwitch) walk(sw *Node) {
|
||||
// Guard against double walk, see #25776.
|
||||
if sw.List.Len() == 0 && sw.Nbody.Len() > 0 {
|
||||
Fatalf("second walk of switch")
|
||||
}
|
||||
|
||||
casebody(sw, nil)
|
||||
|
||||
cond := sw.Left
|
||||
|
|
|
@ -37,7 +37,12 @@ func resolve(n *Node) *Node {
|
|||
}
|
||||
|
||||
if n.Sym.Pkg != localpkg {
|
||||
if inimport {
|
||||
Fatalf("recursive inimport")
|
||||
}
|
||||
inimport = true
|
||||
expandDecl(n)
|
||||
inimport = false
|
||||
return n
|
||||
}
|
||||
|
||||
|
@ -110,19 +115,35 @@ func typekind(t *types.Type) string {
|
|||
return fmt.Sprintf("etype=%d", et)
|
||||
}
|
||||
|
||||
// sprint_depchain prints a dependency chain of nodes into trace.
|
||||
// It is used by typecheck in the case of OLITERAL nodes
|
||||
// to print constant definition loops.
|
||||
func sprint_depchain(trace *string, stack []*Node, cur *Node, first *Node) {
|
||||
for i := len(stack) - 1; i >= 0; i-- {
|
||||
if n := stack[i]; n.Op == cur.Op {
|
||||
if n != first {
|
||||
sprint_depchain(trace, stack[:i], n, first)
|
||||
}
|
||||
*trace += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
|
||||
return
|
||||
func cycleFor(start *Node) []*Node {
|
||||
// Find the start node in typecheck_tcstack.
|
||||
// We know that it must exist because each time we mark
|
||||
// a node with n.SetTypecheck(2) we push it on the stack,
|
||||
// and each time we mark a node with n.SetTypecheck(2) we
|
||||
// pop it from the stack. We hit a cycle when we encounter
|
||||
// a node marked 2 in which case is must be on the stack.
|
||||
i := len(typecheck_tcstack) - 1
|
||||
for i > 0 && typecheck_tcstack[i] != start {
|
||||
i--
|
||||
}
|
||||
|
||||
// collect all nodes with same Op
|
||||
var cycle []*Node
|
||||
for _, n := range typecheck_tcstack[i:] {
|
||||
if n.Op == start.Op {
|
||||
cycle = append(cycle, n)
|
||||
}
|
||||
}
|
||||
|
||||
return cycle
|
||||
}
|
||||
|
||||
func cycleTrace(cycle []*Node) string {
|
||||
var s string
|
||||
for i, n := range cycle {
|
||||
s += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cycle[(i+1)%len(cycle)])
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
var typecheck_tcstack []*Node
|
||||
|
@ -174,10 +195,20 @@ func typecheck(n *Node, top int) *Node {
|
|||
}
|
||||
|
||||
case OTYPE:
|
||||
// Only report a type cycle if we are expecting a type.
|
||||
// Otherwise let other code report an error.
|
||||
if top&Etype == Etype {
|
||||
var trace string
|
||||
sprint_depchain(&trace, typecheck_tcstack, n, n)
|
||||
yyerrorl(n.Pos, "invalid recursive type alias %v%s", n, trace)
|
||||
// A cycle containing only alias types is an error
|
||||
// since it would expand indefinitely when aliases
|
||||
// are substituted.
|
||||
cycle := cycleFor(n)
|
||||
for _, n := range cycle {
|
||||
if n.Name != nil && !n.Name.Param.Alias {
|
||||
lineno = lno
|
||||
return n
|
||||
}
|
||||
}
|
||||
yyerrorl(n.Pos, "invalid recursive type alias %v%s", n, cycleTrace(cycle))
|
||||
}
|
||||
|
||||
case OLITERAL:
|
||||
|
@ -185,9 +216,7 @@ func typecheck(n *Node, top int) *Node {
|
|||
yyerror("%v is not a type", n)
|
||||
break
|
||||
}
|
||||
var trace string
|
||||
sprint_depchain(&trace, typecheck_tcstack, n, n)
|
||||
yyerrorl(n.Pos, "constant definition loop%s", trace)
|
||||
yyerrorl(n.Pos, "constant definition loop%s", cycleTrace(cycleFor(n)))
|
||||
}
|
||||
|
||||
if nsavederrors+nerrors == 0 {
|
||||
|
@ -895,7 +924,7 @@ func typecheck1(n *Node, top int) *Node {
|
|||
yyerror("%v undefined (cannot refer to unexported field or method %v)", n, n.Sym)
|
||||
|
||||
default:
|
||||
if mt := lookdot(n, t, 2); mt != nil { // Case-insensitive lookup.
|
||||
if mt := lookdot(n, t, 2); mt != nil && visible(mt.Sym) { // Case-insensitive lookup.
|
||||
yyerror("%v undefined (type %v has no field or method %v, but does have %v)", n, n.Left.Type, n.Sym, mt.Sym)
|
||||
} else {
|
||||
yyerror("%v undefined (type %v has no field or method %v)", n, n.Left.Type, n.Sym)
|
||||
|
@ -3108,7 +3137,11 @@ func typecheckcomplit(n *Node) *Node {
|
|||
f := lookdot1(nil, l.Sym, t, t.Fields(), 0)
|
||||
if f == nil {
|
||||
if ci := lookdot1(nil, l.Sym, t, t.Fields(), 2); ci != nil { // Case-insensitive lookup.
|
||||
yyerror("unknown field '%v' in struct literal of type %v (but does have %v)", l.Sym, t, ci.Sym)
|
||||
if visible(ci.Sym) {
|
||||
yyerror("unknown field '%v' in struct literal of type %v (but does have %v)", l.Sym, t, ci.Sym)
|
||||
} else {
|
||||
yyerror("unknown field '%v' in struct literal of type %v", l.Sym, t)
|
||||
}
|
||||
continue
|
||||
}
|
||||
p, _ := dotpath(l.Sym, t, nil, true)
|
||||
|
@ -3155,6 +3188,11 @@ func typecheckcomplit(n *Node) *Node {
|
|||
return n
|
||||
}
|
||||
|
||||
// visible reports whether sym is exported or locally defined.
|
||||
func visible(sym *types.Sym) bool {
|
||||
return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == localpkg)
|
||||
}
|
||||
|
||||
// lvalue etc
|
||||
func islvalue(n *Node) bool {
|
||||
switch n.Op {
|
||||
|
|
|
@ -287,7 +287,6 @@ func walkstmt(n *Node) *Node {
|
|||
walkstmtlist(n.Rlist.Slice())
|
||||
|
||||
case ORETURN:
|
||||
walkexprlist(n.List.Slice(), &n.Ninit)
|
||||
if n.List.Len() == 0 {
|
||||
break
|
||||
}
|
||||
|
@ -317,6 +316,9 @@ func walkstmt(n *Node) *Node {
|
|||
|
||||
if samelist(rl, n.List.Slice()) {
|
||||
// special return in disguise
|
||||
// TODO(josharian, 1.12): is "special return" still relevant?
|
||||
// Tests still pass w/o this. See comments on https://go-review.googlesource.com/c/go/+/118318
|
||||
walkexprlist(n.List.Slice(), &n.Ninit)
|
||||
n.List.Set(nil)
|
||||
|
||||
break
|
||||
|
@ -329,6 +331,7 @@ func walkstmt(n *Node) *Node {
|
|||
n.List.Set(reorder3(ll))
|
||||
break
|
||||
}
|
||||
walkexprlist(n.List.Slice(), &n.Ninit)
|
||||
|
||||
ll := ascompatte(nil, false, Curfn.Type.Results(), n.List.Slice(), 1, &n.Ninit)
|
||||
n.List.Set(ll)
|
||||
|
|
|
@ -43,7 +43,7 @@ func Compile(f *Func) {
|
|||
|
||||
// Run all the passes
|
||||
printFunc(f)
|
||||
f.HTMLWriter.WriteFunc("start", f)
|
||||
f.HTMLWriter.WriteFunc("start", "start", f)
|
||||
if BuildDump != "" && BuildDump == f.Name {
|
||||
f.dumpFile("build")
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ func Compile(f *Func) {
|
|||
|
||||
f.Logf(" pass %s end %s\n", p.name, stats)
|
||||
printFunc(f)
|
||||
f.HTMLWriter.WriteFunc(fmt.Sprintf("after %s <span class=\"stats\">%s</span>", phaseName, stats), f)
|
||||
f.HTMLWriter.WriteFunc(phaseName, fmt.Sprintf("%s <span class=\"stats\">%s</span>", phaseName, stats), f)
|
||||
}
|
||||
if p.time || p.mem {
|
||||
// Surround timing information w/ enough context to allow comparisons.
|
||||
|
|
|
@ -397,11 +397,11 @@ func init() {
|
|||
{name: "CMOVQNEF", argLength: 3, reg: gp21, asm: "CMOVQNE", resultInArg0: true},
|
||||
{name: "CMOVQGTF", argLength: 3, reg: gp21, asm: "CMOVQHI", resultInArg0: true},
|
||||
{name: "CMOVQGEF", argLength: 3, reg: gp21, asm: "CMOVQCC", resultInArg0: true},
|
||||
{name: "CMOVLEQF", argLength: 3, reg: gp21, asm: "CMOVLNE", resultInArg0: true},
|
||||
{name: "CMOVLEQF", argLength: 3, reg: gp21pax, asm: "CMOVLNE", resultInArg0: true},
|
||||
{name: "CMOVLNEF", argLength: 3, reg: gp21, asm: "CMOVLNE", resultInArg0: true},
|
||||
{name: "CMOVLGTF", argLength: 3, reg: gp21, asm: "CMOVLHI", resultInArg0: true},
|
||||
{name: "CMOVLGEF", argLength: 3, reg: gp21, asm: "CMOVLCC", resultInArg0: true},
|
||||
{name: "CMOVWEQF", argLength: 3, reg: gp21, asm: "CMOVWNE", resultInArg0: true},
|
||||
{name: "CMOVWEQF", argLength: 3, reg: gp21pax, asm: "CMOVWNE", resultInArg0: true},
|
||||
{name: "CMOVWNEF", argLength: 3, reg: gp21, asm: "CMOVWNE", resultInArg0: true},
|
||||
{name: "CMOVWGTF", argLength: 3, reg: gp21, asm: "CMOVWHI", resultInArg0: true},
|
||||
{name: "CMOVWGEF", argLength: 3, reg: gp21, asm: "CMOVWCC", resultInArg0: true},
|
||||
|
|
|
@ -829,14 +829,14 @@
|
|||
(RSBconst [c] (SUBconst [d] x)) -> (RSBconst [int64(int32(c+d))] x)
|
||||
(RSCconst [c] (ADDconst [d] x) flags) -> (RSCconst [int64(int32(c-d))] x flags)
|
||||
(RSCconst [c] (SUBconst [d] x) flags) -> (RSCconst [int64(int32(c+d))] x flags)
|
||||
(SLLconst [c] (MOVWconst [d])) -> (MOVWconst [int64(uint32(d)<<uint64(c))])
|
||||
(SRLconst [c] (MOVWconst [d])) -> (MOVWconst [int64(uint32(d)>>uint64(c))])
|
||||
(SLLconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(uint32(d)<<uint64(c)))])
|
||||
(SRLconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(uint32(d)>>uint64(c)))])
|
||||
(SRAconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(d)>>uint64(c))])
|
||||
(MUL (MOVWconst [c]) (MOVWconst [d])) -> (MOVWconst [int64(int32(c*d))])
|
||||
(MULA (MOVWconst [c]) (MOVWconst [d]) a) -> (ADDconst [int64(int32(c*d))] a)
|
||||
(MULS (MOVWconst [c]) (MOVWconst [d]) a) -> (SUBconst [int64(int32(c*d))] a)
|
||||
(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) -> (MOVWconst [int64(uint32(c)/uint32(d))])
|
||||
(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) -> (MOVWconst [int64(uint32(c)%uint32(d))])
|
||||
(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) -> (MOVWconst [int64(int32(uint32(c)/uint32(d)))])
|
||||
(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) -> (MOVWconst [int64(int32(uint32(c)%uint32(d)))])
|
||||
(ANDconst [c] (MOVWconst [d])) -> (MOVWconst [c&d])
|
||||
(ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x)
|
||||
(ORconst [c] (MOVWconst [d])) -> (MOVWconst [c|d])
|
||||
|
@ -853,7 +853,7 @@
|
|||
(MOVWreg (MOVWconst [c])) -> (MOVWconst [c])
|
||||
// BFX: Width = c >> 8, LSB = c & 0xff, result = d << (32 - Width - LSB) >> (32 - Width)
|
||||
(BFX [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8)))])
|
||||
(BFXU [c] (MOVWconst [d])) -> (MOVWconst [int64(uint32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8)))])
|
||||
(BFXU [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(uint32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8))))])
|
||||
|
||||
// absorb shifts into ops
|
||||
(ADD x (SLLconst [c] y)) -> (ADDshiftLL x y [c])
|
||||
|
|
|
@ -540,8 +540,12 @@
|
|||
(AtomicCompareAndSwap32 ptr old new_ mem) -> (LoweredAtomicCas32 ptr old new_ mem)
|
||||
(AtomicCompareAndSwap64 ptr old new_ mem) -> (LoweredAtomicCas64 ptr old new_ mem)
|
||||
|
||||
(AtomicAnd8 ptr val mem) -> (LoweredAtomicAnd8 ptr val mem)
|
||||
(AtomicOr8 ptr val mem) -> (LoweredAtomicOr8 ptr val mem)
|
||||
// Currently the updated value is not used, but we need a register to temporarily hold it.
|
||||
(AtomicAnd8 ptr val mem) -> (Select1 (LoweredAtomicAnd8 ptr val mem))
|
||||
(AtomicOr8 ptr val mem) -> (Select1 (LoweredAtomicOr8 ptr val mem))
|
||||
|
||||
(AtomicAdd32Variant ptr val mem) -> (LoweredAtomicAdd32Variant ptr val mem)
|
||||
(AtomicAdd64Variant ptr val mem) -> (LoweredAtomicAdd64Variant ptr val mem)
|
||||
|
||||
// Write barrier.
|
||||
(WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
|
||||
|
|
|
@ -578,6 +578,13 @@ func init() {
|
|||
{name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
|
||||
{name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
|
||||
|
||||
// atomic add variant.
|
||||
// *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
|
||||
// LDADDAL (Rarg0), Rarg1, Rout
|
||||
// ADD Rarg1, Rout
|
||||
{name: "LoweredAtomicAdd64Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
|
||||
{name: "LoweredAtomicAdd32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
|
||||
|
||||
// atomic compare and swap.
|
||||
// arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory. auxint must be zero.
|
||||
// if *arg0 == arg1 {
|
||||
|
@ -596,13 +603,13 @@ func init() {
|
|||
{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
|
||||
|
||||
// atomic and/or.
|
||||
// *arg0 &= (|=) arg1. arg2=mem. returns memory. auxint must be zero.
|
||||
// LDAXRB (Rarg0), Rtmp
|
||||
// AND/OR Rarg1, Rtmp
|
||||
// STLXRB Rtmp, (Rarg0), Rtmp
|
||||
// *arg0 &= (|=) arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
|
||||
// LDAXRB (Rarg0), Rout
|
||||
// AND/OR Rarg1, Rout
|
||||
// STLXRB Rout, (Rarg0), Rtmp
|
||||
// CBNZ Rtmp, -3(PC)
|
||||
{name: "LoweredAtomicAnd8", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
|
||||
{name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "ORR", faultOnNilArg0: true, hasSideEffects: true},
|
||||
{name: "LoweredAtomicAnd8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AND", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true},
|
||||
{name: "LoweredAtomicOr8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true},
|
||||
|
||||
// LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
|
||||
// It saves all GP registers if necessary,
|
||||
|
|
|
@ -390,6 +390,7 @@
|
|||
(I64AddConst [0] x) -> x
|
||||
(I64Eqz (I64Eqz (I64Eqz x))) -> (I64Eqz x)
|
||||
|
||||
// folding offset into load/store
|
||||
((I64Load|I64Load32U|I64Load32S|I64Load16U|I64Load16S|I64Load8U|I64Load8S) [off] (I64AddConst [off2] ptr) mem)
|
||||
&& isU32Bit(off+off2) ->
|
||||
((I64Load|I64Load32U|I64Load32S|I64Load16U|I64Load16S|I64Load8U|I64Load8S) [off+off2] ptr mem)
|
||||
|
@ -397,3 +398,7 @@
|
|||
((I64Store|I64Store32|I64Store16|I64Store8) [off] (I64AddConst [off2] ptr) val mem)
|
||||
&& isU32Bit(off+off2) ->
|
||||
((I64Store|I64Store32|I64Store16|I64Store8) [off+off2] ptr val mem)
|
||||
|
||||
// folding offset into address
|
||||
(I64AddConst [off] (LoweredAddr {sym} [off2] base)) && isU32Bit(off+off2) ->
|
||||
(LoweredAddr {sym} [off+off2] base)
|
||||
|
|
|
@ -103,7 +103,7 @@ func init() {
|
|||
{name: "LoweredClosureCall", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp, 0}, clobbers: callerSave}, aux: "Int64", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "LoweredInterCall", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
|
||||
{name: "LoweredAddr", argLength: 1, reg: gp11, aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // returns base+aux, arg0=base
|
||||
{name: "LoweredAddr", argLength: 1, reg: gp11, aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // returns base+aux+auxint, arg0=base
|
||||
{name: "LoweredMove", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp}}, aux: "Int64"}, // large move. arg0=dst, arg1=src, arg2=mem, auxint=len/8, returns mem
|
||||
{name: "LoweredZero", argLength: 2, reg: regInfo{inputs: []regMask{gp}}, aux: "Int64"}, // large zeroing. arg0=start, arg1=mem, auxint=len/8, returns mem
|
||||
|
||||
|
|
|
@ -515,6 +515,13 @@ var genericOps = []opData{
|
|||
{name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
|
||||
{name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
|
||||
|
||||
// Atomic operation variants
|
||||
// These variants have the same semantics as above atomic operations.
|
||||
// But they are used for generating more efficient code on certain modern machines, with run-time CPU feature detection.
|
||||
// Currently, they are used on ARM64 only.
|
||||
{name: "AtomicAdd32Variant", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
|
||||
{name: "AtomicAdd64Variant", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
|
||||
|
||||
// Clobber experiment op
|
||||
{name: "Clobber", argLength: 0, typ: "Void", aux: "SymOff", symEffect: "None"}, // write an invalid pointer value to the given pointer slot of a stack variable
|
||||
}
|
||||
|
|
|
@ -38,6 +38,11 @@ func (w *HTMLWriter) start(name string) {
|
|||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<style>
|
||||
|
||||
body {
|
||||
font-size: 14px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
#helplink {
|
||||
margin-bottom: 15px;
|
||||
display: block;
|
||||
|
@ -66,6 +71,32 @@ th, td {
|
|||
padding: 5px;
|
||||
}
|
||||
|
||||
td > h2 {
|
||||
cursor: pointer;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
td.collapsed {
|
||||
font-size: 12px;
|
||||
width: 12px;
|
||||
border: 0px;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
td.collapsed div {
|
||||
-moz-transform: rotate(-90.0deg); /* FF3.5+ */
|
||||
-o-transform: rotate(-90.0deg); /* Opera 10.5 */
|
||||
-webkit-transform: rotate(-90.0deg); /* Saf3.1+, Chrome */
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083); /* IE6,IE7 */
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; /* IE8 */
|
||||
margin-top: 10.3em;
|
||||
margin-left: -10em;
|
||||
margin-right: -10em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
td.ssa-prog {
|
||||
width: 600px;
|
||||
word-wrap: break-word;
|
||||
|
@ -131,14 +162,18 @@ dd.ssa-prog {
|
|||
font-size: 11px;
|
||||
}
|
||||
|
||||
.highlight-yellow { background-color: yellow; }
|
||||
.highlight-aquamarine { background-color: aquamarine; }
|
||||
.highlight-coral { background-color: coral; }
|
||||
.highlight-lightpink { background-color: lightpink; }
|
||||
.highlight-lightsteelblue { background-color: lightsteelblue; }
|
||||
.highlight-palegreen { background-color: palegreen; }
|
||||
.highlight-powderblue { background-color: powderblue; }
|
||||
.highlight-skyblue { background-color: skyblue; }
|
||||
.highlight-lightgray { background-color: lightgray; }
|
||||
.highlight-yellow { background-color: yellow; }
|
||||
.highlight-lime { background-color: lime; }
|
||||
.highlight-khaki { background-color: khaki; }
|
||||
.highlight-aqua { background-color: aqua; }
|
||||
.highlight-salmon { background-color: salmon; }
|
||||
|
||||
.outline-blue { outline: blue solid 2px; }
|
||||
.outline-red { outline: red solid 2px; }
|
||||
|
@ -147,6 +182,10 @@ dd.ssa-prog {
|
|||
.outline-fuchsia { outline: fuchsia solid 2px; }
|
||||
.outline-sienna { outline: sienna solid 2px; }
|
||||
.outline-gold { outline: gold solid 2px; }
|
||||
.outline-orangered { outline: orangered solid 2px; }
|
||||
.outline-teal { outline: teal solid 2px; }
|
||||
.outline-maroon { outline: maroon solid 2px; }
|
||||
.outline-black { outline: black solid 2px; }
|
||||
|
||||
</style>
|
||||
|
||||
|
@ -158,8 +197,13 @@ var highlights = [
|
|||
"highlight-lightpink",
|
||||
"highlight-lightsteelblue",
|
||||
"highlight-palegreen",
|
||||
"highlight-skyblue",
|
||||
"highlight-lightgray",
|
||||
"highlight-yellow"
|
||||
"highlight-yellow",
|
||||
"highlight-lime",
|
||||
"highlight-khaki",
|
||||
"highlight-aqua",
|
||||
"highlight-salmon"
|
||||
];
|
||||
|
||||
// state: which value is highlighted this color?
|
||||
|
@ -176,7 +220,11 @@ var outlines = [
|
|||
"outline-darkolivegreen",
|
||||
"outline-fuchsia",
|
||||
"outline-sienna",
|
||||
"outline-gold"
|
||||
"outline-gold",
|
||||
"outline-orangered",
|
||||
"outline-teal",
|
||||
"outline-maroon",
|
||||
"outline-black"
|
||||
];
|
||||
|
||||
// state: which value is outlined this color?
|
||||
|
@ -263,6 +311,56 @@ window.onload = function() {
|
|||
for (var i = 0; i < ssablocks.length; i++) {
|
||||
ssablocks[i].addEventListener('click', ssaBlockClicked);
|
||||
}
|
||||
var expandedDefault = [
|
||||
"start",
|
||||
"deadcode",
|
||||
"opt",
|
||||
"lower",
|
||||
"late deadcode",
|
||||
"regalloc",
|
||||
"genssa",
|
||||
]
|
||||
function isExpDefault(id) {
|
||||
for (var i = 0; i < expandedDefault.length; i++) {
|
||||
if (id.startsWith(expandedDefault[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function toggler(phase) {
|
||||
return function() {
|
||||
toggle_cell(phase+'-col');
|
||||
toggle_cell(phase+'-exp');
|
||||
};
|
||||
}
|
||||
function toggle_cell(id) {
|
||||
var e = document.getElementById(id);
|
||||
if(e.style.display == 'table-cell')
|
||||
e.style.display = 'none';
|
||||
else
|
||||
e.style.display = 'table-cell';
|
||||
}
|
||||
|
||||
var td = document.getElementsByTagName("td");
|
||||
for (var i = 0; i < td.length; i++) {
|
||||
var id = td[i].id;
|
||||
var def = isExpDefault(id);
|
||||
var phase = id.substr(0, id.length-4);
|
||||
if (id.endsWith("-exp")) {
|
||||
var h2 = td[i].getElementsByTagName("h2");
|
||||
if (h2 && h2[0]) {
|
||||
h2[0].addEventListener('click', toggler(phase));
|
||||
}
|
||||
} else {
|
||||
td[i].addEventListener('click', toggler(phase));
|
||||
}
|
||||
if (id.endsWith("-col") && def || id.endsWith("-exp") && !def) {
|
||||
td[i].style.display = 'none';
|
||||
continue
|
||||
}
|
||||
td[i].style.display = 'table-cell';
|
||||
}
|
||||
};
|
||||
|
||||
function toggle_visibility(id) {
|
||||
|
@ -316,24 +414,28 @@ func (w *HTMLWriter) Close() {
|
|||
}
|
||||
|
||||
// WriteFunc writes f in a column headed by title.
|
||||
func (w *HTMLWriter) WriteFunc(title string, f *Func) {
|
||||
func (w *HTMLWriter) WriteFunc(phase, title string, f *Func) {
|
||||
if w == nil {
|
||||
return // avoid generating HTML just to discard it
|
||||
}
|
||||
w.WriteColumn(title, "", f.HTML())
|
||||
w.WriteColumn(phase, title, "", f.HTML())
|
||||
// TODO: Add visual representation of f's CFG.
|
||||
}
|
||||
|
||||
// WriteColumn writes raw HTML in a column headed by title.
|
||||
// It is intended for pre- and post-compilation log output.
|
||||
func (w *HTMLWriter) WriteColumn(title, class, html string) {
|
||||
func (w *HTMLWriter) WriteColumn(phase, title, class, html string) {
|
||||
if w == nil {
|
||||
return
|
||||
}
|
||||
id := strings.Replace(phase, " ", "-", -1)
|
||||
// collapsed column
|
||||
w.Printf("<td id=\"%v-col\" class=\"collapsed\"><div>%v</div></td>", id, phase)
|
||||
|
||||
if class == "" {
|
||||
w.WriteString("<td>")
|
||||
w.Printf("<td id=\"%v-exp\">", id)
|
||||
} else {
|
||||
w.WriteString("<td class=\"" + class + "\">")
|
||||
w.Printf("<td id=\"%v-exp\" class=\"%v\">", id, class)
|
||||
}
|
||||
w.WriteString("<h2>" + title + "</h2>")
|
||||
w.WriteString(html)
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssa
|
||||
|
||||
import "fmt"
|
||||
|
@ -154,7 +158,7 @@ nextb:
|
|||
// if the increment is ±1 or when the limits are constants.
|
||||
if inc.AuxInt != 1 && inc.AuxInt != -1 {
|
||||
ok := false
|
||||
if min.Op == OpConst64 && max.Op == OpConst64 {
|
||||
if min.Op == OpConst64 && max.Op == OpConst64 && inc.AuxInt != 0 {
|
||||
if max.AuxInt > min.AuxInt && max.AuxInt%inc.AuxInt == min.AuxInt%inc.AuxInt { // handle overflow
|
||||
ok = true
|
||||
}
|
||||
|
|
|
@ -1275,6 +1275,8 @@ const (
|
|||
OpARM64LoweredAtomicExchange32
|
||||
OpARM64LoweredAtomicAdd64
|
||||
OpARM64LoweredAtomicAdd32
|
||||
OpARM64LoweredAtomicAdd64Variant
|
||||
OpARM64LoweredAtomicAdd32Variant
|
||||
OpARM64LoweredAtomicCas64
|
||||
OpARM64LoweredAtomicCas32
|
||||
OpARM64LoweredAtomicAnd8
|
||||
|
@ -2287,6 +2289,8 @@ const (
|
|||
OpAtomicCompareAndSwap64
|
||||
OpAtomicAnd8
|
||||
OpAtomicOr8
|
||||
OpAtomicAdd32Variant
|
||||
OpAtomicAdd64Variant
|
||||
OpClobber
|
||||
)
|
||||
|
||||
|
@ -7952,11 +7956,12 @@ var opcodeTable = [...]opInfo{
|
|||
asm: x86.ACMOVLNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
clobbers: 1, // AX
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -8012,11 +8017,12 @@ var opcodeTable = [...]opInfo{
|
|||
asm: x86.ACMOVWNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
clobbers: 1, // AX
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -16722,6 +16728,38 @@ var opcodeTable = [...]opInfo{
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "LoweredAtomicAdd64Variant",
|
||||
argLen: 3,
|
||||
resultNotInArgs: true,
|
||||
faultOnNilArg0: true,
|
||||
hasSideEffects: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
{0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "LoweredAtomicAdd32Variant",
|
||||
argLen: 3,
|
||||
resultNotInArgs: true,
|
||||
faultOnNilArg0: true,
|
||||
hasSideEffects: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
{0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "LoweredAtomicCas64",
|
||||
argLen: 4,
|
||||
|
@ -16759,29 +16797,37 @@ var opcodeTable = [...]opInfo{
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "LoweredAtomicAnd8",
|
||||
argLen: 3,
|
||||
faultOnNilArg0: true,
|
||||
hasSideEffects: true,
|
||||
asm: arm64.AAND,
|
||||
name: "LoweredAtomicAnd8",
|
||||
argLen: 3,
|
||||
resultNotInArgs: true,
|
||||
faultOnNilArg0: true,
|
||||
hasSideEffects: true,
|
||||
asm: arm64.AAND,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
{0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "LoweredAtomicOr8",
|
||||
argLen: 3,
|
||||
faultOnNilArg0: true,
|
||||
hasSideEffects: true,
|
||||
asm: arm64.AORR,
|
||||
name: "LoweredAtomicOr8",
|
||||
argLen: 3,
|
||||
resultNotInArgs: true,
|
||||
faultOnNilArg0: true,
|
||||
hasSideEffects: true,
|
||||
asm: arm64.AORR,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
{0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -27817,6 +27863,18 @@ var opcodeTable = [...]opInfo{
|
|||
hasSideEffects: true,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "AtomicAdd32Variant",
|
||||
argLen: 3,
|
||||
hasSideEffects: true,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "AtomicAdd64Variant",
|
||||
argLen: 3,
|
||||
hasSideEffects: true,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Clobber",
|
||||
auxType: auxSymOff,
|
||||
|
|
|
@ -4044,7 +4044,7 @@ func rewriteValueARM_OpARMBFX_0(v *Value) bool {
|
|||
func rewriteValueARM_OpARMBFXU_0(v *Value) bool {
|
||||
// match: (BFXU [c] (MOVWconst [d]))
|
||||
// cond:
|
||||
// result: (MOVWconst [int64(uint32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8)))])
|
||||
// result: (MOVWconst [int64(int32(uint32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8))))])
|
||||
for {
|
||||
c := v.AuxInt
|
||||
v_0 := v.Args[0]
|
||||
|
@ -4053,7 +4053,7 @@ func rewriteValueARM_OpARMBFXU_0(v *Value) bool {
|
|||
}
|
||||
d := v_0.AuxInt
|
||||
v.reset(OpARMMOVWconst)
|
||||
v.AuxInt = int64(uint32(d) << (32 - uint32(c&0xff) - uint32(c>>8)) >> (32 - uint32(c>>8)))
|
||||
v.AuxInt = int64(int32(uint32(d) << (32 - uint32(c&0xff) - uint32(c>>8)) >> (32 - uint32(c>>8))))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -14103,7 +14103,7 @@ func rewriteValueARM_OpARMSLL_0(v *Value) bool {
|
|||
func rewriteValueARM_OpARMSLLconst_0(v *Value) bool {
|
||||
// match: (SLLconst [c] (MOVWconst [d]))
|
||||
// cond:
|
||||
// result: (MOVWconst [int64(uint32(d)<<uint64(c))])
|
||||
// result: (MOVWconst [int64(int32(uint32(d)<<uint64(c)))])
|
||||
for {
|
||||
c := v.AuxInt
|
||||
v_0 := v.Args[0]
|
||||
|
@ -14112,7 +14112,7 @@ func rewriteValueARM_OpARMSLLconst_0(v *Value) bool {
|
|||
}
|
||||
d := v_0.AuxInt
|
||||
v.reset(OpARMMOVWconst)
|
||||
v.AuxInt = int64(uint32(d) << uint64(c))
|
||||
v.AuxInt = int64(int32(uint32(d) << uint64(c)))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -14274,7 +14274,7 @@ func rewriteValueARM_OpARMSRL_0(v *Value) bool {
|
|||
func rewriteValueARM_OpARMSRLconst_0(v *Value) bool {
|
||||
// match: (SRLconst [c] (MOVWconst [d]))
|
||||
// cond:
|
||||
// result: (MOVWconst [int64(uint32(d)>>uint64(c))])
|
||||
// result: (MOVWconst [int64(int32(uint32(d)>>uint64(c)))])
|
||||
for {
|
||||
c := v.AuxInt
|
||||
v_0 := v.Args[0]
|
||||
|
@ -14283,7 +14283,7 @@ func rewriteValueARM_OpARMSRLconst_0(v *Value) bool {
|
|||
}
|
||||
d := v_0.AuxInt
|
||||
v.reset(OpARMMOVWconst)
|
||||
v.AuxInt = int64(uint32(d) >> uint64(c))
|
||||
v.AuxInt = int64(int32(uint32(d) >> uint64(c)))
|
||||
return true
|
||||
}
|
||||
// match: (SRLconst (SLLconst x [c]) [d])
|
||||
|
@ -21295,7 +21295,7 @@ func rewriteValueARM_OpSelect0_0(v *Value) bool {
|
|||
}
|
||||
// match: (Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d])))
|
||||
// cond:
|
||||
// result: (MOVWconst [int64(uint32(c)/uint32(d))])
|
||||
// result: (MOVWconst [int64(int32(uint32(c)/uint32(d)))])
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpARMCALLudiv {
|
||||
|
@ -21313,7 +21313,7 @@ func rewriteValueARM_OpSelect0_0(v *Value) bool {
|
|||
}
|
||||
d := v_0_1.AuxInt
|
||||
v.reset(OpARMMOVWconst)
|
||||
v.AuxInt = int64(uint32(c) / uint32(d))
|
||||
v.AuxInt = int64(int32(uint32(c) / uint32(d)))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -21364,7 +21364,7 @@ func rewriteValueARM_OpSelect1_0(v *Value) bool {
|
|||
}
|
||||
// match: (Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d])))
|
||||
// cond:
|
||||
// result: (MOVWconst [int64(uint32(c)%uint32(d))])
|
||||
// result: (MOVWconst [int64(int32(uint32(c)%uint32(d)))])
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpARMCALLudiv {
|
||||
|
@ -21382,7 +21382,7 @@ func rewriteValueARM_OpSelect1_0(v *Value) bool {
|
|||
}
|
||||
d := v_0_1.AuxInt
|
||||
v.reset(OpARMMOVWconst)
|
||||
v.AuxInt = int64(uint32(c) % uint32(d))
|
||||
v.AuxInt = int64(int32(uint32(c) % uint32(d)))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -341,8 +341,12 @@ func rewriteValueARM64(v *Value) bool {
|
|||
return rewriteValueARM64_OpAndB_0(v)
|
||||
case OpAtomicAdd32:
|
||||
return rewriteValueARM64_OpAtomicAdd32_0(v)
|
||||
case OpAtomicAdd32Variant:
|
||||
return rewriteValueARM64_OpAtomicAdd32Variant_0(v)
|
||||
case OpAtomicAdd64:
|
||||
return rewriteValueARM64_OpAtomicAdd64_0(v)
|
||||
case OpAtomicAdd64Variant:
|
||||
return rewriteValueARM64_OpAtomicAdd64Variant_0(v)
|
||||
case OpAtomicAnd8:
|
||||
return rewriteValueARM64_OpAtomicAnd8_0(v)
|
||||
case OpAtomicCompareAndSwap32:
|
||||
|
@ -25908,6 +25912,22 @@ func rewriteValueARM64_OpAtomicAdd32_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM64_OpAtomicAdd32Variant_0(v *Value) bool {
|
||||
// match: (AtomicAdd32Variant ptr val mem)
|
||||
// cond:
|
||||
// result: (LoweredAtomicAdd32Variant ptr val mem)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(OpARM64LoweredAtomicAdd32Variant)
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM64_OpAtomicAdd64_0(v *Value) bool {
|
||||
// match: (AtomicAdd64 ptr val mem)
|
||||
// cond:
|
||||
|
@ -25924,22 +25944,44 @@ func rewriteValueARM64_OpAtomicAdd64_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM64_OpAtomicAnd8_0(v *Value) bool {
|
||||
// match: (AtomicAnd8 ptr val mem)
|
||||
func rewriteValueARM64_OpAtomicAdd64Variant_0(v *Value) bool {
|
||||
// match: (AtomicAdd64Variant ptr val mem)
|
||||
// cond:
|
||||
// result: (LoweredAtomicAnd8 ptr val mem)
|
||||
// result: (LoweredAtomicAdd64Variant ptr val mem)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(OpARM64LoweredAtomicAnd8)
|
||||
v.reset(OpARM64LoweredAtomicAdd64Variant)
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM64_OpAtomicAnd8_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
typ := &b.Func.Config.Types
|
||||
_ = typ
|
||||
// match: (AtomicAnd8 ptr val mem)
|
||||
// cond:
|
||||
// result: (Select1 (LoweredAtomicAnd8 ptr val mem))
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(OpSelect1)
|
||||
v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicAnd8, types.NewTuple(typ.UInt8, types.TypeMem))
|
||||
v0.AddArg(ptr)
|
||||
v0.AddArg(val)
|
||||
v0.AddArg(mem)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM64_OpAtomicCompareAndSwap32_0(v *Value) bool {
|
||||
// match: (AtomicCompareAndSwap32 ptr old new_ mem)
|
||||
// cond:
|
||||
|
@ -26051,18 +26093,24 @@ func rewriteValueARM64_OpAtomicLoadPtr_0(v *Value) bool {
|
|||
}
|
||||
}
|
||||
func rewriteValueARM64_OpAtomicOr8_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
typ := &b.Func.Config.Types
|
||||
_ = typ
|
||||
// match: (AtomicOr8 ptr val mem)
|
||||
// cond:
|
||||
// result: (LoweredAtomicOr8 ptr val mem)
|
||||
// result: (Select1 (LoweredAtomicOr8 ptr val mem))
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(OpARM64LoweredAtomicOr8)
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
v.reset(OpSelect1)
|
||||
v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicOr8, types.NewTuple(typ.UInt8, types.TypeMem))
|
||||
v0.AddArg(ptr)
|
||||
v0.AddArg(val)
|
||||
v0.AddArg(mem)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5210,6 +5210,27 @@ func rewriteValueWasm_OpWasmI64AddConst_0(v *Value) bool {
|
|||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (I64AddConst [off] (LoweredAddr {sym} [off2] base))
|
||||
// cond: isU32Bit(off+off2)
|
||||
// result: (LoweredAddr {sym} [off+off2] base)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpWasmLoweredAddr {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
sym := v_0.Aux
|
||||
base := v_0.Args[0]
|
||||
if !(isU32Bit(off + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpWasmLoweredAddr)
|
||||
v.AuxInt = off + off2
|
||||
v.Aux = sym
|
||||
v.AddArg(base)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueWasm_OpWasmI64And_0(v *Value) bool {
|
||||
|
|
|
@ -310,6 +310,7 @@ func storeOrder(values []*Value, sset *sparseSet, storeNumber []int32) []*Value
|
|||
// A constant bound allows this to be stack-allocated. 64 is
|
||||
// enough to cover almost every storeOrder call.
|
||||
stores := make([]*Value, 0, 64)
|
||||
var vardefs map[interface{}]*Value // OpAddr must depend on Vardef for Node
|
||||
hasNilCheck := false
|
||||
sset.clear() // sset is the set of stores that are used in other values
|
||||
for _, v := range values {
|
||||
|
@ -323,6 +324,12 @@ func storeOrder(values []*Value, sset *sparseSet, storeNumber []int32) []*Value
|
|||
if v.Op == OpNilCheck {
|
||||
hasNilCheck = true
|
||||
}
|
||||
if v.Op == OpVarDef {
|
||||
if vardefs == nil { // Lazy init, not all blocks have vardefs
|
||||
vardefs = make(map[interface{}]*Value)
|
||||
}
|
||||
vardefs[v.Aux] = v
|
||||
}
|
||||
}
|
||||
if len(stores) == 0 || !hasNilCheck && f.pass.name == "nilcheckelim" {
|
||||
// there is no store, the order does not matter
|
||||
|
@ -386,7 +393,20 @@ func storeOrder(values []*Value, sset *sparseSet, storeNumber []int32) []*Value
|
|||
stack = stack[:len(stack)-1]
|
||||
continue
|
||||
}
|
||||
|
||||
if w.Op == OpAddr {
|
||||
// OpAddr depends only on relevant VarDef
|
||||
vn := int32(0)
|
||||
if vardefs != nil {
|
||||
if a := vardefs[w.Aux]; a != nil { // if nil, it is in some other block, or global or arg
|
||||
vn = storeNumber[a.ID]
|
||||
}
|
||||
}
|
||||
vn += 2
|
||||
storeNumber[w.ID] = vn
|
||||
count[vn]++
|
||||
stack = stack[:len(stack)-1]
|
||||
continue
|
||||
}
|
||||
max := int32(0) // latest store dependency
|
||||
argsdone := true
|
||||
for _, a := range w.Args {
|
||||
|
|
|
@ -80,15 +80,24 @@ func IsDclstackValid() bool {
|
|||
|
||||
// PkgDef returns the definition associated with s at package scope.
|
||||
func (s *Sym) PkgDef() *Node {
|
||||
return *s.pkgDefPtr()
|
||||
}
|
||||
|
||||
// SetPkgDef sets the definition associated with s at package scope.
|
||||
func (s *Sym) SetPkgDef(n *Node) {
|
||||
*s.pkgDefPtr() = n
|
||||
}
|
||||
|
||||
func (s *Sym) pkgDefPtr() **Node {
|
||||
// Look for outermost saved declaration, which must be the
|
||||
// package scope definition, if present.
|
||||
for _, d := range dclstack {
|
||||
if s == d.sym {
|
||||
return d.def
|
||||
return &d.def
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, the declaration hasn't been shadowed within a
|
||||
// function scope.
|
||||
return s.Def
|
||||
return &s.Def
|
||||
}
|
||||
|
|
|
@ -232,19 +232,13 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value) {
|
|||
|
||||
case ssa.OpWasmLoweredAddr:
|
||||
p := s.Prog(wasm.AGet)
|
||||
switch n := v.Aux.(type) {
|
||||
p.From.Type = obj.TYPE_ADDR
|
||||
switch v.Aux.(type) {
|
||||
case *obj.LSym:
|
||||
p.From = obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN, Sym: n}
|
||||
gc.AddAux(&p.From, v)
|
||||
case *gc.Node:
|
||||
p.From = obj.Addr{
|
||||
Type: obj.TYPE_ADDR,
|
||||
Name: obj.NAME_AUTO,
|
||||
Reg: v.Args[0].Reg(),
|
||||
Offset: n.Xoffset,
|
||||
}
|
||||
if n.Class() == gc.PPARAM || n.Class() == gc.PPARAMOUT {
|
||||
p.From.Name = obj.NAME_PARAM
|
||||
}
|
||||
p.From.Reg = v.Args[0].Reg()
|
||||
gc.AddAux(&p.From, v)
|
||||
default:
|
||||
panic("wasm: bad LoweredAddr")
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
@ -267,9 +266,6 @@ func TestCoverFunc(t *testing.T) {
|
|||
// Check that cover produces correct HTML.
|
||||
// Issue #25767.
|
||||
func TestCoverHTML(t *testing.T) {
|
||||
if _, err := exec.LookPath("diff"); err != nil {
|
||||
t.Skipf("skip test on %s: diff command is required", runtime.GOOS)
|
||||
}
|
||||
testenv.MustHaveGoBuild(t)
|
||||
if !*debug {
|
||||
defer os.Remove(testcover)
|
||||
|
@ -307,16 +303,30 @@ func TestCoverHTML(t *testing.T) {
|
|||
in = false
|
||||
}
|
||||
}
|
||||
if err := ioutil.WriteFile(htmlHTML, out.Bytes(), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
golden, err := ioutil.ReadFile(htmlGolden)
|
||||
if err != nil {
|
||||
t.Fatalf("reading golden file: %v", err)
|
||||
}
|
||||
diff := "diff"
|
||||
if runtime.GOOS == "plan9" {
|
||||
diff = "/bin/ape/diff"
|
||||
// Ignore white space differences.
|
||||
// Break into lines, then compare by breaking into words.
|
||||
goldenLines := strings.Split(string(golden), "\n")
|
||||
outLines := strings.Split(out.String(), "\n")
|
||||
// Compare at the line level, stopping at first different line so
|
||||
// we don't generate tons of output if there's an inserted or deleted line.
|
||||
for i, goldenLine := range goldenLines {
|
||||
if i > len(outLines) {
|
||||
t.Fatalf("output shorter than golden; stops before line %d: %s\n", i+1, goldenLine)
|
||||
}
|
||||
// Convert all white space to simple spaces, for easy comparison.
|
||||
goldenLine = strings.Join(strings.Fields(goldenLine), " ")
|
||||
outLine := strings.Join(strings.Fields(outLines[i]), " ")
|
||||
if outLine != goldenLine {
|
||||
t.Fatalf("line %d differs: got:\n\t%s\nwant:\n\t%s", i+1, outLine, goldenLine)
|
||||
}
|
||||
}
|
||||
if len(goldenLines) != len(outLines) {
|
||||
t.Fatalf("output longer than golden; first extra output line %d: %q\n", len(goldenLines)+1, outLines[len(goldenLines)])
|
||||
}
|
||||
// diff -uw testdata/html/html.html testdata/html/html.golden
|
||||
cmd = exec.Command(diff, "-u", "-w", htmlHTML, htmlGolden)
|
||||
run(cmd, t)
|
||||
}
|
||||
|
||||
func run(c *exec.Cmd, t *testing.T) {
|
||||
|
|
2
src/cmd/dist/build.go
vendored
2
src/cmd/dist/build.go
vendored
|
@ -67,6 +67,7 @@ var okgoarch = []string{
|
|||
"mips64le",
|
||||
"ppc64",
|
||||
"ppc64le",
|
||||
"riscv64",
|
||||
"s390x",
|
||||
"wasm",
|
||||
}
|
||||
|
@ -1393,6 +1394,7 @@ var cgoEnabled = map[string]bool{
|
|||
"linux/mipsle": true,
|
||||
"linux/mips64": true,
|
||||
"linux/mips64le": true,
|
||||
"linux/riscv64": true,
|
||||
"linux/s390x": true,
|
||||
"android/386": true,
|
||||
"android/amd64": true,
|
||||
|
|
2
src/cmd/dist/buildtool.go
vendored
2
src/cmd/dist/buildtool.go
vendored
|
@ -80,6 +80,8 @@ var bootstrapDirs = []string{
|
|||
"cmd/link/internal/s390x",
|
||||
"cmd/link/internal/sym",
|
||||
"cmd/link/internal/x86",
|
||||
"compress/flate",
|
||||
"compress/zlib",
|
||||
"cmd/link/internal/wasm",
|
||||
"container/heap",
|
||||
"debug/dwarf",
|
||||
|
|
43
src/cmd/dist/test.go
vendored
43
src/cmd/dist/test.go
vendored
|
@ -308,11 +308,10 @@ func (t *tester) registerStdTest(pkg string) {
|
|||
timeoutSec := 180
|
||||
for _, pkg := range stdMatches {
|
||||
if pkg == "cmd/go" {
|
||||
timeoutSec *= 2
|
||||
timeoutSec *= 3
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"test",
|
||||
short(),
|
||||
|
@ -325,6 +324,8 @@ func (t *tester) registerStdTest(pkg string) {
|
|||
}
|
||||
if t.compileOnly {
|
||||
args = append(args, "-run=^$")
|
||||
} else if goos == "js" && goarch == "wasm" {
|
||||
args = append(args, "-run=^Test") // exclude examples; Issue 25913
|
||||
}
|
||||
args = append(args, stdMatches...)
|
||||
cmd := exec.Command("go", args...)
|
||||
|
@ -355,7 +356,8 @@ func (t *tester) registerRaceBenchTest(pkg string) {
|
|||
"test",
|
||||
short(),
|
||||
"-race",
|
||||
"-run=^$", // nothing. only benchmarks.
|
||||
t.timeout(1200), // longer timeout for race with benchmarks
|
||||
"-run=^$", // nothing. only benchmarks.
|
||||
"-benchtime=.1s",
|
||||
"-cpu=4",
|
||||
}
|
||||
|
@ -449,7 +451,7 @@ func (t *tester) registerTests() {
|
|||
}
|
||||
|
||||
// Runtime CPU tests.
|
||||
if !t.compileOnly {
|
||||
if !t.compileOnly && goos != "js" { // js can't handle -cpu != 1
|
||||
testName := "runtime:cpu124"
|
||||
t.tests = append(t.tests, distTest{
|
||||
name: testName,
|
||||
|
@ -490,9 +492,9 @@ func (t *tester) registerTests() {
|
|||
// On the builders only, test that a moved GOROOT still works.
|
||||
// Fails on iOS because CC_FOR_TARGET refers to clangwrap.sh
|
||||
// in the unmoved GOROOT.
|
||||
// Fails on Android with an exec format error.
|
||||
// Fails on Android and js/wasm with an exec format error.
|
||||
// Fails on plan9 with "cannot find GOROOT" (issue #21016).
|
||||
if os.Getenv("GO_BUILDER_NAME") != "" && goos != "android" && !t.iOS() && goos != "plan9" {
|
||||
if os.Getenv("GO_BUILDER_NAME") != "" && goos != "android" && !t.iOS() && goos != "plan9" && goos != "js" {
|
||||
t.tests = append(t.tests, distTest{
|
||||
name: "moved_goroot",
|
||||
heading: "moved GOROOT",
|
||||
|
@ -583,14 +585,16 @@ func (t *tester) registerTests() {
|
|||
}
|
||||
|
||||
// sync tests
|
||||
t.tests = append(t.tests, distTest{
|
||||
name: "sync_cpu",
|
||||
heading: "sync -cpu=10",
|
||||
fn: func(dt *distTest) error {
|
||||
t.addCmd(dt, "src", t.goTest(), "sync", t.timeout(120), "-cpu=10", t.runFlag(""))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
if goos != "js" { // js doesn't support -cpu=10
|
||||
t.tests = append(t.tests, distTest{
|
||||
name: "sync_cpu",
|
||||
heading: "sync -cpu=10",
|
||||
fn: func(dt *distTest) error {
|
||||
t.addCmd(dt, "src", t.goTest(), "sync", t.timeout(120), "-cpu=10", t.runFlag(""))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if t.raceDetectorSupported() {
|
||||
t.tests = append(t.tests, distTest{
|
||||
|
@ -714,7 +718,7 @@ func (t *tester) registerTests() {
|
|||
|
||||
// Doc tests only run on builders.
|
||||
// They find problems approximately never.
|
||||
if t.hasBash() && goos != "nacl" && goos != "android" && !t.iOS() && os.Getenv("GO_BUILDER_NAME") != "" {
|
||||
if t.hasBash() && goos != "nacl" && goos != "js" && goos != "android" && !t.iOS() && os.Getenv("GO_BUILDER_NAME") != "" {
|
||||
t.registerTest("doc_progs", "../doc/progs", "time", "go", "run", "run.go")
|
||||
t.registerTest("wiki", "../doc/articles/wiki", "./test.bash")
|
||||
t.registerTest("codewalk", "../doc/codewalk", "time", "./run")
|
||||
|
@ -740,7 +744,7 @@ func (t *tester) registerTests() {
|
|||
})
|
||||
}
|
||||
}
|
||||
if goos != "nacl" && goos != "android" && !t.iOS() {
|
||||
if goos != "nacl" && goos != "android" && !t.iOS() && goos != "js" {
|
||||
t.tests = append(t.tests, distTest{
|
||||
name: "api",
|
||||
heading: "API check",
|
||||
|
@ -1318,7 +1322,7 @@ func (t *tester) raceDetectorSupported() bool {
|
|||
case "linux", "darwin", "freebsd", "windows":
|
||||
// The race detector doesn't work on Alpine Linux:
|
||||
// golang.org/issue/14481
|
||||
return t.cgoEnabled && goarch == "amd64" && gohostos == goos && !isAlpineLinux()
|
||||
return t.cgoEnabled && (goarch == "amd64" || goarch == "ppc64le") && gohostos == goos && !isAlpineLinux()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -1335,13 +1339,16 @@ func (t *tester) runFlag(rx string) string {
|
|||
if t.compileOnly {
|
||||
return "-run=^$"
|
||||
}
|
||||
if rx == "" && goos == "js" && goarch == "wasm" {
|
||||
return "-run=^Test" // exclude examples; Issue 25913
|
||||
}
|
||||
return "-run=" + rx
|
||||
}
|
||||
|
||||
func (t *tester) raceTest(dt *distTest) error {
|
||||
t.addCmd(dt, "src", t.goTest(), "-race", "-i", "runtime/race", "flag", "os", "os/exec")
|
||||
t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("Output"), "runtime/race")
|
||||
t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("TestParse|TestEcho|TestStdinCloseRace|TestClosedPipeRace|TestTypeRace"), "flag", "os", "os/exec", "encoding/gob")
|
||||
t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("TestParse|TestEcho|TestStdinCloseRace|TestClosedPipeRace|TestTypeRace|TestFdRace|TestFileCloseRace"), "flag", "net", "os", "os/exec", "encoding/gob")
|
||||
// We don't want the following line, because it
|
||||
// slows down all.bash (by 10 seconds on my laptop).
|
||||
// The race builder should catch any error here, but doesn't.
|
||||
|
|
|
@ -26,7 +26,7 @@ func TestMain(m *testing.M) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dirsInit(testdataDir)
|
||||
dirsInit(testdataDir, filepath.Join(testdataDir, "nested"), filepath.Join(testdataDir, "nested", "nested"))
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
@ -510,6 +510,24 @@ var tests = []test{
|
|||
"\\)\n+const", // This will appear if the const decl appears twice.
|
||||
},
|
||||
},
|
||||
{
|
||||
"non-imported: pkg.sym",
|
||||
[]string{"nested.Foo"},
|
||||
[]string{"Foo struct"},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"non-imported: pkg only",
|
||||
[]string{"nested"},
|
||||
[]string{"Foo struct"},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"non-imported: pkg sym",
|
||||
[]string{"nested", "Foo"},
|
||||
[]string{"Foo struct"},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
func TestDoc(t *testing.T) {
|
||||
|
|
|
@ -189,11 +189,16 @@ func parseArgs(args []string) (pkg *build.Package, path, symbol string, more boo
|
|||
// Done below.
|
||||
case 2:
|
||||
// Package must be findable and importable.
|
||||
packagePath, ok := findPackage(arg)
|
||||
if !ok {
|
||||
return nil, args[0], args[1], false
|
||||
for {
|
||||
packagePath, ok := findNextPackage(arg)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
if pkg, err := build.ImportDir(packagePath, build.ImportComment); err == nil {
|
||||
return pkg, arg, args[1], true
|
||||
}
|
||||
}
|
||||
return importDir(packagePath), arg, args[1], true
|
||||
return nil, args[0], args[1], false
|
||||
}
|
||||
// Usual case: one argument.
|
||||
// If it contains slashes, it begins with a package path.
|
||||
|
@ -241,9 +246,15 @@ func parseArgs(args []string) (pkg *build.Package, path, symbol string, more boo
|
|||
}
|
||||
// See if we have the basename or tail of a package, as in json for encoding/json
|
||||
// or ivy/value for robpike.io/ivy/value.
|
||||
path, ok := findPackage(arg[0:period])
|
||||
if ok {
|
||||
return importDir(path), arg[0:period], symbol, true
|
||||
pkgName := arg[:period]
|
||||
for {
|
||||
path, ok := findNextPackage(pkgName)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
if pkg, err = build.ImportDir(path, build.ImportComment); err == nil {
|
||||
return pkg, arg[0:period], symbol, true
|
||||
}
|
||||
}
|
||||
dirs.Reset() // Next iteration of for loop must scan all the directories again.
|
||||
}
|
||||
|
@ -338,9 +349,9 @@ func isUpper(name string) bool {
|
|||
return unicode.IsUpper(ch)
|
||||
}
|
||||
|
||||
// findPackage returns the full file name path that first matches the
|
||||
// findNextPackage returns the next full file name path that matches the
|
||||
// (perhaps partial) package path pkg. The boolean reports if any match was found.
|
||||
func findPackage(pkg string) (string, bool) {
|
||||
func findNextPackage(pkg string) (string, bool) {
|
||||
if pkg == "" || isUpper(pkg) { // Upper case symbol cannot be a package name.
|
||||
return "", false
|
||||
}
|
||||
|
|
4
src/cmd/doc/testdata/nested/ignore.go
vendored
Normal file
4
src/cmd/doc/testdata/nested/ignore.go
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// +build ignore
|
||||
|
||||
// Ignored package
|
||||
package nested
|
4
src/cmd/doc/testdata/nested/nested/real.go
vendored
Normal file
4
src/cmd/doc/testdata/nested/nested/real.go
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
package nested
|
||||
|
||||
type Foo struct {
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.
|
||||
// Code generated by mkalldocs.sh; DO NOT EDIT.
|
||||
// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.
|
||||
|
||||
// Go is a tool for managing Go source code.
|
||||
|
@ -419,6 +419,12 @@
|
|||
// (gofmt), a fully qualified path (/usr/you/bin/mytool), or a
|
||||
// command alias, described below.
|
||||
//
|
||||
// To convey to humans and machine tools that code is generated,
|
||||
// generated source should have a line early in the file that
|
||||
// matches the following regular expression (in Go syntax):
|
||||
//
|
||||
// ^// Code generated .* DO NOT EDIT\.$
|
||||
//
|
||||
// Note that go generate does not parse the file, so lines that look
|
||||
// like directives in comments or multiline strings will be treated
|
||||
// as directives.
|
||||
|
@ -579,7 +585,7 @@
|
|||
//
|
||||
// Usage:
|
||||
//
|
||||
// go list [-cgo] [-deps] [-e] [-export] [-f format] [-json] [-list] [-test] [build flags] [packages]
|
||||
// go list [-cgo] [-deps] [-e] [-export] [-f format] [-json] [-test] [build flags] [packages]
|
||||
//
|
||||
// List lists the packages named by the import paths, one per line.
|
||||
//
|
||||
|
@ -1006,6 +1012,7 @@
|
|||
// in the standard user cache directory for the current operating system.
|
||||
// Setting the GOCACHE environment variable overrides this default,
|
||||
// and running 'go env GOCACHE' prints the current cache directory.
|
||||
// You can set the variable to 'off' to disable the cache.
|
||||
//
|
||||
// The go command periodically deletes cached data that has not been
|
||||
// used recently. Running 'go clean -cache' deletes all cached data.
|
||||
|
|
|
@ -99,6 +99,7 @@ func init() {
|
|||
var testGOROOT string
|
||||
|
||||
var testCC string
|
||||
var testGOCACHE string
|
||||
|
||||
// The TestMain function creates a go command for testing purposes and
|
||||
// deletes it after the tests have been run.
|
||||
|
@ -175,6 +176,13 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
}
|
||||
|
||||
out, err = exec.Command(gotool, "env", "GOCACHE").CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "could not find testing GOCACHE: %v\n%s", err, out)
|
||||
os.Exit(2)
|
||||
}
|
||||
testGOCACHE = strings.TrimSpace(string(out))
|
||||
|
||||
// As of Sept 2017, MSan is only supported on linux/amd64.
|
||||
// https://github.com/google/sanitizers/wiki/MemorySanitizer#getting-memorysanitizer
|
||||
canMSan = canCgo && runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
|
||||
|
@ -198,7 +206,7 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
os.Setenv("HOME", "/test-go-home-does-not-exist")
|
||||
if os.Getenv("GOCACHE") == "" {
|
||||
os.Setenv("GOCACHE", "off") // because $HOME is gone
|
||||
os.Setenv("GOCACHE", testGOCACHE) // because $HOME is gone
|
||||
}
|
||||
|
||||
r := m.Run()
|
||||
|
@ -791,7 +799,6 @@ func TestBuildComplex(t *testing.T) {
|
|||
tg.run("build", "-x", "-o", os.DevNull, "complex")
|
||||
|
||||
if _, err := exec.LookPath("gccgo"); err == nil {
|
||||
t.Skip("golang.org/issue/22472")
|
||||
tg.run("build", "-x", "-o", os.DevNull, "-compiler=gccgo", "complex")
|
||||
}
|
||||
}
|
||||
|
@ -1253,14 +1260,14 @@ func TestInternalPackagesInGOROOTAreRespected(t *testing.T) {
|
|||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.runFail("build", "-v", "./testdata/testinternal")
|
||||
tg.grepBoth(`testinternal(\/|\\)p\.go\:3\:8\: use of internal package not allowed`, "wrong error message for testdata/testinternal")
|
||||
tg.grepBoth(`testinternal(\/|\\)p\.go\:3\:8\: use of internal package net/http/internal not allowed`, "wrong error message for testdata/testinternal")
|
||||
}
|
||||
|
||||
func TestInternalPackagesOutsideGOROOTAreRespected(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.runFail("build", "-v", "./testdata/testinternal2")
|
||||
tg.grepBoth(`testinternal2(\/|\\)p\.go\:3\:8\: use of internal package not allowed`, "wrote error message for testdata/testinternal2")
|
||||
tg.grepBoth(`testinternal2(\/|\\)p\.go\:3\:8\: use of internal package .*internal/w not allowed`, "wrote error message for testdata/testinternal2")
|
||||
}
|
||||
|
||||
func TestRunInternal(t *testing.T) {
|
||||
|
@ -1270,7 +1277,7 @@ func TestRunInternal(t *testing.T) {
|
|||
tg.setenv("GOPATH", dir)
|
||||
tg.run("run", filepath.Join(dir, "src/run/good.go"))
|
||||
tg.runFail("run", filepath.Join(dir, "src/run/bad.go"))
|
||||
tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package not allowed`, "unexpected error for run/bad.go")
|
||||
tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package run/subdir/internal/private not allowed`, "unexpected error for run/bad.go")
|
||||
}
|
||||
|
||||
func TestRunPkg(t *testing.T) {
|
||||
|
@ -1975,6 +1982,10 @@ func TestGoListTest(t *testing.T) {
|
|||
|
||||
tg.run("list", "-test", "runtime/cgo")
|
||||
tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
|
||||
|
||||
tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort")
|
||||
tg.grepStdout(`^reflect$`, "missing reflect")
|
||||
tg.grepStdoutNot(`^sort`, "unexpected sort")
|
||||
}
|
||||
|
||||
func TestGoListCgo(t *testing.T) {
|
||||
|
@ -3072,7 +3083,6 @@ func TestIssue7573(t *testing.T) {
|
|||
if _, err := exec.LookPath("gccgo"); err != nil {
|
||||
t.Skip("skipping because no gccgo compiler found")
|
||||
}
|
||||
t.Skip("golang.org/issue/22472")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
@ -3257,9 +3267,9 @@ func TestGoTestCoverMultiPackage(t *testing.T) {
|
|||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.run("test", "-cover", "./testdata/testcover/...")
|
||||
tg.grepStdout(`\?.*testdata/testcover/pkg1.*\d\.\d\d\ds.*coverage:.*0\.0% of statements \[no test files\]`, "expected [no test files] for pkg1")
|
||||
tg.grepStdout(`ok.*testdata/testcover/pkg2.*\d\.\d\d\ds.*coverage:.*0\.0% of statements \[no tests to run\]`, "expected [no tests to run] for pkg2")
|
||||
tg.grepStdout(`ok.*testdata/testcover/pkg3.*\d\.\d\d\ds.*coverage:.*100\.0% of statements`, "expected 100% coverage for pkg3")
|
||||
tg.grepStdout(`\?.*testdata/testcover/pkg1.*(\d\.\d\d\ds|cached).*coverage:.*0\.0% of statements \[no test files\]`, "expected [no test files] for pkg1")
|
||||
tg.grepStdout(`ok.*testdata/testcover/pkg2.*(\d\.\d\d\ds|cached).*coverage:.*0\.0% of statements \[no tests to run\]`, "expected [no tests to run] for pkg2")
|
||||
tg.grepStdout(`ok.*testdata/testcover/pkg3.*(\d\.\d\d\ds|cached).*coverage:.*100\.0% of statements`, "expected 100% coverage for pkg3")
|
||||
}
|
||||
|
||||
// issue 24570
|
||||
|
@ -3268,9 +3278,9 @@ func TestGoTestCoverprofileMultiPackage(t *testing.T) {
|
|||
defer tg.cleanup()
|
||||
tg.creatingTemp("testdata/cover.out")
|
||||
tg.run("test", "-coverprofile=testdata/cover.out", "./testdata/testcover/...")
|
||||
tg.grepStdout(`\?.*testdata/testcover/pkg1.*\d\.\d\d\ds.*coverage:.*0\.0% of statements \[no test files\]`, "expected [no test files] for pkg1")
|
||||
tg.grepStdout(`ok.*testdata/testcover/pkg2.*\d\.\d\d\ds.*coverage:.*0\.0% of statements \[no tests to run\]`, "expected [no tests to run] for pkg2")
|
||||
tg.grepStdout(`ok.*testdata/testcover/pkg3.*\d\.\d\d\ds.*coverage:.*100\.0% of statements`, "expected 100% coverage for pkg3")
|
||||
tg.grepStdout(`\?.*testdata/testcover/pkg1.*(\d\.\d\d\ds|cached).*coverage:.*0\.0% of statements \[no test files\]`, "expected [no test files] for pkg1")
|
||||
tg.grepStdout(`ok.*testdata/testcover/pkg2.*(\d\.\d\d\ds|cached).*coverage:.*0\.0% of statements \[no tests to run\]`, "expected [no tests to run] for pkg2")
|
||||
tg.grepStdout(`ok.*testdata/testcover/pkg3.*(\d\.\d\d\ds|cached).*coverage:.*100\.0% of statements`, "expected 100% coverage for pkg3")
|
||||
if out, err := ioutil.ReadFile("testdata/cover.out"); err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
|
@ -5815,6 +5825,11 @@ func TestTestVet(t *testing.T) {
|
|||
tg.runFail("test", "vetfail/...")
|
||||
tg.grepStderr(`Printf format %d`, "did not diagnose bad Printf")
|
||||
tg.grepStdout(`ok\s+vetfail/p2`, "did not run vetfail/p2")
|
||||
|
||||
// Use -a so that we need to recompute the vet-specific export data for
|
||||
// vetfail/p1.
|
||||
tg.run("test", "-a", "vetfail/p2")
|
||||
tg.grepStderrNot(`invalid.*constraint`, "did diagnose bad build constraint in vetxonly mode")
|
||||
}
|
||||
|
||||
func TestTestVetRebuild(t *testing.T) {
|
||||
|
|
15
src/cmd/go/internal/cache/cache.go
vendored
15
src/cmd/go/internal/cache/cache.go
vendored
|
@ -189,6 +189,21 @@ func (c *Cache) get(id ActionID) (Entry, error) {
|
|||
return Entry{buf, size, time.Unix(0, tm)}, nil
|
||||
}
|
||||
|
||||
// GetFile looks up the action ID in the cache and returns
|
||||
// the name of the corresponding data file.
|
||||
func (c *Cache) GetFile(id ActionID) (file string, entry Entry, err error) {
|
||||
entry, err = c.Get(id)
|
||||
if err != nil {
|
||||
return "", Entry{}, err
|
||||
}
|
||||
file = c.OutputFile(entry.OutputID)
|
||||
info, err := os.Stat(file)
|
||||
if err != nil || info.Size() != entry.Size {
|
||||
return "", Entry{}, errMissing
|
||||
}
|
||||
return file, entry, nil
|
||||
}
|
||||
|
||||
// GetBytes looks up the action ID in the cache and returns
|
||||
// the corresponding output bytes.
|
||||
// GetBytes should only be used for data that can be expected to fit in memory.
|
||||
|
|
|
@ -103,6 +103,16 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a copy of findGOROOT, isSameDir, and isGOROOT in
|
||||
// x/tools/cmd/godoc/goroot.go.
|
||||
// Try to keep them in sync for now.
|
||||
|
||||
// findGOROOT returns the GOROOT value, using either an explicitly
|
||||
// provided environment variable, a GOROOT that contains the current
|
||||
// os.Executable value, or else the GOROOT that the binary was built
|
||||
// with from runtime.GOROOT().
|
||||
//
|
||||
// There is a copy of this code in x/tools/cmd/godoc/goroot.go.
|
||||
func findGOROOT() string {
|
||||
if env := os.Getenv("GOROOT"); env != "" {
|
||||
return filepath.Clean(env)
|
||||
|
@ -162,6 +172,8 @@ func isSameDir(dir1, dir2 string) bool {
|
|||
// It does this by looking for the path/pkg/tool directory,
|
||||
// which is necessary for useful operation of the cmd/go tool,
|
||||
// and is not typically present in a GOPATH.
|
||||
//
|
||||
// There is a copy of this code in x/tools/cmd/godoc/goroot.go.
|
||||
func isGOROOT(path string) bool {
|
||||
stat, err := os.Stat(filepath.Join(path, "pkg", "tool"))
|
||||
if err != nil {
|
||||
|
|
103
src/cmd/go/internal/dirhash/hash.go
Normal file
103
src/cmd/go/internal/dirhash/hash.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package dirhash defines hashes over directory trees.
|
||||
package dirhash
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var DefaultHash = Hash1
|
||||
|
||||
type Hash func(files []string, open func(string) (io.ReadCloser, error)) (string, error)
|
||||
|
||||
func Hash1(files []string, open func(string) (io.ReadCloser, error)) (string, error) {
|
||||
h := sha256.New()
|
||||
files = append([]string(nil), files...)
|
||||
sort.Strings(files)
|
||||
for _, file := range files {
|
||||
if strings.Contains(file, "\n") {
|
||||
return "", errors.New("filenames with newlines are not supported")
|
||||
}
|
||||
r, err := open(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
hf := sha256.New()
|
||||
_, err = io.Copy(hf, r)
|
||||
r.Close()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Fprintf(h, "%x %s\n", hf.Sum(nil), file)
|
||||
}
|
||||
return "h1:" + base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
|
||||
}
|
||||
|
||||
func HashDir(dir, prefix string, hash Hash) (string, error) {
|
||||
files, err := DirFiles(dir, prefix)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
osOpen := func(name string) (io.ReadCloser, error) {
|
||||
return os.Open(filepath.Join(dir, strings.TrimPrefix(name, prefix)))
|
||||
}
|
||||
return hash(files, osOpen)
|
||||
}
|
||||
|
||||
func DirFiles(dir, prefix string) ([]string, error) {
|
||||
var files []string
|
||||
dir = filepath.Clean(dir)
|
||||
err := filepath.Walk(dir, func(file string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
rel := file
|
||||
if dir != "." {
|
||||
rel = file[len(dir)+1:]
|
||||
}
|
||||
f := filepath.Join(prefix, rel)
|
||||
files = append(files, filepath.ToSlash(f))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func HashZip(zipfile string, hash Hash) (string, error) {
|
||||
z, err := zip.OpenReader(zipfile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer z.Close()
|
||||
var files []string
|
||||
zfiles := make(map[string]*zip.File)
|
||||
for _, file := range z.File {
|
||||
files = append(files, file.Name)
|
||||
zfiles[file.Name] = file
|
||||
}
|
||||
zipOpen := func(name string) (io.ReadCloser, error) {
|
||||
f := zfiles[name]
|
||||
if f == nil {
|
||||
return nil, fmt.Errorf("file %q not found in zip", name) // should never happen
|
||||
}
|
||||
return f.Open()
|
||||
}
|
||||
return hash(files, zipOpen)
|
||||
}
|
135
src/cmd/go/internal/dirhash/hash_test.go
Normal file
135
src/cmd/go/internal/dirhash/hash_test.go
Normal file
|
@ -0,0 +1,135 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dirhash
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func h(s string) string {
|
||||
return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))
|
||||
}
|
||||
|
||||
func htop(k string, s string) string {
|
||||
sum := sha256.Sum256([]byte(s))
|
||||
return k + ":" + base64.StdEncoding.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func TestHash1(t *testing.T) {
|
||||
files := []string{"xyz", "abc"}
|
||||
open := func(name string) (io.ReadCloser, error) {
|
||||
return ioutil.NopCloser(strings.NewReader("data for " + name)), nil
|
||||
}
|
||||
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "abc", h("data for xyz"), "xyz"))
|
||||
out, err := Hash1(files, open)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out != want {
|
||||
t.Errorf("Hash1(...) = %s, want %s", out, want)
|
||||
}
|
||||
|
||||
_, err = Hash1([]string{"xyz", "a\nbc"}, open)
|
||||
if err == nil {
|
||||
t.Error("Hash1: expected error on newline in filenames")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashDir(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "dirhash-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz"))
|
||||
out, err := HashDir(dir, "prefix", Hash1)
|
||||
if err != nil {
|
||||
t.Fatalf("HashDir: %v", err)
|
||||
}
|
||||
if out != want {
|
||||
t.Errorf("HashDir(...) = %s, want %s", out, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashZip(t *testing.T) {
|
||||
f, err := ioutil.TempFile("", "dirhash-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
defer f.Close()
|
||||
|
||||
z := zip.NewWriter(f)
|
||||
w, err := z.Create("prefix/xyz")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w.Write([]byte("data for xyz"))
|
||||
w, err = z.Create("prefix/abc")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w.Write([]byte("data for abc"))
|
||||
if err := z.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz"))
|
||||
out, err := HashZip(f.Name(), Hash1)
|
||||
if err != nil {
|
||||
t.Fatalf("HashDir: %v", err)
|
||||
}
|
||||
if out != want {
|
||||
t.Errorf("HashDir(...) = %s, want %s", out, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirFiles(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "dirfiles-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Mkdir(filepath.Join(dir, "subdir"), 0777); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, "subdir", "xyz"), []byte("data for subdir xyz"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prefix := "foo/bar@v2.3.4"
|
||||
out, err := DirFiles(dir, prefix)
|
||||
if err != nil {
|
||||
t.Fatalf("DirFiles: %v", err)
|
||||
}
|
||||
for _, file := range out {
|
||||
if !strings.HasPrefix(file, prefix) {
|
||||
t.Errorf("Dir file = %s, want prefix %s", file, prefix)
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue