mirror of
https://github.com/golang/go.git
synced 2026-02-06 10:55:05 +03:00
Compare commits
10 Commits
go1.19beta
...
dev.boring
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72237f94a4 | ||
|
|
6f12eb26e4 | ||
|
|
40eb21944e | ||
|
|
34a363c12e | ||
|
|
0ced72fe8b | ||
|
|
418403e7ac | ||
|
|
61246509aa | ||
|
|
e1425b300e | ||
|
|
e52cc9d0fd | ||
|
|
2fb6bf8a4a |
5
AUTHORS
5
AUTHORS
@@ -198,7 +198,6 @@ Baiju Muthukadan <baiju.m.mail@gmail.com>
|
||||
Baokun Lee <nototon@gmail.com> <bk@golangcn.org>
|
||||
Bartosz Grzybowski <melkorm@gmail.com>
|
||||
Bastian Ike <bastian.ike@gmail.com>
|
||||
Beijing Bytedance Technology Co., Ltd.
|
||||
Ben Burkert <ben@benburkert.com>
|
||||
Ben Haines <bhainesva@gmail.com>
|
||||
Ben Lubar <ben.lubar@gmail.com>
|
||||
@@ -673,7 +672,6 @@ Jimmy Zelinskie <jimmyzelinskie@gmail.com>
|
||||
Jin-wook Jeong <jeweljar@hanmail.net>
|
||||
Jingcheng Zhang <diogin@gmail.com>
|
||||
Jingguo Yao <yaojingguo@gmail.com>
|
||||
Jinzhu Zhang <wosmvp@gmail.com>
|
||||
Jiong Du <londevil@gmail.com>
|
||||
Jirka Daněk <dnk@mail.muni.cz>
|
||||
Jiulong Wang <jiulongw@gmail.com>
|
||||
@@ -1281,7 +1279,6 @@ Shi Han Ng <shihanng@gmail.com>
|
||||
Shinji Tanaka <shinji.tanaka@gmail.com>
|
||||
Shintaro Kaneko <kaneshin0120@gmail.com>
|
||||
Shivakumar GN <shivakumar.gn@gmail.com>
|
||||
Shuai Tan <hopehook.com@gmail.com> <hopehook@qq.com>
|
||||
Silvan Jegen <s.jegen@gmail.com>
|
||||
Simon Jefford <simon.jefford@gmail.com>
|
||||
Simon Rawet <simon@rawet.se>
|
||||
@@ -1431,7 +1428,6 @@ W. Trevor King <wking@tremily.us>
|
||||
Wade Simmons <wade@wades.im>
|
||||
Wander Lairson Costa <wcosta@mozilla.com>
|
||||
Wayne Ashley Berry <wayneashleyberry@gmail.com>
|
||||
Wayne Zuo <wdvxdr1123@gmail.com> <wdvxdr@golangcn.org>
|
||||
Weaveworks
|
||||
Wèi Cōngruì <crvv.mail@gmail.com>
|
||||
Wei Fu <fhfuwei@163.com>
|
||||
@@ -1475,7 +1471,6 @@ Yoshiyuki Mineo <yoshiyuki.mineo@gmail.com>
|
||||
Yosuke Akatsuka <yosuke.akatsuka@gmail.com>
|
||||
Yuji Yaginuma <yuuji.yaginuma@gmail.com>
|
||||
Yukihiro Nishinaka <6elpinal@gmail.com>
|
||||
YunHao Zhang <zhangyunhao116@gmail.com> <zhangyunhao@bytedance.com>
|
||||
Yury Smolsky <yury@smolsky.by>
|
||||
Yusuke Kagiwada <block.rxckin.beats@gmail.com>
|
||||
Yuusei Kuwana <kuwana@kumama.org>
|
||||
|
||||
@@ -989,6 +989,7 @@ GitHub User @Gusted (25481501) <williamzijl7@hotmail.com>
|
||||
GitHub User @hengwu0 (41297446) <41297446+hengwu0@users.noreply.github.com>
|
||||
GitHub User @hitzhangjie (3725760) <hit.zhangjie@gmail.com>
|
||||
GitHub User @hkhere (33268704) <33268704+hkhere@users.noreply.github.com>
|
||||
GitHub User @hopehook (7326168) <hopehook.com@gmail.com>
|
||||
GitHub User @hqpko (13887251) <whaibin01@hotmail.com>
|
||||
GitHub User @Illirgway (5428603) <illirgway@gmail.com>
|
||||
GitHub User @itchyny (375258) <itchyny@hatena.ne.jp>
|
||||
@@ -1352,7 +1353,6 @@ Jimmy Zelinskie <jimmyzelinskie@gmail.com>
|
||||
Jin-wook Jeong <jeweljar@hanmail.net>
|
||||
Jingcheng Zhang <diogin@gmail.com>
|
||||
Jingguo Yao <yaojingguo@gmail.com>
|
||||
Jinzhu Zhang <wosmvp@gmail.com>
|
||||
Jingnan Si <jingnan.si@gmail.com>
|
||||
Jinkun Zhang <franksnolf@gmail.com>
|
||||
Jinwen Wo <wojinwen@huawei.com>
|
||||
@@ -2451,7 +2451,6 @@ Shivansh Rai <shivansh@freebsd.org>
|
||||
Shivashis Padhi <shivashispadhi@gmail.com>
|
||||
Shoshin Nikita <shoshin_nikita@fastmail.com>
|
||||
Shota Sugiura <s.shota.710.3506@gmail.com>
|
||||
Shuai Tan <hopehook.com@gmail.com> <hopehook@qq.com>
|
||||
Shubham Sharma <shubham.sha12@gmail.com>
|
||||
Shuhei Takahashi <nya@chromium.org>
|
||||
Shun Fan <sfan@google.com>
|
||||
@@ -2736,7 +2735,6 @@ Wander Lairson Costa <wcosta@mozilla.com>
|
||||
Wang Xuerui <git@xen0n.name>
|
||||
Warren Fernandes <warren.f.fernandes@gmail.com>
|
||||
Wayne Ashley Berry <wayneashleyberry@gmail.com>
|
||||
Wayne Zuo <wdvxdr1123@gmail.com> <wdvxdr@golangcn.org>
|
||||
Wedson Almeida Filho <wedsonaf@google.com>
|
||||
Weerasak Chongnguluam <singpor@gmail.com>
|
||||
Wèi Cōngruì <crvv.mail@gmail.com>
|
||||
@@ -2819,7 +2817,6 @@ Yuki OKUSHI <huyuumi.dev@gmail.com>
|
||||
Yuki Osaki <yuki.osaki7@gmail.com>
|
||||
Yuki Yugui Sonoda <yugui@google.com>
|
||||
Yukihiro Nishinaka <6elpinal@gmail.com>
|
||||
YunHao Zhang <zhangyunhao116@gmail.com> <zhangyunhao@bytedance.com>
|
||||
YunQiang Su <syq@debian.org>
|
||||
Yuntao Wang <ytcoode@gmail.com>
|
||||
Yury Smolsky <yury@smolsky.by>
|
||||
|
||||
24
README.boringcrypto.md
Normal file
24
README.boringcrypto.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# dev.boringcrypto branch
|
||||
|
||||
This branch is no more. `GOEXPERIMENT=boringcrypto` on the standard branch does the job now.
|
||||
|
||||
Previous notice:
|
||||
|
||||
We have been working inside Google on a fork of Go that uses
|
||||
BoringCrypto (the core of [BoringSSL][]) for various crypto
|
||||
primitives, in furtherance of some [work related to FIPS 140-2][sp].
|
||||
We have heard that some external users of Go would be interested in
|
||||
this code as well, so this branch holds the patches to make Go use
|
||||
BoringCrypto.
|
||||
|
||||
[BoringSSL]: https://boringssl.googlesource.com/boringssl/
|
||||
[sp]: https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf
|
||||
|
||||
Unlike typical dev branches, we do not intend any eventual merge of
|
||||
this code into the master branch. Instead we intend to maintain in
|
||||
this branch the latest release plus BoringCrypto patches.
|
||||
|
||||
To be clear, we are not making any statements or representations about
|
||||
the suitability of this code in relation to the FIPS 140-2 standard.
|
||||
Interested users will have to evaluate for themselves whether the code
|
||||
is useful for their own purposes.
|
||||
288
api/go1.19.txt
288
api/go1.19.txt
@@ -1,288 +0,0 @@
|
||||
pkg crypto/x509, func ParseRevocationList([]uint8) (*RevocationList, error) #50674
|
||||
pkg crypto/x509, method (*CertPool) Clone() *CertPool #35044
|
||||
pkg crypto/x509, method (*CertPool) Equal(*CertPool) bool #46057
|
||||
pkg crypto/x509, method (*RevocationList) CheckSignatureFrom(*Certificate) error #50674
|
||||
pkg crypto/x509, type RevocationList struct, AuthorityKeyId []uint8 #50674
|
||||
pkg crypto/x509, type RevocationList struct, Extensions []pkix.Extension #50674
|
||||
pkg crypto/x509, type RevocationList struct, Issuer pkix.Name #50674
|
||||
pkg crypto/x509, type RevocationList struct, Raw []uint8 #50674
|
||||
pkg crypto/x509, type RevocationList struct, RawIssuer []uint8 #50674
|
||||
pkg crypto/x509, type RevocationList struct, RawTBSRevocationList []uint8 #50674
|
||||
pkg crypto/x509, type RevocationList struct, Signature []uint8 #50674
|
||||
pkg debug/elf, const EM_LOONGARCH = 258 #46229
|
||||
pkg debug/elf, const EM_LOONGARCH Machine #46229
|
||||
pkg debug/elf, const R_LARCH_32 = 1 #46229
|
||||
pkg debug/elf, const R_LARCH_32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_64 = 2 #46229
|
||||
pkg debug/elf, const R_LARCH_64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD16 = 48 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD16 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD24 = 49 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD24 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD32 = 50 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD64 = 51 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD8 = 47 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD8 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_COPY = 4 #46229
|
||||
pkg debug/elf, const R_LARCH_COPY R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_IRELATIVE = 12 #46229
|
||||
pkg debug/elf, const R_LARCH_IRELATIVE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_JUMP_SLOT = 5 #46229
|
||||
pkg debug/elf, const R_LARCH_JUMP_SLOT R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_MARK_LA = 20 #46229
|
||||
pkg debug/elf, const R_LARCH_MARK_LA R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_MARK_PCREL = 21 #46229
|
||||
pkg debug/elf, const R_LARCH_MARK_PCREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_NONE = 0 #46229
|
||||
pkg debug/elf, const R_LARCH_NONE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_RELATIVE = 3 #46229
|
||||
pkg debug/elf, const R_LARCH_RELATIVE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_ADD = 35 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_ADD R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_AND = 36 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_AND R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_ASSERT = 30 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_ASSERT R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_IF_ELSE = 37 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_IF_ELSE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_NOT = 31 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_NOT R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_10_10_16_S2 = 45 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_10_10_16_S2 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_5_10_16_S2 = 44 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_5_10_16_S2 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_12 = 40 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_12 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16 = 41 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16_S2 = 42 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16_S2 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_5 = 38 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_5 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_5_20 = 43 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_5_20 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_U = 46 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_U R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_U_10_12 = 39 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_U_10_12 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_ABSOLUTE = 23 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_ABSOLUTE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_DUP = 24 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_DUP R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_GPREL = 25 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_GPREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_PCREL = 22 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_PCREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_PLT_PCREL = 29 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_PLT_PCREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GD = 28 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GD R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GOT = 27 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GOT R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_TPREL = 26 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_TPREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SL = 33 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SR = 34 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SR R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SUB = 32 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SUB R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB16 = 53 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB16 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB24 = 54 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB24 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB32 = 55 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB64 = 56 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB8 = 52 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB8 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPMOD32 = 6 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPMOD32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPMOD64 = 7 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPMOD64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPREL32 = 8 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPREL32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPREL64 = 9 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPREL64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_TPREL32 = 10 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_TPREL32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_TPREL64 = 11 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_TPREL64 R_LARCH #46229
|
||||
pkg debug/elf, method (R_LARCH) GoString() string #46229
|
||||
pkg debug/elf, method (R_LARCH) String() string #46229
|
||||
pkg debug/elf, type R_LARCH int #46229
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY = 2 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH = 4 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST = 6 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES = 1 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE = 3 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_CODE = 32 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_CODE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA = 64 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA = 128 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT = 4096 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE = 33554432 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE = 536870912 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_READ = 1073741824 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_READ ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_WRITE = 2147483648 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_WRITE ideal-int #51686
|
||||
pkg debug/pe, method (*File) COFFSymbolReadSectionDefAux(int) (*COFFSymbolAuxFormat5, error) #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Checksum uint32 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumLineNumbers uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumRelocs uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, SecNum uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Selection uint8 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Size uint32 #51686
|
||||
pkg encoding/binary, func AppendUvarint([]uint8, uint64) []uint8 #51644
|
||||
pkg encoding/binary, func AppendVarint([]uint8, int64) []uint8 #51644
|
||||
pkg encoding/binary, type AppendByteOrder interface { AppendUint16, AppendUint32, AppendUint64, String } #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint16) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, String() string #50601
|
||||
pkg encoding/csv, method (*Reader) InputOffset() int64 #43401
|
||||
pkg encoding/xml, method (*Decoder) InputPos() (int, int) #45628
|
||||
pkg flag, func TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string) #45754
|
||||
pkg flag, method (*FlagSet) TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string) #45754
|
||||
pkg fmt, func Append([]uint8, ...interface{}) []uint8 #47579
|
||||
pkg fmt, func Appendf([]uint8, string, ...interface{}) []uint8 #47579
|
||||
pkg fmt, func Appendln([]uint8, ...interface{}) []uint8 #47579
|
||||
pkg go/doc, method (*Package) HTML(string) []uint8 #51082
|
||||
pkg go/doc, method (*Package) Markdown(string) []uint8 #51082
|
||||
pkg go/doc, method (*Package) Parser() *comment.Parser #51082
|
||||
pkg go/doc, method (*Package) Printer() *comment.Printer #51082
|
||||
pkg go/doc, method (*Package) Synopsis(string) string #51082
|
||||
pkg go/doc, method (*Package) Text(string) []uint8 #51082
|
||||
pkg go/doc/comment, func DefaultLookupPackage(string) (string, bool) #51082
|
||||
pkg go/doc/comment, method (*DocLink) DefaultURL(string) string #51082
|
||||
pkg go/doc/comment, method (*Heading) DefaultID() string #51082
|
||||
pkg go/doc/comment, method (*List) BlankBefore() bool #51082
|
||||
pkg go/doc/comment, method (*List) BlankBetween() bool #51082
|
||||
pkg go/doc/comment, method (*Parser) Parse(string) *Doc #51082
|
||||
pkg go/doc/comment, method (*Printer) Comment(*Doc) []uint8 #51082
|
||||
pkg go/doc/comment, method (*Printer) HTML(*Doc) []uint8 #51082
|
||||
pkg go/doc/comment, method (*Printer) Markdown(*Doc) []uint8 #51082
|
||||
pkg go/doc/comment, method (*Printer) Text(*Doc) []uint8 #51082
|
||||
pkg go/doc/comment, type Block interface, unexported methods #51082
|
||||
pkg go/doc/comment, type Code struct #51082
|
||||
pkg go/doc/comment, type Code struct, Text string #51082
|
||||
pkg go/doc/comment, type Doc struct #51082
|
||||
pkg go/doc/comment, type Doc struct, Content []Block #51082
|
||||
pkg go/doc/comment, type Doc struct, Links []*LinkDef #51082
|
||||
pkg go/doc/comment, type DocLink struct #51082
|
||||
pkg go/doc/comment, type DocLink struct, ImportPath string #51082
|
||||
pkg go/doc/comment, type DocLink struct, Name string #51082
|
||||
pkg go/doc/comment, type DocLink struct, Recv string #51082
|
||||
pkg go/doc/comment, type DocLink struct, Text []Text #51082
|
||||
pkg go/doc/comment, type Heading struct #51082
|
||||
pkg go/doc/comment, type Heading struct, Text []Text #51082
|
||||
pkg go/doc/comment, type Italic string #51082
|
||||
pkg go/doc/comment, type Link struct #51082
|
||||
pkg go/doc/comment, type Link struct, Auto bool #51082
|
||||
pkg go/doc/comment, type Link struct, Text []Text #51082
|
||||
pkg go/doc/comment, type Link struct, URL string #51082
|
||||
pkg go/doc/comment, type LinkDef struct #51082
|
||||
pkg go/doc/comment, type LinkDef struct, Text string #51082
|
||||
pkg go/doc/comment, type LinkDef struct, URL string #51082
|
||||
pkg go/doc/comment, type LinkDef struct, Used bool #51082
|
||||
pkg go/doc/comment, type List struct #51082
|
||||
pkg go/doc/comment, type List struct, ForceBlankBefore bool #51082
|
||||
pkg go/doc/comment, type List struct, ForceBlankBetween bool #51082
|
||||
pkg go/doc/comment, type List struct, Items []*ListItem #51082
|
||||
pkg go/doc/comment, type ListItem struct #51082
|
||||
pkg go/doc/comment, type ListItem struct, Content []Block #51082
|
||||
pkg go/doc/comment, type ListItem struct, Number string #51082
|
||||
pkg go/doc/comment, type Paragraph struct #51082
|
||||
pkg go/doc/comment, type Paragraph struct, Text []Text #51082
|
||||
pkg go/doc/comment, type Parser struct #51082
|
||||
pkg go/doc/comment, type Parser struct, LookupPackage func(string) (string, bool) #51082
|
||||
pkg go/doc/comment, type Parser struct, LookupSym func(string, string) bool #51082
|
||||
pkg go/doc/comment, type Parser struct, Words map[string]string #51082
|
||||
pkg go/doc/comment, type Plain string #51082
|
||||
pkg go/doc/comment, type Printer struct #51082
|
||||
pkg go/doc/comment, type Printer struct, DocLinkBaseURL string #51082
|
||||
pkg go/doc/comment, type Printer struct, DocLinkURL func(*DocLink) string #51082
|
||||
pkg go/doc/comment, type Printer struct, HeadingID func(*Heading) string #51082
|
||||
pkg go/doc/comment, type Printer struct, HeadingLevel int #51082
|
||||
pkg go/doc/comment, type Printer struct, TextCodePrefix string #51082
|
||||
pkg go/doc/comment, type Printer struct, TextPrefix string #51082
|
||||
pkg go/doc/comment, type Printer struct, TextWidth int #51082
|
||||
pkg go/doc/comment, type Text interface, unexported methods #51082
|
||||
pkg go/types, method (*Func) Origin() *Func #51682
|
||||
pkg go/types, method (*Var) Origin() *Var #51682
|
||||
pkg hash/maphash, func Bytes(Seed, []uint8) uint64 #42710
|
||||
pkg hash/maphash, func String(Seed, string) uint64 #42710
|
||||
pkg html/template, method (*Template) Funcs(template.FuncMap) *Template #46121
|
||||
pkg html/template, type FuncMap = template.FuncMap #46121
|
||||
pkg net/http, method (*MaxBytesError) Error() string #30715
|
||||
pkg net/http, type MaxBytesError struct #30715
|
||||
pkg net/http, type MaxBytesError struct, Limit int64 #30715
|
||||
pkg net/url, func JoinPath(string, ...string) (string, error) #47005
|
||||
pkg net/url, method (*URL) JoinPath(...string) *URL #47005
|
||||
pkg net/url, type URL struct, OmitHost bool #46059
|
||||
pkg os/exec, method (*Cmd) Environ() []string #50599
|
||||
pkg os/exec, type Cmd struct, Err error #43724
|
||||
pkg os/exec, var ErrDot error #43724
|
||||
pkg regexp/syntax, const ErrNestingDepth = "expression nests too deeply" #51684
|
||||
pkg regexp/syntax, const ErrNestingDepth ErrorCode #51684
|
||||
pkg runtime/debug, func SetMemoryLimit(int64) int64 #48409
|
||||
pkg sort, func Find(int, func(int) int) (int, bool) #50340
|
||||
pkg sync/atomic, method (*Bool) CompareAndSwap(bool, bool) bool #50860
|
||||
pkg sync/atomic, method (*Bool) Load() bool #50860
|
||||
pkg sync/atomic, method (*Bool) Store(bool) #50860
|
||||
pkg sync/atomic, method (*Bool) Swap(bool) bool #50860
|
||||
pkg sync/atomic, method (*Int32) Add(int32) int32 #50860
|
||||
pkg sync/atomic, method (*Int32) CompareAndSwap(int32, int32) bool #50860
|
||||
pkg sync/atomic, method (*Int32) Load() int32 #50860
|
||||
pkg sync/atomic, method (*Int32) Store(int32) #50860
|
||||
pkg sync/atomic, method (*Int32) Swap(int32) int32 #50860
|
||||
pkg sync/atomic, method (*Int64) Add(int64) int64 #50860
|
||||
pkg sync/atomic, method (*Int64) CompareAndSwap(int64, int64) bool #50860
|
||||
pkg sync/atomic, method (*Int64) Load() int64 #50860
|
||||
pkg sync/atomic, method (*Int64) Store(int64) #50860
|
||||
pkg sync/atomic, method (*Int64) Swap(int64) int64 #50860
|
||||
pkg sync/atomic, method (*Pointer[$0]) CompareAndSwap(*$0, *$0) bool #50860
|
||||
pkg sync/atomic, method (*Pointer[$0]) Load() *$0 #50860
|
||||
pkg sync/atomic, method (*Pointer[$0]) Store(*$0) #50860
|
||||
pkg sync/atomic, method (*Pointer[$0]) Swap(*$0) *$0 #50860
|
||||
pkg sync/atomic, method (*Uint32) Add(uint32) uint32 #50860
|
||||
pkg sync/atomic, method (*Uint32) CompareAndSwap(uint32, uint32) bool #50860
|
||||
pkg sync/atomic, method (*Uint32) Load() uint32 #50860
|
||||
pkg sync/atomic, method (*Uint32) Store(uint32) #50860
|
||||
pkg sync/atomic, method (*Uint32) Swap(uint32) uint32 #50860
|
||||
pkg sync/atomic, method (*Uint64) Add(uint64) uint64 #50860
|
||||
pkg sync/atomic, method (*Uint64) CompareAndSwap(uint64, uint64) bool #50860
|
||||
pkg sync/atomic, method (*Uint64) Load() uint64 #50860
|
||||
pkg sync/atomic, method (*Uint64) Store(uint64) #50860
|
||||
pkg sync/atomic, method (*Uint64) Swap(uint64) uint64 #50860
|
||||
pkg sync/atomic, method (*Uintptr) Add(uintptr) uintptr #50860
|
||||
pkg sync/atomic, method (*Uintptr) CompareAndSwap(uintptr, uintptr) bool #50860
|
||||
pkg sync/atomic, method (*Uintptr) Load() uintptr #50860
|
||||
pkg sync/atomic, method (*Uintptr) Store(uintptr) #50860
|
||||
pkg sync/atomic, method (*Uintptr) Swap(uintptr) uintptr #50860
|
||||
pkg sync/atomic, type Bool struct #50860
|
||||
pkg sync/atomic, type Int32 struct #50860
|
||||
pkg sync/atomic, type Int64 struct #50860
|
||||
pkg sync/atomic, type Pointer[$0 interface{}] struct #50860
|
||||
pkg sync/atomic, type Uint32 struct #50860
|
||||
pkg sync/atomic, type Uint64 struct #50860
|
||||
pkg sync/atomic, type Uintptr struct #50860
|
||||
pkg time, method (Duration) Abs() Duration #51414
|
||||
pkg time, method (Time) ZoneBounds() (Time, Time) #50062
|
||||
3
api/next/30715.txt
Normal file
3
api/next/30715.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
pkg net/http, type MaxBytesError struct #30715
|
||||
pkg net/http, type MaxBytesError struct, Limit int64 #30715
|
||||
pkg net/http, method (*MaxBytesError) Error() string #30715
|
||||
1
api/next/35044.txt
Normal file
1
api/next/35044.txt
Normal file
@@ -0,0 +1 @@
|
||||
pkg crypto/x509, method (*CertPool) Clone() *CertPool #35044
|
||||
2
api/next/42710.txt
Normal file
2
api/next/42710.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pkg hash/maphash, func Bytes(Seed, []uint8) uint64 #42710
|
||||
pkg hash/maphash, func String(Seed, string) uint64 #42710
|
||||
1
api/next/45628.txt
Normal file
1
api/next/45628.txt
Normal file
@@ -0,0 +1 @@
|
||||
pkg encoding/xml, method (*Decoder) InputPos() (int, int) #45628
|
||||
2
api/next/45754.txt
Normal file
2
api/next/45754.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pkg flag, func TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string) #45754
|
||||
pkg flag, method (*FlagSet) TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string) #45754
|
||||
1
api/next/46057.txt
Normal file
1
api/next/46057.txt
Normal file
@@ -0,0 +1 @@
|
||||
pkg crypto/x509, method (*CertPool) Equal(*CertPool) bool #46057
|
||||
2
api/next/46059.txt
Normal file
2
api/next/46059.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pkg net/url, type URL struct, OmitHost bool #46059
|
||||
|
||||
2
api/next/46121.txt
Normal file
2
api/next/46121.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pkg html/template, method (*Template) Funcs(template.FuncMap) *Template #46121
|
||||
pkg html/template, type FuncMap = template.FuncMap #46121
|
||||
105
api/next/46229.txt
Normal file
105
api/next/46229.txt
Normal file
@@ -0,0 +1,105 @@
|
||||
pkg debug/elf, const EM_LOONGARCH = 258 #46229
|
||||
pkg debug/elf, const EM_LOONGARCH Machine #46229
|
||||
pkg debug/elf, const R_LARCH_32 = 1 #46229
|
||||
pkg debug/elf, const R_LARCH_32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_64 = 2 #46229
|
||||
pkg debug/elf, const R_LARCH_64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD16 = 48 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD16 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD24 = 49 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD24 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD32 = 50 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD64 = 51 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_ADD8 = 47 #46229
|
||||
pkg debug/elf, const R_LARCH_ADD8 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_COPY = 4 #46229
|
||||
pkg debug/elf, const R_LARCH_COPY R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_IRELATIVE = 12 #46229
|
||||
pkg debug/elf, const R_LARCH_IRELATIVE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_JUMP_SLOT = 5 #46229
|
||||
pkg debug/elf, const R_LARCH_JUMP_SLOT R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_MARK_LA = 20 #46229
|
||||
pkg debug/elf, const R_LARCH_MARK_LA R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_MARK_PCREL = 21 #46229
|
||||
pkg debug/elf, const R_LARCH_MARK_PCREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_NONE = 0 #46229
|
||||
pkg debug/elf, const R_LARCH_NONE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_RELATIVE = 3 #46229
|
||||
pkg debug/elf, const R_LARCH_RELATIVE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_ADD = 35 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_ADD R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_AND = 36 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_AND R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_ASSERT = 30 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_ASSERT R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_IF_ELSE = 37 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_IF_ELSE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_NOT = 31 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_NOT R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_10_10_16_S2 = 45 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_10_10_16_S2 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_5_10_16_S2 = 44 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_5_10_16_S2 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_12 = 40 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_12 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16 = 41 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16_S2 = 42 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16_S2 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_5 = 38 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_5 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_5_20 = 43 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_S_5_20 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_U = 46 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_U R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_U_10_12 = 39 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_POP_32_U_10_12 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_ABSOLUTE = 23 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_ABSOLUTE R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_DUP = 24 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_DUP R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_GPREL = 25 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_GPREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_PCREL = 22 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_PCREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_PLT_PCREL = 29 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_PLT_PCREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GD = 28 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GD R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GOT = 27 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GOT R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_TPREL = 26 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_TPREL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SL = 33 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SL R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SR = 34 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SR R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SUB = 32 #46229
|
||||
pkg debug/elf, const R_LARCH_SOP_SUB R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB16 = 53 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB16 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB24 = 54 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB24 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB32 = 55 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB64 = 56 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_SUB8 = 52 #46229
|
||||
pkg debug/elf, const R_LARCH_SUB8 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPMOD32 = 6 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPMOD32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPMOD64 = 7 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPMOD64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPREL32 = 8 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPREL32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPREL64 = 9 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_DTPREL64 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_TPREL32 = 10 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_TPREL32 R_LARCH #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_TPREL64 = 11 #46229
|
||||
pkg debug/elf, const R_LARCH_TLS_TPREL64 R_LARCH #46229
|
||||
pkg debug/elf, method (R_LARCH) GoString() string #46229
|
||||
pkg debug/elf, method (R_LARCH) String() string #46229
|
||||
pkg debug/elf, type R_LARCH int #46229
|
||||
2
api/next/47005.txt
Normal file
2
api/next/47005.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pkg net/url, func JoinPath(string, ...string) (string, error) #47005
|
||||
pkg net/url, method (*URL) JoinPath(...string) *URL #47005
|
||||
1
api/next/50340.txt
Normal file
1
api/next/50340.txt
Normal file
@@ -0,0 +1 @@
|
||||
pkg sort, func Find(int, func(int) int) (int, bool) #50340
|
||||
1
api/next/50599.txt
Normal file
1
api/next/50599.txt
Normal file
@@ -0,0 +1 @@
|
||||
pkg os/exec, method (*Cmd) Environ() []string #50599
|
||||
5
api/next/50601.txt
Normal file
5
api/next/50601.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
pkg encoding/binary, type AppendByteOrder interface { AppendUint16, AppendUint32, AppendUint64, String } #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint16) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, String() string #50601
|
||||
9
api/next/50674.txt
Normal file
9
api/next/50674.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
pkg crypto/x509, func ParseRevocationList([]uint8) (*RevocationList, error) #50674
|
||||
pkg crypto/x509, method (*RevocationList) CheckSignatureFrom(*Certificate) error #50674
|
||||
pkg crypto/x509, type RevocationList struct, AuthorityKeyId []uint8 #50674
|
||||
pkg crypto/x509, type RevocationList struct, Extensions []pkix.Extension #50674
|
||||
pkg crypto/x509, type RevocationList struct, Issuer pkix.Name #50674
|
||||
pkg crypto/x509, type RevocationList struct, Raw []uint8 #50674
|
||||
pkg crypto/x509, type RevocationList struct, RawIssuer []uint8 #50674
|
||||
pkg crypto/x509, type RevocationList struct, RawTBSRevocationList []uint8 #50674
|
||||
pkg crypto/x509, type RevocationList struct, Signature []uint8 #50674
|
||||
61
api/next/51082.txt
Normal file
61
api/next/51082.txt
Normal file
@@ -0,0 +1,61 @@
|
||||
pkg go/doc, method (*Package) HTML(string) []uint8 #51082
|
||||
pkg go/doc, method (*Package) Markdown(string) []uint8 #51082
|
||||
pkg go/doc, method (*Package) Parser() *comment.Parser #51082
|
||||
pkg go/doc, method (*Package) Printer() *comment.Printer #51082
|
||||
pkg go/doc, method (*Package) Synopsis(string) string #51082
|
||||
pkg go/doc, method (*Package) Text(string) []uint8 #51082
|
||||
pkg go/doc/comment, func DefaultLookupPackage(string) (string, bool) #51082
|
||||
pkg go/doc/comment, method (*DocLink) DefaultURL(string) string #51082
|
||||
pkg go/doc/comment, method (*Heading) DefaultID() string #51082
|
||||
pkg go/doc/comment, method (*List) BlankBefore() bool #51082
|
||||
pkg go/doc/comment, method (*List) BlankBetween() bool #51082
|
||||
pkg go/doc/comment, method (*Parser) Parse(string) *Doc #51082
|
||||
pkg go/doc/comment, method (*Printer) Comment(*Doc) []uint8 #51082
|
||||
pkg go/doc/comment, method (*Printer) HTML(*Doc) []uint8 #51082
|
||||
pkg go/doc/comment, method (*Printer) Markdown(*Doc) []uint8 #51082
|
||||
pkg go/doc/comment, method (*Printer) Text(*Doc) []uint8 #51082
|
||||
pkg go/doc/comment, type Block interface, unexported methods #51082
|
||||
pkg go/doc/comment, type Code struct #51082
|
||||
pkg go/doc/comment, type Code struct, Text string #51082
|
||||
pkg go/doc/comment, type Doc struct #51082
|
||||
pkg go/doc/comment, type Doc struct, Content []Block #51082
|
||||
pkg go/doc/comment, type Doc struct, Links []*LinkDef #51082
|
||||
pkg go/doc/comment, type DocLink struct #51082
|
||||
pkg go/doc/comment, type DocLink struct, ImportPath string #51082
|
||||
pkg go/doc/comment, type DocLink struct, Name string #51082
|
||||
pkg go/doc/comment, type DocLink struct, Recv string #51082
|
||||
pkg go/doc/comment, type DocLink struct, Text []Text #51082
|
||||
pkg go/doc/comment, type Heading struct #51082
|
||||
pkg go/doc/comment, type Heading struct, Text []Text #51082
|
||||
pkg go/doc/comment, type Italic string #51082
|
||||
pkg go/doc/comment, type Link struct #51082
|
||||
pkg go/doc/comment, type Link struct, Auto bool #51082
|
||||
pkg go/doc/comment, type Link struct, Text []Text #51082
|
||||
pkg go/doc/comment, type Link struct, URL string #51082
|
||||
pkg go/doc/comment, type LinkDef struct #51082
|
||||
pkg go/doc/comment, type LinkDef struct, Text string #51082
|
||||
pkg go/doc/comment, type LinkDef struct, URL string #51082
|
||||
pkg go/doc/comment, type LinkDef struct, Used bool #51082
|
||||
pkg go/doc/comment, type List struct #51082
|
||||
pkg go/doc/comment, type List struct, ForceBlankBefore bool #51082
|
||||
pkg go/doc/comment, type List struct, ForceBlankBetween bool #51082
|
||||
pkg go/doc/comment, type List struct, Items []*ListItem #51082
|
||||
pkg go/doc/comment, type ListItem struct #51082
|
||||
pkg go/doc/comment, type ListItem struct, Content []Block #51082
|
||||
pkg go/doc/comment, type ListItem struct, Number string #51082
|
||||
pkg go/doc/comment, type Paragraph struct #51082
|
||||
pkg go/doc/comment, type Paragraph struct, Text []Text #51082
|
||||
pkg go/doc/comment, type Parser struct #51082
|
||||
pkg go/doc/comment, type Parser struct, LookupPackage func(string) (string, bool) #51082
|
||||
pkg go/doc/comment, type Parser struct, LookupSym func(string, string) bool #51082
|
||||
pkg go/doc/comment, type Parser struct, Words map[string]string #51082
|
||||
pkg go/doc/comment, type Plain string #51082
|
||||
pkg go/doc/comment, type Printer struct #51082
|
||||
pkg go/doc/comment, type Printer struct, DocLinkBaseURL string #51082
|
||||
pkg go/doc/comment, type Printer struct, DocLinkURL func(*DocLink) string #51082
|
||||
pkg go/doc/comment, type Printer struct, HeadingID func(*Heading) string #51082
|
||||
pkg go/doc/comment, type Printer struct, HeadingLevel int #51082
|
||||
pkg go/doc/comment, type Printer struct, TextCodePrefix string #51082
|
||||
pkg go/doc/comment, type Printer struct, TextPrefix string #51082
|
||||
pkg go/doc/comment, type Printer struct, TextWidth int #51082
|
||||
pkg go/doc/comment, type Text interface, unexported methods #51082
|
||||
1
api/next/51414.txt
Normal file
1
api/next/51414.txt
Normal file
@@ -0,0 +1 @@
|
||||
pkg time, method (Duration) Abs() Duration #51414
|
||||
2
api/next/51644.txt
Normal file
2
api/next/51644.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pkg encoding/binary, func AppendUvarint([]uint8, uint64) []uint8 #51644
|
||||
pkg encoding/binary, func AppendVarint([]uint8, int64) []uint8 #51644
|
||||
2
api/next/51684.txt
Normal file
2
api/next/51684.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pkg regexp/syntax, const ErrNestingDepth = "expression nests too deeply" #51684
|
||||
pkg regexp/syntax, const ErrNestingDepth ErrorCode #51684
|
||||
36
api/next/51868.txt
Normal file
36
api/next/51868.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY = 2 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH = 4 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST = 6 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES = 1 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE = 3 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_CODE = 32 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_CODE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA = 64 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA = 128 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT = 4096 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE = 33554432 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE = 536870912 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_READ = 1073741824 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_READ ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_WRITE = 2147483648 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_WRITE ideal-int #51686
|
||||
pkg debug/pe, method (*File) COFFSymbolReadSectionDefAux(int) (*COFFSymbolAuxFormat5, error) #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Checksum uint32 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumLineNumbers uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumRelocs uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, SecNum uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Selection uint8 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Size uint32 #51686
|
||||
@@ -1 +1,2 @@
|
||||
branch: master
|
||||
branch: dev.boringcrypto
|
||||
parent-branch: master
|
||||
|
||||
831
doc/go1.19.html
831
doc/go1.19.html
@@ -18,68 +18,22 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
release notes. Go 1.19 is expected to be released in August 2022.
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
<h2 id="language">Changes to the language</h2>
|
||||
|
||||
<p><!-- https://go.dev/issue/52038 -->
|
||||
There is only one small change to the language,
|
||||
a <a href="https://github.com/golang/go/issues/52038">very small correction</a>
|
||||
to the <a href="/ref/spec#Declarations_and_scope">scope of type parameters in method declarations</a>.
|
||||
Existing programs are unaffected.
|
||||
<p>
|
||||
TODO: complete this section
|
||||
</p>
|
||||
|
||||
<h2 id="mem">Memory Model</h2>
|
||||
|
||||
<p><!-- https://go.dev/issue/50859 -->
|
||||
The <a href="/ref/mem">Go memory model</a> has been revised to align Go with
|
||||
the memory model used by C, C++, Java, JavaScript, Rust, and Swift.
|
||||
Go only provides sequentially consistent atomics, not any of the more relaxed forms found in other languages.
|
||||
Along with the memory model update,
|
||||
Go 1.19 introduces <a href="#sync/atomic">new types in the <code>sync/atomic</code> package</a>
|
||||
that make it easier to use atomic values, such as
|
||||
<a href="/pkg/sync/atomic/#Int64">atomic.Int64</a>
|
||||
and
|
||||
<a href="/pkg/sync/atomic/#Pointer">atomic.Pointer[T]</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="ports">Ports</h2>
|
||||
|
||||
<p><!-- https://go.dev/issue/46229 -->
|
||||
Go 1.19 supports the Loongson 64-bit architecture LoongArch on Linux (<code>GOOS=linux</code>, <code>GOARCH=loong64</code>).
|
||||
<p>
|
||||
TODO: complete this section, or delete if not needed
|
||||
</p>
|
||||
|
||||
<h2 id="tools">Tools</h2>
|
||||
|
||||
<h3 id="go-doc">Doc Comments</h3>
|
||||
|
||||
<p><!-- https://go.dev/issue/51082 --><!-- CL 384265, CL 397276, CL 397278, CL 397279, CL 397281, CL 397284 -->
|
||||
Go 1.19 adds support for links, lists, and clearer headings in doc comments.
|
||||
As part of this change, <a href="/cmd/gofmt"><code>gofmt</code></a>
|
||||
now reformats doc comments to make their rendered meaning clearer.
|
||||
See “<a href="/doc/comment">Go Doc Comments</a>”
|
||||
for syntax details and descriptions of common mistakes now highlighted by <code>gofmt</code>.
|
||||
As another part of this change, the new package <a href="/pkg/go/doc/comment">go/doc/comment</a>
|
||||
provides parsing and reformatting of doc comments
|
||||
as well as support for rendering them to HTML, Markdown, and text.
|
||||
<p>
|
||||
TODO: complete this section, or delete if not needed
|
||||
</p>
|
||||
|
||||
<h3 id="go-unix">New <code>unix</code> build constraint</h4>
|
||||
|
||||
<p><!-- CL 389934 --><!-- https://go.dev/issue/20322 --><!-- https://go.dev/issue/51572 -->
|
||||
The build constraint <code>unix</code> is now recognized
|
||||
in <code>//go:build</code> lines. The constraint is satisfied
|
||||
if the target operating system, also known as <code>GOOS</code>, is
|
||||
a Unix or Unix-like system. For the 1.19 release it is satisfied
|
||||
if <code>GOOS</code> is one of
|
||||
<code>aix</code>, <code>android</code>, <code>darwin</code>,
|
||||
<code>dragonfly</code>, <code>freebsd</code>, <code>hurd</code>,
|
||||
<code>illumos</code>, <code>ios</code>, <code>linux</code>,
|
||||
<code>netbsd</code>, <code>openbsd</code>, or <code>solaris</code>.
|
||||
In future releases the <code>unix</code> constraint may match
|
||||
additional newly supported operating systems.
|
||||
</p>
|
||||
|
||||
<h3 id="go-command">Go command</h3>
|
||||
<p>
|
||||
TODO: complete this section.
|
||||
</p>
|
||||
|
||||
<!-- https://go.dev/issue/51461 -->
|
||||
<p>
|
||||
@@ -96,504 +50,70 @@ as well as support for rendering them to HTML, Markdown, and text.
|
||||
with <code>-trimpath</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 404134 -->
|
||||
<code>go</code> <code>test</code> and <code>go</code> <code>generate</code> now place
|
||||
<code>GOROOT/bin</code> at the beginning of the <code>PATH</code> used for the
|
||||
subprocess, so tests and generators that execute the <code>go</code> command
|
||||
will resolve it to same <code>GOROOT</code>.
|
||||
</p>
|
||||
<h4 id="go-unix">New <code>unix</code> build constraint</h4>
|
||||
|
||||
<p><!-- CL 398058 -->
|
||||
<code>go</code> <code>env</code> now quotes entries that contain spaces in
|
||||
the <code>CGO_CFLAGS</code>, <code>CGO_CPPFLAGS</code>, <code>CGO_CXXFLAGS</code>, <code>CGO_FFLAGS</code>, <code>CGO_LDFLAGS</code>,
|
||||
and <code>GOGCCFLAGS</code> variables it reports.
|
||||
</p>
|
||||
|
||||
<h3 id="vet">Vet</h3>
|
||||
|
||||
<p><!-- https://go.dev/issue/47528 -->:
|
||||
The <code>vet</code> checker “errorsas” now reports when
|
||||
<a href="/pkg/errors/#As"><code>errors.As</code></a> is called
|
||||
with a second argument of type <code>*error</code>,
|
||||
a common mistake.
|
||||
<p><!-- CL 389934 -->
|
||||
The build constraint <code>unix</code> is now recognized
|
||||
in <code>//go:build</code> lines. The constraint is satisfied
|
||||
if the target operating system, also known as <code>GOOS</code>, is
|
||||
a Unix or Unix-like system. For the 1.19 release it is satisfied
|
||||
if <code>GOOS</code> is one of
|
||||
<code>aix</code>, <code>android</code>, <code>darwin</code>,
|
||||
<code>dragonfly</code>, <code>freebsd</code>, <code>hurd</code>,
|
||||
<code>illumos</code>, <code>ios</code>, <code>linux</code>,
|
||||
<code>netbsd</code>, <code>openbsd</code>, or <code>solaris</code>.
|
||||
In future releases the <code>unix</code> constraint may match
|
||||
additional newly supported operating systems.
|
||||
</p>
|
||||
|
||||
<h2 id="runtime">Runtime</h2>
|
||||
|
||||
<p><!-- https://go.dev/issue/48409 --><!-- CL 397018 -->
|
||||
The runtime now includes support for a soft memory limit. This memory limit
|
||||
includes the Go heap and all other memory managed by the runtime, and
|
||||
excludes external memory sources such as mappings of the binary itself,
|
||||
memory managed in other languages, and memory held by the operating system on
|
||||
behalf of the Go program. This limit may be managed via
|
||||
<a href="/pkg/runtime/debug/#SetMemoryLimit"><code>runtime/debug.SetMemoryLimit</code></a>
|
||||
or the equivalent
|
||||
<a href="/pkg/runtime/#hdr-Environment_Variables"><code>GOMEMLIMIT</code></a>
|
||||
environment variable. The limit works in conjunction with
|
||||
<a href="/pkg/runtime/debug/#SetGCPercent"><code>runtime/debug.SetGCPercent</code></a>
|
||||
/ <a href="/pkg/runtime/#hdr-Environment_Variables"><code>GOGC</code></a>,
|
||||
and will be respected even if <code>GOGC=off</code>, allowing Go programs to
|
||||
always make maximal use of their memory limit, improving resource efficiency
|
||||
in some cases. See <a href="https://go.dev/doc/gc-guide">the GC guide</a> for
|
||||
a detailed guide explaining the soft memory limit in more detail, as well as
|
||||
a variety of common use-cases and scenarios. Please note that small memory
|
||||
limits, on the order of tens of megabytes or less, are less likely to be
|
||||
respected due to external latency factors, such as OS scheduling. See
|
||||
<a href="https://go.dev/issue/52433">issue 52433</a> for more details. Larger
|
||||
memory limits, on the order of hundreds of megabytes or more, are stable and
|
||||
production-ready.
|
||||
<p>
|
||||
TODO: complete this section, or delete if not needed
|
||||
</p>
|
||||
|
||||
<p><!-- CL 353989 -->
|
||||
In order to limit the effects of GC thrashing when the program's live heap
|
||||
size approaches the soft memory limit, the Go runtime also attempts to limit
|
||||
total GC CPU utilization to 50%, excluding idle time, choosing to use more
|
||||
memory over preventing application progress. In practice, we expect this limit
|
||||
to only play a role in exceptional cases, and the new
|
||||
<a href="/pkg/runtime/metrics/#hdr-Supported_metrics">runtime metric</a>
|
||||
<code>/gc/limiter/last-enabled:gc-cycle</code> reports when this last
|
||||
occurred.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/44163 -->
|
||||
The runtime now schedules many fewer GC worker goroutines on idle operating
|
||||
system threads when the application is idle enough to force a periodic GC
|
||||
cycle.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/18138 --><!-- CL 345889 -->
|
||||
The runtime will now allocate initial goroutine stacks based on the historic
|
||||
average stack usage of goroutines. This avoids some of the early stack growth
|
||||
and copying needed in the average case in exchange for at most 2x wasted
|
||||
space on below-average goroutines.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/46279 --><!-- CL 393354 --><!-- CL 392415 -->
|
||||
On Unix operating systems, Go programs that import package
|
||||
<a href="/pkg/os/">os</a> now automatically increase the open file limit
|
||||
(<code>RLIMIT_NOFILE</code>) to the maximum allowed value;
|
||||
that is, they change the soft limit to match the hard limit.
|
||||
This corrects artificially low limits set on some systems for compatibility with very old C programs using the
|
||||
<a href="https://en.wikipedia.org/wiki/Select_(Unix)"><i>select</i></a> system call.
|
||||
Go programs are not helped by that limit, and instead even simple programs like <code>gofmt</code>
|
||||
often ran out of file descriptors on such systems when processing many files in parallel.
|
||||
One impact of this change is that Go programs that in turn execute very old C programs in child processes
|
||||
may run those programs with too high a limit.
|
||||
This can be corrected by setting the hard limit before invoking the Go program.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/51485 --><!-- CL 390421 -->
|
||||
Unrecoverable fatal errors (such as concurrent map writes, or unlock of
|
||||
unlocked mutexes) now print a simpler traceback excluding runtime metadata
|
||||
(equivalent to a fatal panic) unless <code>GOTRACEBACK=system</code> or
|
||||
<code>crash</code>. Runtime-internal fatal error tracebacks always include
|
||||
full metadata regardless of the value of <code>GOTRACEBACK</code>
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/50614 --><!-- CL 395754 -->
|
||||
Support for debugger-injected function calls has been added on ARM64,
|
||||
enabling users to call functions from their binary in an interactive
|
||||
debugging session when using a debugger that is updated to make use of this
|
||||
functionality.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/44853 -->
|
||||
The <a href="/doc/go1.18#go-build-asan">address sanitizer support added in Go 1.18</a>
|
||||
now handles function arguments and global variables more precisely.
|
||||
</p>
|
||||
|
||||
<h2 id="compiler">Compiler</h2>
|
||||
|
||||
<p><!-- https://go.dev/issue/5496 --><!-- CL 357330, 395714, 403979 -->
|
||||
The compiler now uses
|
||||
a <a href="https://en.wikipedia.org/wiki/Branch_table">jump
|
||||
table</a> to implement large integer and string switch statements.
|
||||
Performance improvements for the switch statement vary but can be
|
||||
on the order of 20% faster.
|
||||
(<code>GOARCH=amd64</code> and <code>GOARCH=arm64</code> only)
|
||||
<p>
|
||||
TODO: complete this section, or delete if not needed
|
||||
</p>
|
||||
<p><!-- CL 402374 -->
|
||||
The <code>riscv64</code> port now supports passing function arguments
|
||||
and result using registers. Benchmarking shows typical performance
|
||||
improvements of 10% or more on <code>riscv64</code>.
|
||||
</p>
|
||||
<p><!-- CL 391014 -->
|
||||
The Go compiler now requires the <code>-p=importpath</code> flag to
|
||||
build a linkable object file. This is already supplied by
|
||||
the <code>go</code> command and by Bazel. Any other build systems
|
||||
that invoke the Go compiler directly will need to make sure they
|
||||
pass this flag as well.
|
||||
</p>
|
||||
|
||||
<h2 id="assembler">Assembler</h2>
|
||||
<p><!-- CL 404298 -->
|
||||
Like the compiler, the assembler now requires the
|
||||
<code>-p=importpath</code> flag to build a linkable object file.
|
||||
This is already supplied by the <code>go</code> command. Any other
|
||||
build systems that invoke the Go assembler directly will need to
|
||||
make sure they pass this flag as well.
|
||||
</p>
|
||||
|
||||
<h2 id="linker">Linker</h2>
|
||||
<p><!-- https://go.dev/issue/50796, CL 380755 -->
|
||||
On ELF platforms, the linker now emits compressed DWARF sections in
|
||||
the standard gABI format (<code>SHF_COMPRESSED</code>), instead of
|
||||
the legacy <code>.zdebug</code> format.
|
||||
<p>
|
||||
TODO: complete this section, or delete if not needed
|
||||
</p>
|
||||
|
||||
<h2 id="library">Core library</h2>
|
||||
|
||||
<h3 id="atomic_types">New atomic types</h3>
|
||||
|
||||
<p><!-- https://go.dev/issue/50860 --><!-- CL 381317 -->
|
||||
The <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> package defines new atomic types
|
||||
<a href="/pkg/sync/atomic/#Bool"><code>Bool</code></a>,
|
||||
<a href="/pkg/sync/atomic/#Int32"><code>Int32</code></a>,
|
||||
<a href="/pkg/sync/atomic/#Int64"><code>Int64</code></a>,
|
||||
<a href="/pkg/sync/atomic/#Uint32"><code>Uint32</code></a>,
|
||||
<a href="/pkg/sync/atomic/#Uint64"><code>Uint64</code></a>,
|
||||
<a href="/pkg/sync/atomic/#Uintptr"><code>Uintptr</code></a>, and
|
||||
<a href="/pkg/sync/atomic/#Pointer"><code>Pointer</code></a>.
|
||||
These types hide the underlying values so that all accesses are forced to use
|
||||
the atomic APIs.
|
||||
<a href="/pkg/sync/atomic/#Pointer"><code>Pointer</code></a> also avoids
|
||||
the need to convert to
|
||||
<a href="/pkg/unsafe/#Pointer"><code>unsafe.Pointer</code></a> at call sites.
|
||||
<a href="/pkg/sync/atomic/#Int64"><code>Int64</code></a> and
|
||||
<a href="/pkg/sync/atomic/#Uint64"><code>Uint64</code></a> are
|
||||
automatically aligned to 64-bit boundaries in structs and allocated data,
|
||||
even on 32-bit systems.
|
||||
<p>
|
||||
TODO: complete this section
|
||||
</p>
|
||||
|
||||
<h3 id="os-exec-path">PATH lookups</h3>
|
||||
|
||||
<p><!-- https://go.dev/issue/43724 -->
|
||||
<!-- CL 381374 --><!-- CL 403274 -->
|
||||
<a href="/pkg/os/exec/#Command"><code>Command</code></a> and
|
||||
<a href="/pkg/os/exec/#LookPath"><code>LookPath</code></a> no longer
|
||||
allow results from a PATH search to be found relative to the current directory.
|
||||
This removes a <a href="https://go.dev/blog/path-security">common source of security problems</a>
|
||||
but may also break existing programs that depend on using, say, <code>exec.Command("prog")</code>
|
||||
to run a binary named <code>prog</code> (or, on Windows, <code>prog.exe</code>) in the current directory.
|
||||
See the <a href="/pkg/os/exec/"><code>os/exec</code></a> package documentation for
|
||||
information about how best to update such programs.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/43947 -->
|
||||
On Windows, <code>Command</code> and <code>LookPath</code> now respect the
|
||||
<a href="https://docs.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-needcurrentdirectoryforexepatha"><code>NoDefaultCurrentDirectoryInExePath</code></a>
|
||||
environment variable, making it possible to disable
|
||||
the default implicit search of “<code>.</code>” in PATH lookups on Windows systems.
|
||||
</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.
|
||||
There are also various performance improvements, not enumerated here.
|
||||
</p>
|
||||
|
||||
<dl id="archive/zip"><dt><a href="/pkg/archive/zip/">archive/zip</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 387976 -->
|
||||
<a href="/pkg/archive/zip/#Reader"><code>Reader</code></a>
|
||||
now ignores non-ZIP data at the start of a ZIP file, matching most other implementations.
|
||||
This is necessary to read some Java JAR files, among other uses.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- archive/zip -->
|
||||
|
||||
<dl id="crypto/rand"><dt><a href="/pkg/crypto/rand/">crypto/rand</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 370894 --><!-- CL 390038 -->
|
||||
<a href="/pkg/crypto/rand/#Read"><code>Read</code></a> no longer buffers
|
||||
random data obtained from the operating system between calls.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 375215 -->
|
||||
On Plan 9, <code>Read</code> has been reimplemented, replacing the ANSI
|
||||
X9.31 algorithm with fast key erasure.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/rand -->
|
||||
<p>
|
||||
TODO: complete this section
|
||||
</p>
|
||||
|
||||
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 400974 --><!-- https://go.dev/issue/45428 -->
|
||||
<p><!-- CL 400974 -->
|
||||
The <code>tls10default</code> <code>GODEBUG</code> option has been
|
||||
removed. It is still possible to enable TLS 1.0 client-side by setting
|
||||
<a href="/pkg/crypto/tls#Config.MinVersion"><code>Config.MinVersion</code></a>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 384894 -->
|
||||
The TLS server and client now reject duplicate extensions in TLS
|
||||
handshakes, as required by RFC 5246, Section 7.4.1.4 and RFC 8446, Section
|
||||
4.2.
|
||||
<code>Config.MinVersion</code>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/tls -->
|
||||
|
||||
<dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 285872 -->
|
||||
<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
|
||||
no longer supports creating certificates with <code>SignatureAlgorithm</code>
|
||||
set to <code>MD5WithRSA</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 400494 -->
|
||||
<code>CreateCertificate</code> no longer accepts negative serial numbers.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 383215 -->
|
||||
<a href="/pkg/crypto/x509/#ParseCertificate"><code>ParseCertificate</code></a>
|
||||
and <a href="/pkg/crypto/x509/#ParseCertificateRequest"><code>ParseCertificateRequest</code></a>
|
||||
now reject certificates and CSRs which contain duplicate extensions.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/46057 --><!-- https://go.dev/issue/35044 --><!-- CL 398237 --><!-- CL 400175 --><!-- CL 388915 -->
|
||||
The new <a href="/pkg/crypto/x509/#CertPool.Clone"><code>CertPool.Clone</code></a>
|
||||
and <a href="/pkg/crypto/x509/#CertPool.Equal"><code>CertPool.Equal</code></a>
|
||||
methods allow cloning a <code>CertPool</code> and checking the equality of two
|
||||
<code>CertPool</code>s respectively.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/50674 --><!-- CL 390834 -->
|
||||
The new function <a href="/pkg/crypto/x509/#ParseRevocationList"><code>ParseRevocationList</code></a>
|
||||
provides a faster, safer to use CRL parser which returns a
|
||||
<a href="/pkg/crypto/x509/#RevocationList"><code>RevocationList</code></a>.
|
||||
To support this addition, <code>RevocationList</code> adds new fields
|
||||
<code>RawIssuer</code>, <code>Signature</code>,
|
||||
<code>AuthorityKeyId</code>, and <code>Extensions</code>.
|
||||
|
||||
The new method <a href="/pkg/crypto/x509/#RevocationList.CheckSignatureFrom"><code>RevocationList.CheckSignatureFrom</a>
|
||||
checks that the signature on a CRL is a valid signature from a
|
||||
<a href="/pkg/crypto/x509/#Certificate">Certificate</a>.
|
||||
|
||||
With the new CRL functionality, the existing functions
|
||||
<a href="/pkg/crypto/x509/#ParseCRL"><code>ParseCRL</code></a> and
|
||||
<a href="/pkg/crypto/x509/#ParseDERCRL"><code>ParseDERCRL</code></a> are deprecated.
|
||||
Additionally the method <a href="/pkg/crypto/x509#Certificate.CheckCRLSignature"><code>Certificate.CheckCRLSignature</code></a>
|
||||
is deprecated.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 389555 -->
|
||||
When building paths, <a href="/pkg/crypto/x509/#Certificate.Verify"><code>Certificate.Verify</code></a>
|
||||
now considers certificates to be equal when the subjects, public keys, and SANs
|
||||
are all equal. Before, it required byte-for-byte equality.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/x509 -->
|
||||
|
||||
<dl id="crypto/x509/pkix"><dt><a href="/pkg/crypto/x509/pkix">crypto/x509/pkix</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 390834 -->
|
||||
The types <a href="/pkg/crypto/x509/pkix#CertificateList"><code>CertificateList</code></a> and
|
||||
<a href="/pkg/crypto/x509/pkix#TBSCertificateList"><code>TBSCertificateList</code></a>
|
||||
have been deprecated. The new <a href="#crypto/x509"><code>crypto/x509</code></code> CRL functionality</a>
|
||||
should be used instead.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/x509/pkix -->
|
||||
|
||||
<dl id="debug"><dt><a href="/pkg/debug/">debug</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 396735 -->
|
||||
The new <code>EM_LONGARCH</code> and <code>R_LARCH_*</code> constants
|
||||
support the loong64 port.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- debug -->
|
||||
|
||||
<dl id="debug/pe"><dt><a href="/pkg/debug/pe/">debug/pe</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/51868 --><!-- CL 394534 -->
|
||||
The new <a href="/pkg/debug/pe/#File.COFFSymbolReadSectionDefAux"><code>File.COFFSymbolReadSectionDefAux</code></a>
|
||||
method, which returns a <a href="/pkg/debug/pe/#COFFSymbolAuxFormat5"><code>COFFSymbolAuxFormat5</code></a>,
|
||||
provides access to COMDAT information in PE file sections.
|
||||
These are supported by new <code>IMAGE_COMDAT_*</code> and <code>IMAGE_SCN_*</code> constants.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- debug/pe -->
|
||||
|
||||
<dl id="encoding/binary"><dt><a href="/pkg/encoding/binary/">encoding/binary</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/50601 --><!-- CL 386017 --><!-- CL 389636 -->
|
||||
The new interface
|
||||
<a href="/pkg/encoding/binary/#AppendByteOrder"><code>AppendByteOrder</code></a>
|
||||
provides efficient methods for appending a <code>uint16</code>, <code>uint32</code>, or <code>uint64</code>
|
||||
to a byte slice.
|
||||
<a href="/pkg/encoding/binary/#BigEndian"><code>BigEndian</code></a> and
|
||||
<a href="/pkg/encoding/binary/#LittleEndian"><code>LittleEndian</code></a> now implement this interface.
|
||||
</p>
|
||||
<p><!-- https://go.dev/issue/51644 --><!-- CL 400176 -->
|
||||
Similarly, the new functions
|
||||
<a href="/pkg/encoding/binary/#AppendUvarint"><code>AppendUvarint</code></a> and
|
||||
<a href="/pkg/encoding/binary/#AppendVarint"><code>AppendVarint</code></a>
|
||||
are efficient appending versions of
|
||||
<a href="/pkg/encoding/binary/#PutUvarint"><code>PutUvarint</code></a> and
|
||||
<a href="/pkg/encoding/binary/#PutVarint"><code>PutVarint</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- encoding/binary -->
|
||||
|
||||
<dl id="encoding/csv"><dt><a href="/pkg/encoding/csv/">encoding/csv</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/43401 --><!-- CL 405675 -->
|
||||
The new method
|
||||
<a href="/pkg/encoding/csv/#Reader.InputOffset"><code>Reader.InputOffset</code></a>
|
||||
reports the reader's current input position as a byte offset,
|
||||
analogous to <code>encoding/json</code>'s
|
||||
<a href="/pkg/encoding/json/#Decoder.InputOffset"><code>Decoder.InputOffset</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- encoding/csv -->
|
||||
|
||||
<dl id="encoding/xml"><dt><a href="/pkg/encoding/xml/">encoding/xml</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/45628 --><!-- CL 311270 -->
|
||||
The new method
|
||||
<a href="/pkg/encoding/xml/#Decoder.InputPos"><code>Decoder.InputPos</code></a>
|
||||
reports the reader's current input position as a line and column,
|
||||
analogous to <code>encoding/csv</code>'s
|
||||
<a href="/pkg/encoding/csv/#Decoder.FieldPos"><code>Decoder.FieldPos</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- encoding/xml -->
|
||||
|
||||
<dl id="flag"><dt><a href="/pkg/flag/">flag</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/45754 --><!-- CL 313329 -->
|
||||
The new function
|
||||
<a href="/pkg/flag/#TextVar"><code>TextVar</code></a>
|
||||
defines a flag with a value implementing
|
||||
<a href="/pkg/encoding/#TextUnmarshaler"><code>encoding.TextUnmarshaler</code></a>,
|
||||
allowing command-line flag variables to have types such as
|
||||
<a href="/pkg/math/big/#Int"><code>big.Int</code></a>,
|
||||
<a href="/pkg/net/netip/#Addr"><code>netip.Addr</code></a>, and
|
||||
<a href="/pkg/time/#Time"><code>time.Time</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- flag -->
|
||||
|
||||
<dl id="fmt"><dt><a href="/pkg/fmt/">fmt</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/47579 --><!-- CL 406177 -->
|
||||
The new functions
|
||||
<a href="/pkg/fmt/#Append"><code>Append</code></a>,
|
||||
<a href="/pkg/fmt/#Appendf"><code>Appendf</code></a>, and
|
||||
<a href="/pkg/fmt/#Appendln"><code>Appendln</code></a>
|
||||
append formatted data to byte slices.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- fmt -->
|
||||
|
||||
<dl id="go/parser"><dt><a href="/pkg/go/parser/">go/parser</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 403696 -->
|
||||
The parser now recognizes <code>~x</code> as a unary expression with operator
|
||||
<a href="/pkg/go/token#TILDE">token.TILDE</a>,
|
||||
allowing better error recovery when a type constraint such as <code>~int</code> is used in an incorrect context.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- go/parser -->
|
||||
|
||||
<dl id="go/types"><dt><a href="/pkg/go/types/">go/types</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/51682 --><!-- CL 395535 -->
|
||||
The new methods <a href="/pkg/go/types/#Func.Origin"><code>Func.Origin</code></a>
|
||||
and <a href="/pkg/go/types/#Var.Origin"><code>Var.Origin</code></a> return the
|
||||
corresponding <a href="/pkg/go/types/#Object"><code>Object</code></a> of the
|
||||
generic type for synthetic <a href="/pkg/go/types/#Func"><code>Func</code></a>
|
||||
and <a href="/pkg/go/types/#Var"><code>Var</code></a> objects created during type
|
||||
instantiation.
|
||||
</p>
|
||||
<p><!-- https://go.dev/issue/52728 --><!-- CL 404885 -->
|
||||
It is no longer possible to produce an infinite number of distinct-but-identical
|
||||
<a href="/pkg/go/types/#Named"><code>Named</code></a> type instantiations via
|
||||
recursive calls to
|
||||
<a href="/pkg/go/types/#Named.Underlying"><code>Named.Underlying</code></a> or
|
||||
<a href="/pkg/go/types/#Named.Method"><code>Named.Method</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- go/types -->
|
||||
|
||||
|
||||
<dl id="hash/maphash"><dt><a href="/pkg/hash/maphash/">hash/maphash</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/42710 --><!-- CL 392494 -->
|
||||
The new functions
|
||||
<a href="/pkg/hash/maphash/#Bytes"><code>Bytes</code></a>
|
||||
and
|
||||
<a href="/pkg/hash/maphash/#String"><code>String</code></a>
|
||||
provide an efficient way hash a single byte slice or string.
|
||||
They are equivalent to using the more general
|
||||
<a href="/pkg/hash/maphash/#Hash"><code>Hash</code></a>
|
||||
with a single write, but they avoid setup overhead for small inputs.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- hash/maphash -->
|
||||
|
||||
<dl id="html/template"><dt><a href="/pkg/html/template/">html/template</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/46121 --><!-- CL 389156 -->
|
||||
The type <a href="/pkg/html/template/#FuncMap"><code>FuncMap</code></a>
|
||||
is now an alias for
|
||||
<code>text/template</code>'s <a href="/pkg/text/template/#FuncMap"><code>FuncMap</code></a>
|
||||
instead of its own named type.
|
||||
This allows writing code that operates on a <code>FuncMap</code> from either setting.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- html/template -->
|
||||
|
||||
<dl id="image/draw"><dt><a href="/pkg/image/draw/">image/draw</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 396795 -->
|
||||
<a href="/pkg/image/draw/#Draw"><code>Draw</code></a> with the
|
||||
<a href="/pkg/image/draw/#Src"><code>Src</code></a> operator preserves
|
||||
<code>Draw</code> with the <code>Src</code> operator preserves
|
||||
non-premultiplied-alpha colors when destination and source images are
|
||||
both <a href="/pkg/image/#NRGBA"><code>image.NRGBA</code></a>
|
||||
or both <a href="/pkg/image/#NRGBA64"><code>image.NRGBA64</code></a>.
|
||||
both <code>*image.NRGBA</code> (or both <code>*image.NRGBA64</code>).
|
||||
This reverts a behavior change accidentally introduced by a Go 1.18
|
||||
library optimization; the code now matches the behavior in Go 1.17 and earlier.
|
||||
library optimization, to match the behavior in Go 1.17 and earlier.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- image/draw -->
|
||||
|
||||
<dl id="io"><dt><a href="/pkg/io/">io</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/51566 --><!-- CL 400236 -->
|
||||
<a href="/pkg/io/#NopCloser"><code>NopCloser</code></a>'s result now implements
|
||||
<a href="/pkg/io/#WriterTo"><code>WriterTo</code></a>
|
||||
whenever its input does.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/50842 -->
|
||||
<a href="/pkg/io/#MultiReader"><code>MultiReader</code></a>'s result now implements
|
||||
<a href="/pkg/io/#WriterTo"><code>WriterTo</code></a> unconditionally.
|
||||
If any underlying reader does not implement <code>WriterTo</code>,
|
||||
it is simulated appropriately.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- io -->
|
||||
|
||||
<dl id="mime"><dt><a href="/pkg/mime/">mime</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 406894 -->
|
||||
On Windows only, the mime package now ignores a registry entry
|
||||
recording that the extension <code>.js</code> should have MIME
|
||||
type <code>text/plain</code>. This is a common unintentional
|
||||
misconfiguration on Windows systems. The effect is
|
||||
that <code>.js</code> will have the default MIME
|
||||
type <code>text/javascript; charset=utf-8</code>.
|
||||
Applications that expect <code>text/plain</code> on Windows must
|
||||
now explicitly call
|
||||
<a href="/pkg/mime/#AddExtensionType"><code>AddExtensionType</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 386016 -->
|
||||
@@ -608,134 +128,39 @@ as well as support for rendering them to HTML, Markdown, and text.
|
||||
issue tracker</a>.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/51428 --><!-- CL 396877 -->
|
||||
<p><!-- CL 396877 -->
|
||||
When a net package function or method returns an "I/O timeout"
|
||||
error, the error will now satisfy <code>errors.Is(err,
|
||||
context.DeadlineExceeded)</code>. When a net package function
|
||||
returns an "operation was canceled" error, the error will now
|
||||
satisfy <code>errors.Is(err, context.Canceled)</code>.
|
||||
These changes are intended to make it easier for code to test
|
||||
for cases in which a context cancellation or timeout causes a net
|
||||
for cases in which a context cancelation or timeout causes a net
|
||||
package function or method to return an error, while preserving
|
||||
backward compatibility for error messages.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/33097 --><!-- CL 400654 -->
|
||||
<a href="/pkg/net/#Resolver.PreferGo"><code>Resolver.PreferGo</code></a>
|
||||
is now implemented on Windows and Plan 9. It previously only worked on Unix
|
||||
platforms. Combined with
|
||||
<a href="/pkg/net/#Dialer.Resolver"><code>Dialer.Resolver</code></a> and
|
||||
<a href="/pkg/net/#Resolver.Dial"><code>Resolver.Dial</code></a>, it's now
|
||||
possible to write portable programs and be in control of all DNS name lookups
|
||||
when dialing.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>net</code> package now has initial support for the <code>netgo</code>
|
||||
build tag on Windows. When used, the package uses the Go DNS client (as used
|
||||
by <code>Resolver.PreferGo</code>) instead of asking Windows for
|
||||
DNS results. The upstream DNS server it discovers from Windows
|
||||
may not yet be correct with complex system network configurations, however.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- net -->
|
||||
|
||||
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 269997 -->
|
||||
<a href="/pkg/net/http/#ResponseWriter"><code>ResponseWriter.WriteHeader</code></a>
|
||||
now supports sending user-defined 1xx informational headers.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 361397 -->
|
||||
The <code>io.ReadCloser</code> returned by
|
||||
<a href="/pkg/net/http/#MaxBytesReader"><code>MaxBytesReader</code></a>
|
||||
will now return the defined error type
|
||||
<a href="/pkg/net/http/#MaxBytesError"><code>MaxBytesError</code></a>
|
||||
when its read limit is exceeded.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 375354 -->
|
||||
The HTTP client will handle a 3xx response without a
|
||||
<code>Location</code> header by returning it to the caller,
|
||||
rather than treating it as an error.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- net/http -->
|
||||
|
||||
<dl id="net/url"><dt><a href="/pkg/net/url/">net/url</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 374654 -->
|
||||
The new
|
||||
<a href="/pkg/net/url/#JoinPath"><code>JoinPath</code></a>
|
||||
function and
|
||||
<a href="/pkg/net/url/#URL.JoinPath"><code>URL.JoinPath</code></a>
|
||||
method create a new <code>URL</code> by joining a list of path
|
||||
elements.
|
||||
</p>
|
||||
<p><!-- https://go.dev/issue/46059 -->
|
||||
The <code>URL</code> type now distinguishes between URLs with no
|
||||
authority and URLs with an empty authority. For example,
|
||||
<code>http:///path</code> has an empty authority (host),
|
||||
while <code>http:/path</code> has none.
|
||||
</p>
|
||||
<p>
|
||||
The new <a href="/pkg/net/url/#URL"><code>URL</code></a> field
|
||||
<code>OmitHost</code> is set to <code>true</code> when a
|
||||
<code>URL</code> has an empty authority.
|
||||
</p>
|
||||
|
||||
</dd>
|
||||
</dl><!-- net/url -->
|
||||
|
||||
<dl id="os/exec"><dt><a href="/pkg/os/exec/">os/exec</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/50599 --><!-- CL 401340 -->
|
||||
A <a href="/pkg/os/exec/#Cmd"><code>Cmd</code></a> with a non-empty <code>Dir</code> field
|
||||
and nil <code>Env</code> now implicitly sets the <code>PWD</code> environment
|
||||
<dd><!-- https://go.dev/issue/50599 -->
|
||||
<p>
|
||||
An <code>exec.Cmd</code> with a non-empty <code>Dir</code> and a
|
||||
nil <code>Env</code> now implicitly sets the <code>PWD</code> environment
|
||||
variable for the subprocess to match <code>Dir</code>.
|
||||
</p>
|
||||
<p>
|
||||
The new method <a href="/pkg/os/exec/#Cmd.Environ"><code>Cmd.Environ</code></a> reports the
|
||||
The new method <code>(*exec.Cmd).Environ</code> reports the
|
||||
environment that would be used to run the command, including the
|
||||
implicitly set <code>PWD</code> variable.
|
||||
aforementioned <code>PWD</code> variable.
|
||||
</p>
|
||||
</dd>
|
||||
</dl> <!-- os/exec -->
|
||||
|
||||
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/47066 --><!-- CL 357331 -->
|
||||
The method <a href="/pkg/reflect/#Value.Bytes"><code>Value.Bytes</code></a>
|
||||
now accepts addressable arrays in addition to slices.
|
||||
</p>
|
||||
<p><!-- CL 400954 -->
|
||||
The methods <a href="/pkg/reflect/#Value.Len"><code>Value.Len</code></a>
|
||||
and <a href="/pkg/reflect/#Value.Cap"><code>Value.Cap</code></a>
|
||||
now successfully operate on a pointer to an array and return the length of that array,
|
||||
to match what the <a href="https://go.dev/ref/spec#Length_and_capacity">builtin
|
||||
<code>len</code> and <code>cap</code> functions do</a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- reflect -->
|
||||
|
||||
<dl id="regexp/syntax"><dt><a href="/pkg/regexp/syntax/">regexp/syntax</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/51684 --><!-- CL 401076 -->
|
||||
Go 1.18 release candidate 1, Go 1.17.8, and Go 1.16.15 included a security fix
|
||||
to the regular expression parser, making it reject very deeply nested expressions.
|
||||
Because Go patch releases do not introduce new API,
|
||||
the parser returned <a href="/pkg/regexp/syntax/#ErrInternalError"><code>syntax.ErrInternalError</code></a> in this case.
|
||||
Go 1.19 adds a more specific error, <a href="/pkg/regexp/syntax/#ErrNestingDepth"><code>syntax.ErrNestingDepth</code></a>,
|
||||
which the parser now returns instead.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- regexp -->
|
||||
|
||||
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/51461 -->
|
||||
The <a href="/pkg/runtime/#GOROOT"><code>GOROOT</code></a> function now returns the empty string
|
||||
The <code>GOROOT</code> function now returns the empty string
|
||||
(instead of <code>"go"</code>) when the binary was built with
|
||||
the <code>-trimpath</code> flag set and the <code>GOROOT</code>
|
||||
variable is not set in the process environment.
|
||||
@@ -743,168 +168,12 @@ as well as support for rendering them to HTML, Markdown, and text.
|
||||
</dd>
|
||||
</dl><!-- runtime -->
|
||||
|
||||
<dl id="runtime/metrics"><dt><a href="/pkg/runtime/metrics/">runtime/metrics</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/47216 --><!-- CL 404305 -->
|
||||
The new <code>/sched/gomaxprocs:threads</code>
|
||||
<a href="/pkg/runtime/metrics/#hdr-Supported_metrics">metric</a> reports
|
||||
the current
|
||||
<a href="/pkg/runtime/#GOMAXPROCS"><code>runtime.GOMAXPROCS</code></a>
|
||||
value.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/47216 --><!-- CL 404306 -->
|
||||
The new <code>/cgo/go-to-c-calls:calls</code>
|
||||
<a href="/pkg/runtime/metrics/#hdr-Supported_metrics">metric</a>
|
||||
reports the total number of calls made from Go to C. This metric is
|
||||
identical to the
|
||||
<a href="/pkg/runtime/#NumCgoCall"><code>runtime.NumCgoCall</code></a>
|
||||
function.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/48409 --><!-- CL 403614 -->
|
||||
The new <code>/gc/limiter/last-enabled:gc-cycle</code>
|
||||
<a href="/pkg/runtime/metrics/#hdr-Supported_metrics">metric</a>
|
||||
reports the last GC cycle when the GC CPU limiter was enabled. See the
|
||||
<a href="#runtime">runtime notes</a> for details about the GC CPU limiter.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- runtime/metrics -->
|
||||
|
||||
<dl id="runtime/pprof"><dt><a href="/pkg/runtime/pprof/">runtime/pprof</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/33250 --><!-- CL 387415 -->
|
||||
Stop-the-world pause times have been significantly reduced when
|
||||
collecting goroutine profiles, reducing the overall latency impact to the
|
||||
application.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 391434 -->
|
||||
<code>MaxRSS</code> is now reported in heap profiles for all Unix
|
||||
operating systems (it was previously only reported for
|
||||
<code>GOOS=android</code>, <code>darwin</code>, <code>ios</code>, and
|
||||
<code>linux</code>).
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- runtime/pprof -->
|
||||
|
||||
<dl id="runtime/race"><dt><a href="/pkg/runtime/race/">runtime/race</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/49761 --><!-- CL 333529 -->
|
||||
The race detector has been upgraded to use thread sanitizer
|
||||
version v3 on all supported platforms
|
||||
except <code>windows/amd64</code>
|
||||
and <code>openbsd/amd64</code>, which remain on v2.
|
||||
Compared to v2, it is now typically 1.5x to 2x faster, uses half
|
||||
as much memory, and it supports an unlimited number of
|
||||
goroutines.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 336549 -->
|
||||
The race detector is now supported on <code>GOARCH=s390x</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- https://go.dev/issue/52090 -->
|
||||
Race detector support for <code>openbsd/amd64</code> has been
|
||||
removed from thread sanitizer upstream, so it is unlikely to
|
||||
ever be updated from v2.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- runtime/race -->
|
||||
|
||||
<dl id="runtime/trace"><dt><a href="/pkg/runtime/trace/">runtime/trace</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 400795 -->
|
||||
When tracing and the
|
||||
<a href="/pkg/runtime/pprof#StartCPUProfile">CPU profiler</a> are
|
||||
enabled simultaneously, the execution trace includes CPU profile
|
||||
samples as instantaneous events.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- runtime/trace -->
|
||||
|
||||
<dl id="sort"><dt><a href="/pkg/sort/">sort</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 371574 -->
|
||||
The sorting algorithm has been rewritten to use
|
||||
<a href="https://arxiv.org/pdf/2106.05123.pdf">pattern-defeating quicksort</a>, which
|
||||
is faster for several common scenarios.
|
||||
</p>
|
||||
<p><!-- https://go.dev/issue/50340 --><!-- CL 396514 -->
|
||||
The new function
|
||||
<a href="/pkg/sort/#Find">Find</a>
|
||||
is like
|
||||
<a href="/pkg/sort/#Search">Search</a>
|
||||
but often easier to use: it returns an additional boolean reporting whether an equal value was found.
|
||||
</p>
|
||||
</dd>
|
||||
</dd>
|
||||
</dl><!-- sort -->
|
||||
|
||||
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 397255 -->
|
||||
<a href="/pkg/strconv/#Quote"><code>Quote</code></a>
|
||||
and related functions now quote the rune U+007F as <code>\x7f</code>,
|
||||
not <code>\u007f</code>,
|
||||
for consistency with other ASCII values.
|
||||
<a href="/pkg/strconv/#strconv.Quote"><code>strconv.Quote</code></a>
|
||||
and related functions now quote the rune 007F as <code>\x7f</code>,
|
||||
not <code>\u007f</code>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- strconv -->
|
||||
|
||||
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/51192 --><!-- CL 385796 -->
|
||||
On PowerPC (<code>GOARCH=ppc64</code>, <code>ppc64le</code>),
|
||||
<a href="/pkg/syscall/#Syscall"><code>Syscall</code></a>,
|
||||
<a href="/pkg/syscall/#Syscall6"><code>Syscall6</code></a>,
|
||||
<a href="/pkg/syscall/#RawSyscall"><code>RawSyscall</code></a>, and
|
||||
<a href="/pkg/syscall/#RawSyscall6"><code>RawSyscall6</code></a>
|
||||
now always return 0 for return value <code>r2</code> instead of an
|
||||
undefined value.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 391434 -->
|
||||
On AIX and Solaris, <code>Getrusage</code> is now defined.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- syscall -->
|
||||
|
||||
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
|
||||
<dd>
|
||||
<p><!-- https://go.dev/issue/51414 --><!-- CL 393515 -->
|
||||
The new method
|
||||
<a href="/pkg/time/#Duration.Abs"><code>Duration.Abs</code></a>
|
||||
provides a convenient and safe way to take the absolute value of a duration,
|
||||
converting −2⁶³ to 2⁶³−1.
|
||||
(This boundary case can happen as the result of subtracting a recent time from the zero time.)
|
||||
</p>
|
||||
<p><!-- https://go.dev/issue/50062 --><!-- CL 405374 -->
|
||||
The new method
|
||||
<a href="/pkg/time/#Time.ZoneBounds"><code>Time.ZoneBounds</code></a>
|
||||
returns the start and end times of the time zone in effect at a given time.
|
||||
It can be used in a loop to enumerate all the known time zone transitions at a given location.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- time -->
|
||||
|
||||
<!-- Silence these false positives from x/build/cmd/relnote: -->
|
||||
<!-- CL 382460 -->
|
||||
<!-- CL 384154 -->
|
||||
<!-- CL 384554 -->
|
||||
<!-- CL 392134 -->
|
||||
<!-- CL 392414 -->
|
||||
<!-- CL 396215 -->
|
||||
<!-- CL 403058 -->
|
||||
<!-- CL 410133 -->
|
||||
<!-- https://go.dev/issue/27837 -->
|
||||
<!-- https://go.dev/issue/38340 -->
|
||||
<!-- https://go.dev/issue/42516 -->
|
||||
<!-- https://go.dev/issue/45713 -->
|
||||
<!-- https://go.dev/issue/46654 -->
|
||||
<!-- https://go.dev/issue/48257 -->
|
||||
<!-- https://go.dev/issue/50447 -->
|
||||
<!-- https://go.dev/issue/50720 -->
|
||||
<!-- https://go.dev/issue/50792 -->
|
||||
<!-- https://go.dev/issue/51115 -->
|
||||
<!-- https://go.dev/issue/51447 -->
|
||||
|
||||
589
doc/go_mem.html
589
doc/go_mem.html
@@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Memory Model",
|
||||
"Subtitle": "Version of June 6, 2022",
|
||||
"Subtitle": "Version of May 31, 2014",
|
||||
"Path": "/ref/mem"
|
||||
}-->
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
p.rule {
|
||||
font-style: italic;
|
||||
}
|
||||
span.event {
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2 id="introduction">Introduction</h2>
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>
|
||||
The Go memory model specifies the conditions under which
|
||||
@@ -19,7 +22,7 @@ observe values produced by writes to the same variable in a different goroutine.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="advice">Advice</h3>
|
||||
<h2>Advice</h2>
|
||||
|
||||
<p>
|
||||
Programs that modify data being simultaneously accessed by multiple goroutines
|
||||
@@ -41,237 +44,90 @@ you are being too clever.
|
||||
Don't be clever.
|
||||
</p>
|
||||
|
||||
<h3 id="overview">Informal Overview</h3>
|
||||
<h2>Happens Before</h2>
|
||||
|
||||
<p>
|
||||
Go approaches its memory model in much the same way as the rest of the language,
|
||||
aiming to keep the semantics simple, understandable, and useful.
|
||||
This section gives a general overview of the approach and should suffice for most programmers.
|
||||
The memory model is specified more formally in the next section.
|
||||
Within a single goroutine, reads and writes must behave
|
||||
as if they executed in the order specified by the program.
|
||||
That is, compilers and processors may reorder the reads and writes
|
||||
executed within a single goroutine only when the reordering
|
||||
does not change the behavior within that goroutine
|
||||
as defined by the language specification.
|
||||
Because of this reordering, the execution order observed
|
||||
by one goroutine may differ from the order perceived
|
||||
by another. For example, if one goroutine
|
||||
executes <code>a = 1; b = 2;</code>, another might observe
|
||||
the updated value of <code>b</code> before the updated value of <code>a</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A <em>data race</em> is defined as
|
||||
a write to a memory location happening concurrently with another read or write to that same location,
|
||||
unless all the accesses involved are atomic data accesses as provided by the <code>sync/atomic</code> package.
|
||||
As noted already, programmers are strongly encouraged to use appropriate synchronization
|
||||
to avoid data races.
|
||||
In the absence of data races, Go programs behave as if all the goroutines
|
||||
were multiplexed onto a single processor.
|
||||
This property is sometimes referred to as DRF-SC: data-race-free programs
|
||||
execute in a sequentially consistent manner.
|
||||
To specify the requirements of reads and writes, we define
|
||||
<i>happens before</i>, a partial order on the execution
|
||||
of memory operations in a Go program. If event <span class="event">e<sub>1</sub></span> happens
|
||||
before event <span class="event">e<sub>2</sub></span>, then we say that <span class="event">e<sub>2</sub></span> happens after <span class="event">e<sub>1</sub></span>.
|
||||
Also, if <span class="event">e<sub>1</sub></span> does not happen before <span class="event">e<sub>2</sub></span> and does not happen
|
||||
after <span class="event">e<sub>2</sub></span>, then we say that <span class="event">e<sub>1</sub></span> and <span class="event">e<sub>2</sub></span> happen concurrently.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
Within a single goroutine, the happens-before order is the
|
||||
order expressed by the program.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
While programmers should write Go programs without data races,
|
||||
there are limitations to what a Go implementation can do in response to a data race.
|
||||
An implementation may always react to a data race by reporting the race and terminating the program.
|
||||
Otherwise, each read of a single-word-sized or sub-word-sized memory location
|
||||
must observe a value actually written to that location (perhaps by a concurrent executing goroutine)
|
||||
and not yet overwritten.
|
||||
These implementation constraints make Go more like Java or JavaScript,
|
||||
in that most races have a limited number of outcomes,
|
||||
and less like C and C++, where the meaning of any program with a race
|
||||
is entirely undefined, and the compiler may do anything at all.
|
||||
Go's approach aims to make errant programs more reliable and easier to debug,
|
||||
while still insisting that races are errors and that tools can diagnose and report them.
|
||||
A read <span class="event">r</span> of a variable <code>v</code> is <i>allowed</i> to observe a write <span class="event">w</span> to <code>v</code>
|
||||
if both of the following hold:
|
||||
</p>
|
||||
|
||||
<h2 id="model">Memory Model</h2>
|
||||
|
||||
<p>
|
||||
The following formal definition of Go's memory model closely follows
|
||||
the approach presented by Hans-J. Boehm and Sarita V. Adve in
|
||||
“<a href="https://www.hpl.hp.com/techreports/2008/HPL-2008-56.pdf">Foundations of the C++ Concurrency Memory Model</a>”,
|
||||
published in PLDI 2008.
|
||||
The definition of data-race-free programs and the guarantee of sequential consistency
|
||||
for race-free progams are equivalent to the ones in that work.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The memory model describes the requirements on program executions,
|
||||
which are made up of goroutine executions,
|
||||
which in turn are made up of memory operations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A <i>memory operation</i> is modeled by four details:
|
||||
</p>
|
||||
<ul>
|
||||
<li>its kind, indicating whether it is an ordinary data read, an ordinary data write,
|
||||
or a <i>synchronizing operation</i> such as an atomic data access,
|
||||
a mutex operation, or a channel operation,
|
||||
<li>its location in the program,
|
||||
<li>the memory location or variable being accessed, and
|
||||
<li>the values read or written by the operation.
|
||||
</ul>
|
||||
<p>
|
||||
Some memory operations are <i>read-like</i>, including read, atomic read, mutex lock, and channel receive.
|
||||
Other memory operations are <i>write-like</i>, including write, atomic write, mutex unlock, channel send, and channel close.
|
||||
Some, such as atomic compare-and-swap, are both read-like and write-like.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A <i>goroutine execution</i> is modeled as a set of memory operations executed by a single goroutine.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Requirement 1</b>:
|
||||
The memory operations in each goroutine must correspond to a correct sequential execution of that goroutine,
|
||||
given the values read from and written to memory.
|
||||
That execution must be consistent with the <i>sequenced before</i> relation,
|
||||
defined as the partial order requirements set out by the <a href="/ref/spec">Go language specification</a>
|
||||
for Go's control flow constructs as well as the <a href="/ref/spec#Order_of_evaluation">order of evaluation for expressions</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A Go <i>program execution</i> is modeled as a set of goroutine executions,
|
||||
together with a mapping <i>W</i> that specifies the write-like operation that each read-like operation reads from.
|
||||
(Multiple executions of the same program can have different program executions.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Requirement 2</b>:
|
||||
For a given program execution, the mapping <i>W</i>, when limited to synchronizing operations,
|
||||
must be explainable by some implicit total order of the synchronizing operations
|
||||
that is consistent with sequencing and the values read and written by those operations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <i>synchronized before</i> relation is a partial order on synchronizing memory operations,
|
||||
derived from <i>W</i>.
|
||||
If a synchronizing read-like memory operation <i>r</i>
|
||||
observes a synchronizing write-like memory operation <i>w</i>
|
||||
(that is, if <i>W</i>(<i>r</i>) = <i>w</i>),
|
||||
then <i>w</i> is synchronized before <i>r</i>.
|
||||
Informally, the synchronized before relation is a subset of the implied total order
|
||||
mentioned in the previous paragraph,
|
||||
limited to the information that <i>W</i> directly observes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <i>happens before</i> relation is defined as the transitive closure of the
|
||||
union of the sequenced before and synchronized before relations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Requirement 3</b>:
|
||||
For an ordinary (non-synchronizing) data read <i>r</i> on a memory location <i>x</i>,
|
||||
<i>W</i>(<i>r</i>) must be a write <i>w</i> that is <i>visible</i> to <i>r</i>,
|
||||
where visible means that both of the following hold:
|
||||
|
||||
<ol>
|
||||
<li><i>w</i> happens before <i>r</i>.
|
||||
<li><i>w</i> does not happen before any other write <i>w'</i> (to <i>x</i>) that happens before <i>r</i>.
|
||||
<li><span class="event">r</span> does not happen before <span class="event">w</span>.</li>
|
||||
<li>There is no other write <span class="event">w'</span> to <code>v</code> that happens
|
||||
after <span class="event">w</span> but before <span class="event">r</span>.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
A <i>read-write data race</i> on memory location <i>x</i>
|
||||
consists of a read-like memory operation <i>r</i> on <i>x</i>
|
||||
and a write-like memory operation <i>w</i> on <i>x</i>,
|
||||
at least one of which is non-synchronizing,
|
||||
which are unordered by happens before
|
||||
(that is, neither <i>r</i> happens before <i>w</i>
|
||||
nor <i>w</i> happens before <i>r</i>).
|
||||
To guarantee that a read <span class="event">r</span> of a variable <code>v</code> observes a
|
||||
particular write <span class="event">w</span> to <code>v</code>, ensure that <span class="event">w</span> is the only
|
||||
write <span class="event">r</span> is allowed to observe.
|
||||
That is, <span class="event">r</span> is <i>guaranteed</i> to observe <span class="event">w</span> if both of the following hold:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li><span class="event">w</span> happens before <span class="event">r</span>.</li>
|
||||
<li>Any other write to the shared variable <code>v</code>
|
||||
either happens before <span class="event">w</span> or after <span class="event">r</span>.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
This pair of conditions is stronger than the first pair;
|
||||
it requires that there are no other writes happening
|
||||
concurrently with <span class="event">w</span> or <span class="event">r</span>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A <i>write-write data race</i> on memory location <i>x</i>
|
||||
consists of two write-like memory operations <i>w</i> and <i>w'</i> on <i>x</i>,
|
||||
at least one of which is non-synchronizing,
|
||||
which are unordered by happens before.
|
||||
Within a single goroutine,
|
||||
there is no concurrency, so the two definitions are equivalent:
|
||||
a read <span class="event">r</span> observes the value written by the most recent write <span class="event">w</span> to <code>v</code>.
|
||||
When multiple goroutines access a shared variable <code>v</code>,
|
||||
they must use synchronization events to establish
|
||||
happens-before conditions that ensure reads observe the
|
||||
desired writes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that if there are no read-write or write-write data races on memory location <i>x</i>,
|
||||
then any read <i>r</i> on <i>x</i> has only one possible <i>W</i>(<i>r</i>):
|
||||
the single <i>w</i> that immediately precedes it in the happens before order.
|
||||
The initialization of variable <code>v</code> with the zero value
|
||||
for <code>v</code>'s type behaves as a write in the memory model.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
More generally, it can be shown that any Go program that is data-race-free,
|
||||
meaning it has no program executions with read-write or write-write data races,
|
||||
can only have outcomes explained by some sequentially consistent interleaving
|
||||
of the goroutine executions.
|
||||
(The proof is the same as Section 7 of Boehm and Adve's paper cited above.)
|
||||
This property is called DRF-SC.
|
||||
Reads and writes of values larger than a single machine word
|
||||
behave as multiple machine-word-sized operations in an
|
||||
unspecified order.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The intent of the formal definition is to match
|
||||
the DRF-SC guarantee provided to race-free programs
|
||||
by other languages, including C, C++, Java, JavaScript, Rust, and Swift.
|
||||
</p>
|
||||
<h2>Synchronization</h2>
|
||||
|
||||
<p>
|
||||
Certain Go language operations such as goroutine creation and memory allocation
|
||||
act as synchronization opeartions.
|
||||
The effect of these operations on the synchronized-before partial order
|
||||
is documented in the “Synchronization” section below.
|
||||
Individual packages are responsible for providing similar documentation
|
||||
for their own operations.
|
||||
</p>
|
||||
|
||||
<h2 id="restrictions">Implementation Restrictions for Programs Containing Data Races</h2>
|
||||
|
||||
<p>
|
||||
The preceding section gave a formal definition of data-race-free program execution.
|
||||
This section informally describes the semantics that implementations must provide
|
||||
for programs that do contain races.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First, any implementation can, upon detecting a data race,
|
||||
report the race and halt execution of the program.
|
||||
Implementations using ThreadSanitizer
|
||||
(accessed with “<code>go</code> <code>build</code> <code>-race</code>”)
|
||||
do exactly this.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Otherwise, a read <i>r</i> of a memory location <i>x</i>
|
||||
that is not larger than a machine word must observe
|
||||
some write <i>w</i> such that <i>r</i> does not happen before <i>w</i>
|
||||
and there is no write <i>w'</i> such that <i>w</i> happens before <i>w'</i>
|
||||
and <i>w'</i> happens before <i>r</i>.
|
||||
That is, each read must observe a value written by a preceding or concurrent write.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Additionally, observation of acausal and “out of thin air” writes is disallowed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Reads of memory locations larger than a single machine word
|
||||
are encouraged but not required to meet the same semantics
|
||||
as word-sized memory locations,
|
||||
observing a single allowed write <i>w</i>.
|
||||
For performance reasons,
|
||||
implementations may instead treat larger operations
|
||||
as a set of individual machine-word-sized operations
|
||||
in an unspecified order.
|
||||
This means that races on multiword data structures
|
||||
can lead to inconsistent values not corresponding to a single write.
|
||||
When the values depend on the consistency
|
||||
of internal (pointer, length) or (pointer, type) pairs,
|
||||
as can be the case for interface values, maps,
|
||||
slices, and strings in most Go implementations,
|
||||
such races can in turn lead to arbitrary memory corruption.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Examples of incorrect synchronization are given in the
|
||||
“Incorrect synchronization” section below.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Examples of the limitations on implementations are given in the
|
||||
“Incorrect compilation” section below.
|
||||
</p>
|
||||
|
||||
<h2 id="synchronization">Synchronization</h2>
|
||||
|
||||
<h3 id="init">Initialization</h3>
|
||||
<h3>Initialization</h3>
|
||||
|
||||
<p>
|
||||
Program initialization runs in a single goroutine,
|
||||
@@ -285,15 +141,15 @@ If a package <code>p</code> imports package <code>q</code>, the completion of
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
The completion of all <code>init</code> functions is synchronized before
|
||||
the start of the function <code>main.main</code>.
|
||||
The start of the function <code>main.main</code> happens after
|
||||
all <code>init</code> functions have finished.
|
||||
</p>
|
||||
|
||||
<h3 id="go">Goroutine creation</h3>
|
||||
<h3>Goroutine creation</h3>
|
||||
|
||||
<p class="rule">
|
||||
The <code>go</code> statement that starts a new goroutine
|
||||
is synchronized before the start of the goroutine's execution.
|
||||
happens before the goroutine's execution begins.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -318,12 +174,11 @@ calling <code>hello</code> will print <code>"hello, world"</code>
|
||||
at some point in the future (perhaps after <code>hello</code> has returned).
|
||||
</p>
|
||||
|
||||
<h3 id="goexit">Goroutine destruction</h3>
|
||||
<h3>Goroutine destruction</h3>
|
||||
|
||||
<p>
|
||||
The exit of a goroutine is not guaranteed to be synchronized before
|
||||
any event in the program.
|
||||
For example, in this program:
|
||||
The exit of a goroutine is not guaranteed to happen before
|
||||
any event in the program. For example, in this program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -348,7 +203,7 @@ use a synchronization mechanism such as a lock or channel
|
||||
communication to establish a relative ordering.
|
||||
</p>
|
||||
|
||||
<h3 id="chan">Channel communication</h3>
|
||||
<h3>Channel communication</h3>
|
||||
|
||||
<p>
|
||||
Channel communication is the main method of synchronization
|
||||
@@ -358,8 +213,8 @@ usually in a different goroutine.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
A send on a channel is synchronized before the completion of the
|
||||
corresponding receive from that channel.
|
||||
A send on a channel happens before the corresponding
|
||||
receive from that channel completes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -384,13 +239,13 @@ func main() {
|
||||
|
||||
<p>
|
||||
is guaranteed to print <code>"hello, world"</code>. The write to <code>a</code>
|
||||
is sequenced before the send on <code>c</code>, which is synchronized before
|
||||
the corresponding receive on <code>c</code> completes, which is sequenced before
|
||||
happens before the send on <code>c</code>, which happens before
|
||||
the corresponding receive on <code>c</code> completes, which happens before
|
||||
the <code>print</code>.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
The closing of a channel is synchronized before a receive that returns a zero value
|
||||
The closing of a channel happens before a receive that returns a zero value
|
||||
because the channel is closed.
|
||||
</p>
|
||||
|
||||
@@ -401,8 +256,8 @@ yields a program with the same guaranteed behavior.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
A receive from an unbuffered channel is synchronized before the completion of
|
||||
the corresponding send on that channel.
|
||||
A receive from an unbuffered channel happens before
|
||||
the send on that channel completes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -428,8 +283,8 @@ func main() {
|
||||
|
||||
<p>
|
||||
is also guaranteed to print <code>"hello, world"</code>. The write to <code>a</code>
|
||||
is sequenced before the receive on <code>c</code>, which is synchronized before
|
||||
the corresponding send on <code>c</code> completes, which is sequenced
|
||||
happens before the receive on <code>c</code>, which happens before
|
||||
the corresponding send on <code>c</code> completes, which happens
|
||||
before the <code>print</code>.
|
||||
</p>
|
||||
|
||||
@@ -441,7 +296,7 @@ crash, or do something else.)
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
The <i>k</i>th receive on a channel with capacity <i>C</i> is synchronized before the completion of the <i>k</i>+<i>C</i>th send from that channel completes.
|
||||
The <i>k</i>th receive on a channel with capacity <i>C</i> happens before the <i>k</i>+<i>C</i>th send from that channel completes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -475,7 +330,7 @@ func main() {
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="locks">Locks</h3>
|
||||
<h3>Locks</h3>
|
||||
|
||||
<p>
|
||||
The <code>sync</code> package implements two lock data types,
|
||||
@@ -484,7 +339,7 @@ The <code>sync</code> package implements two lock data types,
|
||||
|
||||
<p class="rule">
|
||||
For any <code>sync.Mutex</code> or <code>sync.RWMutex</code> variable <code>l</code> and <i>n</i> < <i>m</i>,
|
||||
call <i>n</i> of <code>l.Unlock()</code> is synchronized before call <i>m</i> of <code>l.Lock()</code> returns.
|
||||
call <i>n</i> of <code>l.Unlock()</code> happens before call <i>m</i> of <code>l.Lock()</code> returns.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -510,29 +365,19 @@ func main() {
|
||||
|
||||
<p>
|
||||
is guaranteed to print <code>"hello, world"</code>.
|
||||
The first call to <code>l.Unlock()</code> (in <code>f</code>) is synchronized
|
||||
The first call to <code>l.Unlock()</code> (in <code>f</code>) happens
|
||||
before the second call to <code>l.Lock()</code> (in <code>main</code>) returns,
|
||||
which is sequenced before the <code>print</code>.
|
||||
which happens before the <code>print</code>.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
For any call to <code>l.RLock</code> on a <code>sync.RWMutex</code> variable <code>l</code>,
|
||||
there is an <i>n</i> such that the <i>n</i>th call to <code>l.Unlock</code>
|
||||
is synchronized before the return from <code>l.RLock</code>,
|
||||
and the matching call to <code>l.RUnlock</code> is synchronized before the return from call <i>n</i>+1 to <code>l.Lock</code>.
|
||||
there is an <i>n</i> such that the <code>l.RLock</code> happens (returns) after call <i>n</i> to
|
||||
<code>l.Unlock</code> and the matching <code>l.RUnlock</code> happens
|
||||
before call <i>n</i>+1 to <code>l.Lock</code>.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
A successful call to <code>l.TryLock</code> (or <code>l.TryRLock</code>)
|
||||
is equivalent to a call to <code>l.Lock</code> (or <code>l.RLock</code>).
|
||||
An unsuccessful call has no synchronizing effect at all.
|
||||
As far as the memory model is concerned,
|
||||
<code>l.TryLock</code> (or <code>l.TryRLock</code>)
|
||||
may be considered to be able to return false
|
||||
even when the mutex <i>l</i> is unlocked.
|
||||
</p>
|
||||
|
||||
<h3 id="once">Once</h3>
|
||||
<h3>Once</h3>
|
||||
|
||||
<p>
|
||||
The <code>sync</code> package provides a safe mechanism for
|
||||
@@ -544,8 +389,7 @@ until <code>f()</code> has returned.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
The completion of a single call of <code>f()</code> from <code>once.Do(f)</code>
|
||||
is synchronized before the return of any call of <code>once.Do(f)</code>.
|
||||
A single call of <code>f()</code> from <code>once.Do(f)</code> happens (returns) before any call of <code>once.Do(f)</code> returns.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -580,60 +424,13 @@ The result will be that <code>"hello, world"</code> will be printed
|
||||
twice.
|
||||
</p>
|
||||
|
||||
<h3 id="atomic">Atomic Values</h3>
|
||||
<h2>Incorrect synchronization</h2>
|
||||
|
||||
<p>
|
||||
The APIs in the <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a>
|
||||
package are collectively “atomic operations”
|
||||
that can be used to synchronize the execution of different goroutines.
|
||||
If the effect of an atomic operation <i>A</i> is observed by atomic operation <i>B</i>,
|
||||
then <i>A</i> is synchronized before <i>B</i>.
|
||||
All the atomic operations executed in a program behave as though executed
|
||||
in some sequentially consistent order.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The preceding definition has the same semantics as C++’s sequentially consistent atomics
|
||||
and Java’s <code>volatile</code> variables.
|
||||
</p>
|
||||
|
||||
<h3 id="finalizer">Finalizers</h3>
|
||||
|
||||
<p>
|
||||
The <a href="/pkg/runtime/"><code>runtime</code></a> package provides
|
||||
a <code>SetFinalizer</code> function that adds a finalizer to be called when
|
||||
a particular object is no longer reachable by the program.
|
||||
A call to <code>SetFinalizer(x, f)</code> is synchronized before the finalization call <code>f(x)</code>.
|
||||
</p>
|
||||
|
||||
<h3 id="more">Additional Mechanisms</h3>
|
||||
|
||||
<p>
|
||||
The <code>sync</code> package provides additional synchronization abstractions,
|
||||
including <a href="/pkg/sync/#Cond">condition variables</a>,
|
||||
<a href="/pkg/sync/#Map">lock-free maps</a>,
|
||||
<a href="/pkg/sync/#Pool">allocation pools</a>,
|
||||
and
|
||||
<a href="/pkg/sync/#WaitGroup">wait groups</a>.
|
||||
The documentation for each of these specifies the guarantees it
|
||||
makes concerning synchronization.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Other packages that provide synchronization abstractions
|
||||
should document the guarantees they make too.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="badsync">Incorrect synchronization</h2>
|
||||
|
||||
<p>
|
||||
Programs with races are incorrect and
|
||||
can exhibit non-sequentially consistent executions.
|
||||
In particular, note that a read <i>r</i> may observe the value written by any write <i>w</i>
|
||||
that executes concurrently with <i>r</i>.
|
||||
Even if this occurs, it does not imply that reads happening after <i>r</i>
|
||||
will observe writes that happened before <i>w</i>.
|
||||
Note that a read <span class="event">r</span> may observe the value written by a write <span class="event">w</span>
|
||||
that happens concurrently with <span class="event">r</span>.
|
||||
Even if this occurs, it does not imply that reads happening after <span class="event">r</span>
|
||||
will observe writes that happened before <span class="event">w</span>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -769,197 +566,3 @@ value for <code>g.msg</code>.
|
||||
In all these examples, the solution is the same:
|
||||
use explicit synchronization.
|
||||
</p>
|
||||
|
||||
<h2 id="badcompiler">Incorrect compilation</h2>
|
||||
|
||||
<p>
|
||||
The Go memory model restricts compiler optimizations as much as it does Go programs.
|
||||
Some compiler optimizations that would be valid in single-threaded programs are not valid in all Go programs.
|
||||
In particular, a compiler must not introduce writes that do not exist in the original program,
|
||||
it must not allow a single read to observe multiple values,
|
||||
and it must not allow a single write to write multiple values.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
All the following examples assume that `*p` and `*q` refer to
|
||||
memory locations accessible to multiple goroutines.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Not introducing data races into race-free programs means not moving
|
||||
writes out of conditional statements in which they appear.
|
||||
For example, a compiler must not invert the conditional in this program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
*p = 1
|
||||
if cond {
|
||||
*p = 2
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
That is, the compiler must not rewrite the program into this one:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
*p = 2
|
||||
if !cond {
|
||||
*p = 1
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If <code>cond</code> is false and another goroutine is reading <code>*p</code>,
|
||||
then in the original program, the other goroutine can only observe any prior value of <code>*p</code> and <code>1</code>.
|
||||
In the rewritten program, the other goroutine can observe <code>2</code>, which was previously impossible.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Not introducing data races also means not assuming that loops terminate.
|
||||
For example, a compiler must in general not move the accesses to <code>*p</code> or <code>*q</code>
|
||||
ahead of the loop in this program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
n := 0
|
||||
for e := list; e != nil; e = e.next {
|
||||
n++
|
||||
}
|
||||
i := *p
|
||||
*q = 1
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If <code>list</code> pointed to a cyclic list,
|
||||
then the original program would never access <code>*p</code> or <code>*q</code>,
|
||||
but the rewritten program would.
|
||||
(Moving `*p` ahead would be safe if the compiler can prove `*p` will not panic;
|
||||
moving `*q` ahead would also require the compiler proving that no other
|
||||
goroutine can access `*q`.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Not introducing data races also means not assuming that called functions
|
||||
always return or are free of synchronization operations.
|
||||
For example, a compiler must not move the accesses to <code>*p</code> or <code>*q</code>
|
||||
ahead of the function call in this program
|
||||
(at least not without direct knowledge of the precise behavior of <code>f</code>):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
f()
|
||||
i := *p
|
||||
*q = 1
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If the call never returned, then once again the original program
|
||||
would never access <code>*p</code> or <code>*q</code>, but the rewritten program would.
|
||||
And if the call contained synchronizing operations, then the original program
|
||||
could establish happens before edges preceding the accesses
|
||||
to <code>*p</code> and <code>*q</code>, but the rewritten program would not.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Not allowing a single read to observe multiple values means
|
||||
not reloading local variables from shared memory.
|
||||
For example, a compiler must not discard <code>i</code> and reload it
|
||||
a second time from <code>*p</code> in this program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
i := *p
|
||||
if i < 0 || i >= len(funcs) {
|
||||
panic("invalid function index")
|
||||
}
|
||||
... complex code ...
|
||||
// compiler must NOT reload i = *p here
|
||||
funcs[i]()
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If the complex code needs many registers, a compiler for single-threaded programs
|
||||
could discard <code>i</code> without saving a copy and then reload
|
||||
<code>i = *p</code> just before
|
||||
<code>funcs[i]()</code>.
|
||||
A Go compiler must not, because the value of <code>*p</code> may have changed.
|
||||
(Instead, the compiler could spill <code>i</code> to the stack.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Not allowing a single write to write multiple values also means not using
|
||||
the memory where a local variable will be written as temporary storage before the write.
|
||||
For example, a compiler must not use <code>*p</code> as temporary storage in this program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
*p = i + *p/2
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
That is, it must not rewrite the program into this one:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
*p /= 2
|
||||
*p += i
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If <code>i</code> and <code>*p</code> start equal to 2,
|
||||
the original code does <code>*p = 3</code>,
|
||||
so a racing thread can read only 2 or 3 from <code>*p</code>.
|
||||
The rewritten code does <code>*p = 1</code> and then <code>*p = 3</code>,
|
||||
allowing a racing thread to read 1 as well.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that all these optimizations are permitted in C/C++ compilers:
|
||||
a Go compiler sharing a back end with a C/C++ compiler must take care
|
||||
to disable optimizations that are invalid for Go.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that the prohibition on introducing data races
|
||||
does not apply if the compiler can prove that the races
|
||||
do not affect correct execution on the target platform.
|
||||
For example, on essentially all CPUs, it is valid to rewrite
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
n := 0
|
||||
for i := 0; i < m; i++ {
|
||||
n += *shared
|
||||
}
|
||||
</pre>
|
||||
|
||||
into:
|
||||
|
||||
<pre>
|
||||
n := 0
|
||||
local := *shared
|
||||
for i := 0; i < m; i++ {
|
||||
n += local
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
provided it can be proved that <code>*shared</code> will not fault on access,
|
||||
because the potential added read will not affect any existing concurrent reads or writes.
|
||||
On the other hand, the rewrite would not be valid in a source-to-source translator.
|
||||
</p>
|
||||
|
||||
<h2 id="conclusion">Conclusion</h2>
|
||||
|
||||
<p>
|
||||
Go programmers writing data-race-free programs can rely on
|
||||
sequentially consistent execution of those programs,
|
||||
just as in essentially all other modern programming languages.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When it comes to programs with races,
|
||||
both programmers and compilers should remember the advice:
|
||||
don't be clever.
|
||||
</p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of May 12, 2022",
|
||||
"Subtitle": "Version of April 19, 2022",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
@@ -22,23 +22,20 @@ dependencies.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The syntax is compact and simple to parse, allowing for easy analysis
|
||||
The grammar is compact and simple to parse, allowing for easy analysis
|
||||
by automatic tools such as integrated development environments.
|
||||
</p>
|
||||
|
||||
<h2 id="Notation">Notation</h2>
|
||||
<p>
|
||||
The syntax is specified using a
|
||||
<a href="https://en.wikipedia.org/wiki/Wirth_syntax_notation">variant</a>
|
||||
of Extended Backus-Naur Form (EBNF):
|
||||
The syntax is specified using Extended Backus-Naur Form (EBNF):
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
Syntax = { Production } .
|
||||
Production = production_name "=" [ Expression ] "." .
|
||||
Expression = Term { "|" Term } .
|
||||
Term = Factor { Factor } .
|
||||
Factor = production_name | token [ "…" token ] | Group | Option | Repetition .
|
||||
Expression = Alternative { "|" Alternative } .
|
||||
Alternative = Term { Term } .
|
||||
Term = production_name | token [ "…" token ] | Group | Option | Repetition .
|
||||
Group = "(" Expression ")" .
|
||||
Option = "[" Expression "]" .
|
||||
Repetition = "{" Expression "}" .
|
||||
@@ -56,7 +53,7 @@ operators, in increasing precedence:
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Lowercase production names are used to identify lexical (terminal) tokens.
|
||||
Lower-case production names are used to identify lexical tokens.
|
||||
Non-terminals are in CamelCase. Lexical tokens are enclosed in
|
||||
double quotes <code>""</code> or back quotes <code>``</code>.
|
||||
</p>
|
||||
@@ -82,7 +79,7 @@ will use the unqualified term <i>character</i> to refer to a Unicode code point
|
||||
in the source text.
|
||||
</p>
|
||||
<p>
|
||||
Each code point is distinct; for instance, uppercase and lowercase letters
|
||||
Each code point is distinct; for instance, upper and lower case letters
|
||||
are different characters.
|
||||
</p>
|
||||
<p>
|
||||
@@ -99,13 +96,13 @@ A byte order mark may be disallowed anywhere else in the source.
|
||||
<h3 id="Characters">Characters</h3>
|
||||
|
||||
<p>
|
||||
The following terms are used to denote specific Unicode character categories:
|
||||
The following terms are used to denote specific Unicode character classes:
|
||||
</p>
|
||||
<pre class="ebnf">
|
||||
newline = /* the Unicode code point U+000A */ .
|
||||
unicode_char = /* an arbitrary Unicode code point except newline */ .
|
||||
unicode_letter = /* a Unicode code point categorized as "Letter" */ .
|
||||
unicode_digit = /* a Unicode code point categorized as "Number, decimal digit" */ .
|
||||
unicode_letter = /* a Unicode code point classified as "Letter" */ .
|
||||
unicode_digit = /* a Unicode code point classified as "Number, decimal digit" */ .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -118,7 +115,7 @@ as Unicode letters, and those in the Number category Nd as Unicode digits.
|
||||
<h3 id="Letters_and_digits">Letters and digits</h3>
|
||||
|
||||
<p>
|
||||
The underscore character <code>_</code> (U+005F) is considered a lowercase letter.
|
||||
The underscore character <code>_</code> (U+005F) is considered a letter.
|
||||
</p>
|
||||
<pre class="ebnf">
|
||||
letter = unicode_letter | "_" .
|
||||
@@ -173,7 +170,7 @@ valid token.
|
||||
<h3 id="Semicolons">Semicolons</h3>
|
||||
|
||||
<p>
|
||||
The formal syntax uses semicolons <code>";"</code> as terminators in
|
||||
The formal grammar uses semicolons <code>";"</code> as terminators in
|
||||
a number of productions. Go programs may omit most of these semicolons
|
||||
using the following two rules:
|
||||
</p>
|
||||
@@ -409,7 +406,7 @@ An imaginary literal represents the imaginary part of a
|
||||
<a href="#Constants">complex constant</a>.
|
||||
It consists of an <a href="#Integer_literals">integer</a> or
|
||||
<a href="#Floating-point_literals">floating-point</a> literal
|
||||
followed by the lowercase letter <code>i</code>.
|
||||
followed by the lower-case letter <code>i</code>.
|
||||
The value of an imaginary literal is the value of the respective
|
||||
integer or floating-point literal multiplied by the imaginary unit <i>i</i>.
|
||||
</p>
|
||||
@@ -800,7 +797,7 @@ TypeName = identifier | QualifiedIdent .
|
||||
TypeArgs = "[" TypeList [ "," ] "]" .
|
||||
TypeList = Type { "," Type } .
|
||||
TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
|
||||
SliceType | MapType | ChannelType .
|
||||
SliceType | MapType | ChannelType .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -1089,7 +1086,7 @@ of a struct except that they cannot be used as field names in
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Given a struct type <code>S</code> and a <a href="#Types">named type</a>
|
||||
Given a struct type <code>S</code> and a <a href="#Type_definitions">defined type</a>
|
||||
<code>T</code>, promoted methods are included in the method set of the struct as follows:
|
||||
</p>
|
||||
<ul>
|
||||
@@ -1923,8 +1920,7 @@ A value <code>x</code> of type <code>V</code> is <i>assignable</i> to a <a href=
|
||||
</li>
|
||||
<li>
|
||||
<code>V</code> and <code>T</code> have identical
|
||||
<a href="#Underlying_types">underlying types</a>
|
||||
but are not type parameters and at least one of <code>V</code>
|
||||
<a href="#Underlying_types">underlying types</a> and at least one of <code>V</code>
|
||||
or <code>T</code> is not a <a href="#Types">named type</a>.
|
||||
</li>
|
||||
<li>
|
||||
@@ -2162,8 +2158,9 @@ Go is lexically scoped using <a href="#Blocks">blocks</a>:
|
||||
or result variable is the function body.</li>
|
||||
|
||||
<li>The scope of an identifier denoting a type parameter of a function
|
||||
or declared by a method receiver begins after the name of the function
|
||||
and ends at the end of the function body.</li>
|
||||
or declared by a method receiver is the function body and all parameter lists of the
|
||||
function.
|
||||
</li>
|
||||
|
||||
<li>The scope of an identifier denoting a type parameter of a type
|
||||
begins after the name of the type and ends at the end
|
||||
@@ -2249,8 +2246,8 @@ An identifier may be <i>exported</i> to permit access to it from another package
|
||||
An identifier is exported if both:
|
||||
</p>
|
||||
<ol>
|
||||
<li>the first character of the identifier's name is a Unicode uppercase
|
||||
letter (Unicode character category Lu); and</li>
|
||||
<li>the first character of the identifier's name is a Unicode upper case
|
||||
letter (Unicode class "Lu"); and</li>
|
||||
<li>the identifier is declared in the <a href="#Blocks">package block</a>
|
||||
or it is a <a href="#Struct_types">field name</a> or
|
||||
<a href="#MethodName">method name</a>.</li>
|
||||
@@ -2765,7 +2762,7 @@ with initializer expressions but no types:
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
"var" IdentifierList "=" ExpressionList .
|
||||
"var" IdentifierList = ExpressionList .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
@@ -2783,14 +2780,12 @@ variables provided they were originally declared earlier in the same block
|
||||
and at least one of the non-<a href="#Blank_identifier">blank</a> variables is new.
|
||||
As a consequence, redeclaration can only appear in a multi-variable short declaration.
|
||||
Redeclaration does not introduce a new variable; it just assigns a new value to the original.
|
||||
The non-blank variable names on the left side of <code>:=</code>
|
||||
must be <a href="#Uniqueness_of_identifiers">unique</a>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
field1, offset := nextField(str, 0)
|
||||
field2, offset := nextField(str, offset) // redeclares offset
|
||||
x, y, x := 1, 2, 3 // illegal: x repeated on left side of :=
|
||||
a, a := 1, 2 // illegal: double declaration of a or no new variable if a was declared elsewhere
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -3015,7 +3010,7 @@ declared in the <a href="#Blocks">package block</a> of that package.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
math.Sin // denotes the Sin function in package math
|
||||
math.Sin // denotes the Sin function in package math
|
||||
</pre>
|
||||
|
||||
<h3 id="Composite_literals">Composite literals</h3>
|
||||
@@ -3041,7 +3036,7 @@ Element = Expression | LiteralValue .
|
||||
<p>
|
||||
The LiteralType's <a href="#Core_types">core type</a> <code>T</code>
|
||||
must be a struct, array, slice, or map type
|
||||
(the syntax enforces this constraint except when the type is given
|
||||
(the grammar enforces this constraint except when the type is given
|
||||
as a TypeName).
|
||||
The types of the elements and keys must be <a href="#Assignability">assignable</a>
|
||||
to the respective field, element, and key types of type <code>T</code>;
|
||||
@@ -4841,7 +4836,7 @@ due to two's-complement <a href="#Integer_overflow">integer overflow</a>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
x, q
|
||||
x, q
|
||||
int8 -128
|
||||
int16 -32768
|
||||
int32 -2147483648
|
||||
@@ -6814,8 +6809,7 @@ OuterLoop:
|
||||
|
||||
<p>
|
||||
A "continue" statement begins the next iteration of the
|
||||
innermost enclosing <a href="#For_statements">"for" loop</a>
|
||||
by advancing control to the end of the loop block.
|
||||
innermost <a href="#For_statements">"for" loop</a> at its post statement.
|
||||
The "for" loop must be within the same function.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
# Consult https://www.iana.org/time-zones for the latest versions.
|
||||
|
||||
# Versions to use.
|
||||
CODE=2022a
|
||||
DATA=2022a
|
||||
CODE=2021e
|
||||
DATA=2021e
|
||||
|
||||
set -e
|
||||
rm -rf work
|
||||
|
||||
Binary file not shown.
108
misc/boring/README.md
Normal file
108
misc/boring/README.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# README.md
|
||||
|
||||
This directory holds build scripts for unofficial, unsupported
|
||||
distributions of Go+BoringCrypto.
|
||||
|
||||
## Version strings
|
||||
|
||||
The distribution name for a Go+BoringCrypto release has the form `<GoVersion>b<BoringCryptoVersion>`,
|
||||
where `<GoVersion>` is the Go version the release is based on, and `<BoringCryptoVersion>` is
|
||||
an integer that increments each time there is a new release with different BoringCrypto bits.
|
||||
The `<BoringCryptoVersion>` is stored in the `VERSION` file in this directory.
|
||||
|
||||
For example, the first release is based on Go 1.8.3 is `go1.8.3b1`.
|
||||
If the BoringCrypto bits are updated, the next would be `go1.8.3b2`.
|
||||
If, after that, Go 1.9 is released and the same BoringCrypto code added to it,
|
||||
that would result in `go1.9b2`. There would likely not be a `go1.9b1`,
|
||||
since that would indicate Go 1.9 with the older BoringCrypto code.
|
||||
|
||||
## Releases
|
||||
|
||||
The `build.release` script prepares a binary release and publishes it in Google Cloud Storage
|
||||
at `gs://go-boringcrypto/`, making it available for download at
|
||||
`https://go-boringcrypto.storage.googleapis.com/<FILE>`.
|
||||
The script records each published release in the `RELEASES` file in this directory.
|
||||
|
||||
The `build.docker` script, which must be run after `build.release`, prepares a Docker image
|
||||
and publishes it on Google Artifact Registry.
|
||||
`go1.17.2b7` is published as `us-docker.pkg.dev/google.com/api-project-999119582588/go-boringcrypto/golang:1.17.2b7`.
|
||||
|
||||
## Release process
|
||||
|
||||
Development is done on the dev.boringcrypto branch, which tracks
|
||||
master. Releases are cut from dev.boringcrypto.go1.X branches,
|
||||
which are BoringCrypto backported to the Go 1.X release branches.
|
||||
To issue new BoringCrypto releases based on Go 1.X:
|
||||
|
||||
1. If the BoringCrypto bits have been updated, increment the
|
||||
number in `VERSION`, send that change out as a CL for review,
|
||||
get it committed to dev.boringcrypto, and run `git sync`.
|
||||
|
||||
2. Change to the dev.boringcrypto.go1.X branch and cherry-pick
|
||||
all BoringCrypto updates, including the update of the
|
||||
`VERSION` file. If desired, merge release-branch.go1.X into
|
||||
dev.boringcrypto.go1.X. Mail them out and get them committed.
|
||||
|
||||
3. **Back on the dev.boringcrypto branch**, run `git fetch`,
|
||||
`make.bash` and then `build.release dev.boringcrypto.go1.X`.
|
||||
The script will determine the base Go version and the
|
||||
BoringCrypto version, build a release, and upload it.
|
||||
|
||||
4. Run `build.docker`, which will build and upload a Docker image
|
||||
from the latest release.
|
||||
|
||||
5. Send out a CL with the updated `RELEASES` file and get it
|
||||
committed to dev.boringcrypto.
|
||||
|
||||
## Building from Docker
|
||||
|
||||
A Dockerfile that starts with `FROM golang:1.17.2` can switch
|
||||
to `FROM us-docker.pkg.dev/google.com/api-project-999119582588/go-boringcrypto/golang:1.17.2b7`
|
||||
and should need no other modifications.
|
||||
|
||||
## Building from Bazel
|
||||
|
||||
Starting from [bazelbuild/rules_go](https://github.com/bazelbuild/rules_go)
|
||||
tag 0.7.1, simply download the BoringCrypto-enabled Go SDK using
|
||||
`go_download_sdk()` before calling `go_register_toolchains()`.
|
||||
|
||||
For example, to use Go 1.9.3 with BoringCrypto on Linux, use the following lines
|
||||
in `WORKSPACE`:
|
||||
```python
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_download_sdk", "go_register_toolchains")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_download_sdk(
|
||||
name = "go_sdk",
|
||||
sdks = {
|
||||
"linux_amd64": ("go1.9.3b4.linux-amd64.tar.gz", "db1997b2454a2f27669b849d2d2cafb247a55128d53da678f06cb409310d6660"),
|
||||
},
|
||||
urls = ["https://storage.googleapis.com/go-boringcrypto/{}"],
|
||||
)
|
||||
|
||||
go_register_toolchains()
|
||||
```
|
||||
|
||||
**Note**: you must *not* enable `pure` mode, since cgo must be enabled. To
|
||||
ensure that binaries are linked with BoringCrypto, you can set `pure = "off"` on
|
||||
all relevant `go_binary` rules.
|
||||
|
||||
## Caveat
|
||||
|
||||
BoringCrypto is used for a given build only in limited circumstances:
|
||||
|
||||
- The build must be GOOS=linux, GOARCH=amd64.
|
||||
- The build must have cgo enabled.
|
||||
- The android build tag must not be specified.
|
||||
- The cmd_go_bootstrap build tag must not be specified.
|
||||
|
||||
The version string reported by `runtime.Version` does not indicate that BoringCrypto
|
||||
was actually used for the build. For example, linux/386 and non-cgo linux/amd64 binaries
|
||||
will report a version of `go1.8.3b2` but not be using BoringCrypto.
|
||||
|
||||
To check whether a given binary is using BoringCrypto, run `go tool nm` on it and check
|
||||
that it has symbols named `*_Cfunc__goboringcrypto_*`.
|
||||
|
||||
The program [rsc.io/goversion](https://godoc.org/rsc.io/goversion) will report the
|
||||
crypto implementation used by a given binary when invoked with the `-crypto` flag.
|
||||
213
misc/boring/RELEASES
Normal file
213
misc/boring/RELEASES
Normal file
@@ -0,0 +1,213 @@
|
||||
# This file lists published Go+BoringCrypto releases.
|
||||
# Each line describes a single release: <version> <git commit> <target> <URL> <sha256sum>
|
||||
go1.9rc2b2 91753387bdf7 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9rc2b2.linux-amd64.tar.gz 59355a45e6970e8013060851ddb3f079afe8db52e90db520a0826a13f1b5ae5b
|
||||
go1.8.3b3 f6ff81bac156 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.8.3b3.linux-amd64.tar.gz 6287ad971cd268bb2684fb8b1275dea928ad527823062bc057e73036c419e7af
|
||||
go1.9rc2b4 c339bc4e07a6 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9rc2b4.linux-amd64.tar.gz a8f677d48dc93920065fca4dca1a55bf7110aba132489c47e25d26d55c67eb32
|
||||
go1.9b4 e6ad24cde71e linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9b4.linux-amd64.tar.gz 6592e36a05df8e7c59812328a3a4bfa6c4eed72132fc31245951c3ade3ef2a8a
|
||||
go1.9b4 e6ad24cde71e src https://go-boringcrypto.storage.googleapis.com/go1.9b4.src.tar.gz c85f31dc743fee0e8ce0c6ffc286e27c1f51b66c9b923afafb43cdc378a41091
|
||||
go1.8.3b4 42cb4dcdb59a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.8.3b4.linux-amd64.tar.gz 4011c86e6175925e1c63dc7c19a51f825be53bbe7b08260918e5107b0fbd4f85
|
||||
go1.8.3b4 42cb4dcdb59a src https://go-boringcrypto.storage.googleapis.com/go1.8.3b4.src.tar.gz 2531ca8918aa024aed8f4a6c9e5c3b25bc8777623f1efa66aec7214601d474e4
|
||||
go1.9.2b4 cda3c6f91d7c linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9.2b4.linux-amd64.tar.gz 7c5e9a033ddc3ab36646e3bac7fd16962742710c70c18122e44a9ab56cdd3cf7
|
||||
go1.9.2b4 cda3c6f91d7c src https://go-boringcrypto.storage.googleapis.com/go1.9.2b4.src.tar.gz 38a2260b64a6a5ab20f8972d08b4765bad116721356433f39aebd29c7598218c
|
||||
go1.9.3b4 f4e5ebdf35c8 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9.3b4.linux-amd64.tar.gz db1997b2454a2f27669b849d2d2cafb247a55128d53da678f06cb409310d6660
|
||||
go1.9.3b4 f4e5ebdf35c8 src https://go-boringcrypto.storage.googleapis.com/go1.9.3b4.src.tar.gz 7485e1fc53a9fab9cf34f71de74d69f4c50f9d11a449647de40ee04b59bf8a5b
|
||||
go1.9.7b4 0bad1bef406e linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.9.7b4.linux-amd64.tar.gz 9e33a0deb8fed3bd7fa3d122bb5143be9e0a974a422ab4ddac5e765fa1310a6f
|
||||
go1.9.7b4 0bad1bef406e src https://go-boringcrypto.storage.googleapis.com/go1.9.7b4.src.tar.gz ad9fb6e22a27382c468467ecade4937f725b33818852f1c1da0d09b471e7486c
|
||||
go1.10.3b4 35ba5284935c linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.10.3b4.linux-amd64.tar.gz 6754729d78a375bd1debd980b1e3e7fd49198a980d0bbd8f39e89569aa001942
|
||||
go1.10.3b4 35ba5284935c src https://go-boringcrypto.storage.googleapis.com/go1.10.3b4.src.tar.gz f3e75c60a835c11b97e30429b63917ceb31f799b2ba7e2001d99db908fb8e28f
|
||||
go1.10.4b4 2e2a04a605b6 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.10.4b4.linux-amd64.tar.gz 17c275ff448686fe1908ecbea5d11ad6f4f7caa288d1786b756439703b12b8b2
|
||||
go1.10.4b4 2e2a04a605b6 src https://go-boringcrypto.storage.googleapis.com/go1.10.4b4.src.tar.gz f9cc38e194edabebf338fb74c22f597dc847560618d5d7d4d6cdc28139efa772
|
||||
go1.11b4 685dc1638240 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.11b4.linux-amd64.tar.gz d53417b2071af0104fbc15a957000bccdcb5bbc094df0401f67d51968f7f2e4e
|
||||
go1.11b4 685dc1638240 src https://go-boringcrypto.storage.googleapis.com/go1.11b4.src.tar.gz 39896f0decd6721e81324cb2bb19540706ca97152c6800a6c8ad15a4e4162184
|
||||
go1.11.2b4 35cf0d9f6bbd linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.11.2b4.linux-amd64.tar.gz a9ceb6d0b4413d81ccc94c6460f60ca0c4f36b5dcbf659e1be582cd40c0edfbd
|
||||
go1.11.2b4 35cf0d9f6bbd src https://go-boringcrypto.storage.googleapis.com/go1.11.2b4.src.tar.gz 8e12a8df1428f00239dc67dd438a81f72c9925982e90b6899f66270971bddc1c
|
||||
go1.10.7b4 8b246fe0f595 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.10.7b4.linux-amd64.tar.gz 31917ab96004b9b482399b46928f5c10cdadefed5fda6f4de262efe2c3c7533e
|
||||
go1.10.7b4 8b246fe0f595 src https://go-boringcrypto.storage.googleapis.com/go1.10.7b4.src.tar.gz 323a184c77e3a377f5ed993b04946ee7b1a8e3350aba2894c0944f1e313636f1
|
||||
go1.11.4b4 572c4bce6792 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.11.4b4.linux-amd64.tar.gz e708ef7ecaf17a3e8e6deceadfa167cc1162f710f97ea4bc124d3837d6e2eaa1
|
||||
go1.11.4b4 572c4bce6792 src https://go-boringcrypto.storage.googleapis.com/go1.11.4b4.src.tar.gz ea963b80e218a34470e14e6e997fe06b8c5bf3f9c9bb0c801f7d8ef63b9bcb73
|
||||
go1.10.8b4 4b76b996cb0a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.10.8b4.linux-amd64.tar.gz 6d7d3323030851b595ba7ed66931c352b63de6dfe1ab3e6d6243987765d09819
|
||||
go1.10.8b4 4b76b996cb0a src https://go-boringcrypto.storage.googleapis.com/go1.10.8b4.src.tar.gz c1f5df50a4be3d0cb3aed7b80728f2b23c18deff0383636274742a38c145f939
|
||||
go1.11.5b4 3fb9dafacc45 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.11.5b4.linux-amd64.tar.gz 9b5b2972b452da9ba6bba65bab18fb9e8fbda31b5c489275710e5429d76f568c
|
||||
go1.11.5b4 3fb9dafacc45 src https://go-boringcrypto.storage.googleapis.com/go1.11.5b4.src.tar.gz 1c5801e2af25c9299d9fd94c64f9ec11fd35777c45d5d0f398c0a9884b1cfbbf
|
||||
go1.12.1b4 88e20e81a61f linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.1b4.linux-amd64.tar.gz b71886e0d65e5efea2e0a3cbd0c3cd0daf84c437078e755ecde25f4ac0bbed2f
|
||||
go1.12.1b4 88e20e81a61f src https://go-boringcrypto.storage.googleapis.com/go1.12.1b4.src.tar.gz d44be1396eb2854b5d9c4d8e8ed0cf9fea1e9dc5a02d8f53b41ba571951a329f
|
||||
go1.11.6b4 7be8a5843a9b linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.11.6b4.linux-amd64.tar.gz b704f61b8979e64a46da8884c90cd2b0e2d54e802d55e5f56d7c93752334c197
|
||||
go1.11.6b4 7be8a5843a9b src https://go-boringcrypto.storage.googleapis.com/go1.11.6b4.src.tar.gz a56b45e24b61ad7b3c90dfd906cd22426a4de9e2e697b4c9ef07a2af047bcb0d
|
||||
go1.12.5b4 ad495d31d908 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.5b4.linux-amd64.tar.gz df0e64958cf90f27a65b2175eb80bc34a601136eed8e5559bed2a9e349e33707
|
||||
go1.12.5b4 ad495d31d908 src https://go-boringcrypto.storage.googleapis.com/go1.12.5b4.src.tar.gz 054d482896a77ae2d7d24c7adf08da5a4401b938871e61a5cdabc735c54cea9f
|
||||
go1.11.11b4 346babe6a67f linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.11.11b4.linux-amd64.tar.gz c4dd44fa00f491b3d2ea808af8a6c234f915adb27c014512d725bafc4784d75f
|
||||
go1.11.11b4 346babe6a67f src https://go-boringcrypto.storage.googleapis.com/go1.11.11b4.src.tar.gz 57a724a72f0ba8620cbb48288f39c86ed513c241509ddf73231f4c8cd2a983ac
|
||||
go1.12.6b4 6b86b09ad4d3 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.6b4.linux-amd64.tar.gz eebc2e7f37555760adb361985b861d0cd34f9401cf7456d8d2f2f3082a60eee1
|
||||
go1.12.6b4 6b86b09ad4d3 src https://go-boringcrypto.storage.googleapis.com/go1.12.6b4.src.tar.gz 0e6e9aaf2c72a7e61280ce1e77b2ea24f01a59f4c1e6f0aa72b753206724fd3a
|
||||
go1.11.12b4 845e947ae34f linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.11.12b4.linux-amd64.tar.gz 91808261fc357855fba920df01a933d6104e907793014317de00b92802d494d9
|
||||
go1.11.12b4 845e947ae34f src https://go-boringcrypto.storage.googleapis.com/go1.11.12b4.src.tar.gz 7b64d9e56ea627138d87c7533df8f9932a79ff900f150a8d8e6a3edc2d0066ec
|
||||
go1.12.7b4 bd126d0ad256 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.7b4.linux-amd64.tar.gz 7f0c73cd397bccad48ab4df4188d3651c25bf33102275848c6e67b882e11f680
|
||||
go1.12.7b4 bd126d0ad256 src https://go-boringcrypto.storage.googleapis.com/go1.12.7b4.src.tar.gz 0c48d7b81ef2b948980011fad1d176d6b10636a4016e3aed7438d86e046d816b
|
||||
go1.11.13b4 4f8e7223f936 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.11.13b4.linux-amd64.tar.gz eeb232577065732f5d57a4c77b7d73aa60231ee6fd6496daf7558993e92e403f
|
||||
go1.11.13b4 4f8e7223f936 src https://go-boringcrypto.storage.googleapis.com/go1.11.13b4.src.tar.gz 107da8846803a0a735766ca0947de6cd15cd23d8c584002f06e7ac5f81ecb114
|
||||
go1.12.8b4 55186ba70c1a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.8b4.linux-amd64.tar.gz 63f278abfc1e98546bc0ffc87f000d9aae2b06c0700212cb55ffd17d059fb8e1
|
||||
go1.12.8b4 55186ba70c1a src https://go-boringcrypto.storage.googleapis.com/go1.12.8b4.src.tar.gz c12b1d56ba4e0572f85a08681e05c66293ad53f04b11ce74c688d78fcb882061
|
||||
go1.12.9b4 ee88e5b118b5 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.9b4.linux-amd64.tar.gz d90989cba1db647b795400a9520eab2fa30f8dea50f4189b18d53f757a4bac44
|
||||
go1.12.9b4 ee88e5b118b5 src https://go-boringcrypto.storage.googleapis.com/go1.12.9b4.src.tar.gz 9d4efed8e13fa5ebdadd4fc22f9e35e67bfb34322570c83a15a0879472412e13
|
||||
go1.13b4 28e8a0c21e00 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13b4.linux-amd64.tar.gz 4a909f34bc487badb5ec11646c471ae690393d3f7835b8fbef8466d04ee23cba
|
||||
go1.13b4 28e8a0c21e00 src https://go-boringcrypto.storage.googleapis.com/go1.13b4.src.tar.gz 3c2dbe1bfcd7299b5be4b75529425c0a67b8d6b76f81f993b84ae0d173934257
|
||||
go1.12.10b4 5827153a1db7 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.10b4.linux-amd64.tar.gz 20963fde89fd20eebee9d89003e52702f0379fdb04a68754f9fadf2c302166e3
|
||||
go1.12.10b4 5827153a1db7 src https://go-boringcrypto.storage.googleapis.com/go1.12.10b4.src.tar.gz f5cfe73cfeaaa67619ff4a4bbc587e622d63a6aaa7145253e6583bd59072b323
|
||||
go1.13.1b4 2da1832ad494 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.1b4.linux-amd64.tar.gz 70be1bae05feb67d0560f39767e80707343d96554c5a611fbb93b04ce5913693
|
||||
go1.13.1b4 2da1832ad494 src https://go-boringcrypto.storage.googleapis.com/go1.13.1b4.src.tar.gz cf94520325f376ecaf420b7d25756cdecbed52510a1a079eca67c2c86c3cf39b
|
||||
go1.12.11b4 c5a4ae8c8c1b linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.11b4.linux-amd64.tar.gz a2d90aa130d45b36dd94a7e70accc94e2585eb45823fb7b07ae182ac8bc4a8ca
|
||||
go1.12.11b4 c5a4ae8c8c1b src https://go-boringcrypto.storage.googleapis.com/go1.12.11b4.src.tar.gz c334b70c9af0380fb9d397e89af1e2e2ac03380b5cc7c3327f56536c2f68bf8d
|
||||
go1.13.2b4 6a1c22797f9c linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.2b4.linux-amd64.tar.gz 888c1f6331862af388e730fab4926aa1cb2d4ffc5417e32f9e6d2af7953f0e29
|
||||
go1.13.2b4 6a1c22797f9c src https://go-boringcrypto.storage.googleapis.com/go1.13.2b4.src.tar.gz fc44c7713fcd84fe0587594ae5ee1a1d318a0da18b1156e1f9645c6ffa0335bc
|
||||
go1.12.12b4 cab2e4707a42 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.12b4.linux-amd64.tar.gz 983e996e8f60c78a400fed0edfd16c1718d704e15389c48b4a8b2d835c0d00f2
|
||||
go1.12.12b4 cab2e4707a42 src https://go-boringcrypto.storage.googleapis.com/go1.12.12b4.src.tar.gz 2d653a74c14cde1e414ac558e0bdd182ccbe1198bbff8cd22c8e423552d5e24d
|
||||
go1.13.3b4 cba6efa89376 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.3b4.linux-amd64.tar.gz 9ba0b7696f14dc7ecc912aae6587491853637fab30c4c005339fe36751bfd185
|
||||
go1.13.3b4 cba6efa89376 src https://go-boringcrypto.storage.googleapis.com/go1.13.3b4.src.tar.gz ba83d7e18fa49dc6e4319806e7b5cdee5eb046eb8e9fb38f3034378c4f80944a
|
||||
go1.12.13b4 5d9d84d037da linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.13b4.linux-amd64.tar.gz af3e0d2b9996c632b010da6700b7b8ec52bd3065b3facc478709209a854664eb
|
||||
go1.12.13b4 5d9d84d037da src https://go-boringcrypto.storage.googleapis.com/go1.12.13b4.src.tar.gz d1bae336ea076a0b2bfc984477f4a216a475e134068227e6d9b44faf239bcfb8
|
||||
go1.13.4b4 fa3f24e5c294 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.4b4.linux-amd64.tar.gz 23579d1bea65b2510e507bb0698ec66777bd34674c91dfe617ed130728791dc7
|
||||
go1.13.4b4 fa3f24e5c294 src https://go-boringcrypto.storage.googleapis.com/go1.13.4b4.src.tar.gz 8d82df5b4332acd5a274ac029ee5b5ff073b2a4247e2325610986221858b819d
|
||||
go1.12.16b4 f74e68136cf1 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.16b4.linux-amd64.tar.gz fd70cee8ca9438f99cc71b3586b11a03a36239a5bccbf1c4d06e7206b88bd77d
|
||||
go1.12.16b4 f74e68136cf1 src https://go-boringcrypto.storage.googleapis.com/go1.12.16b4.src.tar.gz 2ae0823cefc34f280d4f4ba0d665ff247ba1429cb43198d10e3bc316d3f29a8d
|
||||
go1.13.7b4 71468339f763 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.7b4.linux-amd64.tar.gz 85945502ad43f506902927f69b514b34a85a20e2bd1020cce87c551645194aa3
|
||||
go1.13.7b4 71468339f763 src https://go-boringcrypto.storage.googleapis.com/go1.13.7b4.src.tar.gz d30fa252de75763adb5886125e19e8bab68dbe8dbad33b0faf09a6be98b12d96
|
||||
go1.12.17b4 9e5b1367cb45 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.12.17b4.linux-amd64.tar.gz ee3a72dc1cfd8a34f32aaa5ddb05076fcb39434fd1bd25aa318234f72b462e31
|
||||
go1.12.17b4 9e5b1367cb45 src https://go-boringcrypto.storage.googleapis.com/go1.12.17b4.src.tar.gz ffb653ec8f4cc33e1e7c308d89c695f322a76f3107e0fc8c639affc6148261bf
|
||||
go1.13.8b4 fdf5e5b5905f linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.8b4.linux-amd64.tar.gz eac505df92aa6d6b76041f4b485d230f839159b8567c96d7980a06ef476ab3df
|
||||
go1.13.8b4 fdf5e5b5905f src https://go-boringcrypto.storage.googleapis.com/go1.13.8b4.src.tar.gz 1aa28fe37a704e94bb34e23578fd07ebbc6a025e9be9b45a898967b84405c41b
|
||||
go1.14b4 99da8fa53467 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14b4.linux-amd64.tar.gz a617e03a6c8813c53b813b865a2e185e12dbfaa76c703c1c48e57ad89651556b
|
||||
go1.14b4 99da8fa53467 src https://go-boringcrypto.storage.googleapis.com/go1.14b4.src.tar.gz ee292639b24923f519f1f0fe1ceaeca8d46feb8c15cf88e228346398c5848380
|
||||
go1.13.9b4 bb8a1014a32c linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.9b4.linux-amd64.tar.gz 565e1a3c62dfc2586471b6ae189ada053a86fc51d88d2eac883a03731071bf77
|
||||
go1.13.9b4 bb8a1014a32c src https://go-boringcrypto.storage.googleapis.com/go1.13.9b4.src.tar.gz 536f0549e7bbdad32270a17d8a282667560b6da2d27a5e3580714338e70185ad
|
||||
go1.14.1b4 e784c3f4d925 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.1b4.linux-amd64.tar.gz 6570991396d531fb628e4c01d697eeee395104147d406aec5a8ba00a213ef63f
|
||||
go1.14.1b4 e784c3f4d925 src https://go-boringcrypto.storage.googleapis.com/go1.14.1b4.src.tar.gz 2c267c3114fa4683f51c281d216d3754b38d5d08144c3acc318cf37165b1b2da
|
||||
go1.13.10b4 b129f40bb33f linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.10b4.linux-amd64.tar.gz a511b2e6ee7b71ca1411d6e4bb07ec33bb5b6974fd1dded77e00520d24d9d000
|
||||
go1.13.10b4 b129f40bb33f src https://go-boringcrypto.storage.googleapis.com/go1.13.10b4.src.tar.gz 5dfa44eea19b0be0c9c394fbbf89b2a14f84380a9d7b87e21eacba3ba030c44b
|
||||
go1.14.2b4 2b0d842f4b24 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.2b4.linux-amd64.tar.gz 82449a7ce57733c0cd3fa7feac89214706ff2b04e387b62619b8e2b8b388ffd9
|
||||
go1.14.2b4 2b0d842f4b24 src https://go-boringcrypto.storage.googleapis.com/go1.14.2b4.src.tar.gz bfcb44fa329d6a2eb5c4ef58bfa114d65b078bf69a361bb77e3ea52ec8975d14
|
||||
go1.13.12b4 488ca930b24a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.12b4.linux-amd64.tar.gz 63193aa2290af5d65d2d6bbddcd11d835d437a4e835954d605863f5b27a7661d
|
||||
go1.13.12b4 488ca930b24a src https://go-boringcrypto.storage.googleapis.com/go1.13.12b4.src.tar.gz 5b0aefb44ba2a08fedb5be0144810bc47559d7d8a6e61638c09dd261706d650e
|
||||
go1.14.4b4 fcdb6aa6ee5d linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.4b4.linux-amd64.tar.gz 682f2167b3d619690b1385196776822b1d2c497607f67e2d19d92faf2bea0b4a
|
||||
go1.14.4b4 fcdb6aa6ee5d src https://go-boringcrypto.storage.googleapis.com/go1.14.4b4.src.tar.gz 2fb759023360f0d42ba434f0409da2460ff4386cab062557f97fe15122b4b4cd
|
||||
go1.13.14b4 852ccd9de7d1 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.14b4.linux-amd64.tar.gz 49c67d3a67fac60e18a264555392aa5925126a75ef0ba152ec315cc874eccb43
|
||||
go1.13.14b4 852ccd9de7d1 src https://go-boringcrypto.storage.googleapis.com/go1.13.14b4.src.tar.gz 7b7dfc62286a07d438370b09f38845acae99c592c6e147722b8f3c098ab8756a
|
||||
go1.14.6b4 8f53ffb15fd5 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.6b4.linux-amd64.tar.gz 953322287806a42d4a73e096aea45511a51a0a323086e98119edcb0dae866c9d
|
||||
go1.14.6b4 8f53ffb15fd5 src https://go-boringcrypto.storage.googleapis.com/go1.14.6b4.src.tar.gz 75fea7a60da4ca225473b500b2d5ce7c302ca7d22eedfdbd3444cd01e6b9f392
|
||||
go1.15b5 a15df605fc4a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15b5.linux-amd64.tar.gz ebcb2212bdb645a16ffc05a1d9b77c94553ed19a6ccbbc73e4868c64777eb70a
|
||||
go1.15b5 a15df605fc4a src https://go-boringcrypto.storage.googleapis.com/go1.15b5.src.tar.gz 7107665853228b2c18f56fec73e217fa3494ccf52c609be839cf6945d501c0f0
|
||||
go1.13.15b4 5622128a77b4 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.13.15b4.linux-amd64.tar.gz 8b45ec0e578dc0a0bc483c2d12c08fee5adbfb39f0854fbe9d45f7d628ed1697
|
||||
go1.13.15b4 5622128a77b4 src https://go-boringcrypto.storage.googleapis.com/go1.13.15b4.src.tar.gz 21eab29a61a43078cd8bcdbbbb4c82ca049a7e2e211aca0c95f6a306e288db4f
|
||||
go1.14.9b4 62cd3338eed7 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.9b4.linux-amd64.tar.gz c81946294cbefa7a3abdf47733c720c3454418d6881c137a2e28f18ea40977aa
|
||||
go1.14.9b4 62cd3338eed7 src https://go-boringcrypto.storage.googleapis.com/go1.14.9b4.src.tar.gz e9c13c4daa10f6aac80b703f61f7e931af92e92146c8b140ae79e20e4af6bccd
|
||||
go1.15.2b5 dbc5602d1839 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.2b5.linux-amd64.tar.gz 30c04d854fc8990017ee8c180c1407a4f26c016e3a4134161bbf41c9d16452e3
|
||||
go1.15.2b5 dbc5602d1839 src https://go-boringcrypto.storage.googleapis.com/go1.15.2b5.src.tar.gz 67432c0b0a02aa6cc0c49ab285f1c6935a16dadfebd77dfabca7e31907240bc9
|
||||
go1.14.10b4 b5fc12785be4 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.10b4.linux-amd64.tar.gz d3aa38fb5108b43b155c21529190e73789df6ca0b37feafd43438aefe42f936e
|
||||
go1.14.10b4 b5fc12785be4 src https://go-boringcrypto.storage.googleapis.com/go1.14.10b4.src.tar.gz daf7603babc49935efdea5befb2ecad823771523a84d1ba6c0e8c10fac982d59
|
||||
go1.15.3b5 ed9dc25d693c linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.3b5.linux-amd64.tar.gz 34ec7ec094f5e9349f1612b5f6d8f014b3a7b37b6986aeedcd0fe7cf2dc76a62
|
||||
go1.15.3b5 ed9dc25d693c src https://go-boringcrypto.storage.googleapis.com/go1.15.3b5.src.tar.gz bc37727287366aabb47594717cebd0a759147d8b2eb4cd3a45a19317af199fe9
|
||||
go1.14.12b4 21ba30ad409a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.12b4.linux-amd64.tar.gz 7f9fb67a3c59fff24e3c51fa2a7435f4195cfb33844c9c2def27c162cc23604b
|
||||
go1.14.12b4 21ba30ad409a src https://go-boringcrypto.storage.googleapis.com/go1.14.12b4.src.tar.gz 948d7a77a4a890a7258102bcc7b63890f238061dfb6a4c06033660e727e87fcf
|
||||
go1.15.5b5 11087322f85d linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.5b5.linux-amd64.tar.gz 9c97488137f1f560b3fff0d8a2a9c45d2de8790fb8952a42b46cc4633528fc48
|
||||
go1.15.5b5 11087322f85d src https://go-boringcrypto.storage.googleapis.com/go1.15.5b5.src.tar.gz ee933cb1a4b591794dbcce99740032506af25ee202765dcc6979feb5abc114fc
|
||||
go1.14.13b4 2bb8e5a94e8a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.13b4.linux-amd64.tar.gz 8fb6e1cefe5535ab704e1b4e26725095dcca0060490842a54dd93e7cd8b206cd
|
||||
go1.14.13b4 2bb8e5a94e8a src https://go-boringcrypto.storage.googleapis.com/go1.14.13b4.src.tar.gz 02e0c4871d12813aee1019bf189b77ccec99dab3a1d5b95ce6abdf85b1810703
|
||||
go1.15.6b5 f78276931172 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.6b5.linux-amd64.tar.gz 245c500f7da70fb2abd1a6021436ed48e2b97dbbdb394a759b0601dc69cf4e77
|
||||
go1.15.6b5 f78276931172 src https://go-boringcrypto.storage.googleapis.com/go1.15.6b5.src.tar.gz 6576a29d019405b14fdc98883fed33c766de2028fbbd3a743a241275275cc7e5
|
||||
go1.14.14b4 9cf003256bc3 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.14b4.linux-amd64.tar.gz 7df65366d26a13c5be16f87f64e832e86db3b8b9ca1b5c6385e0e20bf79dc82f
|
||||
go1.14.14b4 9cf003256bc3 src https://go-boringcrypto.storage.googleapis.com/go1.14.14b4.src.tar.gz aaeda57e2b68ac72783c7aacded814ec660a91c1010c3139156c8e7def86f145
|
||||
go1.15.7b5 79ea7a16d7e3 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.7b5.linux-amd64.tar.gz cb08962897e3802cda96f4ee915ed20fbde7d5d85e688759ef523d2e6ae44851
|
||||
go1.15.7b5 79ea7a16d7e3 src https://go-boringcrypto.storage.googleapis.com/go1.15.7b5.src.tar.gz aa7cb4beff82881cbff4a66e9e07a4004e49384a8fcc95204db9b2f48c12a235
|
||||
go1.15.8b5 2a0dd053ecfa linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.8b5.linux-amd64.tar.gz 9d897bf42a962b064cfc9bed182c18ade0a3f5857d6a075d93b73ca8fe3b1f3a
|
||||
go1.15.8b5 2a0dd053ecfa src https://go-boringcrypto.storage.googleapis.com/go1.15.8b5.src.tar.gz 57964e7762ab03f0ad17bc787585b1709decccf095b7f7d2e9fca61a71e09010
|
||||
go1.14.15b4 47419f9cac61 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.14.15b4.linux-amd64.tar.gz 82ba7297d26afcdade439de5621bdcb16e5261877f204aa60d03b5e07223a5c8
|
||||
go1.14.15b4 47419f9cac61 src https://go-boringcrypto.storage.googleapis.com/go1.14.15b4.src.tar.gz bf77b15f1d905753648db2d91e39c3a740b67b03dfff511aa25a360a78f9742a
|
||||
go1.16b7 67a0be0b437e linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16b7.linux-amd64.tar.gz 56d4e41d55baece6b98bc66bdf772b0eb17518dd287f27c533225cd154ee0a38
|
||||
go1.16b7 67a0be0b437e src https://go-boringcrypto.storage.googleapis.com/go1.16b7.src.tar.gz 7d063cf1cbd252da8b2db54947e5f2f1402ac792e1ea6de76e05ab233f5badbd
|
||||
go1.15.9b5 055f1da6e6b9 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.9b5.linux-amd64.tar.gz 8e44de7d9d36d68e01c0454841f1becb93d4932bb16a623ed6d4de15ecba1239
|
||||
go1.15.9b5 055f1da6e6b9 src https://go-boringcrypto.storage.googleapis.com/go1.15.9b5.src.tar.gz dba0290da6ae46df8d68c6d027b7d6b4775d6dcf8ff9f3cb8a26dbd5b757e696
|
||||
go1.16.1b7 b9bd851b1452 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.1b7.linux-amd64.tar.gz 963f6a4fb8c5ff7668fb17ba52c3d905466058266556844aee79139f7e3c9521
|
||||
go1.16.1b7 b9bd851b1452 src https://go-boringcrypto.storage.googleapis.com/go1.16.1b7.src.tar.gz 8e6849010ae5f3280fea0f6fa6e5b07831ac6e6524a636fab41c0e4f77b529ba
|
||||
go1.15.10b5 229a39e34717 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.10b5.linux-amd64.tar.gz 7533b0307fd995deb9ef68d67899582c336a3c62387d19d03d10202129e9fad3
|
||||
go1.15.10b5 229a39e34717 src https://go-boringcrypto.storage.googleapis.com/go1.15.10b5.src.tar.gz adbaff96b2392a9ab5a20d15fec959983861ec6e554c3c9cd14aec586a0928b3
|
||||
go1.16.2b7 6d5f0ffc93e5 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.2b7.linux-amd64.tar.gz 2871d90630706eba9d3bd2838ec1c0a367c78c2c4f40e74ed75c294e2c5aa358
|
||||
go1.16.2b7 6d5f0ffc93e5 src https://go-boringcrypto.storage.googleapis.com/go1.16.2b7.src.tar.gz 8991c28e30bdd9b34076c2871ab69aac7f306dba08d202aa7301f3adb54ad9f3
|
||||
go1.15.11b5 be25192f119e linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.11b5.linux-amd64.tar.gz c5aa34a83631b3736bc1ab37027bc4fc22eca2353035586a6255be7e29251f43
|
||||
go1.15.11b5 be25192f119e src https://go-boringcrypto.storage.googleapis.com/go1.15.11b5.src.tar.gz 05408824d64ac8ebb6c1d895017e605d45a2c4ebee28995136fe12f4833652d2
|
||||
go1.16.3b7 fcee6b930a01 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.3b7.linux-amd64.tar.gz afe15efce3c1fecc60994d7ba0d41daaa029fa5810c98737121dde7b38a5e2ac
|
||||
go1.16.3b7 fcee6b930a01 src https://go-boringcrypto.storage.googleapis.com/go1.16.3b7.src.tar.gz 5c86175ed86e6ae3826eb827cc51bdda770f22ffaf3258b11135a268153b5057
|
||||
go1.16.4b7 25aff96f4b49 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.4b7.linux-amd64.tar.gz de60f0620f46b1872813f72646fdece76be94f43c1abe84b69033c26f823a31f
|
||||
go1.16.4b7 25aff96f4b49 src https://go-boringcrypto.storage.googleapis.com/go1.16.4b7.src.tar.gz 5b537cf5598bc968764885f4d1f9820578d05d104a6cd7107bb3e443217f4983
|
||||
go1.15.12b5 03a15201e7e0 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.12b5.linux-amd64.tar.gz 9fadc65da7df036bfe702b3f9980e2ca2b184f13d09e8094244f58a866a2f6ee
|
||||
go1.15.12b5 03a15201e7e0 src https://go-boringcrypto.storage.googleapis.com/go1.15.12b5.src.tar.gz 81ec958d893f4ecf90111d09ceb79b36492266a39d1918a22e80443e1d399561
|
||||
go1.16.5b7 e4feea2ce841 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.5b7.linux-amd64.tar.gz 2085b246d7d6908f504d0f33c655c31c3ec6e1ae3d13a020ba58abcf1b6ea7a4
|
||||
go1.16.5b7 e4feea2ce841 src https://go-boringcrypto.storage.googleapis.com/go1.16.5b7.src.tar.gz cfe6cc16eb205d61414338c2b42fa2c4278831785b29e6b79712669418852ef4
|
||||
go1.15.13b5 9647f89f2ac2 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.13b5.linux-amd64.tar.gz 1ad1edeaf3b6bc7696978d4137f55c0b38b8d796a607b89f7f010004aaef60a6
|
||||
go1.15.13b5 9647f89f2ac2 src https://go-boringcrypto.storage.googleapis.com/go1.15.13b5.src.tar.gz 6cc9c5d23947a9dccc0e1afdff5d433398b09df1c5170596a826aac326ece457
|
||||
go1.15.14b5 ddf078e08dc6 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.14b5.linux-amd64.tar.gz 8c4dbdc91e36f3d1db7f14b234973bfcb3b685fe4a6cb2e326ba9cf73a4260c2
|
||||
go1.15.14b5 ddf078e08dc6 src https://go-boringcrypto.storage.googleapis.com/go1.15.14b5.src.tar.gz 0022b68f04a5d8553cfd838d3fe226f18e7095194300b2be4fc49a689daf0e1b
|
||||
go1.16.6b7 6a6b41a8441e linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.6b7.linux-amd64.tar.gz f7f33064643ce0ab8ac1cede100e7eee8509a970178f5be961d9fba331226067
|
||||
go1.16.6b7 6a6b41a8441e src https://go-boringcrypto.storage.googleapis.com/go1.16.6b7.src.tar.gz a1079dd2df6aad3bad584c4187dab98a264075b56b1d257ba27d956340ff7bbf
|
||||
go1.15.15b5 dd96ded6c86b linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.15.15b5.linux-amd64.tar.gz 719d818f70c6eb1e753910fe21624832cf3f719540f22f89863e959ff68c0001
|
||||
go1.15.15b5 dd96ded6c86b src https://go-boringcrypto.storage.googleapis.com/go1.15.15b5.src.tar.gz af2d44c8eef02e093c077c085fbe6964af0ca715f95f4bcea0809fa211cc4ded
|
||||
go1.16.7b7 0d02a0d966b6 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.7b7.linux-amd64.tar.gz d4ca2906640edd9299d12d8204aae0d848b497b79b92424d8705ae748e16f3c5
|
||||
go1.16.7b7 0d02a0d966b6 src https://go-boringcrypto.storage.googleapis.com/go1.16.7b7.src.tar.gz f65503abf459ba1d2f77d4d023fcebd19c62e7c34d3ffd0f1aebb598ffa153d9
|
||||
go1.16.9b7 35d5cd0dcfb9 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.9b7.linux-amd64.tar.gz 6659e3ea17474000d2ac2f4a887a4bac26ab8cf6a0b0779cbd41464a7de23645
|
||||
go1.16.9b7 35d5cd0dcfb9 src https://go-boringcrypto.storage.googleapis.com/go1.16.9b7.src.tar.gz 81a40da773e33230276446955f9ddc85c8ca121432d56842edad49212975a9bc
|
||||
go1.17.2b7 5f1867dc1e67 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.2b7.linux-amd64.tar.gz 60fd88def54b81e489ba2d2d80e5df32150ef1a62c0ece3ff869862141824c81
|
||||
go1.17.2b7 5f1867dc1e67 src https://go-boringcrypto.storage.googleapis.com/go1.17.2b7.src.tar.gz b00e746a053d5e70e27151b9461e5e3413c53bb88bc60e0db107a99284614d17
|
||||
go1.16.10b7 06a4b2790c5b linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.10b7.linux-amd64.tar.gz 9720316c7d91fa0b6a31678745ad68c52c92e4027751602449fb2309c0c3f1de
|
||||
go1.16.10b7 06a4b2790c5b src https://go-boringcrypto.storage.googleapis.com/go1.16.10b7.src.tar.gz 742e1e904d82cd7a17fade53ab9001f5f88b7a3ee9358c587811762fc07cdaa3
|
||||
go1.17.3b7 5a371e30afcb linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.3b7.linux-amd64.tar.gz a5216d1e7401c734b3e29e8aad3c8608f094ae7d37b55e8815211e25922e4d19
|
||||
go1.17.3b7 5a371e30afcb src https://go-boringcrypto.storage.googleapis.com/go1.17.3b7.src.tar.gz 858595a95faf4c730ebe3d40ecba1705b79f7bc2a996fd044cb30da8d9c57534
|
||||
go1.17.4b7 95e6359f6a5d linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.4b7.linux-amd64.tar.gz aa4a69709a08c7d83a6417f978a9e5f32207c0e9da82d39cceff7d9cdf657e59
|
||||
go1.17.4b7 95e6359f6a5d src https://go-boringcrypto.storage.googleapis.com/go1.17.4b7.src.tar.gz 0151f947e1da7a9cec63b06276b9ed4b92d2e5113ae254ebbdb9191b65c711f6
|
||||
go1.16.11b7 c884bd9ef2f1 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.11b7.linux-amd64.tar.gz 8edd1e42a88df0dbb99f1e1487149a856155f24711e19c17ba0f08d76254e2ca
|
||||
go1.16.11b7 c884bd9ef2f1 src https://go-boringcrypto.storage.googleapis.com/go1.16.11b7.src.tar.gz a50f8362af1e44011b342657cac80d817868c6d0f40a6d235c45abc81c16fb92
|
||||
go1.16.12b7 adecd3ffbec7 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.12b7.linux-amd64.tar.gz fd43c36e9bc926634c13e0dc3547046c55f3b5a2448473d8fb51c344ea726542
|
||||
go1.16.12b7 adecd3ffbec7 src https://go-boringcrypto.storage.googleapis.com/go1.16.12b7.src.tar.gz 891e21c67738b63b645ace56fbd3874ff9e8583865ee7907543ae43373411d64
|
||||
go1.17.5b7 dc52cfcd39cd linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.5b7.linux-amd64.tar.gz 92407bbc855fd05c5252a2ee2d4fcb6eb077cf64fd0d70da53ba7914c22ec1d7
|
||||
go1.17.5b7 dc52cfcd39cd src https://go-boringcrypto.storage.googleapis.com/go1.17.5b7.src.tar.gz 4c508aecce1b56e34a4e32605086994606c72010b7caedce7681c1019781c93e
|
||||
go1.16.13b7 bb93480d0093 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.13b7.linux-amd64.tar.gz cd98a2ea753edc9d0206b14b2d40d269ddaee1dea7bc59b91cb8a11fc575f738
|
||||
go1.16.13b7 bb93480d0093 src https://go-boringcrypto.storage.googleapis.com/go1.16.13b7.src.tar.gz e9f8f5f6769fed35924b364f2e1df8ad2fc491569189761047cec14ca5922ee1
|
||||
go1.17.6b7 cfad1ff84c45 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.6b7.linux-amd64.tar.gz 5b55a001fb80f9baaed621c2469977b9c9afe13b9afc6fd5712057856ab86f5d
|
||||
go1.17.6b7 cfad1ff84c45 src https://go-boringcrypto.storage.googleapis.com/go1.17.6b7.src.tar.gz 5178f595dea6d618f7cdf6b9e2346a1a28430b4d547996b766fcd5b34379ca2f
|
||||
go1.17.7b7 172559d22b5d linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.7b7.linux-amd64.tar.gz a69bf0516affb8678873ba40c4ddbc8e3b01bfa8460f5c5f356dd53049d54322
|
||||
go1.17.7b7 172559d22b5d src https://go-boringcrypto.storage.googleapis.com/go1.17.7b7.src.tar.gz eff84edf4f676c691ac21747277e15777789be32dcaa53a0779737b280351453
|
||||
go1.16.14b7 e90b835f3071 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.14b7.linux-amd64.tar.gz 5024e1231d33b9dfffdd7821132dd32eccd42e7415f25618dc8c7304b335edd9
|
||||
go1.16.14b7 e90b835f3071 src https://go-boringcrypto.storage.googleapis.com/go1.16.14b7.src.tar.gz caef2ef601bcc588e6bcb511087c9620200723a4c74191b725fbda94c3be884b
|
||||
go1.17.8b7 4ea866a9969f linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.8b7.linux-amd64.tar.gz 4a1fa2c8d77309e1ef5bafe7e80e75c06e70c0ae1212d9f3d95485017155491d
|
||||
go1.17.8b7 4ea866a9969f src https://go-boringcrypto.storage.googleapis.com/go1.17.8b7.src.tar.gz e42ac342c315d33c47434299a24f33137e7099f278ee6669404c4d7e49e17bcf
|
||||
go1.16.15b7 649671b08fbd linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.16.15b7.linux-amd64.tar.gz 4d62f517786266019c721c35330e23da123eb184eadb5a79379fe81d31d856db
|
||||
go1.16.15b7 649671b08fbd src https://go-boringcrypto.storage.googleapis.com/go1.16.15b7.src.tar.gz 54fc7f2ec0b72b0aaf7726eb5f7f57885252ef46c2c1ca238090cc57850e3ef7
|
||||
go1.18b7 0622ea4d9068 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18b7.linux-amd64.tar.gz baa33bc66b8df97a3c5a328637b85f04d5629f139dc2df946c09ab7214510c61
|
||||
go1.18b7 0622ea4d9068 src https://go-boringcrypto.storage.googleapis.com/go1.18b7.src.tar.gz 6028ffee59903934a3182d45ee3e0c1c9f47fb98f05d9bbb2fabb4771db60792
|
||||
go1.18.1b7 d003f0850a7d linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.1b7.linux-amd64.tar.gz a5b3985341de6ca54f6a8e13e9ae695f0ee202207e25f082c3895a8fc6f89f64
|
||||
go1.18.1b7 d003f0850a7d src https://go-boringcrypto.storage.googleapis.com/go1.18.1b7.src.tar.gz c7f91549b3a197e4a08f64e07546855ca8f82d597f60fd23c7ad2f082640a9fe
|
||||
go1.17.9b7 ed86dfc4e441 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.9b7.linux-amd64.tar.gz 9469d1b4c10f59c921c4666c52baba5f6ca63b1cce0eca95e03b5713ef27577c
|
||||
go1.17.9b7 ed86dfc4e441 src https://go-boringcrypto.storage.googleapis.com/go1.17.9b7.src.tar.gz 5d6bfe543a9a2bf6d8749973c771e40127b8020a769ecc5fb41d0dbd7deae9a6
|
||||
go1.18.2b7 dcdb19874ff3 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.2b7.linux-amd64.tar.gz a53566eebe8e128695ddbd52c080502a0daca1c9f1b893cada9349259ed27e99
|
||||
go1.18.2b7 dcdb19874ff3 src https://go-boringcrypto.storage.googleapis.com/go1.18.2b7.src.tar.gz 3c3ce00cd39cdd2ae9afddd7581c6f8b14f8e96e2bb56b9cb4fec8ff02db63b0
|
||||
go1.17.10b7 6b07de790c08 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.10b7.linux-amd64.tar.gz 3c506a86b1e3e4fcffd6a875e5d47ca23f0a346c1bd6e6163e67dbb96eeec1d5
|
||||
go1.17.10b7 6b07de790c08 src https://go-boringcrypto.storage.googleapis.com/go1.17.10b7.src.tar.gz 9d5914842ea1b36edc2ceb6cfa7d3a79bea450c8b397e86bfae7c73944208f03
|
||||
go1.18.3b7 a69db81af596 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.3b7.linux-amd64.tar.gz 1c13ddfb539141298ee32d26b95345cacdcd245c29fb6bc63acb59f9ba41f519
|
||||
go1.18.3b7 a69db81af596 src https://go-boringcrypto.storage.googleapis.com/go1.18.3b7.src.tar.gz d8123121c491569c698ef713001a2193f13d9a8111a1ba7b2b0d4a2e9bf863db
|
||||
go1.17.11b7 4658e6e324a8 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.11b7.linux-amd64.tar.gz 104a5b10037e7a2646b0458519bf6efe85c6d203ae9f32ede7ed24d4e87f7b2d
|
||||
go1.17.11b7 4658e6e324a8 src https://go-boringcrypto.storage.googleapis.com/go1.17.11b7.src.tar.gz 85a6d4249e38decdaad0cffe784cbe249199e38a18db1c247097a5f91f5d9c10
|
||||
go1.18.4b7 913e3713bed3 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.4b7.linux-amd64.tar.gz 24be93f9718bfb4b7703fe959a69c61e103a0149dda693406cd681f7e00cf6fb
|
||||
go1.18.4b7 913e3713bed3 src https://go-boringcrypto.storage.googleapis.com/go1.18.4b7.src.tar.gz 572ce2d917c06ca87ccd3e51e02e0ad4a09eb0ad283cc762176d11d7cd4777af
|
||||
go1.17.12b7 7d5078e3bf2d linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.12b7.linux-amd64.tar.gz f1a075501f89d1b726a0a71611019679c77944e6ab253991aad79df73859d20a
|
||||
go1.17.12b7 7d5078e3bf2d src https://go-boringcrypto.storage.googleapis.com/go1.17.12b7.src.tar.gz aa7e6eccf8d8ee1fd270eb5acba58b6416ad97decae32ca7eee03193a70defa6
|
||||
go1.18.5b7 270c7b73de4a linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.5b7.linux-amd64.tar.gz 104479cff67e4c749304d95dd5b5e0d065a65780ec03b6378a28432c01504e88
|
||||
go1.18.5b7 270c7b73de4a src https://go-boringcrypto.storage.googleapis.com/go1.18.5b7.src.tar.gz 75f5021bd9b61f837fdd516cc4ec51556c519c7155a2e99ecfb4efeca8655aa7
|
||||
go1.17.13b7 349da2d42d31 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.17.13b7.linux-amd64.tar.gz 489151867b1454ea17d8a02bebb443121623c63585a15c2640e043c432c2d1ef
|
||||
go1.17.13b7 349da2d42d31 src https://go-boringcrypto.storage.googleapis.com/go1.17.13b7.src.tar.gz 8c86eede1718d45a8f934df2b158eb30b5d323255e5ff8885c81319f973f464e
|
||||
go1.18.6b7 5fe109f32326 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.6b7.linux-amd64.tar.gz a81c54b6dfd0750998be758a54ae46ecd5f1442c303c5146e844568c02acb47f
|
||||
go1.18.6b7 5fe109f32326 src https://go-boringcrypto.storage.googleapis.com/go1.18.6b7.src.tar.gz 0afc7b1edb8b7570ba05bc30b112804280b1cc5750e1a3dc8500be5c8b8ba06f
|
||||
go1.18.7b7 e3d1f0e7da63 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.7b7.linux-amd64.tar.gz 96694715f7d8122670a5e919b122470817041077e0f98ffd2c2643df5824ee82
|
||||
go1.18.7b7 e3d1f0e7da63 src https://go-boringcrypto.storage.googleapis.com/go1.18.7b7.src.tar.gz c62ba13f792f64f31381d34a7d6b14aec0b04363eb67085b999d1d6e51a94136
|
||||
go1.18.8b7 94108e21ab6f linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.8b7.linux-amd64.tar.gz 9df1f697273b29a5f8b23e5ed2bfd187237d886c2ebac360f457537c7b17dcd8
|
||||
go1.18.8b7 94108e21ab6f src https://go-boringcrypto.storage.googleapis.com/go1.18.8b7.src.tar.gz c3028846650b42cf77c1c0d540791eaa1283c8e60e2a87e28ae43658ffdc262a
|
||||
go1.18.9b7 fc1ed37e824b linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.9b7.linux-amd64.tar.gz 65f15218ed55697de24d4f58f43ed3c1ff35eb59462aab8002554cc479bf573c
|
||||
go1.18.9b7 fc1ed37e824b src https://go-boringcrypto.storage.googleapis.com/go1.18.9b7.src.tar.gz 45b1ed1d3f63d1fa86c6f26329f11912c1dbfb1fa4fd39cf0eabc84e29f86cd7
|
||||
go1.18.10b7 7058c2cb4132 linux-amd64 https://go-boringcrypto.storage.googleapis.com/go1.18.10b7.linux-amd64.tar.gz 17897c0f3716c8bc8ad3db9a41b7b35820b9d43cff3982193808f9af13e7dae5
|
||||
go1.18.10b7 7058c2cb4132 src https://go-boringcrypto.storage.googleapis.com/go1.18.10b7.src.tar.gz 4ced930d738cb30f4c4b28b7281d1e2e397eda2353b4c8f7c6de82ef589acc0b
|
||||
1
misc/boring/VERSION
Normal file
1
misc/boring/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
8
|
||||
58
misc/boring/build.docker
Executable file
58
misc/boring/build.docker
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2017 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.
|
||||
|
||||
# build.docker builds and publishes a Docker image for
|
||||
# a given Go+BoringCrypto release.
|
||||
|
||||
set -e
|
||||
|
||||
# With no arguments, use the most recent linux-amd64 release in the RELEASES file.
|
||||
case "$#" in
|
||||
0)
|
||||
version=$(grep linux-amd64 RELEASES | tail -1 | awk '{print $1}');;
|
||||
1)
|
||||
version="$1";;
|
||||
*)
|
||||
echo 'usage: build.docker [version]' >&2
|
||||
exit 2
|
||||
esac
|
||||
|
||||
url="$(grep "^$version .* linux-amd64 " RELEASES | awk '{print $4}')"
|
||||
sha256="$(grep "^$version .* linux-amd64 " RELEASES | awk '{print $5}')"
|
||||
if [ "$sha256" = "" ]; then
|
||||
echo "cannot find $version in RELEASES file" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Build a temporary directory with a Dockerfile.
|
||||
dir=$(mktemp -d)
|
||||
trap "rm -rf $dir" EXIT
|
||||
|
||||
if echo "$url" | grep '!' >/dev/null; then
|
||||
# ! is sed delimiter below. Should never happen.
|
||||
echo "URL contains an exclamation mark!" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dversion=$(echo "$version" | sed 's/^go//')
|
||||
sed "s!UUU!$url!; s/SSS/$sha256/; s/VVV/$dversion/" dockerfile.in >$dir/Dockerfile
|
||||
|
||||
dpkg=us-docker.pkg.dev/google.com/api-project-999119582588/go-boringcrypto/golang:$dversion
|
||||
|
||||
docker build --pull -t $dpkg $dir
|
||||
docker run $dpkg go version
|
||||
docker run $dpkg go tool nm /usr/local/go/bin/go >$dir/nm
|
||||
if ! grep crypto/internal/boring/sig.BoringCrypto $dir/nm >/dev/null; then
|
||||
echo 'built docker image but did NOT find sig.BoringCrypto in go command!' >&2
|
||||
exit 2
|
||||
fi
|
||||
if egrep 'crypto/sha256\.\(\*digest\)' $dir/nm >/dev/null; then
|
||||
echo 'built docker image but DID find sha256.(*digest) in go command unexpectedly!' >&2
|
||||
exit 2
|
||||
fi
|
||||
docker push $dpkg
|
||||
|
||||
echo
|
||||
echo published as $dpkg
|
||||
102
misc/boring/build.release
Executable file
102
misc/boring/build.release
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2017 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.
|
||||
|
||||
# build.release builds and publishes a new Go+BoringCrypto release.
|
||||
# After running this script, the change to the RELEASES file should be
|
||||
# sent out for review and committed to the repository (but the release
|
||||
# is already done, so there's not much to review).
|
||||
|
||||
set -e
|
||||
|
||||
case "$#" in
|
||||
0)
|
||||
rev=HEAD;;
|
||||
1)
|
||||
rev="$1";;
|
||||
*)
|
||||
echo 'usage: build.release [git-rev]' >&2
|
||||
exit 2
|
||||
esac
|
||||
|
||||
# Determine commit to use.
|
||||
commit=$(git rev-parse "$rev" | awk '{print substr($1, 1, 12)}')
|
||||
if [ "$commit" = "" ]; then
|
||||
echo 'cannot find commit in git history' >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Determine base Go release from tags.
|
||||
base=$(git log --decorate=short --oneline "$rev" | grep 'tag: go' | sed 1q | sed 's/[),].*//; s/.*tag: //')
|
||||
if [ "$base" = "" ]; then
|
||||
echo "cannot find go release tag in git history for $rev" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Determine boring crypto version from file.
|
||||
boring=$(git show "$commit:misc/boring/VERSION")
|
||||
if [ "$boring" = "" ]; then
|
||||
echo "missing BORINGVERSION file in $commit" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Make sure we're not redefining a published release.
|
||||
version="${base}b${boring}"
|
||||
if grep "^$version " RELEASES >/dev/null; then
|
||||
echo "found $version in RELEASES - not rereleasing" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Show what's going on, while the release builds.
|
||||
# Good time for user to type ^C if something is wrong.
|
||||
echo >&2
|
||||
echo "building $version from $commit" >&2
|
||||
echo >&2
|
||||
git log -n1 "$commit" >&2
|
||||
echo >&2
|
||||
|
||||
# Build the release tool in a temporary directory.
|
||||
dir=$(mktemp -d)
|
||||
trap "rm -rf $dir" EXIT
|
||||
GOBIN="$dir" go install golang.org/x/build/cmd/release@latest
|
||||
|
||||
# Build the release.
|
||||
sha() {
|
||||
if hash sha256sum 2>/dev/null; then
|
||||
sha256sum "$@"
|
||||
else
|
||||
shasum -a 256 "$@"
|
||||
fi
|
||||
}
|
||||
shortgo=$(echo "$base" | perl -pe 's/(go\d+\.\d+)(\.\d+|rc\d+)/$1/')
|
||||
$dir/release -target linux-amd64 -rev "$commit" -version "$version" -skip_long_tests
|
||||
$dir/release -target src -rev "$commit" -version "$version"
|
||||
output="$version.linux-amd64.tar.gz"
|
||||
ls -l "$output"
|
||||
sha256=$(sha "$output" | awk '{print $1}')
|
||||
outputsrc="$version.src.tar.gz"
|
||||
ls -l "$outputsrc"
|
||||
sha256src=$(sha "$outputsrc" | awk '{print $1}')
|
||||
|
||||
trap "rm -f /tmp/go.release.$$ /tmp/go.nm.$$" EXIT
|
||||
tar -xzf "$output" -O go/bin/go >/tmp/go.release.$$
|
||||
go tool nm /tmp/go.release.$$ >/tmp/go.nm.$$
|
||||
if ! grep crypto/internal/boring/sig.BoringCrypto /tmp/go.nm.$$ >/dev/null; then
|
||||
echo 'built release but did NOT find sig.BoringCrypto in go command!' >&2
|
||||
exit 2
|
||||
fi
|
||||
if egrep 'crypto/sha256\.\(\*digest\)' /tmp/go.nm.$$ >/dev/null; then
|
||||
echo 'built release but DID find sha256.(*digest) in go command unexpectedly!' >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Publish the release.
|
||||
gsutil cp "$output" gs://go-boringcrypto/
|
||||
url="https://go-boringcrypto.storage.googleapis.com/$output"
|
||||
gsutil cp "$outputsrc" gs://go-boringcrypto/
|
||||
urlsrc="https://go-boringcrypto.storage.googleapis.com/$outputsrc"
|
||||
|
||||
# Record that it was published.
|
||||
echo "$version $commit linux-amd64 $url $sha256" >>RELEASES
|
||||
echo "$version $commit src $urlsrc $sha256src" >>RELEASES
|
||||
31
misc/boring/dockerfile.in
Normal file
31
misc/boring/dockerfile.in
Normal file
@@ -0,0 +1,31 @@
|
||||
# Template for Dockerfile, used in build.docker script.
|
||||
# Based on https://github.com/docker-library/golang/blob/7e3d99a803/1.13/buster/Dockerfile
|
||||
FROM buildpack-deps:buster-scm
|
||||
|
||||
# gcc for cgo
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
gcc \
|
||||
libc6-dev \
|
||||
make \
|
||||
pkg-config \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GOLANG_VERSION VVV
|
||||
|
||||
RUN set -eux; \
|
||||
\
|
||||
url="UUU"; \
|
||||
wget -O go.tgz "$url"; \
|
||||
echo "SSS go.tgz" | sha256sum -c -; \
|
||||
tar -C /usr/local -xzf go.tgz; \
|
||||
rm go.tgz; \
|
||||
\
|
||||
export PATH="/usr/local/go/bin:$PATH"; \
|
||||
go version
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
|
||||
WORKDIR $GOPATH
|
||||
34
misc/boring/merge.sh
Executable file
34
misc/boring/merge.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "usage: merge.sh <target branch> <source revision>"
|
||||
echo ""
|
||||
echo "example: merge.sh dev.boringcrypto master"
|
||||
echo " merge.sh dev.boringcrypto.go1.10 go1.10.7"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET="$1"
|
||||
SOURCE="$2"
|
||||
WORKTREE="$(mktemp -d)"
|
||||
BRANCH="boring/merge-$TARGET-$(date +%Y%m%d%H%M%S)"
|
||||
|
||||
git fetch
|
||||
git worktree add --track -b "$BRANCH" "$WORKTREE" "origin/$TARGET"
|
||||
|
||||
cd "$WORKTREE"
|
||||
export GIT_GOFMT_HOOK=off
|
||||
git merge --no-commit --no-stat "$SOURCE" || echo "Ignoring conflict..."
|
||||
[[ -f VERSION ]] && git rm -f VERSION
|
||||
git checkout --ours codereview.cfg && git add codereview.cfg
|
||||
git commit -m "all: merge $SOURCE into $TARGET"
|
||||
|
||||
if ! git log --format=%B -n 1 | grep "\[$TARGET\] "; then
|
||||
echo "The commit does not seem to be targeting the BoringCrypto branch."
|
||||
echo "(Or you are missing the git-codereview hooks.)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git codereview mail -trybot HEAD
|
||||
cd - && git worktree remove "$WORKTREE"
|
||||
34
misc/boring/release.sh
Executable file
34
misc/boring/release.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "usage: <target branch> [<target branch> ...]"
|
||||
echo ""
|
||||
echo "example: release.sh dev.boringcrypto.go1.11 dev.boringcrypto.go1.12"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that the Docker daemon is available.
|
||||
docker ps > /dev/null
|
||||
|
||||
WORKTREE="$(mktemp -d)"
|
||||
BRANCH="boring/release-$(date +%Y%m%d%H%M%S)"
|
||||
|
||||
git fetch
|
||||
git worktree add --track -b "$BRANCH" "$WORKTREE" origin/dev.boringcrypto
|
||||
|
||||
cd "$WORKTREE/src"
|
||||
GOEXPERIMENT=boringcrypto ./make.bash
|
||||
|
||||
cd ../misc/boring
|
||||
for branch in "$@"; do
|
||||
./build.release "origin/$branch"
|
||||
./build.docker
|
||||
done
|
||||
|
||||
git add RELEASES
|
||||
git commit -m "misc/boring: add new releases to RELEASES file"
|
||||
git codereview mail
|
||||
|
||||
rm *.tar.gz
|
||||
cd - && git worktree remove "$WORKTREE"
|
||||
28
misc/cgo/test/testdata/issue9400/asm_loong64.s
vendored
28
misc/cgo/test/testdata/issue9400/asm_loong64.s
vendored
@@ -1,28 +0,0 @@
|
||||
// Copyright 2022 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 "textflag.h"
|
||||
|
||||
TEXT ·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0
|
||||
// Rewind stack pointer so anything that happens on the stack
|
||||
// will clobber the test pattern created by the caller
|
||||
ADDV $(1024*8), R3
|
||||
|
||||
// Ask signaller to setgid
|
||||
MOVW $1, R12
|
||||
DBAR
|
||||
MOVW R12, ·Baton(SB)
|
||||
DBAR
|
||||
|
||||
// Wait for setgid completion
|
||||
loop:
|
||||
DBAR
|
||||
MOVW ·Baton(SB), R12
|
||||
OR R13, R13, R13 // hint that we're in a spin loop
|
||||
BNE R12, loop
|
||||
DBAR
|
||||
|
||||
// Restore stack
|
||||
ADDV $(-1024*8), R3
|
||||
RET
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
)
|
||||
|
||||
var gcflags string = os.Getenv("GO_GCFLAGS")
|
||||
var goroot string
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
@@ -44,12 +43,6 @@ func prettyPrintf(format string, args ...interface{}) {
|
||||
}
|
||||
|
||||
func testMain(m *testing.M) int {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
goroot = filepath.Join(cwd, "../../..")
|
||||
|
||||
// Copy testdata into GOPATH/src/testplugin, along with a go.mod file
|
||||
// declaring the same path.
|
||||
|
||||
@@ -120,7 +113,7 @@ func goCmd(t *testing.T, op string, args ...string) {
|
||||
if t != nil {
|
||||
t.Helper()
|
||||
}
|
||||
run(t, filepath.Join(goroot, "bin", "go"), append([]string{op, "-gcflags", gcflags}, args...)...)
|
||||
run(t, "go", append([]string{op, "-gcflags", gcflags}, args...)...)
|
||||
}
|
||||
|
||||
// escape converts a string to something suitable for a shell command line.
|
||||
@@ -218,7 +211,7 @@ func TestIssue18676(t *testing.T) {
|
||||
|
||||
func TestIssue19534(t *testing.T) {
|
||||
// Test that we can load a plugin built in a path with non-alpha characters.
|
||||
goCmd(t, "build", "-buildmode=plugin", "-gcflags=-p=issue.19534", "-ldflags=-pluginpath=issue.19534", "-o", "plugin.so", "./issue19534/plugin.go")
|
||||
goCmd(t, "build", "-buildmode=plugin", "-ldflags='-pluginpath=issue.19534'", "-o", "plugin.so", "./issue19534/plugin.go")
|
||||
goCmd(t, "build", "-o", "issue19534.exe", "./issue19534/main.go")
|
||||
run(t, "./issue19534.exe")
|
||||
}
|
||||
@@ -303,10 +296,6 @@ func TestIssue44956(t *testing.T) {
|
||||
run(t, "./issue44956.exe")
|
||||
}
|
||||
|
||||
func TestIssue52937(t *testing.T) {
|
||||
goCmd(t, "build", "-buildmode=plugin", "-o", "issue52937.so", "./issue52937/main.go")
|
||||
}
|
||||
|
||||
func TestForkExec(t *testing.T) {
|
||||
// Issue 38824: importing the plugin package causes it hang in forkExec on darwin.
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// Copyright 2022 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
|
||||
|
||||
func main() {}
|
||||
func F[T any]() {}
|
||||
func G[T any](T) {}
|
||||
@@ -22,14 +22,6 @@ func TestASAN(t *testing.T) {
|
||||
if !aSanSupported(goos, goarch) {
|
||||
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
|
||||
}
|
||||
// The current implementation is only compatible with the ASan library from version
|
||||
// v7 to v9 (See the description in src/runtime/asan/asan.go). Therefore, using the
|
||||
// -asan option must use a compatible version of ASan library, which requires that
|
||||
// the gcc version is not less than 7 and the clang version is not less than 9,
|
||||
// otherwise a segmentation fault will occur.
|
||||
if !compilerRequiredAsanVersion() {
|
||||
t.Skipf("skipping: too old version of compiler")
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
requireOvercommit(t)
|
||||
@@ -52,11 +44,6 @@ func TestASAN(t *testing.T) {
|
||||
{src: "asan_unsafe_fail1.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail1.go:25"},
|
||||
{src: "asan_unsafe_fail2.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail2.go:25"},
|
||||
{src: "asan_unsafe_fail3.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail3.go:18"},
|
||||
{src: "asan_global1_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global1_fail.go:12"},
|
||||
{src: "asan_global2_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global2_fail.go:19"},
|
||||
{src: "asan_global3_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global3_fail.go:13"},
|
||||
{src: "asan_global4_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global4_fail.go:21"},
|
||||
{src: "asan_global5.go"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
@@ -91,26 +90,9 @@ func replaceEnv(cmd *exec.Cmd, key, value string) {
|
||||
// mustRun executes t and fails cmd with a well-formatted message if it fails.
|
||||
func mustRun(t *testing.T, cmd *exec.Cmd) {
|
||||
t.Helper()
|
||||
out := new(strings.Builder)
|
||||
cmd.Stdout = out
|
||||
cmd.Stderr = out
|
||||
|
||||
err := cmd.Start()
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("%v: %v", cmd, err)
|
||||
}
|
||||
|
||||
if deadline, ok := t.Deadline(); ok {
|
||||
timeout := time.Until(deadline)
|
||||
timeout -= timeout / 10 // Leave 10% headroom for logging and cleanup.
|
||||
timer := time.AfterFunc(timeout, func() {
|
||||
cmd.Process.Signal(syscall.SIGQUIT)
|
||||
})
|
||||
defer timer.Stop()
|
||||
}
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
t.Fatalf("%v exited with %v\n%s", cmd, err, out)
|
||||
t.Fatalf("%#q exited with %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,16 +184,17 @@ func compilerVersion() (version, error) {
|
||||
var match [][]byte
|
||||
if bytes.HasPrefix(out, []byte("gcc")) {
|
||||
compiler.name = "gcc"
|
||||
cmd, err := cc("-v")
|
||||
|
||||
cmd, err := cc("-dumpversion")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out, err := cmd.CombinedOutput()
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
// gcc, but does not support gcc's "-v" flag?!
|
||||
// gcc, but does not support gcc's "-dumpversion" flag?!
|
||||
return err
|
||||
}
|
||||
gccRE := regexp.MustCompile(`gcc version (\d+)\.(\d+)`)
|
||||
gccRE := regexp.MustCompile(`(\d+)\.(\d+)`)
|
||||
match = gccRE.FindSubmatch(out)
|
||||
} else {
|
||||
clangRE := regexp.MustCompile(`clang version (\d+)\.(\d+)`)
|
||||
@@ -252,22 +235,6 @@ func compilerSupportsLocation() bool {
|
||||
}
|
||||
}
|
||||
|
||||
// compilerRequiredAsanVersion reports whether the compiler is the version required by Asan.
|
||||
func compilerRequiredAsanVersion() bool {
|
||||
compiler, err := compilerVersion()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
switch compiler.name {
|
||||
case "gcc":
|
||||
return compiler.major >= 7
|
||||
case "clang":
|
||||
return compiler.major >= 9
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type compilerCheck struct {
|
||||
once sync.Once
|
||||
err error
|
||||
@@ -511,7 +478,7 @@ func mSanSupported(goos, goarch string) bool {
|
||||
func aSanSupported(goos, goarch string) bool {
|
||||
switch goos {
|
||||
case "linux":
|
||||
return goarch == "amd64" || goarch == "arm64" || goarch == "riscv64"
|
||||
return goarch == "amd64" || goarch == "arm64"
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright 2022 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int test(int *a) {
|
||||
a[2] = 300; // BOOM
|
||||
return a[2];
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "fmt"
|
||||
|
||||
var cIntArray [2]C.int
|
||||
|
||||
func main() {
|
||||
r := C.test(&cIntArray[0])
|
||||
fmt.Println("r value = ", r)
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright 2022 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct ss {
|
||||
int *p;
|
||||
int len;
|
||||
int cap;
|
||||
};
|
||||
|
||||
int test(struct ss *a) {
|
||||
struct ss *t = a + 1;
|
||||
t->len = 100; // BOOM
|
||||
return t->len;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import "fmt"
|
||||
|
||||
var tt C.struct_ss
|
||||
|
||||
func main() {
|
||||
r := C.test(&tt)
|
||||
fmt.Println("r value = ", r)
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright 2022 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int test(int *a) {
|
||||
int* p = a+1;
|
||||
*p = 10; // BOOM
|
||||
return *p;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var cIntV C.int
|
||||
|
||||
func main() {
|
||||
r := C.test((*C.int)(unsafe.Pointer(&cIntV)))
|
||||
fmt.Printf("r value is %d", r)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright 2022 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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var intGlo int
|
||||
|
||||
func main() {
|
||||
r := bar(&intGlo)
|
||||
fmt.Printf("r value is %d", r)
|
||||
}
|
||||
|
||||
func bar(a *int) int {
|
||||
p := (*int)(unsafe.Add(unsafe.Pointer(a), 1*unsafe.Sizeof(int(1))))
|
||||
if *p == 10 { // BOOM
|
||||
fmt.Println("its value is 10")
|
||||
}
|
||||
return *p
|
||||
}
|
||||
22
misc/cgo/testsanitizers/testdata/asan_global5.go
vendored
22
misc/cgo/testsanitizers/testdata/asan_global5.go
vendored
@@ -1,22 +0,0 @@
|
||||
// Copyright 2022 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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Any struct {
|
||||
s string
|
||||
b int64
|
||||
}
|
||||
|
||||
var Sg = []interface{}{
|
||||
Any{"a", 10},
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(Sg[0])
|
||||
}
|
||||
2
misc/cgo/testsanitizers/testdata/tsan11.go
vendored
2
misc/cgo/testsanitizers/testdata/tsan11.go
vendored
@@ -45,7 +45,7 @@ static void register_handler(int signo) {
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
ch := make(chan os.Signal, 1)
|
||||
ch := make(chan os.Signal)
|
||||
signal.Notify(ch, syscall.SIGUSR2)
|
||||
|
||||
C.register_handler(C.int(syscall.SIGUSR1))
|
||||
|
||||
2
misc/cgo/testsanitizers/testdata/tsan12.go
vendored
2
misc/cgo/testsanitizers/testdata/tsan12.go
vendored
@@ -22,7 +22,7 @@ import (
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
ch := make(chan os.Signal, 1)
|
||||
ch := make(chan os.Signal)
|
||||
signal.Notify(ch, syscall.SIGUSR1)
|
||||
|
||||
if err := exec.Command("true").Run(); err != nil {
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
)
|
||||
|
||||
var gopathInstallDir, gorootInstallDir string
|
||||
var oldGOROOT string
|
||||
|
||||
// This is the smallest set of packages we can link into a shared
|
||||
// library (runtime/cgo is built implicitly).
|
||||
@@ -61,7 +60,7 @@ func goCmd(t *testing.T, args ...string) string {
|
||||
newargs = append(newargs, "-x", "-ldflags=-v")
|
||||
}
|
||||
newargs = append(newargs, args[1:]...)
|
||||
c := exec.Command(filepath.Join(oldGOROOT, "bin", "go"), newargs...)
|
||||
c := exec.Command("go", newargs...)
|
||||
stderr := new(strings.Builder)
|
||||
c.Stderr = stderr
|
||||
|
||||
@@ -91,12 +90,6 @@ func goCmd(t *testing.T, args ...string) string {
|
||||
|
||||
// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
|
||||
func testMain(m *testing.M) (int, error) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
oldGOROOT = filepath.Join(cwd, "../../..")
|
||||
|
||||
workDir, err := os.MkdirTemp("", "shared_test")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -194,6 +187,11 @@ func cloneTestdataModule(gopath string) (string, error) {
|
||||
// GOROOT/pkg relevant to this test into the given directory.
|
||||
// It must be run from within the testdata module.
|
||||
func cloneGOROOTDeps(goroot string) error {
|
||||
oldGOROOT := strings.TrimSpace(goCmd(nil, "env", "GOROOT"))
|
||||
if oldGOROOT == "" {
|
||||
return fmt.Errorf("go env GOROOT returned an empty string")
|
||||
}
|
||||
|
||||
// Before we clone GOROOT, figure out which packages we need to copy over.
|
||||
listArgs := []string{
|
||||
"list",
|
||||
|
||||
@@ -13,9 +13,9 @@ goto end
|
||||
:ok
|
||||
|
||||
set OLDPATH=%PATH%
|
||||
call .\make.bat --no-banner --no-local
|
||||
call make.bat --no-banner --no-local
|
||||
if %GOBUILDFAIL%==1 goto end
|
||||
call .\run.bat --no-rebuild --no-local
|
||||
call run.bat --no-rebuild --no-local
|
||||
if %GOBUILDFAIL%==1 goto end
|
||||
:: we must restore %PATH% before running "dist banner" so that the latter
|
||||
:: can get the original %PATH% and give suggestion to add %GOROOT%/bin
|
||||
|
||||
@@ -33,10 +33,6 @@ type Reader struct {
|
||||
Comment string
|
||||
decompressors map[uint16]Decompressor
|
||||
|
||||
// Some JAR files are zip files with a prefix that is a bash script.
|
||||
// The baseOffset field is the start of the zip file proper.
|
||||
baseOffset int64
|
||||
|
||||
// fileList is a list of files sorted by ename,
|
||||
// for use by the Open method.
|
||||
fileListOnce sync.Once
|
||||
@@ -56,8 +52,9 @@ type File struct {
|
||||
FileHeader
|
||||
zip *Reader
|
||||
zipr io.ReaderAt
|
||||
headerOffset int64 // includes overall ZIP archive baseOffset
|
||||
headerOffset int64
|
||||
zip64 bool // zip64 extended information extra field presence
|
||||
descErr error // error reading the data descriptor during init
|
||||
}
|
||||
|
||||
// OpenReader will open the Zip file specified by name and return a ReadCloser.
|
||||
@@ -94,12 +91,11 @@ func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
|
||||
}
|
||||
|
||||
func (z *Reader) init(r io.ReaderAt, size int64) error {
|
||||
end, baseOffset, err := readDirectoryEnd(r, size)
|
||||
end, err := readDirectoryEnd(r, size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
z.r = r
|
||||
z.baseOffset = baseOffset
|
||||
// Since the number of directory records is not validated, it is not
|
||||
// safe to preallocate z.File without first checking that the specified
|
||||
// number of files is reasonable, since a malformed archive may
|
||||
@@ -111,7 +107,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
|
||||
}
|
||||
z.Comment = end.comment
|
||||
rs := io.NewSectionReader(r, 0, size)
|
||||
if _, err = rs.Seek(z.baseOffset+int64(end.directoryOffset), io.SeekStart); err != nil {
|
||||
if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
buf := bufio.NewReader(rs)
|
||||
@@ -123,27 +119,12 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
|
||||
for {
|
||||
f := &File{zip: z, zipr: r}
|
||||
err = readDirectoryHeader(f, buf)
|
||||
|
||||
// For compatibility with other zip programs,
|
||||
// if we have a non-zero base offset and can't read
|
||||
// the first directory header, try again with a zero
|
||||
// base offset.
|
||||
if err == ErrFormat && z.baseOffset != 0 && len(z.File) == 0 {
|
||||
z.baseOffset = 0
|
||||
if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
buf.Reset(rs)
|
||||
continue
|
||||
}
|
||||
|
||||
if err == ErrFormat || err == io.ErrUnexpectedEOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.headerOffset += z.baseOffset
|
||||
z.File = append(z.File, f)
|
||||
}
|
||||
if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here
|
||||
@@ -514,7 +495,7 @@ func readDataDescriptor(r io.Reader, f *File) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, baseOffset int64, err error) {
|
||||
func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
|
||||
// look for directoryEndSignature in the last 1k, then in the last 65k
|
||||
var buf []byte
|
||||
var directoryEndOffset int64
|
||||
@@ -524,7 +505,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, baseOffset
|
||||
}
|
||||
buf = make([]byte, int(bLen))
|
||||
if _, err := r.ReadAt(buf, size-bLen); err != nil && err != io.EOF {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
if p := findSignatureInBlock(buf); p >= 0 {
|
||||
buf = buf[p:]
|
||||
@@ -532,7 +513,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, baseOffset
|
||||
break
|
||||
}
|
||||
if i == 1 || bLen == size {
|
||||
return nil, 0, ErrFormat
|
||||
return nil, ErrFormat
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,7 +530,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, baseOffset
|
||||
}
|
||||
l := int(d.commentLen)
|
||||
if l > len(b) {
|
||||
return nil, 0, errors.New("zip: invalid comment length")
|
||||
return nil, errors.New("zip: invalid comment length")
|
||||
}
|
||||
d.comment = string(b[:l])
|
||||
|
||||
@@ -557,21 +538,17 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, baseOffset
|
||||
if d.directoryRecords == 0xffff || d.directorySize == 0xffff || d.directoryOffset == 0xffffffff {
|
||||
p, err := findDirectory64End(r, directoryEndOffset)
|
||||
if err == nil && p >= 0 {
|
||||
directoryEndOffset = p
|
||||
err = readDirectory64End(r, p, d)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
baseOffset = directoryEndOffset - int64(d.directorySize) - int64(d.directoryOffset)
|
||||
|
||||
// Make sure directoryOffset points to somewhere in our file.
|
||||
if o := baseOffset + int64(d.directoryOffset); o < 0 || o >= size {
|
||||
return nil, 0, ErrFormat
|
||||
if o := int64(d.directoryOffset); o < 0 || o >= size {
|
||||
return nil, ErrFormat
|
||||
}
|
||||
return d, baseOffset, nil
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// findDirectory64End tries to read the zip64 locator just before the
|
||||
@@ -676,7 +653,6 @@ type fileListEntry struct {
|
||||
name string
|
||||
file *File
|
||||
isDir bool
|
||||
isDup bool
|
||||
}
|
||||
|
||||
type fileInfoDirEntry interface {
|
||||
@@ -684,14 +660,11 @@ type fileInfoDirEntry interface {
|
||||
fs.DirEntry
|
||||
}
|
||||
|
||||
func (e *fileListEntry) stat() (fileInfoDirEntry, error) {
|
||||
if e.isDup {
|
||||
return nil, errors.New(e.name + ": duplicate entries in zip file")
|
||||
}
|
||||
func (e *fileListEntry) stat() fileInfoDirEntry {
|
||||
if !e.isDir {
|
||||
return headerFileInfo{&e.file.FileHeader}, nil
|
||||
return headerFileInfo{&e.file.FileHeader}
|
||||
}
|
||||
return e, nil
|
||||
return e
|
||||
}
|
||||
|
||||
// Only used for directories.
|
||||
@@ -726,37 +699,17 @@ func toValidName(name string) string {
|
||||
|
||||
func (r *Reader) initFileList() {
|
||||
r.fileListOnce.Do(func() {
|
||||
// files and knownDirs map from a file/directory name
|
||||
// to an index into the r.fileList entry that we are
|
||||
// building. They are used to mark duplicate entries.
|
||||
files := make(map[string]int)
|
||||
knownDirs := make(map[string]int)
|
||||
|
||||
// dirs[name] is true if name is known to be a directory,
|
||||
// because it appears as a prefix in a path.
|
||||
dirs := make(map[string]bool)
|
||||
|
||||
knownDirs := make(map[string]bool)
|
||||
for _, file := range r.File {
|
||||
isDir := len(file.Name) > 0 && file.Name[len(file.Name)-1] == '/'
|
||||
name := toValidName(file.Name)
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if idx, ok := files[name]; ok {
|
||||
r.fileList[idx].isDup = true
|
||||
continue
|
||||
}
|
||||
if idx, ok := knownDirs[name]; ok {
|
||||
r.fileList[idx].isDup = true
|
||||
continue
|
||||
}
|
||||
|
||||
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
|
||||
dirs[dir] = true
|
||||
}
|
||||
|
||||
idx := len(r.fileList)
|
||||
entry := fileListEntry{
|
||||
name: name,
|
||||
file: file,
|
||||
@@ -764,23 +717,17 @@ func (r *Reader) initFileList() {
|
||||
}
|
||||
r.fileList = append(r.fileList, entry)
|
||||
if isDir {
|
||||
knownDirs[name] = idx
|
||||
} else {
|
||||
files[name] = idx
|
||||
knownDirs[name] = true
|
||||
}
|
||||
}
|
||||
for dir := range dirs {
|
||||
if _, ok := knownDirs[dir]; !ok {
|
||||
if idx, ok := files[dir]; ok {
|
||||
r.fileList[idx].isDup = true
|
||||
} else {
|
||||
entry := fileListEntry{
|
||||
name: dir,
|
||||
file: nil,
|
||||
isDir: true,
|
||||
}
|
||||
r.fileList = append(r.fileList, entry)
|
||||
if !knownDirs[dir] {
|
||||
entry := fileListEntry{
|
||||
name: dir,
|
||||
file: nil,
|
||||
isDir: true,
|
||||
}
|
||||
r.fileList = append(r.fileList, entry)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -875,7 +822,7 @@ type openDir struct {
|
||||
}
|
||||
|
||||
func (d *openDir) Close() error { return nil }
|
||||
func (d *openDir) Stat() (fs.FileInfo, error) { return d.e.stat() }
|
||||
func (d *openDir) Stat() (fs.FileInfo, error) { return d.e.stat(), nil }
|
||||
|
||||
func (d *openDir) Read([]byte) (int, error) {
|
||||
return 0, &fs.PathError{Op: "read", Path: d.e.name, Err: errors.New("is a directory")}
|
||||
@@ -894,11 +841,7 @@ func (d *openDir) ReadDir(count int) ([]fs.DirEntry, error) {
|
||||
}
|
||||
list := make([]fs.DirEntry, n)
|
||||
for i := range list {
|
||||
s, err := d.files[d.offset+i].stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list[i] = s
|
||||
list[i] = d.files[d.offset+i].stat()
|
||||
}
|
||||
d.offset += n
|
||||
return list, nil
|
||||
|
||||
@@ -90,42 +90,6 @@ var tests = []ZipTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "test-prefix.zip",
|
||||
Comment: "This is a zipfile comment.",
|
||||
File: []ZipTestFile{
|
||||
{
|
||||
Name: "test.txt",
|
||||
Content: []byte("This is a test text file.\n"),
|
||||
Modified: time.Date(2010, 9, 5, 12, 12, 1, 0, timeZone(+10*time.Hour)),
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "gophercolor16x16.png",
|
||||
File: "gophercolor16x16.png",
|
||||
Modified: time.Date(2010, 9, 5, 15, 52, 58, 0, timeZone(+10*time.Hour)),
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "test-baddirsz.zip",
|
||||
Comment: "This is a zipfile comment.",
|
||||
File: []ZipTestFile{
|
||||
{
|
||||
Name: "test.txt",
|
||||
Content: []byte("This is a test text file.\n"),
|
||||
Modified: time.Date(2010, 9, 5, 12, 12, 1, 0, timeZone(+10*time.Hour)),
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "gophercolor16x16.png",
|
||||
File: "gophercolor16x16.png",
|
||||
Modified: time.Date(2010, 9, 5, 15, 52, 58, 0, timeZone(+10*time.Hour)),
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "r.zip",
|
||||
Source: returnRecursiveZip,
|
||||
@@ -523,35 +487,6 @@ var tests = []ZipTest{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dupdir.zip",
|
||||
File: []ZipTestFile{
|
||||
{
|
||||
Name: "a/",
|
||||
Content: []byte{},
|
||||
Mode: fs.ModeDir | 0666,
|
||||
Modified: time.Date(2021, 12, 29, 0, 0, 0, 0, timeZone(0)),
|
||||
},
|
||||
{
|
||||
Name: "a/b",
|
||||
Content: []byte{},
|
||||
Mode: 0666,
|
||||
Modified: time.Date(2021, 12, 29, 0, 0, 0, 0, timeZone(0)),
|
||||
},
|
||||
{
|
||||
Name: "a/b/",
|
||||
Content: []byte{},
|
||||
Mode: fs.ModeDir | 0666,
|
||||
Modified: time.Date(2021, 12, 29, 0, 0, 0, 0, timeZone(0)),
|
||||
},
|
||||
{
|
||||
Name: "a/b/c",
|
||||
Content: []byte{},
|
||||
Mode: 0666,
|
||||
Modified: time.Date(2021, 12, 29, 0, 0, 0, 0, timeZone(0)),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
@@ -1076,7 +1011,7 @@ func TestIssue10957(t *testing.T) {
|
||||
"\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" +
|
||||
"00000000PK\x01\x0200000000" +
|
||||
"0000000000000000\v\x00\x00\x00" +
|
||||
"\x00\x0000PK\x05\x06000000\x05\x00\xfd\x00\x00\x00" +
|
||||
"\x00\x0000PK\x05\x06000000\x05\x000000" +
|
||||
"\v\x00\x00\x00\x00\x00")
|
||||
z, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
if err != nil {
|
||||
@@ -1121,7 +1056,7 @@ func TestIssue11146(t *testing.T) {
|
||||
"0000000000000000PK\x01\x02" +
|
||||
"0000\b0\b\x00000000000000" +
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000000PK\x05\x06\x00\x00" +
|
||||
"\x00\x0000\x01\x00\x26\x00\x00\x008\x00\x00\x00\x00\x00")
|
||||
"\x00\x0000\x01\x0000008\x00\x00\x00\x00\x00")
|
||||
z, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -1188,7 +1123,6 @@ func TestFS(t *testing.T) {
|
||||
[]string{"a/b/c"},
|
||||
},
|
||||
} {
|
||||
test := test
|
||||
t.Run(test.file, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
z, err := OpenReader(test.file)
|
||||
@@ -1203,60 +1137,6 @@ func TestFS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFSWalk(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
file string
|
||||
want []string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
file: "testdata/unix.zip",
|
||||
want: []string{".", "dir", "dir/bar", "dir/empty", "hello", "readonly"},
|
||||
},
|
||||
{
|
||||
file: "testdata/subdir.zip",
|
||||
want: []string{".", "a", "a/b", "a/b/c"},
|
||||
},
|
||||
{
|
||||
file: "testdata/dupdir.zip",
|
||||
wantErr: true,
|
||||
},
|
||||
} {
|
||||
test := test
|
||||
t.Run(test.file, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
z, err := OpenReader(test.file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var files []string
|
||||
sawErr := false
|
||||
err = fs.WalkDir(z, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
if !test.wantErr {
|
||||
t.Errorf("%s: %v", path, err)
|
||||
}
|
||||
sawErr = true
|
||||
return nil
|
||||
}
|
||||
files = append(files, path)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("fs.WalkDir error: %v", err)
|
||||
}
|
||||
if test.wantErr && !sawErr {
|
||||
t.Error("succeeded but want error")
|
||||
} else if !test.wantErr && sawErr {
|
||||
t.Error("unexpected error")
|
||||
}
|
||||
if test.want != nil && !reflect.DeepEqual(files, test.want) {
|
||||
t.Errorf("got %v want %v", files, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFSModTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
z, err := OpenReader("testdata/subdir.zip")
|
||||
|
||||
BIN
src/archive/zip/testdata/dupdir.zip
vendored
BIN
src/archive/zip/testdata/dupdir.zip
vendored
Binary file not shown.
BIN
src/archive/zip/testdata/readme.notzip
vendored
BIN
src/archive/zip/testdata/readme.notzip
vendored
Binary file not shown.
BIN
src/archive/zip/testdata/test-baddirsz.zip
vendored
BIN
src/archive/zip/testdata/test-baddirsz.zip
vendored
Binary file not shown.
BIN
src/archive/zip/testdata/test-prefix.zip
vendored
BIN
src/archive/zip/testdata/test-prefix.zip
vendored
Binary file not shown.
@@ -203,8 +203,7 @@ func (b *Reader) Discard(n int) (discarded int, err error) {
|
||||
// The bytes are taken from at most one Read on the underlying Reader,
|
||||
// hence n may be less than len(p).
|
||||
// To read exactly len(p) bytes, use io.ReadFull(b, p).
|
||||
// If the underlying Reader can return a non-zero count with io.EOF,
|
||||
// then this Read method can do so as well; see the [io.Reader] docs.
|
||||
// At EOF, the count will be zero and err will be io.EOF.
|
||||
func (b *Reader) Read(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
if n == 0 {
|
||||
|
||||
@@ -236,7 +236,7 @@ func imag(c ComplexType) FloatType
|
||||
//
|
||||
// x, ok := <-c
|
||||
//
|
||||
// will also set ok to false for a closed and empty channel.
|
||||
// will also set ok to false for a closed channel.
|
||||
func close(c chan<- Type)
|
||||
|
||||
// The panic built-in function stops normal execution of the current
|
||||
|
||||
@@ -140,36 +140,6 @@ var indexTests = []BinOpTest{
|
||||
{"abc", "c", 2},
|
||||
{"abc", "x", -1},
|
||||
{"barfoobarfooyyyzzzyyyzzzyyyzzzyyyxxxzzzyyy", "x", 33},
|
||||
{"fofofofooofoboo", "oo", 7},
|
||||
{"fofofofofofoboo", "ob", 11},
|
||||
{"fofofofofofoboo", "boo", 12},
|
||||
{"fofofofofofoboo", "oboo", 11},
|
||||
{"fofofofofoooboo", "fooo", 8},
|
||||
{"fofofofofofoboo", "foboo", 10},
|
||||
{"fofofofofofoboo", "fofob", 8},
|
||||
{"fofofofofofofoffofoobarfoo", "foffof", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffof", 13},
|
||||
{"fofofofofofofoffofoobarfoo", "foffofo", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffofo", 13},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffofoo", 13},
|
||||
{"fofofofofofofoffofoobarfoo", "foffofoo", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffofoob", 13},
|
||||
{"fofofofofofofoffofoobarfoo", "foffofoob", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffofooba", 13},
|
||||
{"fofofofofofofoffofoobarfoo", "foffofooba", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffofoobar", 13},
|
||||
{"fofofofofofofoffofoobarfoo", "foffofoobar", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffofoobarf", 13},
|
||||
{"fofofofofofofoffofoobarfoo", "foffofoobarf", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffofoobarfo", 13},
|
||||
{"fofofofofofofoffofoobarfoo", "foffofoobarfo", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "foffofoobarfoo", 13},
|
||||
{"fofofofofofofoffofoobarfoo", "foffofoobarfoo", 12},
|
||||
{"fofofofofoofofoffofoobarfoo", "ofoffofoobarfoo", 12},
|
||||
{"fofofofofofofoffofoobarfoo", "ofoffofoobarfoo", 11},
|
||||
{"fofofofofoofofoffofoobarfoo", "fofoffofoobarfoo", 11},
|
||||
{"fofofofofofofoffofoobarfoo", "fofoffofoobarfoo", 10},
|
||||
{"fofofofofoofofoffofoobarfoo", "foobars", -1},
|
||||
{"foofyfoobarfoobar", "y", 4},
|
||||
{"oooooooooooooooooooooo", "r", -1},
|
||||
{"oxoxoxoxoxoxoxoxoxoxoxoy", "oy", 22},
|
||||
|
||||
@@ -10,7 +10,7 @@ set GOBUILDFAIL=0
|
||||
|
||||
go tool dist env -w -p >env.bat
|
||||
if errorlevel 1 goto fail
|
||||
call .\env.bat
|
||||
call env.bat
|
||||
del env.bat
|
||||
echo.
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ import (
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
exec "internal/execabs"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
||||
@@ -11,11 +11,11 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
exec "internal/execabs"
|
||||
"internal/goversion"
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/arm"
|
||||
"cmd/internal/obj/arm64"
|
||||
"cmd/internal/obj/loong64"
|
||||
"cmd/internal/obj/mips"
|
||||
"cmd/internal/obj/ppc64"
|
||||
"cmd/internal/obj/riscv"
|
||||
@@ -61,8 +60,6 @@ func Set(GOARCH string, shared bool) *Arch {
|
||||
return archArm()
|
||||
case "arm64":
|
||||
return archArm64()
|
||||
case "loong64":
|
||||
return archLoong64(&loong64.Linkloong64)
|
||||
case "mips":
|
||||
return archMips(&mips.Linkmips)
|
||||
case "mipsle":
|
||||
@@ -505,59 +502,6 @@ func archMips64(linkArch *obj.LinkArch) *Arch {
|
||||
}
|
||||
}
|
||||
|
||||
func archLoong64(linkArch *obj.LinkArch) *Arch {
|
||||
register := make(map[string]int16)
|
||||
// Create maps for easy lookup of instruction names etc.
|
||||
// Note that there is no list of names as there is for x86.
|
||||
for i := loong64.REG_R0; i <= loong64.REG_R31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
for i := loong64.REG_F0; i <= loong64.REG_F31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
for i := loong64.REG_FCSR0; i <= loong64.REG_FCSR31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
for i := loong64.REG_FCC0; i <= loong64.REG_FCC31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
// Pseudo-registers.
|
||||
register["SB"] = RSB
|
||||
register["FP"] = RFP
|
||||
register["PC"] = RPC
|
||||
// Avoid unintentionally clobbering g using R22.
|
||||
delete(register, "R22")
|
||||
register["g"] = loong64.REG_R22
|
||||
register["RSB"] = loong64.REG_R31
|
||||
registerPrefix := map[string]bool{
|
||||
"F": true,
|
||||
"FCSR": true,
|
||||
"FCC": true,
|
||||
"R": true,
|
||||
}
|
||||
|
||||
instructions := make(map[string]obj.As)
|
||||
for i, s := range obj.Anames {
|
||||
instructions[s] = obj.As(i)
|
||||
}
|
||||
for i, s := range loong64.Anames {
|
||||
if obj.As(i) >= obj.A_ARCHSPECIFIC {
|
||||
instructions[s] = obj.As(i) + obj.ABaseLoong64
|
||||
}
|
||||
}
|
||||
// Annoying alias.
|
||||
instructions["JAL"] = loong64.AJAL
|
||||
|
||||
return &Arch{
|
||||
LinkArch: linkArch,
|
||||
Instructions: instructions,
|
||||
Register: register,
|
||||
RegisterPrefix: registerPrefix,
|
||||
RegisterNumber: loong64RegisterNumber,
|
||||
IsJump: jumpLoong64,
|
||||
}
|
||||
}
|
||||
|
||||
func archRISCV64(shared bool) *Arch {
|
||||
register := make(map[string]int16)
|
||||
|
||||
|
||||
@@ -47,11 +47,6 @@ var arm64Jump = map[string]bool{
|
||||
"JMP": true,
|
||||
"TBNZ": true,
|
||||
"TBZ": true,
|
||||
|
||||
// ADR isn't really a jump, but it takes a PC or label reference,
|
||||
// which needs to patched like a jump.
|
||||
"ADR": true,
|
||||
"ADRP": true,
|
||||
}
|
||||
|
||||
func jumpArm64(word string) bool {
|
||||
@@ -86,16 +81,6 @@ func GetARM64SpecialOperand(name string) arm64.SpecialOperand {
|
||||
return arm64.SPOP_END
|
||||
}
|
||||
|
||||
// IsARM64ADR reports whether the op (as defined by an arm64.A* constant) is
|
||||
// one of the comparison instructions that require special handling.
|
||||
func IsARM64ADR(op obj.As) bool {
|
||||
switch op {
|
||||
case arm64.AADR, arm64.AADRP:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsARM64CMP reports whether the op (as defined by an arm64.A* constant) is
|
||||
// one of the comparison instructions that require special handling.
|
||||
func IsARM64CMP(op obj.As) bool {
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
// This file encapsulates some of the odd characteristics of the
|
||||
// Loong64 (LoongArch64) instruction set, to minimize its interaction
|
||||
// with the core of the assembler.
|
||||
|
||||
package arch
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/loong64"
|
||||
)
|
||||
|
||||
func jumpLoong64(word string) bool {
|
||||
switch word {
|
||||
case "BEQ", "BFPF", "BFPT", "BLTZ", "BGEZ", "BLEZ", "BGTZ", "BLT", "BLTU", "JIRL", "BNE", "BGE", "BGEU", "JMP", "JAL", "CALL":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsLoong64CMP reports whether the op (as defined by an loong64.A* constant) is
|
||||
// one of the CMP instructions that require special handling.
|
||||
func IsLoong64CMP(op obj.As) bool {
|
||||
switch op {
|
||||
case loong64.ACMPEQF, loong64.ACMPEQD, loong64.ACMPGEF, loong64.ACMPGED,
|
||||
loong64.ACMPGTF, loong64.ACMPGTD:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsLoong64MUL reports whether the op (as defined by an loong64.A* constant) is
|
||||
// one of the MUL/DIV/REM instructions that require special handling.
|
||||
func IsLoong64MUL(op obj.As) bool {
|
||||
switch op {
|
||||
case loong64.AMUL, loong64.AMULU, loong64.AMULV, loong64.AMULVU,
|
||||
loong64.ADIV, loong64.ADIVU, loong64.ADIVV, loong64.ADIVVU,
|
||||
loong64.AREM, loong64.AREMU, loong64.AREMV, loong64.AREMVU:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func loong64RegisterNumber(name string, n int16) (int16, bool) {
|
||||
switch name {
|
||||
case "F":
|
||||
if 0 <= n && n <= 31 {
|
||||
return loong64.REG_F0 + n, true
|
||||
}
|
||||
case "FCSR":
|
||||
if 0 <= n && n <= 31 {
|
||||
return loong64.REG_FCSR0 + n, true
|
||||
}
|
||||
case "FCC":
|
||||
if 0 <= n && n <= 31 {
|
||||
return loong64.REG_FCC0 + n, true
|
||||
}
|
||||
case "R":
|
||||
if 0 <= n && n <= 31 {
|
||||
return loong64.REG_R0 + n, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"cmd/asm/internal/flags"
|
||||
"cmd/asm/internal/lex"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/ppc64"
|
||||
"cmd/internal/obj/x86"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/sys"
|
||||
@@ -394,7 +393,6 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
|
||||
Pos: p.pos(),
|
||||
As: op,
|
||||
}
|
||||
targetAddr := &prog.To
|
||||
switch len(a) {
|
||||
case 0:
|
||||
if p.arch.Family == sys.Wasm {
|
||||
@@ -407,57 +405,24 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
|
||||
target = &a[0]
|
||||
case 2:
|
||||
// Special 2-operand jumps.
|
||||
if p.arch.Family == sys.ARM64 && arch.IsARM64ADR(op) {
|
||||
// ADR label, R. Label is in From.
|
||||
target = &a[0]
|
||||
prog.To = a[1]
|
||||
targetAddr = &prog.From
|
||||
} else {
|
||||
target = &a[1]
|
||||
prog.From = a[0]
|
||||
}
|
||||
target = &a[1]
|
||||
prog.From = a[0]
|
||||
case 3:
|
||||
if p.arch.Family == sys.PPC64 {
|
||||
// Special 3-operand jumps.
|
||||
// a[1] is a register number expressed as a constant or register value
|
||||
// First two must be constants; a[1] is a register number.
|
||||
target = &a[2]
|
||||
prog.From = a[0]
|
||||
if a[0].Type != obj.TYPE_CONST {
|
||||
// Legacy code may use a plain constant, accept it, and coerce
|
||||
// into a constant. E.g:
|
||||
// BC 4,...
|
||||
// into
|
||||
// BC $4,...
|
||||
prog.From = obj.Addr{
|
||||
Type: obj.TYPE_CONST,
|
||||
Offset: p.getConstant(prog, op, &a[0]),
|
||||
}
|
||||
|
||||
prog.From = obj.Addr{
|
||||
Type: obj.TYPE_CONST,
|
||||
Offset: p.getConstant(prog, op, &a[0]),
|
||||
}
|
||||
|
||||
// Likewise, fixup usage like:
|
||||
// BC x,LT,...
|
||||
// BC x,foo+2,...
|
||||
// BC x,4
|
||||
// BC x,$5
|
||||
// into
|
||||
// BC x,CR0LT,...
|
||||
// BC x,CR0EQ,...
|
||||
// BC x,CR1LT,...
|
||||
// BC x,CR1GT,...
|
||||
// The first and second case demonstrate a symbol name which is
|
||||
// effectively discarded. In these cases, the offset determines
|
||||
// the CR bit.
|
||||
prog.Reg = a[1].Reg
|
||||
if a[1].Type != obj.TYPE_REG {
|
||||
// The CR bit is represented as a constant 0-31. Convert it to a Reg.
|
||||
c := p.getConstant(prog, op, &a[1])
|
||||
reg, success := ppc64.ConstantToCRbit(c)
|
||||
if !success {
|
||||
p.errorf("invalid CR bit register number %d", c)
|
||||
}
|
||||
prog.Reg = reg
|
||||
reg := int16(p.getConstant(prog, op, &a[1]))
|
||||
reg, ok := p.arch.RegisterNumber("R", reg)
|
||||
if !ok {
|
||||
p.errorf("bad register number %d", reg)
|
||||
return
|
||||
}
|
||||
prog.Reg = reg
|
||||
break
|
||||
}
|
||||
if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 || p.arch.Family == sys.RISCV64 {
|
||||
@@ -468,14 +433,6 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
break
|
||||
}
|
||||
if p.arch.Family == sys.Loong64 {
|
||||
// 3-operand jumps.
|
||||
// First two must be registers
|
||||
target = &a[2]
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
break
|
||||
}
|
||||
if p.arch.Family == sys.S390X {
|
||||
// 3-operand jumps.
|
||||
target = &a[2]
|
||||
@@ -504,7 +461,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
|
||||
p.errorf("wrong number of arguments to %s instruction", op)
|
||||
return
|
||||
case 4:
|
||||
if p.arch.Family == sys.S390X || p.arch.Family == sys.PPC64 {
|
||||
if p.arch.Family == sys.S390X {
|
||||
// 4-operand compare-and-branch.
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
@@ -521,20 +478,20 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
|
||||
switch {
|
||||
case target.Type == obj.TYPE_BRANCH:
|
||||
// JMP 4(PC)
|
||||
*targetAddr = obj.Addr{
|
||||
prog.To = obj.Addr{
|
||||
Type: obj.TYPE_BRANCH,
|
||||
Offset: p.pc + 1 + target.Offset, // +1 because p.pc is incremented in append, below.
|
||||
}
|
||||
case target.Type == obj.TYPE_REG:
|
||||
// JMP R1
|
||||
*targetAddr = *target
|
||||
prog.To = *target
|
||||
case target.Type == obj.TYPE_MEM && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
|
||||
// JMP main·morestack(SB)
|
||||
*targetAddr = *target
|
||||
prog.To = *target
|
||||
case target.Type == obj.TYPE_INDIR && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
|
||||
// JMP *main·morestack(SB)
|
||||
*targetAddr = *target
|
||||
targetAddr.Type = obj.TYPE_INDIR
|
||||
prog.To = *target
|
||||
prog.To.Type = obj.TYPE_INDIR
|
||||
case target.Type == obj.TYPE_MEM && target.Reg == 0 && target.Offset == 0:
|
||||
// JMP exit
|
||||
if target.Sym == nil {
|
||||
@@ -543,20 +500,20 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
|
||||
}
|
||||
targetProg := p.labels[target.Sym.Name]
|
||||
if targetProg == nil {
|
||||
p.toPatch = append(p.toPatch, Patch{targetAddr, target.Sym.Name})
|
||||
p.toPatch = append(p.toPatch, Patch{prog, target.Sym.Name})
|
||||
} else {
|
||||
p.branch(targetAddr, targetProg)
|
||||
p.branch(prog, targetProg)
|
||||
}
|
||||
case target.Type == obj.TYPE_MEM && target.Name == obj.NAME_NONE:
|
||||
// JMP 4(R0)
|
||||
*targetAddr = *target
|
||||
prog.To = *target
|
||||
// On the ppc64, 9a encodes BR (CTR) as BR CTR. We do the same.
|
||||
if p.arch.Family == sys.PPC64 && target.Offset == 0 {
|
||||
targetAddr.Type = obj.TYPE_REG
|
||||
prog.To.Type = obj.TYPE_REG
|
||||
}
|
||||
case target.Type == obj.TYPE_CONST:
|
||||
// JMP $4
|
||||
*targetAddr = a[0]
|
||||
prog.To = a[0]
|
||||
case target.Type == obj.TYPE_NONE:
|
||||
// JMP
|
||||
default:
|
||||
@@ -574,17 +531,17 @@ func (p *Parser) patch() {
|
||||
p.errorf("undefined label %s", patch.label)
|
||||
return
|
||||
}
|
||||
p.branch(patch.addr, targetProg)
|
||||
p.branch(patch.prog, targetProg)
|
||||
}
|
||||
p.toPatch = p.toPatch[:0]
|
||||
}
|
||||
|
||||
func (p *Parser) branch(addr *obj.Addr, target *obj.Prog) {
|
||||
*addr = obj.Addr{
|
||||
func (p *Parser) branch(jmp, target *obj.Prog) {
|
||||
jmp.To = obj.Addr{
|
||||
Type: obj.TYPE_BRANCH,
|
||||
Index: 0,
|
||||
}
|
||||
addr.Val = target
|
||||
jmp.To.Val = target
|
||||
}
|
||||
|
||||
// asmInstruction assembles an instruction.
|
||||
@@ -636,12 +593,6 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
break
|
||||
}
|
||||
} else if p.arch.Family == sys.Loong64 {
|
||||
if arch.IsLoong64CMP(op) {
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
break
|
||||
}
|
||||
}
|
||||
prog.From = a[0]
|
||||
prog.To = a[1]
|
||||
@@ -651,10 +602,6 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.To = a[2]
|
||||
case sys.Loong64:
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.To = a[2]
|
||||
case sys.ARM:
|
||||
// Special cases.
|
||||
if arch.IsARMSTREX(op) {
|
||||
|
||||
@@ -447,13 +447,6 @@ func TestMIPSEndToEnd(t *testing.T) {
|
||||
testEndToEnd(t, "mips64", "mips64")
|
||||
}
|
||||
|
||||
func TestLOONG64Encoder(t *testing.T) {
|
||||
testEndToEnd(t, "loong64", "loong64enc1")
|
||||
testEndToEnd(t, "loong64", "loong64enc2")
|
||||
testEndToEnd(t, "loong64", "loong64enc3")
|
||||
testEndToEnd(t, "loong64", "loong64")
|
||||
}
|
||||
|
||||
func TestPPC64EndToEnd(t *testing.T) {
|
||||
testEndToEnd(t, "ppc64", "ppc64")
|
||||
}
|
||||
|
||||
@@ -125,11 +125,6 @@ func TestMIPS64OperandParser(t *testing.T) {
|
||||
testOperandParser(t, parser, mips64OperandTests)
|
||||
}
|
||||
|
||||
func TestLOONG64OperandParser(t *testing.T) {
|
||||
parser := newParser("loong64")
|
||||
testOperandParser(t, parser, loong64OperandTests)
|
||||
}
|
||||
|
||||
func TestS390XOperandParser(t *testing.T) {
|
||||
parser := newParser("s390x")
|
||||
testOperandParser(t, parser, s390xOperandTests)
|
||||
@@ -148,7 +143,6 @@ func TestFuncAddress(t *testing.T) {
|
||||
{"ppc64", ppc64OperandTests},
|
||||
{"mips", mipsOperandTests},
|
||||
{"mips64", mips64OperandTests},
|
||||
{"loong64", loong64OperandTests},
|
||||
{"s390x", s390xOperandTests},
|
||||
} {
|
||||
t.Run(sub.arch, func(t *testing.T) {
|
||||
@@ -851,88 +845,6 @@ var mipsOperandTests = []operandTest{
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
var loong64OperandTests = []operandTest{
|
||||
{"$((1<<63)-1)", "$9223372036854775807"},
|
||||
{"$(-64*1024)", "$-65536"},
|
||||
{"$(1024 * 8)", "$8192"},
|
||||
{"$-1", "$-1"},
|
||||
{"$-24(R4)", "$-24(R4)"},
|
||||
{"$0", "$0"},
|
||||
{"$0(R1)", "$(R1)"},
|
||||
{"$0.5", "$(0.5)"},
|
||||
{"$0x7000", "$28672"},
|
||||
{"$0x88888eef", "$2290650863"},
|
||||
{"$1", "$1"},
|
||||
{"$_main<>(SB)", "$_main<>(SB)"},
|
||||
{"$argframe(FP)", "$argframe(FP)"},
|
||||
{"$~3", "$-4"},
|
||||
{"(-288-3*8)(R1)", "-312(R1)"},
|
||||
{"(16)(R7)", "16(R7)"},
|
||||
{"(8)(g)", "8(g)"},
|
||||
{"(R0)", "(R0)"},
|
||||
{"(R3)", "(R3)"},
|
||||
{"(R4)", "(R4)"},
|
||||
{"(R5)", "(R5)"},
|
||||
{"-1(R4)", "-1(R4)"},
|
||||
{"-1(R5)", "-1(R5)"},
|
||||
{"6(PC)", "6(PC)"},
|
||||
{"F14", "F14"},
|
||||
{"F15", "F15"},
|
||||
{"F16", "F16"},
|
||||
{"F17", "F17"},
|
||||
{"F18", "F18"},
|
||||
{"F19", "F19"},
|
||||
{"F20", "F20"},
|
||||
{"F21", "F21"},
|
||||
{"F22", "F22"},
|
||||
{"F23", "F23"},
|
||||
{"F24", "F24"},
|
||||
{"F25", "F25"},
|
||||
{"F26", "F26"},
|
||||
{"F27", "F27"},
|
||||
{"F28", "F28"},
|
||||
{"F29", "F29"},
|
||||
{"F30", "F30"},
|
||||
{"F31", "F31"},
|
||||
{"R0", "R0"},
|
||||
{"R1", "R1"},
|
||||
{"R11", "R11"},
|
||||
{"R12", "R12"},
|
||||
{"R13", "R13"},
|
||||
{"R14", "R14"},
|
||||
{"R15", "R15"},
|
||||
{"R16", "R16"},
|
||||
{"R17", "R17"},
|
||||
{"R18", "R18"},
|
||||
{"R19", "R19"},
|
||||
{"R2", "R2"},
|
||||
{"R20", "R20"},
|
||||
{"R21", "R21"},
|
||||
{"R23", "R23"},
|
||||
{"R24", "R24"},
|
||||
{"R25", "R25"},
|
||||
{"R26", "R26"},
|
||||
{"R27", "R27"},
|
||||
{"R28", "R28"},
|
||||
{"R29", "R29"},
|
||||
{"R30", "R30"},
|
||||
{"R3", "R3"},
|
||||
{"R4", "R4"},
|
||||
{"R5", "R5"},
|
||||
{"R6", "R6"},
|
||||
{"R7", "R7"},
|
||||
{"R8", "R8"},
|
||||
{"R9", "R9"},
|
||||
{"a(FP)", "a(FP)"},
|
||||
{"g", "g"},
|
||||
{"RSB", "R31"},
|
||||
{"ret+8(FP)", "ret+8(FP)"},
|
||||
{"runtime·abort(SB)", "runtime.abort(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·trunc(SB)", "\"\".trunc(SB)"},
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
var s390xOperandTests = []operandTest{
|
||||
{"$((1<<63)-1)", "$9223372036854775807"},
|
||||
{"$(-64*1024)", "$-65536"},
|
||||
|
||||
@@ -49,7 +49,7 @@ type Parser struct {
|
||||
}
|
||||
|
||||
type Patch struct {
|
||||
addr *obj.Addr
|
||||
prog *obj.Prog
|
||||
label string
|
||||
}
|
||||
|
||||
|
||||
2
src/cmd/asm/internal/asm/testdata/arm.s
vendored
2
src/cmd/asm/internal/asm/testdata/arm.s
vendored
@@ -1042,7 +1042,7 @@ jmp_label_3:
|
||||
BFI $29, $2, R8 // 1881dee7
|
||||
BFI $16, $8, R1, R2 // BFI $16, R1, $8, R2 // 1124d7e7
|
||||
|
||||
// synthetic arithmetic
|
||||
// synthetic arithmatic
|
||||
ADD $0xffffffaa, R2, R3 // ADD $4294967210, R2, R3 // 55b0e0e30b3082e0
|
||||
ADD $0xffffff55, R5 // ADD $4294967125, R5 // aab0e0e30b5085e0
|
||||
ADD.S $0xffffffab, R2, R3 // ADD.S $4294967211, R2, R3 // 54b0e0e30b3092e0
|
||||
|
||||
6
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
6
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
@@ -10,6 +10,7 @@
|
||||
|
||||
TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||
|
||||
|
||||
// arithmetic operations
|
||||
ADDW $1, R2, R3
|
||||
ADDW R1, R2, R3
|
||||
@@ -850,11 +851,6 @@ again:
|
||||
JMP foo(SB)
|
||||
CALL foo(SB)
|
||||
|
||||
// ADR
|
||||
ADR next, R11 // ADR R11 // 2b000010
|
||||
next:
|
||||
NOP
|
||||
|
||||
// LDP/STP
|
||||
LDP (R0), (R0, R1) // 000440a9
|
||||
LDP (R0), (R1, R2) // 010840a9
|
||||
|
||||
11
src/cmd/asm/internal/asm/testdata/loong64.s
vendored
11
src/cmd/asm/internal/asm/testdata/loong64.s
vendored
@@ -1,11 +0,0 @@
|
||||
// Copyright 2022 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 "../../../../../runtime/textflag.h"
|
||||
// TODO: cover more instruction
|
||||
|
||||
TEXT foo(SB),DUPOK|NOSPLIT,$0
|
||||
JAL 1(PC) //CALL 1(PC) //000c0054
|
||||
JAL (R4) //CALL (R4) //8100004c
|
||||
JAL foo(SB) //CALL foo(SB) //00100054
|
||||
209
src/cmd/asm/internal/asm/testdata/loong64enc1.s
vendored
209
src/cmd/asm/internal/asm/testdata/loong64enc1.s
vendored
@@ -1,209 +0,0 @@
|
||||
// Copyright 2022 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 "../../../../../runtime/textflag.h"
|
||||
|
||||
TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
lable1:
|
||||
BFPT 1(PC) // 00050048
|
||||
BFPT lable1 // BFPT 2 //1ffdff4b
|
||||
|
||||
lable2:
|
||||
BFPF 1(PC) // 00040048
|
||||
BFPF lable2 // BFPF 4 // 1ffcff4b
|
||||
|
||||
JMP foo(SB) // 00100050
|
||||
JMP (R4) // 8000004c
|
||||
JMP 1(PC) // 00040058
|
||||
MOVW $65536, R4 // 04020014
|
||||
MOVW $4096, R4 // 24000014
|
||||
MOVV $65536, R4 // 04020014
|
||||
MOVV $4096, R4 // 24000014
|
||||
MOVW R4, R5 // 85001700
|
||||
MOVV R4, R5 // 85001500
|
||||
MOVBU R4, R5 // 85fc4303
|
||||
SUB R4, R5, R6 // a6101100
|
||||
SUBV R4, R5, R6 // a6901100
|
||||
ADD R4, R5, R6 // a6101000
|
||||
ADDV R4, R5, R6 // a6901000
|
||||
AND R4, R5, R6 // a6901400
|
||||
SUB R4, R5 // a5101100
|
||||
SUBV R4, R5 // a5901100
|
||||
ADD R4, R5 // a5101000
|
||||
ADDV R4, R5 // a5901000
|
||||
AND R4, R5 // a5901400
|
||||
NEGW R4, R5 // 05101100
|
||||
NEGV R4, R5 // 05901100
|
||||
SLL R4, R5 // a5101700
|
||||
SLL R4, R5, R6 // a6101700
|
||||
SRL R4, R5 // a5901700
|
||||
SRL R4, R5, R6 // a6901700
|
||||
SRA R4, R5 // a5101800
|
||||
SRA R4, R5, R6 // a6101800
|
||||
SLLV R4, R5 // a5901800
|
||||
SLLV R4, R5, R6 // a6901800
|
||||
CLO R4, R5 // 85100000
|
||||
CLZ R4, R5 // 85140000
|
||||
ADDF F4, F5 // a5900001
|
||||
ADDF F4, R5, F6 // a6900001
|
||||
CMPEQF F4, R5 // a010120c
|
||||
ABSF F4, F5 // 85041401
|
||||
MOVVF F4, F5 // 85181d01
|
||||
MOVF F4, F5 // 85941401
|
||||
MOVD F4, F5 // 85981401
|
||||
MOVW R4, result+16(FP) // 64608029
|
||||
MOVWU R4, result+16(FP) // 64608029
|
||||
MOVV R4, result+16(FP) // 6460c029
|
||||
MOVB R4, result+16(FP) // 64600029
|
||||
MOVBU R4, result+16(FP) // 64600029
|
||||
MOVWL R4, result+16(FP) // 6460002f
|
||||
MOVVL R4, result+16(FP) // 6460802f
|
||||
MOVW R4, 1(R5) // a4048029
|
||||
MOVWU R4, 1(R5) // a4048029
|
||||
MOVV R4, 1(R5) // a404c029
|
||||
MOVB R4, 1(R5) // a4040029
|
||||
MOVBU R4, 1(R5) // a4040029
|
||||
MOVWL R4, 1(R5) // a404002f
|
||||
MOVVL R4, 1(R5) // a404802f
|
||||
SC R4, 1(R5) // a4040021
|
||||
SCV R4, 1(R5) // a4040023
|
||||
MOVW y+8(FP), R4 // 64408028
|
||||
MOVWU y+8(FP), R4 // 6440802a
|
||||
MOVV y+8(FP), R4 // 6440c028
|
||||
MOVB y+8(FP), R4 // 64400028
|
||||
MOVBU y+8(FP), R4 // 6440002a
|
||||
MOVWL y+8(FP), R4 // 6440002e
|
||||
MOVVL y+8(FP), R4 // 6440802e
|
||||
MOVW 1(R5), R4 // a4048028
|
||||
MOVWU 1(R5), R4 // a404802a
|
||||
MOVV 1(R5), R4 // a404c028
|
||||
MOVB 1(R5), R4 // a4040028
|
||||
MOVBU 1(R5), R4 // a404002a
|
||||
MOVWL 1(R5), R4 // a404002e
|
||||
MOVVL 1(R5), R4 // a404802e
|
||||
LL 1(R5), R4 // a4040020
|
||||
LLV 1(R5), R4 // a4040022
|
||||
MOVW $4(R4), R5 // 8510c002
|
||||
MOVV $4(R4), R5 // 8510c002
|
||||
MOVW $-1, R4 // 04fcff02
|
||||
MOVV $-1, R4 // 04fcff02
|
||||
MOVW $1, R4 // 0404c002
|
||||
MOVV $1, R4 // 0404c002
|
||||
ADD $-1, R4, R5 // 85fcbf02
|
||||
ADD $-1, R4 // 84fcbf02
|
||||
ADDV $-1, R4, R5 // 85fcff02
|
||||
ADDV $-1, R4 // 84fcff02
|
||||
AND $1, R4, R5 // 85044003
|
||||
AND $1, R4 // 84044003
|
||||
SLL $4, R4, R5 // 85904000
|
||||
SLL $4, R4 // 84904000
|
||||
SRL $4, R4, R5 // 85904400
|
||||
SRL $4, R4 // 84904400
|
||||
SRA $4, R4, R5 // 85904800
|
||||
SRA $4, R4 // 84904800
|
||||
SLLV $4, R4, R5 // 85104100
|
||||
SLLV $4, R4 // 84104100
|
||||
SYSCALL // 00002b00
|
||||
BEQ R4, R5, 1(PC) // 85040058
|
||||
BEQ R4, 1(PC) // 80040058
|
||||
BLTU R4, 1(PC) // 80040068
|
||||
MOVW y+8(FP), F4 // 6440002b
|
||||
MOVF y+8(FP), F4 // 6440002b
|
||||
MOVD y+8(FP), F4 // 6440802b
|
||||
MOVW 1(F5), F4 // a404002b
|
||||
MOVF 1(F5), F4 // a404002b
|
||||
MOVD 1(F5), F4 // a404802b
|
||||
MOVW F4, result+16(FP) // 6460402b
|
||||
MOVF F4, result+16(FP) // 6460402b
|
||||
MOVD F4, result+16(FP) // 6460c02b
|
||||
MOVW F4, 1(F5) // a404402b
|
||||
MOVF F4, 1(F5) // a404402b
|
||||
MOVD F4, 1(F5) // a404c02b
|
||||
MOVW R4, F5 // 85a41401
|
||||
MOVW F4, R5 // 85b41401
|
||||
MOVV R4, F5 // 85a81401
|
||||
MOVV F4, R5 // 85b81401
|
||||
WORD $74565 // 45230100
|
||||
BREAK R4, result+16(FP) // 64600006
|
||||
BREAK R4, 1(R5) // a4040006
|
||||
BREAK // 00002a00
|
||||
UNDEF // 00002a00
|
||||
|
||||
// mul
|
||||
MUL R4, R5 // a5101c00
|
||||
MUL R4, R5, R6 // a6101c00
|
||||
MULV R4, R5 // a5901d00
|
||||
MULV R4, R5, R6 // a6901d00
|
||||
MULVU R4, R5 // a5901d00
|
||||
MULVU R4, R5, R6 // a6901d00
|
||||
MULHV R4, R5 // a5101e00
|
||||
MULHV R4, R5, R6 // a6101e00
|
||||
MULHVU R4, R5 // a5901e00
|
||||
MULHVU R4, R5, R6 // a6901e00
|
||||
REMV R4, R5 // a5902200
|
||||
REMV R4, R5, R6 // a6902200
|
||||
REMVU R4, R5 // a5902300
|
||||
REMVU R4, R5, R6 // a6902300
|
||||
DIVV R4, R5 // a5102200
|
||||
DIVV R4, R5, R6 // a6102200
|
||||
DIVVU R4, R5 // a5102300
|
||||
DIVVU R4, R5, R6 // a6102300
|
||||
|
||||
MOVH R4, result+16(FP) // 64604029
|
||||
MOVH R4, 1(R5) // a4044029
|
||||
MOVH y+8(FP), R4 // 64404028
|
||||
MOVH 1(R5), R4 // a4044028
|
||||
MOVHU R4, R5 // 8500cf00
|
||||
MOVHU R4, result+16(FP) // 64604029
|
||||
MOVHU R4, 1(R5) // a4044029
|
||||
MOVHU y+8(FP), R4 // 6440402a
|
||||
MOVHU 1(R5), R4 // a404402a
|
||||
MULU R4, R5 // a5101c00
|
||||
MULU R4, R5, R6 // a6101c00
|
||||
MULH R4, R5 // a5901c00
|
||||
MULH R4, R5, R6 // a6901c00
|
||||
MULHU R4, R5 // a5101d00
|
||||
MULHU R4, R5, R6 // a6101d00
|
||||
REM R4, R5 // a5902000
|
||||
REM R4, R5, R6 // a6902000
|
||||
REMU R4, R5 // a5902100
|
||||
REMU R4, R5, R6 // a6902100
|
||||
DIV R4, R5 // a5102000
|
||||
DIV R4, R5, R6 // a6102000
|
||||
DIVU R4, R5 // a5102100
|
||||
DIVU R4, R5, R6 // a6102100
|
||||
SRLV R4, R5 // a5101900
|
||||
SRLV R4, R5, R6 // a6101900
|
||||
SRLV $4, R4, R5 // 85104500
|
||||
SRLV $4, R4 // 84104500
|
||||
SRLV $32, R4, R5 // 85804500
|
||||
SRLV $32, R4 // 84804500
|
||||
|
||||
MOVFD F4, F5 // 85241901
|
||||
MOVDF F4, F5 // 85181901
|
||||
MOVWF F4, F5 // 85101d01
|
||||
MOVFW F4, F5 // 85041b01
|
||||
MOVWD F4, F5 // 85201d01
|
||||
MOVDW F4, F5 // 85081b01
|
||||
NEGF F4, F5 // 85141401
|
||||
NEGD F4, F5 // 85181401
|
||||
ABSD F4, F5 // 85081401
|
||||
TRUNCDW F4, F5 // 85881a01
|
||||
TRUNCFW F4, F5 // 85841a01
|
||||
SQRTF F4, F5 // 85441401
|
||||
SQRTD F4, F5 // 85481401
|
||||
|
||||
DBAR // 00007238
|
||||
NOOP // 00004003
|
||||
|
||||
MOVWR R4, result+16(FP) // 6460402f
|
||||
MOVWR R4, 1(R5) // a404402f
|
||||
MOVWR y+8(FP), R4 // 6440402e
|
||||
MOVWR 1(R5), R4 // a404402e
|
||||
|
||||
CMPGTF F4, R5 // a090110c
|
||||
CMPGTD F4, R5 // a090210c
|
||||
CMPGEF F4, R5 // a090130c
|
||||
CMPGED F4, R5 // a090230c
|
||||
CMPEQD F4, R5 // a010220c
|
||||
82
src/cmd/asm/internal/asm/testdata/loong64enc2.s
vendored
82
src/cmd/asm/internal/asm/testdata/loong64enc2.s
vendored
@@ -1,82 +0,0 @@
|
||||
// Copyright 2022 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 "../../../../../runtime/textflag.h"
|
||||
|
||||
TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVB R4, R5 // 85e04000a5e04800
|
||||
MOVWU R4, R5 // 85804100a5804500
|
||||
MOVW $74565, R4 // 4402001484148d03
|
||||
MOVW $4097, R4 // 2400001484048003
|
||||
MOVV $74565, R4 // 4402001484148d03
|
||||
MOVV $4097, R4 // 2400001484048003
|
||||
AND $-1, R4, R5 // 1efcbf0285f81400
|
||||
AND $-1, R4 // 1efcbf0284f81400
|
||||
MOVW $-1, F4 // 1efcbf02c4a71401
|
||||
MOVW $1, F4 // 1e048002c4a71401
|
||||
TEQ $4, R4, R5 // 8508005c04002a00
|
||||
TEQ $4, R4 // 0408005c04002a00
|
||||
TNE $4, R4, R5 // 8508005804002a00
|
||||
TNE $4, R4 // 0408005804002a00
|
||||
ADD $65536, R4, R5 // 1e02001485781000
|
||||
ADD $4096, R4, R5 // 3e00001485781000
|
||||
ADD $65536, R4 // 1e02001484781000
|
||||
ADD $4096, R4 // 3e00001484781000
|
||||
ADDV $65536, R4, R5 // 1e02001485f81000
|
||||
ADDV $4096, R4, R5 // 3e00001485f81000
|
||||
ADDV $65536, R4 // 1e02001484f81000
|
||||
ADDV $4096, R4 // 3e00001484f81000
|
||||
AND $65536, R4, R5 // 1e02001485f81400
|
||||
AND $4096, R4, R5 // 3e00001485f81400
|
||||
AND $65536, R4 // 1e02001484f81400
|
||||
AND $4096, R4 // 3e00001484f81400
|
||||
SGT $65536, R4, R5 // 1e02001485781200
|
||||
SGT $4096, R4, R5 // 3e00001485781200
|
||||
SGT $65536, R4 // 1e02001484781200
|
||||
SGT $4096, R4 // 3e00001484781200
|
||||
SGTU $65536, R4, R5 // 1e02001485f81200
|
||||
SGTU $4096, R4, R5 // 3e00001485f81200
|
||||
SGTU $65536, R4 // 1e02001484f81200
|
||||
SGTU $4096, R4 // 3e00001484f81200
|
||||
ADDU $65536, R4, R5 // 1e02001485781000
|
||||
ADDU $4096, R4, R5 // 3e00001485781000
|
||||
ADDU $65536, R4 // 1e02001484781000
|
||||
ADDU $4096, R4 // 3e00001484781000
|
||||
ADDVU $65536, R4, R5 // 1e02001485f81000
|
||||
ADDVU $4096, R4, R5 // 3e00001485f81000
|
||||
ADDVU $65536, R4 // 1e02001484f81000
|
||||
ADDVU $4096, R4 // 3e00001484f81000
|
||||
OR $65536, R4, R5 // 1e02001485781500
|
||||
OR $4096, R4, R5 // 3e00001485781500
|
||||
OR $65536, R4 // 1e02001484781500
|
||||
OR $4096, R4 // 3e00001484781500
|
||||
OR $-1, R4, R5 // 1efcbf0285781500
|
||||
OR $-1, R4 // 1efcbf0284781500
|
||||
XOR $65536, R4, R5 // 1e02001485f81500
|
||||
XOR $4096, R4, R5 // 3e00001485f81500
|
||||
XOR $65536, R4 // 1e02001484f81500
|
||||
XOR $4096, R4 // 3e00001484f81500
|
||||
XOR $-1, R4, R5 // 1efcbf0285f81500
|
||||
XOR $-1, R4 // 1efcbf0284f81500
|
||||
MOVH R4, R5 // 85c04000a5c04800
|
||||
|
||||
// relocation instructions
|
||||
MOVW R4, name(SB) // 1e00001cc4038029
|
||||
MOVWU R4, name(SB) // 1e00001cc4038029
|
||||
MOVV R4, name(SB) // 1e00001cc403c029
|
||||
MOVB R4, name(SB) // 1e00001cc4030029
|
||||
MOVBU R4, name(SB) // 1e00001cc4030029
|
||||
MOVF F4, name(SB) // 1e00001cc403402b
|
||||
MOVD F4, name(SB) // 1e00001cc403c02b
|
||||
MOVW name(SB), R4 // 1e00001cc4038028
|
||||
MOVWU name(SB), R4 // 1e00001cc403802a
|
||||
MOVV name(SB), R4 // 1e00001cc403c028
|
||||
MOVB name(SB), R4 // 1e00001cc4030028
|
||||
MOVBU name(SB), R4 // 1e00001cc403002a
|
||||
MOVF name(SB), F4 // 1e00001cc403002b
|
||||
MOVD name(SB), F4 // 1e00001cc403802b
|
||||
MOVH R4, name(SB) // 1e00001cc4034029
|
||||
MOVH name(SB), R4 // 1e00001cc4034028
|
||||
MOVHU R4, name(SB) // 1e00001cc4034029
|
||||
MOVHU name(SB), R4 // 1e00001cc403402a
|
||||
131
src/cmd/asm/internal/asm/testdata/loong64enc3.s
vendored
131
src/cmd/asm/internal/asm/testdata/loong64enc3.s
vendored
@@ -1,131 +0,0 @@
|
||||
// Copyright 2022 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 "../../../../../runtime/textflag.h"
|
||||
|
||||
TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVW $65536(R4), R5 // 1e020014de03800385f81000
|
||||
MOVW $4096(R4), R5 // 3e000014de03800385f81000
|
||||
MOVV $65536(R4), R5 // 1e020014de03800385f81000
|
||||
MOVV $4096(R4), R5 // 3e000014de03800385f81000
|
||||
ADD $74565, R4 // 5e020014de178d0384781000
|
||||
ADD $4097, R4 // 3e000014de07800384781000
|
||||
ADDV $74565, R4 // 5e020014de178d0384f81000
|
||||
ADDV $4097, R4 // 3e000014de07800384f81000
|
||||
AND $74565, R4 // 5e020014de178d0384f81400
|
||||
AND $4097, R4 // 3e000014de07800384f81400
|
||||
ADD $74565, R4, R5 // 5e020014de178d0385781000
|
||||
ADD $4097, R4, R5 // 3e000014de07800385781000
|
||||
ADDV $74565, R4, R5 // 5e020014de178d0385f81000
|
||||
ADDV $4097, R4, R5 // 3e000014de07800385f81000
|
||||
AND $74565, R4, R5 // 5e020014de178d0385f81400
|
||||
AND $4097, R4, R5 // 3e000014de07800385f81400
|
||||
|
||||
MOVW R4, result+65540(FP) // 1e020014de8f1000c4338029
|
||||
MOVW R4, result+4097(FP) // 3e000014de8f1000c4278029
|
||||
MOVWU R4, result+65540(FP) // 1e020014de8f1000c4338029
|
||||
MOVWU R4, result+4097(FP) // 3e000014de8f1000c4278029
|
||||
MOVV R4, result+65540(FP) // 1e020014de8f1000c433c029
|
||||
MOVV R4, result+4097(FP) // 3e000014de8f1000c427c029
|
||||
MOVB R4, result+65540(FP) // 1e020014de8f1000c4330029
|
||||
MOVB R4, result+4097(FP) // 3e000014de8f1000c4270029
|
||||
MOVBU R4, result+65540(FP) // 1e020014de8f1000c4330029
|
||||
MOVBU R4, result+4097(FP) // 3e000014de8f1000c4270029
|
||||
MOVW R4, 65536(R5) // 1e020014de971000c4038029
|
||||
MOVW R4, 4096(R5) // 3e000014de971000c4038029
|
||||
MOVWU R4, 65536(R5) // 1e020014de971000c4038029
|
||||
MOVWU R4, 4096(R5) // 3e000014de971000c4038029
|
||||
MOVV R4, 65536(R5) // 1e020014de971000c403c029
|
||||
MOVV R4, 4096(R5) // 3e000014de971000c403c029
|
||||
MOVB R4, 65536(R5) // 1e020014de971000c4030029
|
||||
MOVB R4, 4096(R5) // 3e000014de971000c4030029
|
||||
MOVBU R4, 65536(R5) // 1e020014de971000c4030029
|
||||
MOVBU R4, 4096(R5) // 3e000014de971000c4030029
|
||||
SC R4, 65536(R5) // 1e020014de971000c4030021
|
||||
SC R4, 4096(R5) // 3e000014de971000c4030021
|
||||
MOVW y+65540(FP), R4 // 1e020014de8f1000c4338028
|
||||
MOVWU y+65540(FP), R4 // 1e020014de8f1000c433802a
|
||||
MOVV y+65540(FP), R4 // 1e020014de8f1000c433c028
|
||||
MOVB y+65540(FP), R4 // 1e020014de8f1000c4330028
|
||||
MOVBU y+65540(FP), R4 // 1e020014de8f1000c433002a
|
||||
MOVW y+4097(FP), R4 // 3e000014de8f1000c4278028
|
||||
MOVWU y+4097(FP), R4 // 3e000014de8f1000c427802a
|
||||
MOVV y+4097(FP), R4 // 3e000014de8f1000c427c028
|
||||
MOVB y+4097(FP), R4 // 3e000014de8f1000c4270028
|
||||
MOVBU y+4097(FP), R4 // 3e000014de8f1000c427002a
|
||||
MOVW 65536(R5), R4 // 1e020014de971000c4038028
|
||||
MOVWU 65536(R5), R4 // 1e020014de971000c403802a
|
||||
MOVV 65536(R5), R4 // 1e020014de971000c403c028
|
||||
MOVB 65536(R5), R4 // 1e020014de971000c4030028
|
||||
MOVBU 65536(R5), R4 // 1e020014de971000c403002a
|
||||
MOVW 4096(R5), R4 // 3e000014de971000c4038028
|
||||
MOVWU 4096(R5), R4 // 3e000014de971000c403802a
|
||||
MOVV 4096(R5), R4 // 3e000014de971000c403c028
|
||||
MOVB 4096(R5), R4 // 3e000014de971000c4030028
|
||||
MOVBU 4096(R5), R4 // 3e000014de971000c403002a
|
||||
MOVW y+65540(FP), F4 // 1e020014de8f1000c433002b
|
||||
MOVF y+65540(FP), F4 // 1e020014de8f1000c433002b
|
||||
MOVD y+65540(FP), F4 // 1e020014de8f1000c433802b
|
||||
MOVW y+4097(FP), F4 // 3e000014de8f1000c427002b
|
||||
MOVF y+4097(FP), F4 // 3e000014de8f1000c427002b
|
||||
MOVD y+4097(FP), F4 // 3e000014de8f1000c427802b
|
||||
MOVW 65536(R5), F4 // 1e020014de971000c403002b
|
||||
MOVF 65536(R5), F4 // 1e020014de971000c403002b
|
||||
MOVD 65536(R5), F4 // 1e020014de971000c403802b
|
||||
MOVW 4096(R5), F4 // 3e000014de971000c403002b
|
||||
MOVF 4096(R5), F4 // 3e000014de971000c403002b
|
||||
MOVD 4096(R5), F4 // 3e000014de971000c403802b
|
||||
MOVW F4, result+65540(FP) // 1e020014de8f1000c433402b
|
||||
MOVF F4, result+65540(FP) // 1e020014de8f1000c433402b
|
||||
MOVD F4, result+65540(FP) // 1e020014de8f1000c433c02b
|
||||
MOVW F4, result+4097(FP) // 3e000014de8f1000c427402b
|
||||
MOVF F4, result+4097(FP) // 3e000014de8f1000c427402b
|
||||
MOVD F4, result+4097(FP) // 3e000014de8f1000c427c02b
|
||||
MOVW F4, 65536(R5) // 1e020014de971000c403402b
|
||||
MOVF F4, 65536(R5) // 1e020014de971000c403402b
|
||||
MOVD F4, 65536(R5) // 1e020014de971000c403c02b
|
||||
MOVW F4, 4096(R5) // 3e000014de971000c403402b
|
||||
MOVF F4, 4096(R5) // 3e000014de971000c403402b
|
||||
MOVD F4, 4096(R5) // 3e000014de971000c403c02b
|
||||
|
||||
MOVH R4, result+65540(FP) // 1e020014de8f1000c4334029
|
||||
MOVH R4, 65536(R5) // 1e020014de971000c4034029
|
||||
MOVH y+65540(FP), R4 // 1e020014de8f1000c4334028
|
||||
MOVH 65536(R5), R4 // 1e020014de971000c4034028
|
||||
MOVH R4, result+4097(FP) // 3e000014de8f1000c4274029
|
||||
MOVH R4, 4096(R5) // 3e000014de971000c4034029
|
||||
MOVH y+4097(FP), R4 // 3e000014de8f1000c4274028
|
||||
MOVH 4096(R5), R4 // 3e000014de971000c4034028
|
||||
MOVHU R4, result+65540(FP) // 1e020014de8f1000c4334029
|
||||
MOVHU R4, 65536(R5) // 1e020014de971000c4034029
|
||||
MOVHU y+65540(FP), R4 // 1e020014de8f1000c433402a
|
||||
MOVHU 65536(R5), R4 // 1e020014de971000c403402a
|
||||
MOVHU R4, result+4097(FP) // 3e000014de8f1000c4274029
|
||||
MOVHU R4, 4096(R5) // 3e000014de971000c4034029
|
||||
MOVHU y+4097(FP), R4 // 3e000014de8f1000c427402a
|
||||
MOVHU 4096(R5), R4 // 3e000014de971000c403402a
|
||||
SGT $74565, R4 // 5e020014de178d0384781200
|
||||
SGT $74565, R4, R5 // 5e020014de178d0385781200
|
||||
SGT $4097, R4 // 3e000014de07800384781200
|
||||
SGT $4097, R4, R5 // 3e000014de07800385781200
|
||||
SGTU $74565, R4 // 5e020014de178d0384f81200
|
||||
SGTU $74565, R4, R5 // 5e020014de178d0385f81200
|
||||
SGTU $4097, R4 // 3e000014de07800384f81200
|
||||
SGTU $4097, R4, R5 // 3e000014de07800385f81200
|
||||
ADDU $74565, R4 // 5e020014de178d0384781000
|
||||
ADDU $74565, R4, R5 // 5e020014de178d0385781000
|
||||
ADDU $4097, R4 // 3e000014de07800384781000
|
||||
ADDU $4097, R4, R5 // 3e000014de07800385781000
|
||||
ADDVU $4097, R4 // 3e000014de07800384f81000
|
||||
ADDVU $4097, R4, R5 // 3e000014de07800385f81000
|
||||
ADDVU $74565, R4 // 5e020014de178d0384f81000
|
||||
ADDVU $74565, R4, R5 // 5e020014de178d0385f81000
|
||||
OR $74565, R4 // 5e020014de178d0384781500
|
||||
OR $74565, R4, R5 // 5e020014de178d0385781500
|
||||
OR $4097, R4 // 3e000014de07800384781500
|
||||
OR $4097, R4, R5 // 3e000014de07800385781500
|
||||
XOR $74565, R4 // 5e020014de178d0384f81500
|
||||
XOR $74565, R4, R5 // 5e020014de178d0385f81500
|
||||
XOR $4097, R4 // 3e000014de07800384f81500
|
||||
XOR $4097, R4, R5 // 3e000014de07800385f81500
|
||||
75
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
75
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
@@ -24,7 +24,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVW $-32767, R5 // 38a08001
|
||||
MOVW $-32768, R6 // 38c08000
|
||||
MOVW $1234567, R5 // 6405001260a5d687
|
||||
MOVD 8(R3), R4 // e8830008
|
||||
MOVD 8(R3), R4 // e8830008
|
||||
MOVD (R3)(R4), R5 // 7ca4182a
|
||||
MOVW 4(R3), R4 // e8830006
|
||||
MOVW (R3)(R4), R5 // 7ca41aaa
|
||||
@@ -41,7 +41,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVDBR (R3)(R4), R5 // 7ca41c28
|
||||
MOVWBR (R3)(R4), R5 // 7ca41c2c
|
||||
MOVHBR (R3)(R4), R5 // 7ca41e2c
|
||||
MOVD $foo+4009806848(FP), R5 // 3ca1ef0138a5cc40
|
||||
MOVD $foo+4009806848(FP), R5 // 3ca1ef0138a5cc20
|
||||
MOVD $foo(SB), R5 // 3ca0000038a50000
|
||||
|
||||
MOVDU 8(R3), R4 // e8830009
|
||||
@@ -79,14 +79,14 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVBU R4, 1(R3) // 9c830001
|
||||
MOVBU R5, (R3)(R4) // 7ca419ee
|
||||
|
||||
MOVB $0, R4 // 38800000
|
||||
MOVBZ $0, R4 // 38800000
|
||||
MOVH $0, R4 // 38800000
|
||||
MOVHZ $0, R4 // 38800000
|
||||
MOVW $0, R4 // 38800000
|
||||
MOVWZ $0, R4 // 38800000
|
||||
MOVD $0, R4 // 38800000
|
||||
MOVD $0, R0 // 38000000
|
||||
MOVB $0, R4 // 38800000
|
||||
MOVBZ $0, R4 // 38800000
|
||||
MOVH $0, R4 // 38800000
|
||||
MOVHZ $0, R4 // 38800000
|
||||
MOVW $0, R4 // 38800000
|
||||
MOVWZ $0, R4 // 38800000
|
||||
MOVD $0, R4 // 38800000
|
||||
MOVD $0, R0 // 38000000
|
||||
|
||||
ADD $1, R3 // 38630001
|
||||
ADD $1, R3, R4 // 38830001
|
||||
@@ -351,18 +351,11 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
CRORN CR0GT, CR0EQ, CR0SO // 4c620b42
|
||||
CRXOR CR0GT, CR0EQ, CR0SO // 4c620982
|
||||
|
||||
ISEL $0, R3, R4, R5 // 7ca3201e
|
||||
ISEL $1, R3, R4, R5 // 7ca3205e
|
||||
ISEL $0, R3, R4, R5 // 7ca3201e
|
||||
ISEL $2, R3, R4, R5 // 7ca3209e
|
||||
ISEL $3, R3, R4, R5 // 7ca320de
|
||||
ISEL $4, R3, R4, R5 // 7ca3211e
|
||||
ISEL $31, R3, R4, R5 // 7ca327de
|
||||
ISEL CR0LT, R3, R4, R5 // 7ca3201e
|
||||
ISEL CR0GT, R3, R4, R5 // 7ca3205e
|
||||
ISEL CR0EQ, R3, R4, R5 // 7ca3209e
|
||||
ISEL CR0SO, R3, R4, R5 // 7ca320de
|
||||
ISEL CR1LT, R3, R4, R5 // 7ca3211e
|
||||
ISEL CR7SO, R3, R4, R5 // 7ca327de
|
||||
POPCNTB R3, R4 // 7c6400f4
|
||||
POPCNTW R3, R4 // 7c6402f4
|
||||
POPCNTD R3, R4 // 7c6403f4
|
||||
@@ -772,51 +765,9 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVFL R1, $3 // 7c203120
|
||||
|
||||
// Verify supported bdnz/bdz encodings.
|
||||
BC 16,0,0(PC) // BC $16, CR0LT, 0(PC) // 42000000
|
||||
BC 16,0,0(PC) // BC $16,R0,0(PC) // 42000000
|
||||
BDNZ 0(PC) // 42000000
|
||||
BDZ 0(PC) // 42400000
|
||||
BC 18,0,0(PC) // BC $18, CR0LT, 0(PC) // 42400000
|
||||
|
||||
// Verify the supported forms of bcclr[l]
|
||||
BC $20,CR0LT,$1,LR // 4e800820
|
||||
BC $20,CR0LT,$0,LR // 4e800020
|
||||
BC $20,CR0LT,LR // 4e800020
|
||||
BC $20,CR0GT,LR // 4e810020
|
||||
BC 20,CR0LT,LR // BC $20,CR0LT,LR // 4e800020
|
||||
BC 20,undefined_symbol,LR // BC $20,CR0LT,LR // 4e800020
|
||||
BC 20,undefined_symbol+1,LR // BC $20,CR0GT,LR // 4e810020
|
||||
JMP LR // 4e800020
|
||||
BR LR // JMP LR // 4e800020
|
||||
BCL $20,CR0LT,$1,LR // 4e800821
|
||||
BCL $20,CR0LT,$0,LR // 4e800021
|
||||
BCL $20,CR0LT,LR // 4e800021
|
||||
BCL $20,CR0GT,LR // 4e810021
|
||||
BCL 20,CR0LT,LR // BCL $20,CR0LT,LR // 4e800021
|
||||
BCL 20,undefined_symbol,LR // BCL $20,CR0LT,LR // 4e800021
|
||||
BCL 20,undefined_symbol+1,LR // BCL $20,CR0GT,LR // 4e810021
|
||||
|
||||
// Verify the supported forms of bcctr[l]
|
||||
BC $20,CR0LT,CTR // 4e800420
|
||||
BC $20,CR0GT,CTR // 4e810420
|
||||
BC 20,CR0LT,CTR // BC $20,CR0LT,CTR // 4e800420
|
||||
BC 20,undefined_symbol,CTR // BC $20,CR0LT,CTR // 4e800420
|
||||
BC 20,undefined_symbol+1,CTR // BC $20,CR0GT,CTR // 4e810420
|
||||
JMP CTR // 4e800420
|
||||
BR CTR // JMP CTR // 4e800420
|
||||
BCL $20,CR0LT,CTR // 4e800421
|
||||
BCL $20,CR0GT,CTR // 4e810421
|
||||
BCL 20,CR0LT,CTR // BCL $20,CR0LT,CTR // 4e800421
|
||||
BCL 20,undefined_symbol,CTR // BCL $20,CR0LT,CTR // 4e800421
|
||||
BCL 20,undefined_symbol+1,CTR // BCL $20,CR0GT,CTR // 4e810421
|
||||
|
||||
// Verify bc encoding (without pic enabled)
|
||||
BC $16,CR0LT,0(PC) // 42000000
|
||||
BCL $16,CR0LT,0(PC) // 42000001
|
||||
BC $18,CR0LT,0(PC) // 42400000
|
||||
|
||||
MOVD SPR(3), 4(R1) // 7fe302a6fbe10004
|
||||
MOVD XER, 4(R1) // 7fe102a6fbe10004
|
||||
MOVD 4(R1), SPR(3) // ebe100047fe303a6
|
||||
MOVD 4(R1), XER // ebe100047fe103a6
|
||||
BC 18,0,0(PC) // BC $18,R0,0(PC) // 42400000
|
||||
|
||||
RET
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/objabi"
|
||||
"flag"
|
||||
"fmt"
|
||||
@@ -24,7 +23,7 @@ var (
|
||||
Linkshared = flag.Bool("linkshared", false, "generate code that will be linked against Go shared libraries")
|
||||
AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
|
||||
SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble")
|
||||
Importpath = flag.String("p", obj.UnlinkablePkg, "set expected package import to path")
|
||||
Importpath = flag.String("p", "", "set expected package import to path")
|
||||
Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)")
|
||||
CompilingRuntime = flag.Bool("compiling-runtime", false, "source to be compiled is part of the Go runtime")
|
||||
)
|
||||
|
||||
@@ -53,11 +53,6 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// <= go 1.7 doesn't embed the contentID or actionID, so no slash is present
|
||||
if !strings.Contains(id, "/") {
|
||||
log.Fatalf("%s: build ID is a legacy format...binary too old for this tool", file)
|
||||
}
|
||||
|
||||
newID := id[:strings.LastIndex(id, "/")] + "/" + buildid.HashToString(hash)
|
||||
if len(newID) != len(id) {
|
||||
log.Fatalf("%s: build ID length mismatch %q vs %q", file, id, newID)
|
||||
|
||||
@@ -576,23 +576,8 @@ func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
|
||||
switch e.Tag {
|
||||
case dwarf.TagVariable:
|
||||
name, _ := e.Val(dwarf.AttrName).(string)
|
||||
// As of https://reviews.llvm.org/D123534, clang
|
||||
// now emits DW_TAG_variable DIEs that have
|
||||
// no name (so as to be able to describe the
|
||||
// type and source locations of constant strings
|
||||
// like the second arg in the call below:
|
||||
//
|
||||
// myfunction(42, "foo")
|
||||
//
|
||||
// If a var has no name we won't see attempts to
|
||||
// refer to it via "C.<name>", so skip these vars
|
||||
//
|
||||
// See issue 53000 for more context.
|
||||
if name == "" {
|
||||
break
|
||||
}
|
||||
typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
|
||||
if typOff == 0 {
|
||||
if name == "" || typOff == 0 {
|
||||
if e.Val(dwarf.AttrSpecification) != nil {
|
||||
// Since we are reading all the DWARF,
|
||||
// assume we will see the variable elsewhere.
|
||||
@@ -826,7 +811,6 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
|
||||
|
||||
params := name.FuncType.Params
|
||||
args := call.Call.Args
|
||||
end := call.Call.End()
|
||||
|
||||
// Avoid a crash if the number of arguments doesn't match
|
||||
// the number of parameters.
|
||||
@@ -974,7 +958,7 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
|
||||
if nu {
|
||||
needsUnsafe = true
|
||||
}
|
||||
sb.WriteString(gofmtPos(m, end))
|
||||
sb.WriteString(gofmtLine(m))
|
||||
|
||||
sb.WriteString("(")
|
||||
for i := range params {
|
||||
@@ -1638,8 +1622,6 @@ func (p *Package) gccMachine() []string {
|
||||
} else if gomips == "softfloat" {
|
||||
return []string{"-mabi=32", "-msoft-float"}
|
||||
}
|
||||
case "loong64":
|
||||
return []string{"-mabi=lp64d"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -2242,8 +2224,6 @@ var dwarfToName = map[string]string{
|
||||
"long long unsigned int": "ulonglong",
|
||||
"signed char": "schar",
|
||||
"unsigned char": "uchar",
|
||||
"unsigned long": "ulong", // Used by Clang 14; issue 53013.
|
||||
"unsigned long long": "ulonglong", // Used by Clang 14; issue 53013.
|
||||
}
|
||||
|
||||
const signedDelta = 64
|
||||
|
||||
@@ -175,7 +175,6 @@ var ptrSizeMap = map[string]int64{
|
||||
"amd64": 8,
|
||||
"arm": 4,
|
||||
"arm64": 8,
|
||||
"loong64": 8,
|
||||
"m68k": 4,
|
||||
"mips": 4,
|
||||
"mipsle": 4,
|
||||
@@ -201,7 +200,6 @@ var intSizeMap = map[string]int64{
|
||||
"amd64": 8,
|
||||
"arm": 4,
|
||||
"arm64": 8,
|
||||
"loong64": 8,
|
||||
"m68k": 4,
|
||||
"mips": 4,
|
||||
"mipsle": 4,
|
||||
|
||||
@@ -14,10 +14,10 @@ import (
|
||||
"go/ast"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
exec "internal/execabs"
|
||||
"internal/xcoff"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
@@ -174,7 +174,7 @@ func (p *Package) writeDefs() {
|
||||
// the external linker will add DT_NEEDED
|
||||
// entries as needed on ELF systems.
|
||||
// Treat function variables differently
|
||||
// to avoid type conflict errors from LTO
|
||||
// to avoid type confict errors from LTO
|
||||
// (Link Time Optimization).
|
||||
if n.Kind == "fpvar" {
|
||||
fmt.Fprintf(fm, "extern void %s();\n", n.C)
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/token"
|
||||
exec "internal/execabs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// run runs the command argv, feeding in stdin on standard input.
|
||||
|
||||
@@ -15,12 +15,10 @@ the compiler. Roughly speaking, these translate to the first two and last two
|
||||
phases we are going to list here. A third term, "middle-end", often refers to
|
||||
much of the work that happens in the second phase.
|
||||
|
||||
Note that the `go/*` family of packages, such as `go/parser` and
|
||||
`go/types`, are mostly unused by the compiler. Since the compiler was
|
||||
initially written in C, the `go/*` packages were developed to enable
|
||||
writing tools working with Go code, such as `gofmt` and `vet`.
|
||||
However, over time the compiler's internal APIs have slowly evolved to
|
||||
be more familiar to users of the `go/*` packages.
|
||||
Note that the `go/*` family of packages, such as `go/parser` and `go/types`,
|
||||
have no relation to the compiler. Since the compiler was initially written in C,
|
||||
the `go/*` packages were developed to enable writing tools working with Go code,
|
||||
such as `gofmt` and `vet`.
|
||||
|
||||
It should be clarified that the name "gc" stands for "Go compiler", and has
|
||||
little to do with uppercase "GC", which stands for garbage collection.
|
||||
@@ -38,71 +36,33 @@ nodes corresponding to the various elements of the source such as expressions,
|
||||
declarations, and statements. The syntax tree also includes position information
|
||||
which is used for error reporting and the creation of debugging information.
|
||||
|
||||
### 2. Type checking
|
||||
### 2. Type-checking and AST transformations
|
||||
|
||||
* `cmd/compile/internal/types2` (type checking)
|
||||
* `cmd/compile/internal/gc` (create compiler AST, type checking, AST transformations)
|
||||
|
||||
The types2 package is a port of `go/types` to use the syntax package's
|
||||
AST instead of `go/ast`.
|
||||
The gc package includes its own AST definition carried over from when it was written
|
||||
in C. All of its code is written in terms of this AST, so the first thing that the gc
|
||||
package must do is convert the syntax package's syntax tree to the compiler's
|
||||
AST representation. This extra step may be refactored away in the future.
|
||||
|
||||
### 3. IR construction ("noding")
|
||||
The gc AST is then type-checked. The first steps are name resolution and type
|
||||
inference, which determine which object belongs to which identifier, and what
|
||||
type each expression has. Type-checking includes certain extra checks, such as
|
||||
"declared and not used" as well as determining whether or not a function
|
||||
terminates.
|
||||
|
||||
* `cmd/compile/internal/types` (compiler types)
|
||||
* `cmd/compile/internal/ir` (compiler AST)
|
||||
* `cmd/compile/internal/typecheck` (AST transformations)
|
||||
* `cmd/compile/internal/noder` (create compiler AST)
|
||||
|
||||
The compiler middle end uses its own AST definition and representation of Go
|
||||
types carried over from when it was written in C. All of its code is written in
|
||||
terms of these, so the next step after type checking is to convert the syntax
|
||||
and types2 representations to ir and types. This process is referred to as
|
||||
"noding."
|
||||
|
||||
There are currently two noding implementations:
|
||||
|
||||
1. irgen (aka "-G=3" or sometimes "noder2") is the implementation used starting
|
||||
with Go 1.18, and
|
||||
|
||||
2. Unified IR is another, in-development implementation (enabled with
|
||||
`GOEXPERIMENT=unified`), which also implements import/export and inlining.
|
||||
|
||||
Up through Go 1.18, there was a third noding implementation (just
|
||||
"noder" or "-G=0"), which directly converted the pre-type-checked
|
||||
syntax representation into IR and then invoked package typecheck's
|
||||
type checker. This implementation was removed after Go 1.18, so now
|
||||
package typecheck is only used for IR transformations.
|
||||
|
||||
### 4. Middle end
|
||||
|
||||
* `cmd/compile/internal/deadcode` (dead code elimination)
|
||||
* `cmd/compile/internal/inline` (function call inlining)
|
||||
* `cmd/compile/internal/devirtualize` (devirtualization of known interface method calls)
|
||||
* `cmd/compile/internal/escape` (escape analysis)
|
||||
|
||||
Several optimization passes are performed on the IR representation:
|
||||
dead code elimination, (early) devirtualization, function call
|
||||
Certain transformations are also done on the AST. Some nodes are refined based
|
||||
on type information, such as string additions being split from the arithmetic
|
||||
addition node type. Some other examples are dead code elimination, function call
|
||||
inlining, and escape analysis.
|
||||
|
||||
### 5. Walk
|
||||
|
||||
* `cmd/compile/internal/walk` (order of evaluation, desugaring)
|
||||
|
||||
The final pass over the IR representation is "walk," which serves two purposes:
|
||||
|
||||
1. It decomposes complex statements into individual, simpler statements,
|
||||
introducing temporary variables and respecting order of evaluation. This step
|
||||
is also referred to as "order."
|
||||
|
||||
2. It desugars higher-level Go constructs into more primitive ones. For example,
|
||||
`switch` statements are turned into binary search or jump tables, and
|
||||
operations on maps and channels are replaced with runtime calls.
|
||||
|
||||
### 6. Generic SSA
|
||||
### 3. Generic SSA
|
||||
|
||||
* `cmd/compile/internal/gc` (converting to SSA)
|
||||
* `cmd/compile/internal/ssa` (SSA passes and rules)
|
||||
* `cmd/compile/internal/ssagen` (converting IR to SSA)
|
||||
|
||||
In this phase, IR is converted into Static Single Assignment (SSA) form, a
|
||||
|
||||
In this phase, the AST is converted into Static Single Assignment (SSA) form, a
|
||||
lower-level intermediate representation with specific properties that make it
|
||||
easier to implement optimizations and to eventually generate machine code from
|
||||
it.
|
||||
@@ -124,7 +84,7 @@ unneeded nil checks, and removal of unused branches. The generic rewrite rules
|
||||
mainly concern expressions, such as replacing some expressions with constant
|
||||
values, and optimizing multiplications and float operations.
|
||||
|
||||
### 7. Generating machine code
|
||||
### 4. Generating machine code
|
||||
|
||||
* `cmd/compile/internal/ssa` (SSA lowering and arch-specific passes)
|
||||
* `cmd/internal/obj` (machine code generation)
|
||||
|
||||
@@ -1,849 +0,0 @@
|
||||
// Copyright 2022 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 abt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
LEAF_HEIGHT = 1
|
||||
ZERO_HEIGHT = 0
|
||||
NOT_KEY32 = int32(-0x80000000)
|
||||
)
|
||||
|
||||
// T is the exported applicative balanced tree data type.
|
||||
// A T can be used as a value; updates to one copy of the value
|
||||
// do not change other copies.
|
||||
type T struct {
|
||||
root *node32
|
||||
size int
|
||||
}
|
||||
|
||||
// node32 is the internal tree node data type
|
||||
type node32 struct {
|
||||
// Standard conventions hold for left = smaller, right = larger
|
||||
left, right *node32
|
||||
data interface{}
|
||||
key int32
|
||||
height_ int8
|
||||
}
|
||||
|
||||
func makeNode(key int32) *node32 {
|
||||
return &node32{key: key, height_: LEAF_HEIGHT}
|
||||
}
|
||||
|
||||
// IsSingle returns true iff t is empty.
|
||||
func (t *T) IsEmpty() bool {
|
||||
return t.root == nil
|
||||
}
|
||||
|
||||
// IsSingle returns true iff t is a singleton (leaf).
|
||||
func (t *T) IsSingle() bool {
|
||||
return t.root != nil && t.root.isLeaf()
|
||||
}
|
||||
|
||||
// VisitInOrder applies f to the key and data pairs in t,
|
||||
// with keys ordered from smallest to largest.
|
||||
func (t *T) VisitInOrder(f func(int32, interface{})) {
|
||||
if t.root == nil {
|
||||
return
|
||||
}
|
||||
t.root.visitInOrder(f)
|
||||
}
|
||||
|
||||
func (n *node32) nilOrData() interface{} {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
return n.data
|
||||
}
|
||||
|
||||
func (n *node32) nilOrKeyAndData() (k int32, d interface{}) {
|
||||
if n == nil {
|
||||
k = NOT_KEY32
|
||||
d = nil
|
||||
} else {
|
||||
k = n.key
|
||||
d = n.data
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (n *node32) height() int8 {
|
||||
if n == nil {
|
||||
return 0
|
||||
}
|
||||
return n.height_
|
||||
}
|
||||
|
||||
// Find returns the data associated with x in the tree, or
|
||||
// nil if x is not in the tree.
|
||||
func (t *T) Find(x int32) interface{} {
|
||||
return t.root.find(x).nilOrData()
|
||||
}
|
||||
|
||||
// Insert either adds x to the tree if x was not previously
|
||||
// a key in the tree, or updates the data for x in the tree if
|
||||
// x was already a key in the tree. The previous data associated
|
||||
// with x is returned, and is nil if x was not previously a
|
||||
// key in the tree.
|
||||
func (t *T) Insert(x int32, data interface{}) interface{} {
|
||||
if x == NOT_KEY32 {
|
||||
panic("Cannot use sentinel value -0x80000000 as key")
|
||||
}
|
||||
n := t.root
|
||||
var newroot *node32
|
||||
var o *node32
|
||||
if n == nil {
|
||||
n = makeNode(x)
|
||||
newroot = n
|
||||
} else {
|
||||
newroot, n, o = n.aInsert(x)
|
||||
}
|
||||
var r interface{}
|
||||
if o != nil {
|
||||
r = o.data
|
||||
} else {
|
||||
t.size++
|
||||
}
|
||||
n.data = data
|
||||
t.root = newroot
|
||||
return r
|
||||
}
|
||||
|
||||
func (t *T) Copy() *T {
|
||||
u := *t
|
||||
return &u
|
||||
}
|
||||
|
||||
func (t *T) Delete(x int32) interface{} {
|
||||
n := t.root
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
d, s := n.aDelete(x)
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
t.root = s
|
||||
t.size--
|
||||
return d.data
|
||||
}
|
||||
|
||||
func (t *T) DeleteMin() (int32, interface{}) {
|
||||
n := t.root
|
||||
if n == nil {
|
||||
return NOT_KEY32, nil
|
||||
}
|
||||
d, s := n.aDeleteMin()
|
||||
if d == nil {
|
||||
return NOT_KEY32, nil
|
||||
}
|
||||
t.root = s
|
||||
t.size--
|
||||
return d.key, d.data
|
||||
}
|
||||
|
||||
func (t *T) DeleteMax() (int32, interface{}) {
|
||||
n := t.root
|
||||
if n == nil {
|
||||
return NOT_KEY32, nil
|
||||
}
|
||||
d, s := n.aDeleteMax()
|
||||
if d == nil {
|
||||
return NOT_KEY32, nil
|
||||
}
|
||||
t.root = s
|
||||
t.size--
|
||||
return d.key, d.data
|
||||
}
|
||||
|
||||
func (t *T) Size() int {
|
||||
return t.size
|
||||
}
|
||||
|
||||
// Intersection returns the intersection of t and u, where the result
|
||||
// data for any common keys is given by f(t's data, u's data) -- f need
|
||||
// not be symmetric. If f returns nil, then the key and data are not
|
||||
// added to the result. If f itself is nil, then whatever value was
|
||||
// already present in the smaller set is used.
|
||||
func (t *T) Intersection(u *T, f func(x, y interface{}) interface{}) *T {
|
||||
if t.Size() == 0 || u.Size() == 0 {
|
||||
return &T{}
|
||||
}
|
||||
|
||||
// For faster execution and less allocation, prefer t smaller, iterate over t.
|
||||
if t.Size() <= u.Size() {
|
||||
v := t.Copy()
|
||||
for it := t.Iterator(); !it.Done(); {
|
||||
k, d := it.Next()
|
||||
e := u.Find(k)
|
||||
if e == nil {
|
||||
v.Delete(k)
|
||||
continue
|
||||
}
|
||||
if f == nil {
|
||||
continue
|
||||
}
|
||||
if c := f(d, e); c != d {
|
||||
if c == nil {
|
||||
v.Delete(k)
|
||||
} else {
|
||||
v.Insert(k, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
v := u.Copy()
|
||||
for it := u.Iterator(); !it.Done(); {
|
||||
k, e := it.Next()
|
||||
d := t.Find(k)
|
||||
if d == nil {
|
||||
v.Delete(k)
|
||||
continue
|
||||
}
|
||||
if f == nil {
|
||||
continue
|
||||
}
|
||||
if c := f(d, e); c != d {
|
||||
if c == nil {
|
||||
v.Delete(k)
|
||||
} else {
|
||||
v.Insert(k, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// Union returns the union of t and u, where the result data for any common keys
|
||||
// is given by f(t's data, u's data) -- f need not be symmetric. If f returns nil,
|
||||
// then the key and data are not added to the result. If f itself is nil, then
|
||||
// whatever value was already present in the larger set is used.
|
||||
func (t *T) Union(u *T, f func(x, y interface{}) interface{}) *T {
|
||||
if t.Size() == 0 {
|
||||
return u
|
||||
}
|
||||
if u.Size() == 0 {
|
||||
return t
|
||||
}
|
||||
|
||||
if t.Size() >= u.Size() {
|
||||
v := t.Copy()
|
||||
for it := u.Iterator(); !it.Done(); {
|
||||
k, e := it.Next()
|
||||
d := t.Find(k)
|
||||
if d == nil {
|
||||
v.Insert(k, e)
|
||||
continue
|
||||
}
|
||||
if f == nil {
|
||||
continue
|
||||
}
|
||||
if c := f(d, e); c != d {
|
||||
if c == nil {
|
||||
v.Delete(k)
|
||||
} else {
|
||||
v.Insert(k, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
v := u.Copy()
|
||||
for it := t.Iterator(); !it.Done(); {
|
||||
k, d := it.Next()
|
||||
e := u.Find(k)
|
||||
if e == nil {
|
||||
v.Insert(k, d)
|
||||
continue
|
||||
}
|
||||
if f == nil {
|
||||
continue
|
||||
}
|
||||
if c := f(d, e); c != d {
|
||||
if c == nil {
|
||||
v.Delete(k)
|
||||
} else {
|
||||
v.Insert(k, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Difference returns the difference of t and u, subject to the result
|
||||
// of f applied to data corresponding to equal keys. If f returns nil
|
||||
// (or if f is nil) then the key+data are excluded, as usual. If f
|
||||
// returns not-nil, then that key+data pair is inserted. instead.
|
||||
func (t *T) Difference(u *T, f func(x, y interface{}) interface{}) *T {
|
||||
if t.Size() == 0 {
|
||||
return &T{}
|
||||
}
|
||||
if u.Size() == 0 {
|
||||
return t
|
||||
}
|
||||
v := t.Copy()
|
||||
for it := t.Iterator(); !it.Done(); {
|
||||
k, d := it.Next()
|
||||
e := u.Find(k)
|
||||
if e != nil {
|
||||
if f == nil {
|
||||
v.Delete(k)
|
||||
continue
|
||||
}
|
||||
c := f(d, e)
|
||||
if c == nil {
|
||||
v.Delete(k)
|
||||
continue
|
||||
}
|
||||
if c != d {
|
||||
v.Insert(k, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (t *T) Iterator() Iterator {
|
||||
return Iterator{it: t.root.iterator()}
|
||||
}
|
||||
|
||||
func (t *T) Equals(u *T) bool {
|
||||
if t == u {
|
||||
return true
|
||||
}
|
||||
if t.Size() != u.Size() {
|
||||
return false
|
||||
}
|
||||
return t.root.equals(u.root)
|
||||
}
|
||||
|
||||
// This doesn't build with go1.4, sigh
|
||||
// func (t *T) String() string {
|
||||
// var b strings.Builder
|
||||
// first := true
|
||||
// for it := t.Iterator(); !it.IsEmpty(); {
|
||||
// k, v := it.Next()
|
||||
// if first {
|
||||
// first = false
|
||||
// } else {
|
||||
// b.WriteString("; ")
|
||||
// }
|
||||
// b.WriteString(strconv.FormatInt(int64(k), 10))
|
||||
// b.WriteString(":")
|
||||
// b.WriteString(v.String())
|
||||
// }
|
||||
// return b.String()
|
||||
// }
|
||||
|
||||
func (t *T) String() string {
|
||||
var b string
|
||||
first := true
|
||||
for it := t.Iterator(); !it.Done(); {
|
||||
k, v := it.Next()
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
b += ("; ")
|
||||
}
|
||||
b += (strconv.FormatInt(int64(k), 10))
|
||||
b += (":")
|
||||
b += fmt.Sprint(v)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (t *node32) equals(u *node32) bool {
|
||||
if t == u {
|
||||
return true
|
||||
}
|
||||
it, iu := t.iterator(), u.iterator()
|
||||
for !it.done() && !iu.done() {
|
||||
nt := it.next()
|
||||
nu := iu.next()
|
||||
if nt == nu {
|
||||
continue
|
||||
}
|
||||
if nt.key != nu.key {
|
||||
return false
|
||||
}
|
||||
if nt.data != nu.data {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return it.done() == iu.done()
|
||||
}
|
||||
|
||||
func (t *T) Equiv(u *T, eqv func(x, y interface{}) bool) bool {
|
||||
if t == u {
|
||||
return true
|
||||
}
|
||||
if t.Size() != u.Size() {
|
||||
return false
|
||||
}
|
||||
return t.root.equiv(u.root, eqv)
|
||||
}
|
||||
|
||||
func (t *node32) equiv(u *node32, eqv func(x, y interface{}) bool) bool {
|
||||
if t == u {
|
||||
return true
|
||||
}
|
||||
it, iu := t.iterator(), u.iterator()
|
||||
for !it.done() && !iu.done() {
|
||||
nt := it.next()
|
||||
nu := iu.next()
|
||||
if nt == nu {
|
||||
continue
|
||||
}
|
||||
if nt.key != nu.key {
|
||||
return false
|
||||
}
|
||||
if !eqv(nt.data, nu.data) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return it.done() == iu.done()
|
||||
}
|
||||
|
||||
type iterator struct {
|
||||
parents []*node32
|
||||
}
|
||||
|
||||
type Iterator struct {
|
||||
it iterator
|
||||
}
|
||||
|
||||
func (it *Iterator) Next() (int32, interface{}) {
|
||||
x := it.it.next()
|
||||
if x == nil {
|
||||
return NOT_KEY32, nil
|
||||
}
|
||||
return x.key, x.data
|
||||
}
|
||||
|
||||
func (it *Iterator) Done() bool {
|
||||
return len(it.it.parents) == 0
|
||||
}
|
||||
|
||||
func (t *node32) iterator() iterator {
|
||||
if t == nil {
|
||||
return iterator{}
|
||||
}
|
||||
it := iterator{parents: make([]*node32, 0, int(t.height()))}
|
||||
it.leftmost(t)
|
||||
return it
|
||||
}
|
||||
|
||||
func (it *iterator) leftmost(t *node32) {
|
||||
for t != nil {
|
||||
it.parents = append(it.parents, t)
|
||||
t = t.left
|
||||
}
|
||||
}
|
||||
|
||||
func (it *iterator) done() bool {
|
||||
return len(it.parents) == 0
|
||||
}
|
||||
|
||||
func (it *iterator) next() *node32 {
|
||||
l := len(it.parents)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
x := it.parents[l-1] // return value
|
||||
if x.right != nil {
|
||||
it.leftmost(x.right)
|
||||
return x
|
||||
}
|
||||
// discard visited top of parents
|
||||
l--
|
||||
it.parents = it.parents[:l]
|
||||
y := x // y is known visited/returned
|
||||
for l > 0 && y == it.parents[l-1].right {
|
||||
y = it.parents[l-1]
|
||||
l--
|
||||
it.parents = it.parents[:l]
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// Min returns the minimum element of t.
|
||||
// If t is empty, then (NOT_KEY32, nil) is returned.
|
||||
func (t *T) Min() (k int32, d interface{}) {
|
||||
return t.root.min().nilOrKeyAndData()
|
||||
}
|
||||
|
||||
// Max returns the maximum element of t.
|
||||
// If t is empty, then (NOT_KEY32, nil) is returned.
|
||||
func (t *T) Max() (k int32, d interface{}) {
|
||||
return t.root.max().nilOrKeyAndData()
|
||||
}
|
||||
|
||||
// Glb returns the greatest-lower-bound-exclusive of x and the associated
|
||||
// data. If x has no glb in the tree, then (NOT_KEY32, nil) is returned.
|
||||
func (t *T) Glb(x int32) (k int32, d interface{}) {
|
||||
return t.root.glb(x, false).nilOrKeyAndData()
|
||||
}
|
||||
|
||||
// GlbEq returns the greatest-lower-bound-inclusive of x and the associated
|
||||
// data. If x has no glbEQ in the tree, then (NOT_KEY32, nil) is returned.
|
||||
func (t *T) GlbEq(x int32) (k int32, d interface{}) {
|
||||
return t.root.glb(x, true).nilOrKeyAndData()
|
||||
}
|
||||
|
||||
// Lub returns the least-upper-bound-exclusive of x and the associated
|
||||
// data. If x has no lub in the tree, then (NOT_KEY32, nil) is returned.
|
||||
func (t *T) Lub(x int32) (k int32, d interface{}) {
|
||||
return t.root.lub(x, false).nilOrKeyAndData()
|
||||
}
|
||||
|
||||
// LubEq returns the least-upper-bound-inclusive of x and the associated
|
||||
// data. If x has no lubEq in the tree, then (NOT_KEY32, nil) is returned.
|
||||
func (t *T) LubEq(x int32) (k int32, d interface{}) {
|
||||
return t.root.lub(x, true).nilOrKeyAndData()
|
||||
}
|
||||
|
||||
func (t *node32) isLeaf() bool {
|
||||
return t.left == nil && t.right == nil && t.height_ == LEAF_HEIGHT
|
||||
}
|
||||
|
||||
func (t *node32) visitInOrder(f func(int32, interface{})) {
|
||||
if t.left != nil {
|
||||
t.left.visitInOrder(f)
|
||||
}
|
||||
f(t.key, t.data)
|
||||
if t.right != nil {
|
||||
t.right.visitInOrder(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *node32) find(key int32) *node32 {
|
||||
for t != nil {
|
||||
if key < t.key {
|
||||
t = t.left
|
||||
} else if key > t.key {
|
||||
t = t.right
|
||||
} else {
|
||||
return t
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *node32) min() *node32 {
|
||||
if t == nil {
|
||||
return t
|
||||
}
|
||||
for t.left != nil {
|
||||
t = t.left
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *node32) max() *node32 {
|
||||
if t == nil {
|
||||
return t
|
||||
}
|
||||
for t.right != nil {
|
||||
t = t.right
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *node32) glb(key int32, allow_eq bool) *node32 {
|
||||
var best *node32 = nil
|
||||
for t != nil {
|
||||
if key <= t.key {
|
||||
if allow_eq && key == t.key {
|
||||
return t
|
||||
}
|
||||
// t is too big, glb is to left.
|
||||
t = t.left
|
||||
} else {
|
||||
// t is a lower bound, record it and seek a better one.
|
||||
best = t
|
||||
t = t.right
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
func (t *node32) lub(key int32, allow_eq bool) *node32 {
|
||||
var best *node32 = nil
|
||||
for t != nil {
|
||||
if key >= t.key {
|
||||
if allow_eq && key == t.key {
|
||||
return t
|
||||
}
|
||||
// t is too small, lub is to right.
|
||||
t = t.right
|
||||
} else {
|
||||
// t is a upper bound, record it and seek a better one.
|
||||
best = t
|
||||
t = t.left
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
func (t *node32) aInsert(x int32) (newroot, newnode, oldnode *node32) {
|
||||
// oldnode default of nil is good, others should be assigned.
|
||||
if x == t.key {
|
||||
oldnode = t
|
||||
newt := *t
|
||||
newnode = &newt
|
||||
newroot = newnode
|
||||
return
|
||||
}
|
||||
if x < t.key {
|
||||
if t.left == nil {
|
||||
t = t.copy()
|
||||
n := makeNode(x)
|
||||
t.left = n
|
||||
newnode = n
|
||||
newroot = t
|
||||
t.height_ = 2 // was balanced w/ 0, sibling is height 0 or 1
|
||||
return
|
||||
}
|
||||
var new_l *node32
|
||||
new_l, newnode, oldnode = t.left.aInsert(x)
|
||||
t = t.copy()
|
||||
t.left = new_l
|
||||
if new_l.height() > 1+t.right.height() {
|
||||
newroot = t.aLeftIsHigh(newnode)
|
||||
} else {
|
||||
t.height_ = 1 + max(t.left.height(), t.right.height())
|
||||
newroot = t
|
||||
}
|
||||
} else { // x > t.key
|
||||
if t.right == nil {
|
||||
t = t.copy()
|
||||
n := makeNode(x)
|
||||
t.right = n
|
||||
newnode = n
|
||||
newroot = t
|
||||
t.height_ = 2 // was balanced w/ 0, sibling is height 0 or 1
|
||||
return
|
||||
}
|
||||
var new_r *node32
|
||||
new_r, newnode, oldnode = t.right.aInsert(x)
|
||||
t = t.copy()
|
||||
t.right = new_r
|
||||
if new_r.height() > 1+t.left.height() {
|
||||
newroot = t.aRightIsHigh(newnode)
|
||||
} else {
|
||||
t.height_ = 1 + max(t.left.height(), t.right.height())
|
||||
newroot = t
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *node32) aDelete(key int32) (deleted, newSubTree *node32) {
|
||||
if t == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if key < t.key {
|
||||
oh := t.left.height()
|
||||
d, tleft := t.left.aDelete(key)
|
||||
if tleft == t.left {
|
||||
return d, t
|
||||
}
|
||||
return d, t.copy().aRebalanceAfterLeftDeletion(oh, tleft)
|
||||
} else if key > t.key {
|
||||
oh := t.right.height()
|
||||
d, tright := t.right.aDelete(key)
|
||||
if tright == t.right {
|
||||
return d, t
|
||||
}
|
||||
return d, t.copy().aRebalanceAfterRightDeletion(oh, tright)
|
||||
}
|
||||
|
||||
if t.height() == LEAF_HEIGHT {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// Interior delete by removing left.Max or right.Min,
|
||||
// then swapping contents
|
||||
if t.left.height() > t.right.height() {
|
||||
oh := t.left.height()
|
||||
d, tleft := t.left.aDeleteMax()
|
||||
r := t
|
||||
t = t.copy()
|
||||
t.data, t.key = d.data, d.key
|
||||
return r, t.aRebalanceAfterLeftDeletion(oh, tleft)
|
||||
}
|
||||
|
||||
oh := t.right.height()
|
||||
d, tright := t.right.aDeleteMin()
|
||||
r := t
|
||||
t = t.copy()
|
||||
t.data, t.key = d.data, d.key
|
||||
return r, t.aRebalanceAfterRightDeletion(oh, tright)
|
||||
}
|
||||
|
||||
func (t *node32) aDeleteMin() (deleted, newSubTree *node32) {
|
||||
if t == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if t.left == nil { // leaf or left-most
|
||||
return t, t.right
|
||||
}
|
||||
oh := t.left.height()
|
||||
d, tleft := t.left.aDeleteMin()
|
||||
if tleft == t.left {
|
||||
return d, t
|
||||
}
|
||||
return d, t.copy().aRebalanceAfterLeftDeletion(oh, tleft)
|
||||
}
|
||||
|
||||
func (t *node32) aDeleteMax() (deleted, newSubTree *node32) {
|
||||
if t == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if t.right == nil { // leaf or right-most
|
||||
return t, t.left
|
||||
}
|
||||
|
||||
oh := t.right.height()
|
||||
d, tright := t.right.aDeleteMax()
|
||||
if tright == t.right {
|
||||
return d, t
|
||||
}
|
||||
return d, t.copy().aRebalanceAfterRightDeletion(oh, tright)
|
||||
}
|
||||
|
||||
func (t *node32) aRebalanceAfterLeftDeletion(oldLeftHeight int8, tleft *node32) *node32 {
|
||||
t.left = tleft
|
||||
|
||||
if oldLeftHeight == tleft.height() || oldLeftHeight == t.right.height() {
|
||||
// this node is still balanced and its height is unchanged
|
||||
return t
|
||||
}
|
||||
|
||||
if oldLeftHeight > t.right.height() {
|
||||
// left was larger
|
||||
t.height_--
|
||||
return t
|
||||
}
|
||||
|
||||
// left height fell by 1 and it was already less than right height
|
||||
t.right = t.right.copy()
|
||||
return t.aRightIsHigh(nil)
|
||||
}
|
||||
|
||||
func (t *node32) aRebalanceAfterRightDeletion(oldRightHeight int8, tright *node32) *node32 {
|
||||
t.right = tright
|
||||
|
||||
if oldRightHeight == tright.height() || oldRightHeight == t.left.height() {
|
||||
// this node is still balanced and its height is unchanged
|
||||
return t
|
||||
}
|
||||
|
||||
if oldRightHeight > t.left.height() {
|
||||
// left was larger
|
||||
t.height_--
|
||||
return t
|
||||
}
|
||||
|
||||
// right height fell by 1 and it was already less than left height
|
||||
t.left = t.left.copy()
|
||||
return t.aLeftIsHigh(nil)
|
||||
}
|
||||
|
||||
// aRightIsHigh does rotations necessary to fix a high right child
|
||||
// assume that t and t.right are already fresh copies.
|
||||
func (t *node32) aRightIsHigh(newnode *node32) *node32 {
|
||||
right := t.right
|
||||
if right.right.height() < right.left.height() {
|
||||
// double rotation
|
||||
if newnode != right.left {
|
||||
right.left = right.left.copy()
|
||||
}
|
||||
t.right = right.leftToRoot()
|
||||
}
|
||||
t = t.rightToRoot()
|
||||
return t
|
||||
}
|
||||
|
||||
// aLeftIsHigh does rotations necessary to fix a high left child
|
||||
// assume that t and t.left are already fresh copies.
|
||||
func (t *node32) aLeftIsHigh(newnode *node32) *node32 {
|
||||
left := t.left
|
||||
if left.left.height() < left.right.height() {
|
||||
// double rotation
|
||||
if newnode != left.right {
|
||||
left.right = left.right.copy()
|
||||
}
|
||||
t.left = left.rightToRoot()
|
||||
}
|
||||
t = t.leftToRoot()
|
||||
return t
|
||||
}
|
||||
|
||||
// rightToRoot does that rotation, modifying t and t.right in the process.
|
||||
func (t *node32) rightToRoot() *node32 {
|
||||
// this
|
||||
// left right
|
||||
// rl rr
|
||||
//
|
||||
// becomes
|
||||
//
|
||||
// right
|
||||
// this rr
|
||||
// left rl
|
||||
//
|
||||
right := t.right
|
||||
rl := right.left
|
||||
right.left = t
|
||||
// parent's child ptr fixed in caller
|
||||
t.right = rl
|
||||
t.height_ = 1 + max(rl.height(), t.left.height())
|
||||
right.height_ = 1 + max(t.height(), right.right.height())
|
||||
return right
|
||||
}
|
||||
|
||||
// leftToRoot does that rotation, modifying t and t.left in the process.
|
||||
func (t *node32) leftToRoot() *node32 {
|
||||
// this
|
||||
// left right
|
||||
// ll lr
|
||||
//
|
||||
// becomes
|
||||
//
|
||||
// left
|
||||
// ll this
|
||||
// lr right
|
||||
//
|
||||
left := t.left
|
||||
lr := left.right
|
||||
left.right = t
|
||||
// parent's child ptr fixed in caller
|
||||
t.left = lr
|
||||
t.height_ = 1 + max(lr.height(), t.right.height())
|
||||
left.height_ = 1 + max(t.height(), left.left.height())
|
||||
return left
|
||||
}
|
||||
|
||||
func max(a, b int8) int8 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (t *node32) copy() *node32 {
|
||||
u := *t
|
||||
return &u
|
||||
}
|
||||
@@ -1,700 +0,0 @@
|
||||
// Copyright 2022 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 abt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func makeTree(te *testing.T, x []int32, check bool) (t *T, k int, min, max int32) {
|
||||
t = &T{}
|
||||
k = 0
|
||||
min = int32(0x7fffffff)
|
||||
max = int32(-0x80000000)
|
||||
history := []*T{}
|
||||
|
||||
for _, d := range x {
|
||||
d = d + d // double everything for Glb/Lub testing.
|
||||
|
||||
if check {
|
||||
history = append(history, t.Copy())
|
||||
}
|
||||
|
||||
t.Insert(d, stringer(fmt.Sprintf("%v", d)))
|
||||
|
||||
k++
|
||||
if d < min {
|
||||
min = d
|
||||
}
|
||||
if d > max {
|
||||
max = d
|
||||
}
|
||||
|
||||
if !check {
|
||||
continue
|
||||
}
|
||||
|
||||
for j, old := range history {
|
||||
s, i := old.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Old tree consistency problem %v at k=%d, j=%d, old=\n%v, t=\n%v", s, k, j, old.DebugString(), t.DebugString())
|
||||
return
|
||||
}
|
||||
if i != j {
|
||||
te.Errorf("Wrong tree size %v, expected %v for old %v", i, j, old.DebugString())
|
||||
}
|
||||
}
|
||||
s, i := t.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Tree consistency problem at %v", s)
|
||||
return
|
||||
}
|
||||
if i != k {
|
||||
te.Errorf("Wrong tree size %v, expected %v for %v", i, k, t.DebugString())
|
||||
return
|
||||
}
|
||||
if t.Size() != k {
|
||||
te.Errorf("Wrong t.Size() %v, expected %v for %v", t.Size(), k, t.DebugString())
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func applicInsert(te *testing.T, x []int32) {
|
||||
makeTree(te, x, true)
|
||||
}
|
||||
|
||||
func applicFind(te *testing.T, x []int32) {
|
||||
t, _, _, _ := makeTree(te, x, false)
|
||||
|
||||
for _, d := range x {
|
||||
d = d + d // double everything for Glb/Lub testing.
|
||||
s := fmt.Sprintf("%v", d)
|
||||
f := t.Find(d)
|
||||
|
||||
// data
|
||||
if s != fmt.Sprint(f) {
|
||||
te.Errorf("s(%v) != f(%v)", s, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applicBounds(te *testing.T, x []int32) {
|
||||
t, _, min, max := makeTree(te, x, false)
|
||||
for _, d := range x {
|
||||
d = d + d // double everything for Glb/Lub testing.
|
||||
s := fmt.Sprintf("%v", d)
|
||||
|
||||
kg, g := t.Glb(d + 1)
|
||||
kge, ge := t.GlbEq(d)
|
||||
kl, l := t.Lub(d - 1)
|
||||
kle, le := t.LubEq(d)
|
||||
|
||||
// keys
|
||||
if d != kg {
|
||||
te.Errorf("d(%v) != kg(%v)", d, kg)
|
||||
}
|
||||
if d != kl {
|
||||
te.Errorf("d(%v) != kl(%v)", d, kl)
|
||||
}
|
||||
if d != kge {
|
||||
te.Errorf("d(%v) != kge(%v)", d, kge)
|
||||
}
|
||||
if d != kle {
|
||||
te.Errorf("d(%v) != kle(%v)", d, kle)
|
||||
}
|
||||
// data
|
||||
if s != fmt.Sprint(g) {
|
||||
te.Errorf("s(%v) != g(%v)", s, g)
|
||||
}
|
||||
if s != fmt.Sprint(l) {
|
||||
te.Errorf("s(%v) != l(%v)", s, l)
|
||||
}
|
||||
if s != fmt.Sprint(ge) {
|
||||
te.Errorf("s(%v) != ge(%v)", s, ge)
|
||||
}
|
||||
if s != fmt.Sprint(le) {
|
||||
te.Errorf("s(%v) != le(%v)", s, le)
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range x {
|
||||
d = d + d // double everything for Glb/Lub testing.
|
||||
s := fmt.Sprintf("%v", d)
|
||||
kge, ge := t.GlbEq(d + 1)
|
||||
kle, le := t.LubEq(d - 1)
|
||||
if d != kge {
|
||||
te.Errorf("d(%v) != kge(%v)", d, kge)
|
||||
}
|
||||
if d != kle {
|
||||
te.Errorf("d(%v) != kle(%v)", d, kle)
|
||||
}
|
||||
if s != fmt.Sprint(ge) {
|
||||
te.Errorf("s(%v) != ge(%v)", s, ge)
|
||||
}
|
||||
if s != fmt.Sprint(le) {
|
||||
te.Errorf("s(%v) != le(%v)", s, le)
|
||||
}
|
||||
}
|
||||
|
||||
kg, g := t.Glb(min)
|
||||
kge, ge := t.GlbEq(min - 1)
|
||||
kl, l := t.Lub(max)
|
||||
kle, le := t.LubEq(max + 1)
|
||||
fmin := t.Find(min - 1)
|
||||
fmax := t.Find(max + 1)
|
||||
|
||||
if kg != NOT_KEY32 || kge != NOT_KEY32 || kl != NOT_KEY32 || kle != NOT_KEY32 {
|
||||
te.Errorf("Got non-error-key for missing query")
|
||||
}
|
||||
|
||||
if g != nil || ge != nil || l != nil || le != nil || fmin != nil || fmax != nil {
|
||||
te.Errorf("Got non-error-data for missing query")
|
||||
}
|
||||
}
|
||||
|
||||
func applicDeleteMin(te *testing.T, x []int32) {
|
||||
t, _, _, _ := makeTree(te, x, false)
|
||||
_, size := t.wellFormed()
|
||||
history := []*T{}
|
||||
for !t.IsEmpty() {
|
||||
k, _ := t.Min()
|
||||
history = append(history, t.Copy())
|
||||
kd, _ := t.DeleteMin()
|
||||
if kd != k {
|
||||
te.Errorf("Deleted minimum key %v not equal to minimum %v", kd, k)
|
||||
}
|
||||
for j, old := range history {
|
||||
s, i := old.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Tree consistency problem %s at old after DeleteMin, old=\n%stree=\n%v", s, old.DebugString(), t.DebugString())
|
||||
return
|
||||
}
|
||||
if i != len(x)-j {
|
||||
te.Errorf("Wrong old tree size %v, expected %v after DeleteMin, old=\n%vtree\n%v", i, len(x)-j, old.DebugString(), t.DebugString())
|
||||
return
|
||||
}
|
||||
}
|
||||
size--
|
||||
s, i := t.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Tree consistency problem at %v after DeleteMin, tree=\n%v", s, t.DebugString())
|
||||
return
|
||||
}
|
||||
if i != size {
|
||||
te.Errorf("Wrong tree size %v, expected %v after DeleteMin", i, size)
|
||||
return
|
||||
}
|
||||
if t.Size() != size {
|
||||
te.Errorf("Wrong t.Size() %v, expected %v for %v", t.Size(), i, t.DebugString())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applicDeleteMax(te *testing.T, x []int32) {
|
||||
t, _, _, _ := makeTree(te, x, false)
|
||||
_, size := t.wellFormed()
|
||||
history := []*T{}
|
||||
|
||||
for !t.IsEmpty() {
|
||||
k, _ := t.Max()
|
||||
history = append(history, t.Copy())
|
||||
kd, _ := t.DeleteMax()
|
||||
if kd != k {
|
||||
te.Errorf("Deleted maximum key %v not equal to maximum %v", kd, k)
|
||||
}
|
||||
|
||||
for j, old := range history {
|
||||
s, i := old.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Tree consistency problem %s at old after DeleteMin, old=\n%stree=\n%v", s, old.DebugString(), t.DebugString())
|
||||
return
|
||||
}
|
||||
if i != len(x)-j {
|
||||
te.Errorf("Wrong old tree size %v, expected %v after DeleteMin, old=\n%vtree\n%v", i, len(x)-j, old.DebugString(), t.DebugString())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
size--
|
||||
s, i := t.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Tree consistency problem at %v after DeleteMax, tree=\n%v", s, t.DebugString())
|
||||
return
|
||||
}
|
||||
if i != size {
|
||||
te.Errorf("Wrong tree size %v, expected %v after DeleteMax", i, size)
|
||||
return
|
||||
}
|
||||
if t.Size() != size {
|
||||
te.Errorf("Wrong t.Size() %v, expected %v for %v", t.Size(), i, t.DebugString())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applicDelete(te *testing.T, x []int32) {
|
||||
t, _, _, _ := makeTree(te, x, false)
|
||||
_, size := t.wellFormed()
|
||||
history := []*T{}
|
||||
|
||||
missing := t.Delete(11)
|
||||
if missing != nil {
|
||||
te.Errorf("Returned a value when there should have been none, %v", missing)
|
||||
return
|
||||
}
|
||||
|
||||
s, i := t.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Tree consistency problem at %v after delete of missing value, tree=\n%v", s, t.DebugString())
|
||||
return
|
||||
}
|
||||
if size != i {
|
||||
te.Errorf("Delete of missing data should not change tree size, expected %d, got %d", size, i)
|
||||
return
|
||||
}
|
||||
|
||||
for _, d := range x {
|
||||
d += d // double
|
||||
vWant := fmt.Sprintf("%v", d)
|
||||
history = append(history, t.Copy())
|
||||
v := t.Delete(d)
|
||||
|
||||
for j, old := range history {
|
||||
s, i := old.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Tree consistency problem %s at old after DeleteMin, old=\n%stree=\n%v", s, old.DebugString(), t.DebugString())
|
||||
return
|
||||
}
|
||||
if i != len(x)-j {
|
||||
te.Errorf("Wrong old tree size %v, expected %v after DeleteMin, old=\n%vtree\n%v", i, len(x)-j, old.DebugString(), t.DebugString())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if v.(*sstring).s != vWant {
|
||||
te.Errorf("Deleted %v expected %v but got %v", d, vWant, v)
|
||||
return
|
||||
}
|
||||
size--
|
||||
s, i := t.wellFormed()
|
||||
if s != "" {
|
||||
te.Errorf("Tree consistency problem at %v after Delete %d, tree=\n%v", s, d, t.DebugString())
|
||||
return
|
||||
}
|
||||
if i != size {
|
||||
te.Errorf("Wrong tree size %v, expected %v after Delete", i, size)
|
||||
return
|
||||
}
|
||||
if t.Size() != size {
|
||||
te.Errorf("Wrong t.Size() %v, expected %v for %v", t.Size(), i, t.DebugString())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func applicIterator(te *testing.T, x []int32) {
|
||||
t, _, _, _ := makeTree(te, x, false)
|
||||
it := t.Iterator()
|
||||
for !it.Done() {
|
||||
k0, d0 := it.Next()
|
||||
k1, d1 := t.DeleteMin()
|
||||
if k0 != k1 || d0 != d1 {
|
||||
te.Errorf("Iterator and deleteMin mismatch, k0, k1, d0, d1 = %v, %v, %v, %v", k0, k1, d0, d1)
|
||||
return
|
||||
}
|
||||
}
|
||||
if t.Size() != 0 {
|
||||
te.Errorf("Iterator ended early, remaining tree = \n%s", t.DebugString())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func equiv(a, b interface{}) bool {
|
||||
sa, sb := a.(*sstring), b.(*sstring)
|
||||
return *sa == *sb
|
||||
}
|
||||
|
||||
func applicEquals(te *testing.T, x, y []int32) {
|
||||
t, _, _, _ := makeTree(te, x, false)
|
||||
u, _, _, _ := makeTree(te, y, false)
|
||||
if !t.Equiv(t, equiv) {
|
||||
te.Errorf("Equiv failure, t == t, =\n%v", t.DebugString())
|
||||
return
|
||||
}
|
||||
if !t.Equiv(t.Copy(), equiv) {
|
||||
te.Errorf("Equiv failure, t == t.Copy(), =\n%v", t.DebugString())
|
||||
return
|
||||
}
|
||||
if !t.Equiv(u, equiv) {
|
||||
te.Errorf("Equiv failure, t == u, =\n%v", t.DebugString())
|
||||
return
|
||||
}
|
||||
v := t.Copy()
|
||||
|
||||
v.DeleteMax()
|
||||
if t.Equiv(v, equiv) {
|
||||
te.Errorf("!Equiv failure, t != v, =\n%v\nand%v\n", t.DebugString(), v.DebugString())
|
||||
return
|
||||
}
|
||||
|
||||
if v.Equiv(u, equiv) {
|
||||
te.Errorf("!Equiv failure, v != u, =\n%v\nand%v\n", v.DebugString(), u.DebugString())
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func tree(x []int32) *T {
|
||||
t := &T{}
|
||||
for _, d := range x {
|
||||
t.Insert(d, stringer(fmt.Sprintf("%v", d)))
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func treePlus1(x []int32) *T {
|
||||
t := &T{}
|
||||
for _, d := range x {
|
||||
t.Insert(d, stringer(fmt.Sprintf("%v", d+1)))
|
||||
}
|
||||
return t
|
||||
}
|
||||
func TestApplicInsert(t *testing.T) {
|
||||
applicInsert(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25})
|
||||
applicInsert(t, []int32{1, 2, 3, 4})
|
||||
applicInsert(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
applicInsert(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
|
||||
applicInsert(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicInsert(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicInsert(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
|
||||
applicInsert(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
|
||||
}
|
||||
|
||||
func TestApplicFind(t *testing.T) {
|
||||
applicFind(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25})
|
||||
applicFind(t, []int32{1, 2, 3, 4})
|
||||
applicFind(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
applicFind(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
|
||||
applicFind(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicFind(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicFind(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
|
||||
applicFind(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
|
||||
}
|
||||
|
||||
func TestBounds(t *testing.T) {
|
||||
applicBounds(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25})
|
||||
applicBounds(t, []int32{1, 2, 3, 4})
|
||||
applicBounds(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
applicBounds(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
|
||||
applicBounds(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicBounds(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicBounds(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
|
||||
applicBounds(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
|
||||
}
|
||||
func TestDeleteMin(t *testing.T) {
|
||||
applicDeleteMin(t, []int32{1, 2, 3, 4})
|
||||
applicDeleteMin(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25})
|
||||
applicDeleteMin(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
applicDeleteMin(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
|
||||
applicDeleteMin(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicDeleteMin(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicDeleteMin(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
|
||||
applicDeleteMin(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
|
||||
}
|
||||
func TestDeleteMax(t *testing.T) {
|
||||
applicDeleteMax(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25})
|
||||
applicDeleteMax(t, []int32{1, 2, 3, 4})
|
||||
applicDeleteMax(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
applicDeleteMax(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
|
||||
applicDeleteMax(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicDeleteMax(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicDeleteMax(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
|
||||
applicDeleteMax(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
|
||||
}
|
||||
func TestDelete(t *testing.T) {
|
||||
applicDelete(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25})
|
||||
applicDelete(t, []int32{1, 2, 3, 4})
|
||||
applicDelete(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
applicDelete(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
|
||||
applicDelete(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicDelete(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicDelete(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
|
||||
applicDelete(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
|
||||
}
|
||||
func TestIterator(t *testing.T) {
|
||||
applicIterator(t, []int32{1, 2, 3, 4})
|
||||
applicIterator(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
applicIterator(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25})
|
||||
applicIterator(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
|
||||
applicIterator(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicIterator(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicIterator(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
|
||||
applicIterator(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
|
||||
}
|
||||
func TestEquals(t *testing.T) {
|
||||
applicEquals(t, []int32{1, 2, 3, 4}, []int32{4, 3, 2, 1})
|
||||
|
||||
applicEquals(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25},
|
||||
[]int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25})
|
||||
applicEquals(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
|
||||
[]int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
|
||||
applicEquals(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24},
|
||||
[]int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2})
|
||||
}
|
||||
|
||||
func first(x, y interface{}) interface{} {
|
||||
return x
|
||||
}
|
||||
func second(x, y interface{}) interface{} {
|
||||
return y
|
||||
}
|
||||
func alwaysNil(x, y interface{}) interface{} {
|
||||
return nil
|
||||
}
|
||||
func smaller(x, y interface{}) interface{} {
|
||||
xi, _ := strconv.Atoi(fmt.Sprint(x))
|
||||
yi, _ := strconv.Atoi(fmt.Sprint(y))
|
||||
if xi < yi {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
func assert(t *testing.T, expected, got *T, what string) {
|
||||
s, _ := got.wellFormed()
|
||||
if s != "" {
|
||||
t.Errorf("Tree consistency problem %v for 'got' in assert for %s, tree=\n%v", s, what, got.DebugString())
|
||||
return
|
||||
}
|
||||
|
||||
if !expected.Equiv(got, equiv) {
|
||||
t.Errorf("%s fail, expected\n%vgot\n%v\n", what, expected.DebugString(), got.DebugString())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetOps(t *testing.T) {
|
||||
A := tree([]int32{1, 2, 3, 4})
|
||||
B := tree([]int32{3, 4, 5, 6, 7})
|
||||
|
||||
AIB := tree([]int32{3, 4})
|
||||
ADB := tree([]int32{1, 2})
|
||||
BDA := tree([]int32{5, 6, 7})
|
||||
AUB := tree([]int32{1, 2, 3, 4, 5, 6, 7})
|
||||
AXB := tree([]int32{1, 2, 5, 6, 7})
|
||||
|
||||
aib1 := A.Intersection(B, first)
|
||||
assert(t, AIB, aib1, "aib1")
|
||||
if A.Find(3) != aib1.Find(3) {
|
||||
t.Errorf("Failed aliasing/reuse check, A/aib1")
|
||||
}
|
||||
aib2 := A.Intersection(B, second)
|
||||
assert(t, AIB, aib2, "aib2")
|
||||
if B.Find(3) != aib2.Find(3) {
|
||||
t.Errorf("Failed aliasing/reuse check, B/aib2")
|
||||
}
|
||||
aib3 := B.Intersection(A, first)
|
||||
assert(t, AIB, aib3, "aib3")
|
||||
if A.Find(3) != aib3.Find(3) {
|
||||
// A is smaller, intersection favors reuse from smaller when function is "first"
|
||||
t.Errorf("Failed aliasing/reuse check, A/aib3")
|
||||
}
|
||||
aib4 := B.Intersection(A, second)
|
||||
assert(t, AIB, aib4, "aib4")
|
||||
if A.Find(3) != aib4.Find(3) {
|
||||
t.Errorf("Failed aliasing/reuse check, A/aib4")
|
||||
}
|
||||
|
||||
aub1 := A.Union(B, first)
|
||||
assert(t, AUB, aub1, "aub1")
|
||||
if B.Find(3) != aub1.Find(3) {
|
||||
// B is larger, union favors reuse from larger when function is "first"
|
||||
t.Errorf("Failed aliasing/reuse check, A/aub1")
|
||||
}
|
||||
aub2 := A.Union(B, second)
|
||||
assert(t, AUB, aub2, "aub2")
|
||||
if B.Find(3) != aub2.Find(3) {
|
||||
t.Errorf("Failed aliasing/reuse check, B/aub2")
|
||||
}
|
||||
aub3 := B.Union(A, first)
|
||||
assert(t, AUB, aub3, "aub3")
|
||||
if B.Find(3) != aub3.Find(3) {
|
||||
t.Errorf("Failed aliasing/reuse check, B/aub3")
|
||||
}
|
||||
aub4 := B.Union(A, second)
|
||||
assert(t, AUB, aub4, "aub4")
|
||||
if A.Find(3) != aub4.Find(3) {
|
||||
t.Errorf("Failed aliasing/reuse check, A/aub4")
|
||||
}
|
||||
|
||||
axb1 := A.Union(B, alwaysNil)
|
||||
assert(t, AXB, axb1, "axb1")
|
||||
axb2 := B.Union(A, alwaysNil)
|
||||
assert(t, AXB, axb2, "axb2")
|
||||
|
||||
adb := A.Difference(B, alwaysNil)
|
||||
assert(t, ADB, adb, "adb")
|
||||
bda := B.Difference(A, nil)
|
||||
assert(t, BDA, bda, "bda")
|
||||
|
||||
Ap1 := treePlus1([]int32{1, 2, 3, 4})
|
||||
|
||||
ada1_1 := A.Difference(Ap1, smaller)
|
||||
assert(t, A, ada1_1, "ada1_1")
|
||||
ada1_2 := Ap1.Difference(A, smaller)
|
||||
assert(t, A, ada1_2, "ada1_2")
|
||||
|
||||
}
|
||||
|
||||
type sstring struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func (s *sstring) String() string {
|
||||
return s.s
|
||||
}
|
||||
|
||||
func stringer(s string) interface{} {
|
||||
return &sstring{s}
|
||||
}
|
||||
|
||||
// wellFormed ensures that a red-black tree meets
|
||||
// all of its invariants and returns a string identifying
|
||||
// the first problem encountered. If there is no problem
|
||||
// then the returned string is empty. The size is also
|
||||
// returned to allow comparison of calculated tree size
|
||||
// with expected.
|
||||
func (t *T) wellFormed() (s string, i int) {
|
||||
if t.root == nil {
|
||||
s = ""
|
||||
i = 0
|
||||
return
|
||||
}
|
||||
return t.root.wellFormedSubtree(nil, -0x80000000, 0x7fffffff)
|
||||
}
|
||||
|
||||
// wellFormedSubtree ensures that a red-black subtree meets
|
||||
// all of its invariants and returns a string identifying
|
||||
// the first problem encountered. If there is no problem
|
||||
// then the returned string is empty. The size is also
|
||||
// returned to allow comparison of calculated tree size
|
||||
// with expected.
|
||||
func (t *node32) wellFormedSubtree(parent *node32, keyMin, keyMax int32) (s string, i int) {
|
||||
i = -1 // initialize to a failing value
|
||||
s = "" // s is the reason for failure; empty means okay.
|
||||
|
||||
if keyMin >= t.key {
|
||||
s = " min >= t.key"
|
||||
return
|
||||
}
|
||||
|
||||
if keyMax <= t.key {
|
||||
s = " max <= t.key"
|
||||
return
|
||||
}
|
||||
|
||||
l := t.left
|
||||
r := t.right
|
||||
|
||||
lh := l.height()
|
||||
rh := r.height()
|
||||
mh := max(lh, rh)
|
||||
th := t.height()
|
||||
dh := lh - rh
|
||||
if dh < 0 {
|
||||
dh = -dh
|
||||
}
|
||||
if dh > 1 {
|
||||
s = fmt.Sprintf(" dh > 1, t=%d", t.key)
|
||||
return
|
||||
}
|
||||
|
||||
if l == nil && r == nil {
|
||||
if th != LEAF_HEIGHT {
|
||||
s = " leaf height wrong"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if th != mh+1 {
|
||||
s = " th != mh + 1"
|
||||
return
|
||||
}
|
||||
|
||||
if l != nil {
|
||||
if th <= lh {
|
||||
s = " t.height <= l.height"
|
||||
} else if th > 2+lh {
|
||||
s = " t.height > 2+l.height"
|
||||
} else if t.key <= l.key {
|
||||
s = " t.key <= l.key"
|
||||
}
|
||||
if s != "" {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
if th <= rh {
|
||||
s = " t.height <= r.height"
|
||||
} else if th > 2+rh {
|
||||
s = " t.height > 2+r.height"
|
||||
} else if t.key >= r.key {
|
||||
s = " t.key >= r.key"
|
||||
}
|
||||
if s != "" {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ii := 1
|
||||
if l != nil {
|
||||
res, il := l.wellFormedSubtree(t, keyMin, t.key)
|
||||
if res != "" {
|
||||
s = ".L" + res
|
||||
return
|
||||
}
|
||||
ii += il
|
||||
}
|
||||
if r != nil {
|
||||
res, ir := r.wellFormedSubtree(t, t.key, keyMax)
|
||||
if res != "" {
|
||||
s = ".R" + res
|
||||
return
|
||||
}
|
||||
ii += ir
|
||||
}
|
||||
i = ii
|
||||
return
|
||||
}
|
||||
|
||||
func (t *T) DebugString() string {
|
||||
if t.root == nil {
|
||||
return ""
|
||||
}
|
||||
return t.root.DebugString(0)
|
||||
}
|
||||
|
||||
// DebugString prints the tree with nested information
|
||||
// to allow an eyeball check on the tree balance.
|
||||
func (t *node32) DebugString(indent int) string {
|
||||
s := ""
|
||||
if t.left != nil {
|
||||
s = s + t.left.DebugString(indent+1)
|
||||
}
|
||||
for i := 0; i < indent; i++ {
|
||||
s = s + " "
|
||||
}
|
||||
s = s + fmt.Sprintf("%v=%v:%d\n", t.key, t.data, t.height_)
|
||||
if t.right != nil {
|
||||
s = s + t.right.DebugString(indent+1)
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -99,22 +99,21 @@ func genshift(s *ssagen.State, v *ssa.Value, as obj.As, r0, r1, r int16, typ int
|
||||
return p
|
||||
}
|
||||
|
||||
// generate the memory operand for the indexed load/store instructions.
|
||||
// base and idx are registers.
|
||||
func genIndexedOperand(op ssa.Op, base, idx int16) obj.Addr {
|
||||
// generate the memory operand for the indexed load/store instructions
|
||||
func genIndexedOperand(v *ssa.Value) obj.Addr {
|
||||
// Reg: base register, Index: (shifted) index register
|
||||
mop := obj.Addr{Type: obj.TYPE_MEM, Reg: base}
|
||||
switch op {
|
||||
mop := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[0].Reg()}
|
||||
switch v.Op {
|
||||
case ssa.OpARM64MOVDloadidx8, ssa.OpARM64MOVDstoreidx8, ssa.OpARM64MOVDstorezeroidx8,
|
||||
ssa.OpARM64FMOVDloadidx8, ssa.OpARM64FMOVDstoreidx8:
|
||||
mop.Index = arm64.REG_LSL | 3<<5 | idx&31
|
||||
mop.Index = arm64.REG_LSL | 3<<5 | v.Args[1].Reg()&31
|
||||
case ssa.OpARM64MOVWloadidx4, ssa.OpARM64MOVWUloadidx4, ssa.OpARM64MOVWstoreidx4, ssa.OpARM64MOVWstorezeroidx4,
|
||||
ssa.OpARM64FMOVSloadidx4, ssa.OpARM64FMOVSstoreidx4:
|
||||
mop.Index = arm64.REG_LSL | 2<<5 | idx&31
|
||||
mop.Index = arm64.REG_LSL | 2<<5 | v.Args[1].Reg()&31
|
||||
case ssa.OpARM64MOVHloadidx2, ssa.OpARM64MOVHUloadidx2, ssa.OpARM64MOVHstoreidx2, ssa.OpARM64MOVHstorezeroidx2:
|
||||
mop.Index = arm64.REG_LSL | 1<<5 | idx&31
|
||||
mop.Index = arm64.REG_LSL | 1<<5 | v.Args[1].Reg()&31
|
||||
default: // not shifted
|
||||
mop.Index = idx
|
||||
mop.Index = v.Args[1].Reg()
|
||||
}
|
||||
return mop
|
||||
}
|
||||
@@ -466,7 +465,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||
ssa.OpARM64FMOVDloadidx8,
|
||||
ssa.OpARM64FMOVSloadidx4:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From = genIndexedOperand(v.Op, v.Args[0].Reg(), v.Args[1].Reg())
|
||||
p.From = genIndexedOperand(v)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpARM64LDAR,
|
||||
@@ -505,7 +504,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||
ssa.OpARM64MOVDstoreidx8,
|
||||
ssa.OpARM64FMOVDstoreidx8:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.To = genIndexedOperand(v.Op, v.Args[0].Reg(), v.Args[1].Reg())
|
||||
p.To = genIndexedOperand(v)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = v.Args[2].Reg()
|
||||
case ssa.OpARM64STP:
|
||||
@@ -534,7 +533,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||
ssa.OpARM64MOVWstorezeroidx4,
|
||||
ssa.OpARM64MOVDstorezeroidx8:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.To = genIndexedOperand(v.Op, v.Args[0].Reg(), v.Args[1].Reg())
|
||||
p.To = genIndexedOperand(v)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = arm64.REGZERO
|
||||
case ssa.OpARM64MOVQstorezero:
|
||||
@@ -1326,20 +1325,6 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
|
||||
s.CombJump(b, next, &leJumps)
|
||||
case ssa.BlockARM64GTnoov:
|
||||
s.CombJump(b, next, >Jumps)
|
||||
|
||||
case ssa.BlockARM64JUMPTABLE:
|
||||
// MOVD (TABLE)(IDX<<3), Rtmp
|
||||
// JMP (Rtmp)
|
||||
p := s.Prog(arm64.AMOVD)
|
||||
p.From = genIndexedOperand(ssa.OpARM64MOVDloadidx8, b.Controls[1].Reg(), b.Controls[0].Reg())
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = arm64.REGTMP
|
||||
p = s.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = arm64.REGTMP
|
||||
// Save jump tables for later resolution of the target blocks.
|
||||
s.JumpTables = append(s.JumpTables, b)
|
||||
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
|
||||
@@ -70,7 +70,6 @@ var NoInstrumentPkgs = []string{
|
||||
"runtime/msan",
|
||||
"runtime/asan",
|
||||
"internal/cpu",
|
||||
"buildcfg",
|
||||
}
|
||||
|
||||
// Don't insert racefuncenter/racefuncexit into the following packages.
|
||||
|
||||
@@ -31,7 +31,6 @@ type DebugFlags struct {
|
||||
LocationLists int `help:"print information about DWARF location list creation"`
|
||||
Nil int `help:"print information about nil checks"`
|
||||
NoOpenDefer int `help:"disable open-coded defers"`
|
||||
NoRefName int `help:"do not include referenced symbol names in object file"`
|
||||
PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"`
|
||||
Panic int `help:"show all compiler panics"`
|
||||
Slice int `help:"print information about slice compilation"`
|
||||
|
||||
@@ -192,7 +192,6 @@ func ParseFlags() {
|
||||
Ctxt.Flag_optimize = Flag.N == 0
|
||||
Ctxt.Debugasm = int(Flag.S)
|
||||
Ctxt.Flag_maymorestack = Debug.MayMoreStack
|
||||
Ctxt.Flag_noRefName = Debug.NoRefName != 0
|
||||
|
||||
if flag.NArg() < 1 {
|
||||
usage()
|
||||
|
||||
@@ -7,7 +7,6 @@ package escape
|
||||
import (
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/typecheck"
|
||||
"cmd/compile/internal/types"
|
||||
)
|
||||
|
||||
func isSliceSelfAssign(dst, src ir.Node) bool {
|
||||
@@ -186,16 +185,10 @@ func HeapAllocReason(n ir.Node) string {
|
||||
if n.Type().Size() > ir.MaxStackVarSize {
|
||||
return "too large for stack"
|
||||
}
|
||||
if n.Type().Alignment() > int64(types.PtrSize) {
|
||||
return "too aligned for stack"
|
||||
}
|
||||
|
||||
if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Size() > ir.MaxImplicitStackVarSize {
|
||||
return "too large for stack"
|
||||
}
|
||||
if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Alignment() > int64(types.PtrSize) {
|
||||
return "too aligned for stack"
|
||||
}
|
||||
|
||||
if n.Op() == ir.OCLOSURE && typecheck.ClosureType(n.(*ir.ClosureExpr)).Size() > ir.MaxImplicitStackVarSize {
|
||||
return "too large for stack"
|
||||
|
||||
@@ -70,10 +70,8 @@ func Main(archInit func(*ssagen.ArchInfo)) {
|
||||
// See bugs 31188 and 21945 (CLs 170638, 98075, 72371).
|
||||
base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin
|
||||
|
||||
base.DebugSSA = ssa.PhaseOption
|
||||
base.ParseFlags()
|
||||
|
||||
types.LocalPkg = types.NewPkg(base.Ctxt.Pkgpath, "")
|
||||
types.LocalPkg = types.NewPkg("", "")
|
||||
types.LocalPkg.Prefix = "\"\""
|
||||
|
||||
// We won't know localpkg's height until after import
|
||||
// processing. In the mean time, set to MaxPkgHeight to ensure
|
||||
@@ -102,6 +100,9 @@ func Main(archInit func(*ssagen.ArchInfo)) {
|
||||
// pseudo-package used for methods with anonymous receivers
|
||||
ir.Pkgs.Go = types.NewPkg("go", "")
|
||||
|
||||
base.DebugSSA = ssa.PhaseOption
|
||||
base.ParseFlags()
|
||||
|
||||
// Record flags that affect the build result. (And don't
|
||||
// record flags that don't, since that would cause spurious
|
||||
// changes in the binary.)
|
||||
@@ -139,7 +140,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
|
||||
|
||||
types.ParseLangFlag()
|
||||
|
||||
symABIs := ssagen.NewSymABIs()
|
||||
symABIs := ssagen.NewSymABIs(base.Ctxt.Pkgpath)
|
||||
if base.Flag.SymABIs != "" {
|
||||
symABIs.ReadSymABIs(base.Flag.SymABIs)
|
||||
}
|
||||
@@ -187,14 +188,8 @@ func Main(archInit func(*ssagen.ArchInfo)) {
|
||||
|
||||
// Parse and typecheck input.
|
||||
noder.LoadPackage(flag.Args())
|
||||
|
||||
// As a convenience to users (toolchain maintainers, in particular),
|
||||
// when compiling a package named "main", we default the package
|
||||
// path to "main" if the -p flag was not specified.
|
||||
if base.Ctxt.Pkgpath == obj.UnlinkablePkg && types.LocalPkg.Name == "main" {
|
||||
base.Ctxt.Pkgpath = "main"
|
||||
types.LocalPkg.Path = "main"
|
||||
types.LocalPkg.Prefix = "main"
|
||||
}
|
||||
|
||||
dwarfgen.RecordPackageName()
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/noder"
|
||||
"cmd/compile/internal/objw"
|
||||
"cmd/compile/internal/pkginit"
|
||||
"cmd/compile/internal/reflectdata"
|
||||
"cmd/compile/internal/staticdata"
|
||||
"cmd/compile/internal/typecheck"
|
||||
@@ -20,7 +19,6 @@ import (
|
||||
"cmd/internal/objabi"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// These modes say which kind of object file to generate.
|
||||
@@ -112,6 +110,7 @@ func dumpCompilerObj(bout *bio.Writer) {
|
||||
func dumpdata() {
|
||||
numExterns := len(typecheck.Target.Externs)
|
||||
numDecls := len(typecheck.Target.Decls)
|
||||
|
||||
dumpglobls(typecheck.Target.Externs)
|
||||
reflectdata.CollectPTabs()
|
||||
numExports := len(typecheck.Target.Exports)
|
||||
@@ -280,17 +279,6 @@ func addGCLocals() {
|
||||
|
||||
func ggloblnod(nam *ir.Name) {
|
||||
s := nam.Linksym()
|
||||
|
||||
// main_inittask and runtime_inittask in package runtime (and in
|
||||
// test/initempty.go) aren't real variable declarations, but
|
||||
// linknamed variables pointing to the compiler's generated
|
||||
// .inittask symbol. The real symbol was already written out in
|
||||
// pkginit.Task, so we need to avoid writing them out a second time
|
||||
// here, otherwise base.Ctxt.Globl will fail.
|
||||
if strings.HasSuffix(s.Name, "..inittask") && s.OnList() {
|
||||
return
|
||||
}
|
||||
|
||||
s.Gotype = reflectdata.TypeLinksym(nam.Type())
|
||||
flags := 0
|
||||
if nam.Readonly() {
|
||||
@@ -299,22 +287,9 @@ func ggloblnod(nam *ir.Name) {
|
||||
if nam.Type() != nil && !nam.Type().HasPointers() {
|
||||
flags |= obj.NOPTR
|
||||
}
|
||||
size := nam.Type().Size()
|
||||
linkname := nam.Sym().Linkname
|
||||
name := nam.Sym().Name
|
||||
|
||||
// We've skipped linkname'd globals's instrument, so we can skip them here as well.
|
||||
if base.Flag.ASan && linkname == "" && pkginit.InstrumentGlobalsMap[name] != nil {
|
||||
// Write the new size of instrumented global variables that have
|
||||
// trailing redzones into object file.
|
||||
rzSize := pkginit.GetRedzoneSizeForGlobal(size)
|
||||
sizeWithRZ := rzSize + size
|
||||
base.Ctxt.Globl(s, sizeWithRZ, flags)
|
||||
} else {
|
||||
base.Ctxt.Globl(s, size, flags)
|
||||
}
|
||||
if nam.Libfuzzer8BitCounter() {
|
||||
s.Type = objabi.SLIBFUZZER_8BIT_COUNTER
|
||||
base.Ctxt.Globl(s, nam.Type().Size(), flags)
|
||||
if nam.LibfuzzerExtraCounter() {
|
||||
s.Type = objabi.SLIBFUZZER_EXTRA_COUNTER
|
||||
}
|
||||
if nam.Sym().Linkname != "" {
|
||||
// Make sure linkname'd symbol is non-package. When a symbol is
|
||||
|
||||
@@ -44,7 +44,7 @@ func compile(t *testing.T, dirname, filename, outdirname string) string {
|
||||
}
|
||||
basename := filepath.Base(filename)
|
||||
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p", strings.TrimSuffix(outname, ".o"), "-o", outname, filename)
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-o", outname, filename)
|
||||
cmd.Dir = dirname
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"cmd/compile/internal/types2"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"internal/pkgbits"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -139,14 +138,12 @@ type anyType struct{}
|
||||
func (t anyType) Underlying() types2.Type { return t }
|
||||
func (t anyType) String() string { return "any" }
|
||||
|
||||
// See cmd/compile/internal/noder.derivedInfo.
|
||||
type derivedInfo struct {
|
||||
idx pkgbits.Index
|
||||
idx int
|
||||
needed bool
|
||||
}
|
||||
|
||||
// See cmd/compile/internal/noder.typeInfo.
|
||||
type typeInfo struct {
|
||||
idx pkgbits.Index
|
||||
idx int
|
||||
derived bool
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ type readerTypeBound struct {
|
||||
boundIdx int
|
||||
}
|
||||
|
||||
func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
|
||||
func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx int, marker pkgbits.SyncMarker) *reader {
|
||||
return &reader{
|
||||
Decoder: pr.NewDecoder(k, idx, marker),
|
||||
p: pr,
|
||||
@@ -104,7 +104,7 @@ func (r *reader) posBase() *syntax.PosBase {
|
||||
return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase))
|
||||
}
|
||||
|
||||
func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *syntax.PosBase {
|
||||
func (pr *pkgReader) posBaseIdx(idx int) *syntax.PosBase {
|
||||
if b := pr.posBases[idx]; b != nil {
|
||||
return b
|
||||
}
|
||||
@@ -134,7 +134,7 @@ func (r *reader) pkg() *types2.Package {
|
||||
return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg))
|
||||
}
|
||||
|
||||
func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types2.Package {
|
||||
func (pr *pkgReader) pkgIdx(idx int) *types2.Package {
|
||||
// TODO(mdempsky): Consider using some non-nil pointer to indicate
|
||||
// the universe scope, so we don't need to keep re-reading it.
|
||||
if pkg := pr.pkgs[idx]; pkg != nil {
|
||||
@@ -148,13 +148,11 @@ func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types2.Package {
|
||||
|
||||
func (r *reader) doPkg() *types2.Package {
|
||||
path := r.String()
|
||||
switch path {
|
||||
case "":
|
||||
path = r.p.PkgPath()
|
||||
case "builtin":
|
||||
if path == "builtin" {
|
||||
return nil // universe
|
||||
case "unsafe":
|
||||
return types2.Unsafe
|
||||
}
|
||||
if path == "" {
|
||||
path = r.p.PkgPath()
|
||||
}
|
||||
|
||||
if pkg := r.p.imports[path]; pkg != nil {
|
||||
@@ -187,7 +185,7 @@ func (r *reader) typ() types2.Type {
|
||||
func (r *reader) typInfo() typeInfo {
|
||||
r.Sync(pkgbits.SyncType)
|
||||
if r.Bool() {
|
||||
return typeInfo{idx: pkgbits.Index(r.Len()), derived: true}
|
||||
return typeInfo{idx: r.Len(), derived: true}
|
||||
}
|
||||
return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false}
|
||||
}
|
||||
@@ -364,7 +362,7 @@ func (r *reader) obj() (types2.Object, []types2.Type) {
|
||||
return obj, targs
|
||||
}
|
||||
|
||||
func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
|
||||
func (pr *pkgReader) objIdx(idx int) (*types2.Package, string) {
|
||||
rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
|
||||
|
||||
objPkg, objName := rname.qualifiedIdent()
|
||||
@@ -373,7 +371,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
|
||||
tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
|
||||
|
||||
if tag == pkgbits.ObjStub {
|
||||
base.Assertf(objPkg == nil || objPkg == types2.Unsafe, "unexpected stub package: %v", objPkg)
|
||||
assert(objPkg == nil || objPkg == types2.Unsafe)
|
||||
return objPkg, objName
|
||||
}
|
||||
|
||||
@@ -434,7 +432,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
|
||||
return objPkg, objName
|
||||
}
|
||||
|
||||
func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
|
||||
func (pr *pkgReader) objDictIdx(idx int) *readerDict {
|
||||
r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
|
||||
|
||||
var dict readerDict
|
||||
|
||||
@@ -483,6 +483,10 @@ func inlcopy(n ir.Node) ir.Node {
|
||||
newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), oldfn.Nname.Sym())
|
||||
// XXX OK to share fn.Type() ??
|
||||
newfn.Nname.SetType(oldfn.Nname.Type())
|
||||
// Ntype can be nil for -G=3 mode.
|
||||
if oldfn.Nname.Ntype != nil {
|
||||
newfn.Nname.Ntype = inlcopy(oldfn.Nname.Ntype).(ir.Ntype)
|
||||
}
|
||||
newfn.Body = inlcopylist(oldfn.Body)
|
||||
// Make shallow copy of the Dcl and ClosureVar slices
|
||||
newfn.Dcl = append([]*ir.Name(nil), oldfn.Dcl...)
|
||||
@@ -701,36 +705,17 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
|
||||
// apparent when we first created the instantiation of the generic function.
|
||||
// We can't handle this if we actually do the inlining, since we want to know
|
||||
// all interface conversions immediately after stenciling. So, we avoid
|
||||
// inlining in this case, see issue #49309. (1)
|
||||
//
|
||||
// See discussion on go.dev/cl/406475 for more background.
|
||||
if !fn.Type().Params().HasShape() {
|
||||
// inlining in this case. See #49309.
|
||||
if !fn.Type().HasShape() {
|
||||
for _, arg := range n.Args {
|
||||
if arg.Type().HasShape() {
|
||||
if logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc),
|
||||
fmt.Sprintf("inlining function %v has no-shape params with shape args", ir.FuncName(fn)))
|
||||
fmt.Sprintf("inlining non-shape function %v with shape args", ir.FuncName(fn)))
|
||||
}
|
||||
return n
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Don't inline a function fn that has shape parameters, but is passed no shape arg.
|
||||
// See comments (1) above, and issue #51909.
|
||||
inlineable := len(n.Args) == 0 // Function has shape in type, with no arguments can always be inlined.
|
||||
for _, arg := range n.Args {
|
||||
if arg.Type().HasShape() {
|
||||
inlineable = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !inlineable {
|
||||
if logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc),
|
||||
fmt.Sprintf("inlining function %v has shape params with no-shape args", ir.FuncName(fn)))
|
||||
}
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) {
|
||||
@@ -949,6 +934,10 @@ func oldInline(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr
|
||||
lab := ir.NewLabelStmt(base.Pos, retlabel)
|
||||
body = append(body, lab)
|
||||
|
||||
if !typecheck.Go117ExportTypes {
|
||||
typecheck.Stmts(body)
|
||||
}
|
||||
|
||||
if base.Flag.GenDwarfInl > 0 {
|
||||
for _, v := range inlfvars {
|
||||
v.SetPos(subst.updatedPos(v.Pos()))
|
||||
@@ -1148,6 +1137,11 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node {
|
||||
oldfn := n.Func
|
||||
newfn := ir.NewClosureFunc(oldfn.Pos(), true)
|
||||
|
||||
// Ntype can be nil for -G=3 mode.
|
||||
if oldfn.Nname.Ntype != nil {
|
||||
newfn.Nname.Ntype = subst.node(oldfn.Nname.Ntype).(ir.Ntype)
|
||||
}
|
||||
|
||||
if subst.newclofn != nil {
|
||||
//fmt.Printf("Inlining a closure with a nested closure\n")
|
||||
}
|
||||
|
||||
@@ -191,6 +191,7 @@ type ClosureExpr struct {
|
||||
type CompLitExpr struct {
|
||||
miniExpr
|
||||
origNode
|
||||
Ntype Ntype
|
||||
List Nodes // initialized values
|
||||
Prealloc *Name
|
||||
// For OSLICELIT, Len is the backing array length.
|
||||
@@ -199,13 +200,11 @@ type CompLitExpr struct {
|
||||
Len int64
|
||||
}
|
||||
|
||||
func NewCompLitExpr(pos src.XPos, op Op, typ *types.Type, list []Node) *CompLitExpr {
|
||||
n := &CompLitExpr{List: list}
|
||||
func NewCompLitExpr(pos src.XPos, op Op, typ Ntype, list []Node) *CompLitExpr {
|
||||
n := &CompLitExpr{Ntype: typ}
|
||||
n.pos = pos
|
||||
n.SetOp(op)
|
||||
if typ != nil {
|
||||
n.SetType(typ)
|
||||
}
|
||||
n.List = list
|
||||
n.orig = n
|
||||
return n
|
||||
}
|
||||
@@ -409,6 +408,7 @@ func (n *MakeExpr) SetOp(op Op) {
|
||||
// (It may be copied and assigned a type, though.)
|
||||
type NilExpr struct {
|
||||
miniExpr
|
||||
Sym_ *types.Sym // TODO: Remove
|
||||
}
|
||||
|
||||
func NewNilExpr(pos src.XPos) *NilExpr {
|
||||
@@ -418,6 +418,9 @@ func NewNilExpr(pos src.XPos) *NilExpr {
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *NilExpr) Sym() *types.Sym { return n.Sym_ }
|
||||
func (n *NilExpr) SetSym(x *types.Sym) { n.Sym_ = x }
|
||||
|
||||
// A ParenExpr is a parenthesized expression (X).
|
||||
// It may end up being a value or a type.
|
||||
type ParenExpr struct {
|
||||
@@ -435,6 +438,16 @@ func NewParenExpr(pos src.XPos, x Node) *ParenExpr {
|
||||
func (n *ParenExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
|
||||
func (n *ParenExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
|
||||
|
||||
func (*ParenExpr) CanBeNtype() {}
|
||||
|
||||
// SetOTYPE changes n to be an OTYPE node returning t,
|
||||
// like all the type nodes in type.go.
|
||||
func (n *ParenExpr) SetOTYPE(t *types.Type) {
|
||||
n.op = OTYPE
|
||||
n.typ = t
|
||||
t.SetNod(n)
|
||||
}
|
||||
|
||||
// A RawOrigExpr represents an arbitrary Go expression as a string value.
|
||||
// When printed in diagnostics, the string value is written out exactly as-is.
|
||||
type RawOrigExpr struct {
|
||||
@@ -544,6 +557,10 @@ func (n *SelectorExpr) FuncName() *Name {
|
||||
return fn
|
||||
}
|
||||
|
||||
// Before type-checking, bytes.Buffer is a SelectorExpr.
|
||||
// After type-checking it becomes a Name.
|
||||
func (*SelectorExpr) CanBeNtype() {}
|
||||
|
||||
// A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
|
||||
type SliceExpr struct {
|
||||
miniExpr
|
||||
@@ -615,24 +632,33 @@ func NewStarExpr(pos src.XPos, x Node) *StarExpr {
|
||||
func (n *StarExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
|
||||
func (n *StarExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
|
||||
|
||||
func (*StarExpr) CanBeNtype() {}
|
||||
|
||||
// SetOTYPE changes n to be an OTYPE node returning t,
|
||||
// like all the type nodes in type.go.
|
||||
func (n *StarExpr) SetOTYPE(t *types.Type) {
|
||||
n.op = OTYPE
|
||||
n.X = nil
|
||||
n.typ = t
|
||||
t.SetNod(n)
|
||||
}
|
||||
|
||||
// A TypeAssertionExpr is a selector expression X.(Type).
|
||||
// Before type-checking, the type is Ntype.
|
||||
type TypeAssertExpr struct {
|
||||
miniExpr
|
||||
X Node
|
||||
X Node
|
||||
Ntype Ntype
|
||||
|
||||
// Runtime type information provided by walkDotType for
|
||||
// assertions from non-empty interface to concrete type.
|
||||
ITab *AddrExpr `mknode:"-"` // *runtime.itab for Type implementing X's type
|
||||
Itab *AddrExpr `mknode:"-"` // *runtime.itab for Type implementing X's type
|
||||
}
|
||||
|
||||
func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr {
|
||||
n := &TypeAssertExpr{X: x}
|
||||
func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr {
|
||||
n := &TypeAssertExpr{X: x, Ntype: typ}
|
||||
n.pos = pos
|
||||
n.op = ODOTTYPE
|
||||
if typ != nil {
|
||||
n.SetType(typ)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@@ -645,29 +671,24 @@ func (n *TypeAssertExpr) SetOp(op Op) {
|
||||
}
|
||||
}
|
||||
|
||||
// A DynamicTypeAssertExpr asserts that X is of dynamic type RType.
|
||||
// A DynamicTypeAssertExpr asserts that X is of dynamic type T.
|
||||
type DynamicTypeAssertExpr struct {
|
||||
miniExpr
|
||||
X Node
|
||||
|
||||
// RType is an expression that yields a *runtime._type value
|
||||
// representing the asserted type.
|
||||
//
|
||||
// BUG(mdempsky): If ITab is non-nil, RType may be nil.
|
||||
RType Node
|
||||
|
||||
// ITab is an expression that yields a *runtime.itab value
|
||||
// representing the asserted type within the assertee expression's
|
||||
// original interface type.
|
||||
//
|
||||
// ITab is only used for assertions from non-empty interface type to
|
||||
// a concrete (i.e., non-interface) type. For all other assertions,
|
||||
// ITab is nil.
|
||||
ITab Node
|
||||
// N = not an interface
|
||||
// E = empty interface
|
||||
// I = nonempty interface
|
||||
// For E->N, T is a *runtime.type for N
|
||||
// For I->N, T is a *runtime.itab for N+I
|
||||
// For E->I, T is a *runtime.type for I
|
||||
// For I->I, ditto
|
||||
// For I->E, T is a *runtime.type for interface{} (unnecessary, but just to fill in the slot)
|
||||
// For E->E, ditto
|
||||
T Node
|
||||
}
|
||||
|
||||
func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, rtype Node) *DynamicTypeAssertExpr {
|
||||
n := &DynamicTypeAssertExpr{X: x, RType: rtype}
|
||||
func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, t Node) *DynamicTypeAssertExpr {
|
||||
n := &DynamicTypeAssertExpr{X: x, T: t}
|
||||
n.pos = pos
|
||||
n.op = op
|
||||
return n
|
||||
@@ -717,10 +738,10 @@ func (n *InstExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
|
||||
type InstExpr struct {
|
||||
miniExpr
|
||||
X Node
|
||||
Targs []Ntype
|
||||
Targs []Node
|
||||
}
|
||||
|
||||
func NewInstExpr(pos src.XPos, op Op, x Node, targs []Ntype) *InstExpr {
|
||||
func NewInstExpr(pos src.XPos, op Op, x Node, targs []Node) *InstExpr {
|
||||
n := &InstExpr{X: x, Targs: targs}
|
||||
n.pos = pos
|
||||
n.op = op
|
||||
|
||||
@@ -210,6 +210,7 @@ var OpPrec = []int{
|
||||
OSTR2BYTES: 8,
|
||||
OSTR2RUNES: 8,
|
||||
OSTRUCTLIT: 8,
|
||||
OTFUNC: 8,
|
||||
OTYPE: 8,
|
||||
OUNSAFEADD: 8,
|
||||
OUNSAFESLICE: 8,
|
||||
@@ -644,6 +645,9 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||
}
|
||||
fmt.Fprintf(s, "%v", n.Type())
|
||||
|
||||
case OTFUNC:
|
||||
fmt.Fprint(s, "<func>")
|
||||
|
||||
case OCLOSURE:
|
||||
n := n.(*ClosureExpr)
|
||||
if !exportFormat {
|
||||
@@ -663,10 +667,15 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||
fmt.Fprintf(s, "%v{%s}", typ, ellipsisIf(len(n.List) != 0))
|
||||
return
|
||||
}
|
||||
if n.Ntype != nil {
|
||||
fmt.Fprintf(s, "%v{%s}", n.Ntype, ellipsisIf(len(n.List) != 0))
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprint(s, "composite literal")
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(s, "(%v{ %.v })", n.Type(), n.List)
|
||||
fmt.Fprintf(s, "(%v{ %.v })", n.Ntype, n.List)
|
||||
|
||||
case OPTRLIT:
|
||||
n := n.(*AddrExpr)
|
||||
@@ -713,6 +722,10 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||
case ODOTTYPE, ODOTTYPE2:
|
||||
n := n.(*TypeAssertExpr)
|
||||
exprFmt(n.X, s, nprec)
|
||||
if n.Ntype != nil {
|
||||
fmt.Fprintf(s, ".(%v)", n.Ntype)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(s, ".(%v)", n.Type())
|
||||
|
||||
case OINDEX, OINDEXMAP:
|
||||
@@ -1125,6 +1138,11 @@ func dumpNode(w io.Writer, n Node, depth int) {
|
||||
fmt.Fprintf(w, "%+v", n.Op())
|
||||
}
|
||||
dumpNodeHeader(w, n)
|
||||
if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
|
||||
indent(w, depth)
|
||||
fmt.Fprintf(w, "%+v-ntype", n.Op())
|
||||
dumpNode(w, n.Name().Ntype, depth+1)
|
||||
}
|
||||
return
|
||||
|
||||
case OASOP:
|
||||
@@ -1135,6 +1153,11 @@ func dumpNode(w io.Writer, n Node, depth int) {
|
||||
case OTYPE:
|
||||
fmt.Fprintf(w, "%+v %+v", n.Op(), n.Sym())
|
||||
dumpNodeHeader(w, n)
|
||||
if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
|
||||
indent(w, depth)
|
||||
fmt.Fprintf(w, "%+v-ntype", n.Op())
|
||||
dumpNode(w, n.Name().Ntype, depth+1)
|
||||
}
|
||||
return
|
||||
|
||||
case OCLOSURE:
|
||||
|
||||
@@ -268,14 +268,14 @@ func PkgFuncName(f *Func) string {
|
||||
s := f.Sym()
|
||||
pkg := s.Pkg
|
||||
|
||||
// TODO(mdempsky): Remove after submitting CL 393715? This matches
|
||||
// how PkgFuncName has historically handled local functions, but
|
||||
// drchase points out it contradicts the documentation.
|
||||
if pkg == types.LocalPkg {
|
||||
p := base.Ctxt.Pkgpath
|
||||
if pkg != nil && pkg.Path != "" {
|
||||
p = pkg.Path
|
||||
}
|
||||
if p == "" {
|
||||
return s.Name
|
||||
}
|
||||
|
||||
return pkg.Path + "." + s.Name
|
||||
return p + "." + s.Name
|
||||
}
|
||||
|
||||
var CurFunc *Func
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user