chore: go mod vendor / tidy
This commit is contained in:
parent
a379b31a19
commit
b9f2d1f568
21
go.mod
21
go.mod
@ -4,11 +4,9 @@ go 1.22.7
|
|||||||
|
|
||||||
toolchain go1.23.1
|
toolchain go1.23.1
|
||||||
|
|
||||||
replace github.com/urfave/cli/v3 => github.com/urfave/cli/v3 v3.0.0-alpha9.1.0.20241019193437-5053ec708a44
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb
|
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb
|
||||||
git.coopcloud.tech/coop-cloud/godotenv v1.5.2-0.20231130100509-01bff8284355
|
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.7
|
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||||
github.com/charmbracelet/lipgloss v1.0.0
|
github.com/charmbracelet/lipgloss v1.0.0
|
||||||
github.com/charmbracelet/log v0.4.0
|
github.com/charmbracelet/log v0.4.0
|
||||||
@ -16,7 +14,7 @@ require (
|
|||||||
github.com/docker/cli v27.4.1+incompatible
|
github.com/docker/cli v27.4.1+incompatible
|
||||||
github.com/docker/docker v27.4.1+incompatible
|
github.com/docker/docker v27.4.1+incompatible
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
github.com/go-git/go-git/v5 v5.12.0
|
github.com/go-git/go-git/v5 v5.13.1
|
||||||
github.com/google/go-cmp v0.6.0
|
github.com/google/go-cmp v0.6.0
|
||||||
github.com/moby/sys/signal v0.7.1
|
github.com/moby/sys/signal v0.7.1
|
||||||
github.com/moby/term v0.5.0
|
github.com/moby/term v0.5.0
|
||||||
@ -30,7 +28,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
dario.cat/mergo v1.0.1 // indirect
|
dario.cat/mergo v1.0.1 // indirect
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.1.3 // indirect
|
github.com/ProtonMail/go-crypto v1.1.3 // indirect
|
||||||
@ -54,7 +52,7 @@ require (
|
|||||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.6.0 // indirect
|
github.com/go-git/go-billy/v5 v5.6.1 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
@ -77,6 +75,7 @@ require (
|
|||||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
github.com/mmcloughlin/avo v0.6.0 // indirect
|
||||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||||
github.com/moby/sys/user v0.3.0 // indirect
|
github.com/moby/sys/user v0.3.0 // indirect
|
||||||
@ -88,7 +87,7 @@ require (
|
|||||||
github.com/opencontainers/runc v1.1.13 // indirect
|
github.com/opencontainers/runc v1.1.13 // indirect
|
||||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.61.0 // indirect
|
github.com/prometheus/common v0.61.0 // indirect
|
||||||
@ -114,13 +113,15 @@ require (
|
|||||||
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
||||||
golang.org/x/crypto v0.31.0 // indirect
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
|
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 // indirect
|
||||||
|
golang.org/x/mod v0.22.0 // indirect
|
||||||
golang.org/x/net v0.33.0 // indirect
|
golang.org/x/net v0.33.0 // indirect
|
||||||
golang.org/x/sync v0.10.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
golang.org/x/text v0.21.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
golang.org/x/time v0.8.0 // indirect
|
golang.org/x/time v0.8.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8 // indirect
|
golang.org/x/tools v0.28.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
|
||||||
google.golang.org/grpc v1.69.2 // indirect
|
google.golang.org/grpc v1.69.2 // indirect
|
||||||
google.golang.org/protobuf v1.36.1 // indirect
|
google.golang.org/protobuf v1.36.1 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
30
go.sum
30
go.sum
@ -27,8 +27,8 @@ coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb/go.mod h1:ESVm0wQKcbcFi
|
|||||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
git.coopcloud.tech/coop-cloud/godotenv v1.5.2-0.20231130100509-01bff8284355 h1:tCv2B4qoN6RMheKDnCzIafOkWS5BB1h7hwhmo+9bVeE=
|
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c h1:oeKnUB79PKYD8D0/unYuu7MRcWryQQWOns8+JL+acrs=
|
||||||
git.coopcloud.tech/coop-cloud/godotenv v1.5.2-0.20231130100509-01bff8284355/go.mod h1:Q8V1zbtPAlzYSr/Dvky3wS6x58IQAl3rot2me1oSO2Q=
|
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c/go.mod h1:fQuhwrpg6qb9NlFXKYi/LysWu1wxjraS8sxyW12CUF0=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
||||||
@ -37,6 +37,8 @@ github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9mo
|
|||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||||
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
|
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
|
||||||
@ -131,6 +133,7 @@ github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq
|
|||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
@ -342,6 +345,7 @@ github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7Bv
|
|||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||||
|
github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ=
|
||||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
@ -374,14 +378,19 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
|||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||||
|
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||||
github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
|
github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
|
||||||
github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
|
github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
|
||||||
|
github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA=
|
||||||
|
github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||||
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
||||||
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
|
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
|
||||||
|
github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M=
|
||||||
|
github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
@ -519,6 +528,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de
|
|||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
|
||||||
@ -649,6 +659,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
|||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||||
|
github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY=
|
||||||
|
github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8=
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
@ -750,6 +762,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko
|
|||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||||
|
github.com/pjbgf/sha1cd v0.3.1 h1:Dh2GYdpJnO84lIw0LJwTFXjcNbasP/bklicSznyAaPI=
|
||||||
|
github.com/pjbgf/sha1cd v0.3.1/go.mod h1:Y8t7jSB/dEI/lQE04A1HVKteqjj9bX5O4+Cex0TCu8s=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
@ -804,6 +818,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
|||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
|
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
@ -990,6 +1005,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
|||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
|
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
|
||||||
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||||
|
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 h1:9kj3STMvgqy3YA4VQXBrN7925ICMxD5wzMRcgA30588=
|
||||||
|
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@ -1012,6 +1029,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||||
|
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -1224,6 +1243,8 @@ golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4X
|
|||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
|
||||||
|
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -1274,8 +1295,12 @@ google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7Fc
|
|||||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8 h1:st3LcW/BPi75W4q1jJTEor/QWwbNlPlDG0JTn6XhZu0=
|
google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8 h1:st3LcW/BPi75W4q1jJTEor/QWwbNlPlDG0JTn6XhZu0=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:klhJGKFyG8Tn50enBn7gizg4nXGXJ+jqEREdCWaPcV4=
|
google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:klhJGKFyG8Tn50enBn7gizg4nXGXJ+jqEREdCWaPcV4=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
@ -1351,6 +1376,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
|
18
vendor/github.com/Azure/go-ansiterm/osc_string_state.go
generated
vendored
18
vendor/github.com/Azure/go-ansiterm/osc_string_state.go
generated
vendored
@ -11,21 +11,13 @@ func (oscState oscStringState) Handle(b byte) (s state, e error) {
|
|||||||
return nextState, err
|
return nextState, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
// There are several control characters and sequences which can
|
||||||
case isOscStringTerminator(b):
|
// terminate an OSC string. Most of them are handled by the baseState
|
||||||
|
// handler. The ANSI_BEL character is a special case which behaves as a
|
||||||
|
// terminator only for an OSC string.
|
||||||
|
if b == ANSI_BEL {
|
||||||
return oscState.parser.ground, nil
|
return oscState.parser.ground, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return oscState, nil
|
return oscState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// See below for OSC string terminators for linux
|
|
||||||
// http://man7.org/linux/man-pages/man4/console_codes.4.html
|
|
||||||
func isOscStringTerminator(b byte) bool {
|
|
||||||
|
|
||||||
if b == ANSI_BEL || b == 0x5C {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
3
vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
generated
vendored
3
vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
generated
vendored
@ -11,7 +11,7 @@ compatibility status with go-git.
|
|||||||
| `init` | `--bare` | ✅ | | |
|
| `init` | `--bare` | ✅ | | |
|
||||||
| `init` | `--template` <br/> `--separate-git-dir` <br/> `--shared` | ❌ | | |
|
| `init` | `--template` <br/> `--separate-git-dir` <br/> `--shared` | ❌ | | |
|
||||||
| `clone` | | ✅ | | - [PlainClone](_examples/clone/main.go) |
|
| `clone` | | ✅ | | - [PlainClone](_examples/clone/main.go) |
|
||||||
| `clone` | Authentication: <br/> - none <br/> - access token <br/> - username + password <br/> - ssh | ✅ | | - [clone ssh](_examples/clone/auth/ssh/main.go) <br/> - [clone access token](_examples/clone/auth/basic/access_token/main.go) <br/> - [clone user + password](_examples/clone/auth/basic/username_password/main.go) |
|
| `clone` | Authentication: <br/> - none <br/> - access token <br/> - username + password <br/> - ssh | ✅ | | - [clone ssh (private_key)](_examples/clone/auth/ssh/private_key/main.go) <br/> - [clone ssh (ssh_agent)](_examples/clone/auth/ssh/ssh_agent/main.go) <br/> - [clone access token](_examples/clone/auth/basic/access_token/main.go) <br/> - [clone user + password](_examples/clone/auth/basic/username_password/main.go) |
|
||||||
| `clone` | `--progress` <br/> `--single-branch` <br/> `--depth` <br/> `--origin` <br/> `--recurse-submodules` <br/>`--shared` | ✅ | | - [recurse submodules](_examples/clone/main.go) <br/> - [progress](_examples/progress/main.go) |
|
| `clone` | `--progress` <br/> `--single-branch` <br/> `--depth` <br/> `--origin` <br/> `--recurse-submodules` <br/>`--shared` | ✅ | | - [recurse submodules](_examples/clone/main.go) <br/> - [progress](_examples/progress/main.go) |
|
||||||
|
|
||||||
## Basic snapshotting
|
## Basic snapshotting
|
||||||
@ -34,6 +34,7 @@ compatibility status with go-git.
|
|||||||
| `merge` | | ⚠️ (partial) | Fast-forward only | |
|
| `merge` | | ⚠️ (partial) | Fast-forward only | |
|
||||||
| `mergetool` | | ❌ | | |
|
| `mergetool` | | ❌ | | |
|
||||||
| `stash` | | ❌ | | |
|
| `stash` | | ❌ | | |
|
||||||
|
| `sparse-checkout` | | ✅ | | - [sparse-checkout](_examples/sparse-checkout/main.go) |
|
||||||
| `tag` | | ✅ | | - [tag](_examples/tag/main.go) <br/> - [tag create and push](_examples/tag-create-push/main.go) |
|
| `tag` | | ✅ | | - [tag](_examples/tag/main.go) <br/> - [tag create and push](_examples/tag-create-push/main.go) |
|
||||||
|
|
||||||
## Sharing and updating projects
|
## Sharing and updating projects
|
||||||
|
7
vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md
generated
vendored
7
vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md
generated
vendored
@ -31,6 +31,13 @@ In order for a PR to be accepted it needs to pass a list of requirements:
|
|||||||
- If the PR is a new feature, it has to come with a suite of unit tests, that tests the new functionality.
|
- If the PR is a new feature, it has to come with a suite of unit tests, that tests the new functionality.
|
||||||
- In any case, all the PRs have to pass the personal evaluation of at least one of the maintainers of go-git.
|
- In any case, all the PRs have to pass the personal evaluation of at least one of the maintainers of go-git.
|
||||||
|
|
||||||
|
### Branches
|
||||||
|
|
||||||
|
The `master` branch is currently used for maintaining the `v5` major release only. The accepted changes would
|
||||||
|
be dependency bumps, bug fixes and small changes that aren't needed for `v6`. New development should target the
|
||||||
|
`v6-exp` branch, and if agreed with at least one go-git maintainer, it can be back ported to `v5` by creating
|
||||||
|
a new PR that targets `master`.
|
||||||
|
|
||||||
### Format of the commit message
|
### Format of the commit message
|
||||||
|
|
||||||
Every commit message should describe what was changed, under which context and, if applicable, the GitHub issue it relates to:
|
Every commit message should describe what was changed, under which context and, if applicable, the GitHub issue it relates to:
|
||||||
|
13
vendor/github.com/go-git/go-git/v5/blame.go
generated
vendored
13
vendor/github.com/go-git/go-git/v5/blame.go
generated
vendored
@ -97,13 +97,10 @@ func Blame(c *object.Commit, path string) (*BlameResult, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if finished == true {
|
if finished {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
b.lineToCommit = make([]*object.Commit, finalLength)
|
b.lineToCommit = make([]*object.Commit, finalLength)
|
||||||
for i := range needsMap {
|
for i := range needsMap {
|
||||||
@ -309,8 +306,8 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
|
|||||||
for h := range hunks {
|
for h := range hunks {
|
||||||
hLines := countLines(hunks[h].Text)
|
hLines := countLines(hunks[h].Text)
|
||||||
for hl := 0; hl < hLines; hl++ {
|
for hl := 0; hl < hLines; hl++ {
|
||||||
switch {
|
switch hunks[h].Type {
|
||||||
case hunks[h].Type == diffmatchpatch.DiffEqual:
|
case diffmatchpatch.DiffEqual:
|
||||||
prevl++
|
prevl++
|
||||||
curl++
|
curl++
|
||||||
if curl == curItem.NeedsMap[need].Cur {
|
if curl == curItem.NeedsMap[need].Cur {
|
||||||
@ -322,7 +319,7 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
|
|||||||
break out
|
break out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case hunks[h].Type == diffmatchpatch.DiffInsert:
|
case diffmatchpatch.DiffInsert:
|
||||||
curl++
|
curl++
|
||||||
if curl == curItem.NeedsMap[need].Cur {
|
if curl == curItem.NeedsMap[need].Cur {
|
||||||
// the line we want is added, it may have been added here (or by another parent), skip it for now
|
// the line we want is added, it may have been added here (or by another parent), skip it for now
|
||||||
@ -331,7 +328,7 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
|
|||||||
break out
|
break out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case hunks[h].Type == diffmatchpatch.DiffDelete:
|
case diffmatchpatch.DiffDelete:
|
||||||
prevl += hLines
|
prevl += hLines
|
||||||
continue out
|
continue out
|
||||||
default:
|
default:
|
||||||
|
2
vendor/github.com/go-git/go-git/v5/config/config.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/config/config.go
generated
vendored
@ -252,6 +252,7 @@ const (
|
|||||||
extensionsSection = "extensions"
|
extensionsSection = "extensions"
|
||||||
fetchKey = "fetch"
|
fetchKey = "fetch"
|
||||||
urlKey = "url"
|
urlKey = "url"
|
||||||
|
pushurlKey = "pushurl"
|
||||||
bareKey = "bare"
|
bareKey = "bare"
|
||||||
worktreeKey = "worktree"
|
worktreeKey = "worktree"
|
||||||
commentCharKey = "commentChar"
|
commentCharKey = "commentChar"
|
||||||
@ -633,6 +634,7 @@ func (c *RemoteConfig) unmarshal(s *format.Subsection) error {
|
|||||||
|
|
||||||
c.Name = c.raw.Name
|
c.Name = c.raw.Name
|
||||||
c.URLs = append([]string(nil), c.raw.Options.GetAll(urlKey)...)
|
c.URLs = append([]string(nil), c.raw.Options.GetAll(urlKey)...)
|
||||||
|
c.URLs = append(c.URLs, c.raw.Options.GetAll(pushurlKey)...)
|
||||||
c.Fetch = fetch
|
c.Fetch = fetch
|
||||||
c.Mirror = c.raw.Options.Get(mirrorKey) == "true"
|
c.Mirror = c.raw.Options.Get(mirrorKey) == "true"
|
||||||
|
|
||||||
|
7
vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go
generated
vendored
7
vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go
generated
vendored
@ -43,6 +43,11 @@ func tokenizeExpression(ch rune, tokenType token, check runeCategoryValidator, r
|
|||||||
return tokenType, string(data), nil
|
return tokenType, string(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maxRevisionLength holds the maximum length that will be parsed for a
|
||||||
|
// revision. Git itself doesn't enforce a max length, but rather leans on
|
||||||
|
// the OS to enforce it via its ARG_MAX.
|
||||||
|
const maxRevisionLength = 128 * 1024 // 128kb
|
||||||
|
|
||||||
var zeroRune = rune(0)
|
var zeroRune = rune(0)
|
||||||
|
|
||||||
// scanner represents a lexical scanner.
|
// scanner represents a lexical scanner.
|
||||||
@ -52,7 +57,7 @@ type scanner struct {
|
|||||||
|
|
||||||
// newScanner returns a new instance of scanner.
|
// newScanner returns a new instance of scanner.
|
||||||
func newScanner(r io.Reader) *scanner {
|
func newScanner(r io.Reader) *scanner {
|
||||||
return &scanner{r: bufio.NewReader(r)}
|
return &scanner{r: bufio.NewReader(io.LimitReader(r, maxRevisionLength))}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan extracts tokens and their strings counterpart
|
// Scan extracts tokens and their strings counterpart
|
||||||
|
26
vendor/github.com/go-git/go-git/v5/options.go
generated
vendored
26
vendor/github.com/go-git/go-git/v5/options.go
generated
vendored
@ -416,6 +416,9 @@ type ResetOptions struct {
|
|||||||
// the index (resetting it to the tree of Commit) and the working tree
|
// the index (resetting it to the tree of Commit) and the working tree
|
||||||
// depending on Mode. If empty MixedReset is used.
|
// depending on Mode. If empty MixedReset is used.
|
||||||
Mode ResetMode
|
Mode ResetMode
|
||||||
|
// Files, if not empty will constrain the reseting the index to only files
|
||||||
|
// specified in this list.
|
||||||
|
Files []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields and sets the default values.
|
// Validate validates the fields and sets the default values.
|
||||||
@ -790,3 +793,26 @@ type PlainInitOptions struct {
|
|||||||
|
|
||||||
// Validate validates the fields and sets the default values.
|
// Validate validates the fields and sets the default values.
|
||||||
func (o *PlainInitOptions) Validate() error { return nil }
|
func (o *PlainInitOptions) Validate() error { return nil }
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNoRestorePaths = errors.New("you must specify path(s) to restore")
|
||||||
|
)
|
||||||
|
|
||||||
|
// RestoreOptions describes how a restore should be performed.
|
||||||
|
type RestoreOptions struct {
|
||||||
|
// Marks to restore the content in the index
|
||||||
|
Staged bool
|
||||||
|
// Marks to restore the content of the working tree
|
||||||
|
Worktree bool
|
||||||
|
// List of file paths that will be restored
|
||||||
|
Files []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates the fields and sets the default values.
|
||||||
|
func (o *RestoreOptions) Validate() error {
|
||||||
|
if len(o.Files) == 0 {
|
||||||
|
return ErrNoRestorePaths
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
4
vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
generated
vendored
@ -64,6 +64,10 @@ func ReadPatterns(fs billy.Filesystem, path []string) (ps []Pattern, err error)
|
|||||||
|
|
||||||
for _, fi := range fis {
|
for _, fi := range fis {
|
||||||
if fi.IsDir() && fi.Name() != gitDir {
|
if fi.IsDir() && fi.Name() != gitDir {
|
||||||
|
if NewMatcher(ps).Match(append(path, fi.Name()), true) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var subps []Pattern
|
var subps []Pattern
|
||||||
subps, err = ReadPatterns(fs, append(path, fi.Name()))
|
subps, err = ReadPatterns(fs, append(path, fi.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
115
vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
generated
vendored
115
vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
generated
vendored
@ -24,8 +24,8 @@ var (
|
|||||||
// ErrInvalidChecksum is returned by Decode if the SHA1 hash mismatch with
|
// ErrInvalidChecksum is returned by Decode if the SHA1 hash mismatch with
|
||||||
// the read content
|
// the read content
|
||||||
ErrInvalidChecksum = errors.New("invalid checksum")
|
ErrInvalidChecksum = errors.New("invalid checksum")
|
||||||
|
// ErrUnknownExtension is returned when an index extension is encountered that is considered mandatory
|
||||||
errUnknownExtension = errors.New("unknown extension")
|
ErrUnknownExtension = errors.New("unknown extension")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -39,6 +39,7 @@ const (
|
|||||||
|
|
||||||
// A Decoder reads and decodes index files from an input stream.
|
// A Decoder reads and decodes index files from an input stream.
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
|
buf *bufio.Reader
|
||||||
r io.Reader
|
r io.Reader
|
||||||
hash hash.Hash
|
hash hash.Hash
|
||||||
lastEntry *Entry
|
lastEntry *Entry
|
||||||
@ -49,8 +50,10 @@ type Decoder struct {
|
|||||||
// NewDecoder returns a new decoder that reads from r.
|
// NewDecoder returns a new decoder that reads from r.
|
||||||
func NewDecoder(r io.Reader) *Decoder {
|
func NewDecoder(r io.Reader) *Decoder {
|
||||||
h := hash.New(hash.CryptoType)
|
h := hash.New(hash.CryptoType)
|
||||||
|
buf := bufio.NewReader(r)
|
||||||
return &Decoder{
|
return &Decoder{
|
||||||
r: io.TeeReader(r, h),
|
buf: buf,
|
||||||
|
r: io.TeeReader(buf, h),
|
||||||
hash: h,
|
hash: h,
|
||||||
extReader: bufio.NewReader(nil),
|
extReader: bufio.NewReader(nil),
|
||||||
}
|
}
|
||||||
@ -210,71 +213,75 @@ func (d *Decoder) readExtensions(idx *Index) error {
|
|||||||
// count that they are not supported by jgit or libgit
|
// count that they are not supported by jgit or libgit
|
||||||
|
|
||||||
var expected []byte
|
var expected []byte
|
||||||
|
var peeked []byte
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
var header [4]byte
|
// we should always be able to peek for 4 bytes (header) + 4 bytes (extlen) + final hash
|
||||||
|
// if this fails, we know that we're at the end of the index
|
||||||
|
peekLen := 4 + 4 + d.hash.Size()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
expected = d.hash.Sum(nil)
|
expected = d.hash.Sum(nil)
|
||||||
|
peeked, err = d.buf.Peek(peekLen)
|
||||||
var n int
|
if len(peeked) < peekLen {
|
||||||
if n, err = io.ReadFull(d.r, header[:]); err != nil {
|
// there can't be an extension at this point, so let's bail out
|
||||||
if n == 0 {
|
|
||||||
err = io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
err = d.readExtension(idx, header[:])
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != errUnknownExtension {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return d.readChecksum(expected, header)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) readExtension(idx *Index, header []byte) error {
|
|
||||||
switch {
|
|
||||||
case bytes.Equal(header, treeExtSignature):
|
|
||||||
r, err := d.getExtensionReader()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = d.readExtension(idx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.readChecksum(expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) readExtension(idx *Index) error {
|
||||||
|
var header [4]byte
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(d.r, header[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := d.getExtensionReader()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case bytes.Equal(header[:], treeExtSignature):
|
||||||
idx.Cache = &Tree{}
|
idx.Cache = &Tree{}
|
||||||
d := &treeExtensionDecoder{r}
|
d := &treeExtensionDecoder{r}
|
||||||
if err := d.Decode(idx.Cache); err != nil {
|
if err := d.Decode(idx.Cache); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case bytes.Equal(header, resolveUndoExtSignature):
|
case bytes.Equal(header[:], resolveUndoExtSignature):
|
||||||
r, err := d.getExtensionReader()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
idx.ResolveUndo = &ResolveUndo{}
|
idx.ResolveUndo = &ResolveUndo{}
|
||||||
d := &resolveUndoDecoder{r}
|
d := &resolveUndoDecoder{r}
|
||||||
if err := d.Decode(idx.ResolveUndo); err != nil {
|
if err := d.Decode(idx.ResolveUndo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case bytes.Equal(header, endOfIndexEntryExtSignature):
|
case bytes.Equal(header[:], endOfIndexEntryExtSignature):
|
||||||
r, err := d.getExtensionReader()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
idx.EndOfIndexEntry = &EndOfIndexEntry{}
|
idx.EndOfIndexEntry = &EndOfIndexEntry{}
|
||||||
d := &endOfIndexEntryDecoder{r}
|
d := &endOfIndexEntryDecoder{r}
|
||||||
if err := d.Decode(idx.EndOfIndexEntry); err != nil {
|
if err := d.Decode(idx.EndOfIndexEntry); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return errUnknownExtension
|
// See https://git-scm.com/docs/index-format, which says:
|
||||||
|
// If the first byte is 'A'..'Z' the extension is optional and can be ignored.
|
||||||
|
if header[0] < 'A' || header[0] > 'Z' {
|
||||||
|
return ErrUnknownExtension
|
||||||
|
}
|
||||||
|
|
||||||
|
d := &unknownExtensionDecoder{r}
|
||||||
|
if err := d.Decode(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -290,11 +297,10 @@ func (d *Decoder) getExtensionReader() (*bufio.Reader, error) {
|
|||||||
return d.extReader, nil
|
return d.extReader, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) readChecksum(expected []byte, alreadyRead [4]byte) error {
|
func (d *Decoder) readChecksum(expected []byte) error {
|
||||||
var h plumbing.Hash
|
var h plumbing.Hash
|
||||||
copy(h[:4], alreadyRead[:])
|
|
||||||
|
|
||||||
if _, err := io.ReadFull(d.r, h[4:]); err != nil {
|
if _, err := io.ReadFull(d.r, h[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,3 +482,22 @@ func (d *endOfIndexEntryDecoder) Decode(e *EndOfIndexEntry) error {
|
|||||||
_, err = io.ReadFull(d.r, e.Hash[:])
|
_, err = io.ReadFull(d.r, e.Hash[:])
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type unknownExtensionDecoder struct {
|
||||||
|
r *bufio.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *unknownExtensionDecoder) Decode() error {
|
||||||
|
var buf [1024]byte
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, err := d.r.Read(buf[:])
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
94
vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go
generated
vendored
94
vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go
generated
vendored
@ -3,8 +3,11 @@ package index
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-git/go-git/v5/plumbing/hash"
|
"github.com/go-git/go-git/v5/plumbing/hash"
|
||||||
@ -13,7 +16,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// EncodeVersionSupported is the range of supported index versions
|
// EncodeVersionSupported is the range of supported index versions
|
||||||
EncodeVersionSupported uint32 = 3
|
EncodeVersionSupported uint32 = 4
|
||||||
|
|
||||||
// ErrInvalidTimestamp is returned by Encode if a Index with a Entry with
|
// ErrInvalidTimestamp is returned by Encode if a Index with a Entry with
|
||||||
// negative timestamp values
|
// negative timestamp values
|
||||||
@ -22,20 +25,25 @@ var (
|
|||||||
|
|
||||||
// An Encoder writes an Index to an output stream.
|
// An Encoder writes an Index to an output stream.
|
||||||
type Encoder struct {
|
type Encoder struct {
|
||||||
w io.Writer
|
w io.Writer
|
||||||
hash hash.Hash
|
hash hash.Hash
|
||||||
|
lastEntry *Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncoder returns a new encoder that writes to w.
|
// NewEncoder returns a new encoder that writes to w.
|
||||||
func NewEncoder(w io.Writer) *Encoder {
|
func NewEncoder(w io.Writer) *Encoder {
|
||||||
h := hash.New(hash.CryptoType)
|
h := hash.New(hash.CryptoType)
|
||||||
mw := io.MultiWriter(w, h)
|
mw := io.MultiWriter(w, h)
|
||||||
return &Encoder{mw, h}
|
return &Encoder{mw, h, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode writes the Index to the stream of the encoder.
|
// Encode writes the Index to the stream of the encoder.
|
||||||
func (e *Encoder) Encode(idx *Index) error {
|
func (e *Encoder) Encode(idx *Index) error {
|
||||||
// TODO: support v4
|
return e.encode(idx, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) encode(idx *Index, footer bool) error {
|
||||||
|
|
||||||
// TODO: support extensions
|
// TODO: support extensions
|
||||||
if idx.Version > EncodeVersionSupported {
|
if idx.Version > EncodeVersionSupported {
|
||||||
return ErrUnsupportedVersion
|
return ErrUnsupportedVersion
|
||||||
@ -49,7 +57,10 @@ func (e *Encoder) Encode(idx *Index) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.encodeFooter()
|
if footer {
|
||||||
|
return e.encodeFooter()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) encodeHeader(idx *Index) error {
|
func (e *Encoder) encodeHeader(idx *Index) error {
|
||||||
@ -64,7 +75,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
|
|||||||
sort.Sort(byName(idx.Entries))
|
sort.Sort(byName(idx.Entries))
|
||||||
|
|
||||||
for _, entry := range idx.Entries {
|
for _, entry := range idx.Entries {
|
||||||
if err := e.encodeEntry(entry); err != nil {
|
if err := e.encodeEntry(idx, entry); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
entryLength := entryHeaderLength
|
entryLength := entryHeaderLength
|
||||||
@ -73,7 +84,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wrote := entryLength + len(entry.Name)
|
wrote := entryLength + len(entry.Name)
|
||||||
if err := e.padEntry(wrote); err != nil {
|
if err := e.padEntry(idx, wrote); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,7 +92,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) encodeEntry(entry *Entry) error {
|
func (e *Encoder) encodeEntry(idx *Index, entry *Entry) error {
|
||||||
sec, nsec, err := e.timeToUint32(&entry.CreatedAt)
|
sec, nsec, err := e.timeToUint32(&entry.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -132,9 +143,68 @@ func (e *Encoder) encodeEntry(entry *Entry) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch idx.Version {
|
||||||
|
case 2, 3:
|
||||||
|
err = e.encodeEntryName(entry)
|
||||||
|
case 4:
|
||||||
|
err = e.encodeEntryNameV4(entry)
|
||||||
|
default:
|
||||||
|
err = ErrUnsupportedVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) encodeEntryName(entry *Entry) error {
|
||||||
return binary.Write(e.w, []byte(entry.Name))
|
return binary.Write(e.w, []byte(entry.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) encodeEntryNameV4(entry *Entry) error {
|
||||||
|
name := entry.Name
|
||||||
|
l := 0
|
||||||
|
if e.lastEntry != nil {
|
||||||
|
dir := path.Dir(e.lastEntry.Name) + "/"
|
||||||
|
if strings.HasPrefix(entry.Name, dir) {
|
||||||
|
l = len(e.lastEntry.Name) - len(dir)
|
||||||
|
name = strings.TrimPrefix(entry.Name, dir)
|
||||||
|
} else {
|
||||||
|
l = len(e.lastEntry.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.lastEntry = entry
|
||||||
|
|
||||||
|
err := binary.WriteVariableWidthInt(e.w, int64(l))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return binary.Write(e.w, []byte(name+string('\x00')))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) encodeRawExtension(signature string, data []byte) error {
|
||||||
|
if len(signature) != 4 {
|
||||||
|
return fmt.Errorf("invalid signature length")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := e.w.Write([]byte(signature))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = binary.WriteUint32(e.w, uint32(len(data)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = e.w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
|
func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
|
||||||
if t.IsZero() {
|
if t.IsZero() {
|
||||||
return 0, 0, nil
|
return 0, 0, nil
|
||||||
@ -147,7 +217,11 @@ func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
|
|||||||
return uint32(t.Unix()), uint32(t.Nanosecond()), nil
|
return uint32(t.Unix()), uint32(t.Nanosecond()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) padEntry(wrote int) error {
|
func (e *Encoder) padEntry(idx *Index, wrote int) error {
|
||||||
|
if idx.Version == 4 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
padLen := 8 - wrote%8
|
padLen := 8 - wrote%8
|
||||||
|
|
||||||
_, err := e.w.Write(bytes.Repeat([]byte{'\x00'}, padLen))
|
_, err := e.w.Write(bytes.Repeat([]byte{'\x00'}, padLen))
|
||||||
|
20
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go
generated
vendored
20
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go
generated
vendored
@ -32,19 +32,17 @@ func (idx *deltaIndex) findMatch(src, tgt []byte, tgtOffset int) (srcOffset, l i
|
|||||||
return 0, -1
|
return 0, -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tgt) >= tgtOffset+s && len(src) >= blksz {
|
h := hashBlock(tgt, tgtOffset)
|
||||||
h := hashBlock(tgt, tgtOffset)
|
tIdx := h & idx.mask
|
||||||
tIdx := h & idx.mask
|
eIdx := idx.table[tIdx]
|
||||||
eIdx := idx.table[tIdx]
|
if eIdx == 0 {
|
||||||
if eIdx != 0 {
|
return
|
||||||
srcOffset = idx.entries[eIdx]
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
l = matchLength(src, tgt, tgtOffset, srcOffset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srcOffset = idx.entries[eIdx]
|
||||||
|
|
||||||
|
l = matchLength(src, tgt, tgtOffset, srcOffset)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
generated
vendored
21
vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
generated
vendored
@ -26,6 +26,13 @@ var (
|
|||||||
const (
|
const (
|
||||||
payload = 0x7f // 0111 1111
|
payload = 0x7f // 0111 1111
|
||||||
continuation = 0x80 // 1000 0000
|
continuation = 0x80 // 1000 0000
|
||||||
|
|
||||||
|
// maxPatchPreemptionSize defines what is the max size of bytes to be
|
||||||
|
// premptively made available for a patch operation.
|
||||||
|
maxPatchPreemptionSize uint = 65536
|
||||||
|
|
||||||
|
// minDeltaSize defines the smallest size for a delta.
|
||||||
|
minDeltaSize = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
type offset struct {
|
type offset struct {
|
||||||
@ -86,9 +93,13 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PatchDelta returns the result of applying the modification deltas in delta to src.
|
// PatchDelta returns the result of applying the modification deltas in delta to src.
|
||||||
// An error will be returned if delta is corrupted (ErrDeltaLen) or an action command
|
// An error will be returned if delta is corrupted (ErrInvalidDelta) or an action command
|
||||||
// is not copy from source or copy from delta (ErrDeltaCmd).
|
// is not copy from source or copy from delta (ErrDeltaCmd).
|
||||||
func PatchDelta(src, delta []byte) ([]byte, error) {
|
func PatchDelta(src, delta []byte) ([]byte, error) {
|
||||||
|
if len(src) == 0 || len(delta) < minDeltaSize {
|
||||||
|
return nil, ErrInvalidDelta
|
||||||
|
}
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
if err := patchDelta(b, src, delta); err != nil {
|
if err := patchDelta(b, src, delta); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -239,7 +250,9 @@ func patchDelta(dst *bytes.Buffer, src, delta []byte) error {
|
|||||||
remainingTargetSz := targetSz
|
remainingTargetSz := targetSz
|
||||||
|
|
||||||
var cmd byte
|
var cmd byte
|
||||||
dst.Grow(int(targetSz))
|
|
||||||
|
growSz := min(targetSz, maxPatchPreemptionSize)
|
||||||
|
dst.Grow(int(growSz))
|
||||||
for {
|
for {
|
||||||
if len(delta) == 0 {
|
if len(delta) == 0 {
|
||||||
return ErrInvalidDelta
|
return ErrInvalidDelta
|
||||||
@ -403,6 +416,10 @@ func patchDeltaWriter(dst io.Writer, base io.ReaderAt, delta io.Reader,
|
|||||||
// This must be called twice on the delta data buffer, first to get the
|
// This must be called twice on the delta data buffer, first to get the
|
||||||
// expected source buffer size, and again to get the target buffer size.
|
// expected source buffer size, and again to get the target buffer size.
|
||||||
func decodeLEB128(input []byte) (uint, []byte) {
|
func decodeLEB128(input []byte) (uint, []byte) {
|
||||||
|
if len(input) == 0 {
|
||||||
|
return 0, input
|
||||||
|
}
|
||||||
|
|
||||||
var num, sz uint
|
var num, sz uint
|
||||||
var b byte
|
var b byte
|
||||||
for {
|
for {
|
||||||
|
2
vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go
generated
vendored
@ -140,6 +140,8 @@ func asciiHexToByte(b byte) (byte, error) {
|
|||||||
return b - '0', nil
|
return b - '0', nil
|
||||||
case b >= 'a' && b <= 'f':
|
case b >= 'a' && b <= 'f':
|
||||||
return b - 'a' + 10, nil
|
return b - 'a' + 10, nil
|
||||||
|
case b >= 'A' && b <= 'F':
|
||||||
|
return b - 'A' + 10, nil
|
||||||
default:
|
default:
|
||||||
return 0, ErrInvalidPktLen
|
return 0, ErrInvalidPktLen
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go
generated
vendored
1
vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go
generated
vendored
@ -19,6 +19,7 @@ var (
|
|||||||
// a PKCS#7 (S/MIME) signature.
|
// a PKCS#7 (S/MIME) signature.
|
||||||
x509SignatureFormat = signatureFormat{
|
x509SignatureFormat = signatureFormat{
|
||||||
[]byte("-----BEGIN CERTIFICATE-----"),
|
[]byte("-----BEGIN CERTIFICATE-----"),
|
||||||
|
[]byte("-----BEGIN SIGNED MESSAGE-----"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// sshSignatureFormat is the format of an SSH signature.
|
// sshSignatureFormat is the format of an SSH signature.
|
||||||
|
1
vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
generated
vendored
1
vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
generated
vendored
@ -295,6 +295,7 @@ func (s TreeEntrySorter) Swap(i, j int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Encode transforms a Tree into a plumbing.EncodedObject.
|
// Encode transforms a Tree into a plumbing.EncodedObject.
|
||||||
|
// The tree entries must be sorted by name.
|
||||||
func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
|
func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
|
||||||
o.SetType(plumbing.TreeObject)
|
o.SetType(plumbing.TreeObject)
|
||||||
w, err := o.Writer()
|
w, err := o.Writer()
|
||||||
|
76
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/filter.go
generated
vendored
Normal file
76
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/filter.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package packp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrUnsupportedObjectFilterType = errors.New("unsupported object filter type")
|
||||||
|
|
||||||
|
// Filter values enable the partial clone capability which causes
|
||||||
|
// the server to omit objects that match the filter.
|
||||||
|
//
|
||||||
|
// See [Git's documentation] for more details.
|
||||||
|
//
|
||||||
|
// [Git's documentation]: https://github.com/git/git/blob/e02ecfcc534e2021aae29077a958dd11c3897e4c/Documentation/rev-list-options.txt#L948
|
||||||
|
type Filter string
|
||||||
|
|
||||||
|
type BlobLimitPrefix string
|
||||||
|
|
||||||
|
const (
|
||||||
|
BlobLimitPrefixNone BlobLimitPrefix = ""
|
||||||
|
BlobLimitPrefixKibi BlobLimitPrefix = "k"
|
||||||
|
BlobLimitPrefixMebi BlobLimitPrefix = "m"
|
||||||
|
BlobLimitPrefixGibi BlobLimitPrefix = "g"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FilterBlobNone omits all blobs.
|
||||||
|
func FilterBlobNone() Filter {
|
||||||
|
return "blob:none"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterBlobLimit omits blobs of size at least n bytes (when prefix is
|
||||||
|
// BlobLimitPrefixNone), n kibibytes (when prefix is BlobLimitPrefixKibi),
|
||||||
|
// n mebibytes (when prefix is BlobLimitPrefixMebi) or n gibibytes (when
|
||||||
|
// prefix is BlobLimitPrefixGibi). n can be zero, in which case all blobs
|
||||||
|
// will be omitted.
|
||||||
|
func FilterBlobLimit(n uint64, prefix BlobLimitPrefix) Filter {
|
||||||
|
return Filter(fmt.Sprintf("blob:limit=%d%s", n, prefix))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterTreeDepth omits all blobs and trees whose depth from the root tree
|
||||||
|
// is larger or equal to depth.
|
||||||
|
func FilterTreeDepth(depth uint64) Filter {
|
||||||
|
return Filter(fmt.Sprintf("tree:%d", depth))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterObjectType omits all objects which are not of the requested type t.
|
||||||
|
// Supported types are TagObject, CommitObject, TreeObject and BlobObject.
|
||||||
|
func FilterObjectType(t plumbing.ObjectType) (Filter, error) {
|
||||||
|
switch t {
|
||||||
|
case plumbing.TagObject:
|
||||||
|
fallthrough
|
||||||
|
case plumbing.CommitObject:
|
||||||
|
fallthrough
|
||||||
|
case plumbing.TreeObject:
|
||||||
|
fallthrough
|
||||||
|
case plumbing.BlobObject:
|
||||||
|
return Filter(fmt.Sprintf("object:type=%s", t.String())), nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("%w: %s", ErrUnsupportedObjectFilterType, t.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterCombine combines multiple Filter values together.
|
||||||
|
func FilterCombine(filters ...Filter) Filter {
|
||||||
|
var escapedFilters []string
|
||||||
|
|
||||||
|
for _, filter := range filters {
|
||||||
|
escapedFilters = append(escapedFilters, url.QueryEscape(string(filter)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Filter(fmt.Sprintf("combine:%s", strings.Join(escapedFilters, "+")))
|
||||||
|
}
|
2
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go
generated
vendored
@ -114,7 +114,7 @@ func (d *Demuxer) nextPackData() ([]byte, error) {
|
|||||||
|
|
||||||
size := len(content)
|
size := len(content)
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return nil, nil
|
return nil, io.EOF
|
||||||
} else if size > d.max {
|
} else if size > d.max {
|
||||||
return nil, ErrMaxPackedExceeded
|
return nil, ErrMaxPackedExceeded
|
||||||
}
|
}
|
||||||
|
3
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go
generated
vendored
3
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go
generated
vendored
@ -120,6 +120,9 @@ func (r *ServerResponse) decodeACKLine(line []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp := bytes.Index(line, []byte(" "))
|
sp := bytes.Index(line, []byte(" "))
|
||||||
|
if sp+41 > len(line) {
|
||||||
|
return fmt.Errorf("malformed ACK %q", line)
|
||||||
|
}
|
||||||
h := plumbing.NewHash(string(line[sp+1 : sp+41]))
|
h := plumbing.NewHash(string(line[sp+1 : sp+41]))
|
||||||
r.ACKs = append(r.ACKs, h)
|
r.ACKs = append(r.ACKs, h)
|
||||||
return nil
|
return nil
|
||||||
|
1
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
generated
vendored
1
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
generated
vendored
@ -17,6 +17,7 @@ type UploadRequest struct {
|
|||||||
Wants []plumbing.Hash
|
Wants []plumbing.Hash
|
||||||
Shallows []plumbing.Hash
|
Shallows []plumbing.Hash
|
||||||
Depth Depth
|
Depth Depth
|
||||||
|
Filter Filter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depth values stores the desired depth of the requested packfile: see
|
// Depth values stores the desired depth of the requested packfile: see
|
||||||
|
11
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
generated
vendored
11
vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
generated
vendored
@ -132,6 +132,17 @@ func (e *ulReqEncoder) encodeDepth() stateFn {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return e.encodeFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ulReqEncoder) encodeFilter() stateFn {
|
||||||
|
if filter := e.data.Filter; filter != "" {
|
||||||
|
if err := e.pe.Encodef("filter %s\n", filter); err != nil {
|
||||||
|
e.err = fmt.Errorf("encoding filter %s: %s", filter, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return e.encodeFlush
|
return e.encodeFlush
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
vendor/github.com/go-git/go-git/v5/plumbing/reference.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/plumbing/reference.go
generated
vendored
@ -188,7 +188,7 @@ func (r ReferenceName) Validate() error {
|
|||||||
|
|
||||||
isBranch := r.IsBranch()
|
isBranch := r.IsBranch()
|
||||||
isTag := r.IsTag()
|
isTag := r.IsTag()
|
||||||
for _, part := range parts {
|
for i, part := range parts {
|
||||||
// rule 6
|
// rule 6
|
||||||
if len(part) == 0 {
|
if len(part) == 0 {
|
||||||
return ErrInvalidReferenceName
|
return ErrInvalidReferenceName
|
||||||
@ -205,7 +205,7 @@ func (r ReferenceName) Validate() error {
|
|||||||
return ErrInvalidReferenceName
|
return ErrInvalidReferenceName
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBranch || isTag) && strings.HasPrefix(part, "-") { // branches & tags can't start with -
|
if (isBranch || isTag) && strings.HasPrefix(part, "-") && (i == 2) { // branches & tags can't start with -
|
||||||
return ErrInvalidReferenceName
|
return ErrInvalidReferenceName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
generated
vendored
7
vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
generated
vendored
@ -19,6 +19,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -295,7 +296,11 @@ func parseFile(endpoint string) (*Endpoint, bool) {
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
path := endpoint
|
path, err := filepath.Abs(endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
return &Endpoint{
|
return &Endpoint{
|
||||||
Protocol: "file",
|
Protocol: "file",
|
||||||
Path: path,
|
Path: path,
|
||||||
|
19
vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
generated
vendored
19
vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
generated
vendored
@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||||
@ -95,7 +96,23 @@ func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.Auth
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &command{cmd: execabs.Command(cmd, ep.Path)}, nil
|
return &command{cmd: execabs.Command(cmd, adjustPathForWindows(ep.Path))}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDriveLetter(c byte) bool {
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
||||||
|
}
|
||||||
|
|
||||||
|
// On Windows, the path that results from a file: URL has a leading slash. This
|
||||||
|
// has to be removed if there's a drive letter
|
||||||
|
func adjustPathForWindows(p string) string {
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
if len(p) >= 3 && p[0] == '/' && isDriveLetter(p[1]) && p[2] == ':' {
|
||||||
|
return p[1:]
|
||||||
|
}
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
type command struct {
|
type command struct {
|
||||||
|
6
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
generated
vendored
6
vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
generated
vendored
@ -430,11 +430,11 @@ func NewErr(r *http.Response) error {
|
|||||||
|
|
||||||
switch r.StatusCode {
|
switch r.StatusCode {
|
||||||
case http.StatusUnauthorized:
|
case http.StatusUnauthorized:
|
||||||
return transport.ErrAuthenticationRequired
|
return fmt.Errorf("%w: %s", transport.ErrAuthenticationRequired, reason)
|
||||||
case http.StatusForbidden:
|
case http.StatusForbidden:
|
||||||
return transport.ErrAuthorizationFailed
|
return fmt.Errorf("%w: %s", transport.ErrAuthorizationFailed, reason)
|
||||||
case http.StatusNotFound:
|
case http.StatusNotFound:
|
||||||
return transport.ErrRepositoryNotFound
|
return fmt.Errorf("%w: %s", transport.ErrRepositoryNotFound, reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
return plumbing.NewUnexpectedError(&Err{r, reason})
|
return plumbing.NewUnexpectedError(&Err{r, reason})
|
||||||
|
12
vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go
generated
vendored
12
vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go
generated
vendored
@ -40,8 +40,16 @@ func (l *fsLoader) Load(ep *transport.Endpoint) (storer.Storer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fs.Stat("config"); err != nil {
|
var bare bool
|
||||||
return nil, transport.ErrRepositoryNotFound
|
if _, err := fs.Stat("config"); err == nil {
|
||||||
|
bare = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bare {
|
||||||
|
// do not use git.GitDirName due to import cycle
|
||||||
|
if _, err := fs.Stat(".git"); err != nil {
|
||||||
|
return nil, transport.ErrRepositoryNotFound
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filesystem.NewStorage(fs, cache.NewObjectLRUDefault()), nil
|
return filesystem.NewStorage(fs, cache.NewObjectLRUDefault()), nil
|
||||||
|
33
vendor/github.com/go-git/go-git/v5/remote.go
generated
vendored
33
vendor/github.com/go-git/go-git/v5/remote.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-git/go-billy/v5/osfs"
|
"github.com/go-git/go-billy/v5/osfs"
|
||||||
|
|
||||||
"github.com/go-git/go-git/v5/config"
|
"github.com/go-git/go-git/v5/config"
|
||||||
"github.com/go-git/go-git/v5/internal/url"
|
"github.com/go-git/go-git/v5/internal/url"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
@ -82,7 +83,7 @@ func (r *Remote) String() string {
|
|||||||
var fetch, push string
|
var fetch, push string
|
||||||
if len(r.c.URLs) > 0 {
|
if len(r.c.URLs) > 0 {
|
||||||
fetch = r.c.URLs[0]
|
fetch = r.c.URLs[0]
|
||||||
push = r.c.URLs[0]
|
push = r.c.URLs[len(r.c.URLs)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s\t%s (fetch)\n%[1]s\t%[3]s (push)", r.c.Name, fetch, push)
|
return fmt.Sprintf("%s\t%s (fetch)\n%[1]s\t%[3]s (push)", r.c.Name, fetch, push)
|
||||||
@ -109,8 +110,8 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
|
|||||||
return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name)
|
return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.RemoteURL == "" {
|
if o.RemoteURL == "" && len(r.c.URLs) > 0 {
|
||||||
o.RemoteURL = r.c.URLs[0]
|
o.RemoteURL = r.c.URLs[len(r.c.URLs)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
|
s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
|
||||||
@ -491,7 +492,18 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !updated && !updatedPrune {
|
if !updated && !updatedPrune {
|
||||||
return remoteRefs, NoErrAlreadyUpToDate
|
// No references updated, but may have fetched new objects, check if we now have any of our wants
|
||||||
|
for _, hash := range req.Wants {
|
||||||
|
exists, _ := objectExists(r.s, hash)
|
||||||
|
if exists {
|
||||||
|
updated = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !updated {
|
||||||
|
return remoteRefs, NoErrAlreadyUpToDate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return remoteRefs, nil
|
return remoteRefs, nil
|
||||||
@ -878,17 +890,12 @@ func getHavesFromRef(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to load the commit if we know the remote already
|
|
||||||
// has this hash.
|
|
||||||
if remoteRefs[h] {
|
|
||||||
haves[h] = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
commit, err := object.GetCommit(s, h)
|
commit, err := object.GetCommit(s, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Ignore the error if this isn't a commit.
|
if !errors.Is(err, plumbing.ErrObjectNotFound) {
|
||||||
haves[ref.Hash()] = true
|
// Ignore the error if this isn't a commit.
|
||||||
|
haves[ref.Hash()] = true
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
vendor/github.com/go-git/go-git/v5/repository.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/repository.go
generated
vendored
@ -956,7 +956,7 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o.RecurseSubmodules != NoRecurseSubmodules {
|
if o.RecurseSubmodules != NoRecurseSubmodules {
|
||||||
if err := w.updateSubmodules(&SubmoduleUpdateOptions{
|
if err := w.updateSubmodules(ctx, &SubmoduleUpdateOptions{
|
||||||
RecurseSubmodules: o.RecurseSubmodules,
|
RecurseSubmodules: o.RecurseSubmodules,
|
||||||
Depth: func() int {
|
Depth: func() int {
|
||||||
if o.ShallowSubmodules {
|
if o.ShallowSubmodules {
|
||||||
@ -1037,7 +1037,7 @@ func (r *Repository) setIsBare(isBare bool) error {
|
|||||||
return r.Storer.SetConfig(cfg)
|
return r.Storer.SetConfig(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.RemoteConfig, head *plumbing.Reference) error {
|
func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.RemoteConfig, _ *plumbing.Reference) error {
|
||||||
if !o.SingleBranch {
|
if !o.SingleBranch {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
69
vendor/github.com/go-git/go-git/v5/status.go
generated
vendored
69
vendor/github.com/go-git/go-git/v5/status.go
generated
vendored
@ -4,6 +4,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
mindex "github.com/go-git/go-git/v5/utils/merkletrie/index"
|
||||||
|
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Status represents the current status of a Worktree.
|
// Status represents the current status of a Worktree.
|
||||||
@ -77,3 +80,69 @@ const (
|
|||||||
Copied StatusCode = 'C'
|
Copied StatusCode = 'C'
|
||||||
UpdatedButUnmerged StatusCode = 'U'
|
UpdatedButUnmerged StatusCode = 'U'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StatusStrategy defines the different types of strategies when processing
|
||||||
|
// the worktree status.
|
||||||
|
type StatusStrategy int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TODO: (V6) Review the default status strategy.
|
||||||
|
// TODO: (V6) Review the type used to represent Status, to enable lazy
|
||||||
|
// processing of statuses going direct to the backing filesystem.
|
||||||
|
defaultStatusStrategy = Empty
|
||||||
|
|
||||||
|
// Empty starts its status map from empty. Missing entries for a given
|
||||||
|
// path means that the file is untracked. This causes a known issue (#119)
|
||||||
|
// whereby unmodified files can be incorrectly reported as untracked.
|
||||||
|
//
|
||||||
|
// This can be used when returning the changed state within a modified Worktree.
|
||||||
|
// For example, to check whether the current worktree is clean.
|
||||||
|
Empty StatusStrategy = 0
|
||||||
|
// Preload goes through all existing nodes from the index and add them to the
|
||||||
|
// status map as unmodified. This is currently the most reliable strategy
|
||||||
|
// although it comes at a performance cost in large repositories.
|
||||||
|
//
|
||||||
|
// This method is recommended when fetching the status of unmodified files.
|
||||||
|
// For example, to confirm the status of a specific file that is either
|
||||||
|
// untracked or unmodified.
|
||||||
|
Preload StatusStrategy = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s StatusStrategy) new(w *Worktree) (Status, error) {
|
||||||
|
switch s {
|
||||||
|
case Preload:
|
||||||
|
return preloadStatus(w)
|
||||||
|
case Empty:
|
||||||
|
return make(Status), nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("%w: %+v", ErrUnsupportedStatusStrategy, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func preloadStatus(w *Worktree) (Status, error) {
|
||||||
|
idx, err := w.r.Storer.Index()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
idxRoot := mindex.NewRootNode(idx)
|
||||||
|
nodes := []noder.Noder{idxRoot}
|
||||||
|
|
||||||
|
status := make(Status)
|
||||||
|
for len(nodes) > 0 {
|
||||||
|
var node noder.Noder
|
||||||
|
node, nodes = nodes[0], nodes[1:]
|
||||||
|
if node.IsDir() {
|
||||||
|
children, err := node.Children()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nodes = append(nodes, children...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fs := status.File(node.Name())
|
||||||
|
fs.Worktree = Unmodified
|
||||||
|
fs.Staging = Unmodified
|
||||||
|
}
|
||||||
|
|
||||||
|
return status, nil
|
||||||
|
}
|
||||||
|
35
vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
generated
vendored
35
vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
generated
vendored
@ -72,6 +72,9 @@ var (
|
|||||||
// ErrIsDir is returned when a reference file is attempting to be read,
|
// ErrIsDir is returned when a reference file is attempting to be read,
|
||||||
// but the path specified is a directory.
|
// but the path specified is a directory.
|
||||||
ErrIsDir = errors.New("reference path is a directory")
|
ErrIsDir = errors.New("reference path is a directory")
|
||||||
|
// ErrEmptyRefFile is returned when a reference file is attempted to be read,
|
||||||
|
// but the file is empty
|
||||||
|
ErrEmptyRefFile = errors.New("ref file is empty")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options holds configuration for the storage.
|
// Options holds configuration for the storage.
|
||||||
@ -249,7 +252,7 @@ func (d *DotGit) objectPacks() ([]plumbing.Hash, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
h := plumbing.NewHash(n[5 : len(n)-5]) //pack-(hash).pack
|
h := plumbing.NewHash(n[5 : len(n)-5]) // pack-(hash).pack
|
||||||
if h.IsZero() {
|
if h.IsZero() {
|
||||||
// Ignore files with badly-formatted names.
|
// Ignore files with badly-formatted names.
|
||||||
continue
|
continue
|
||||||
@ -661,18 +664,33 @@ func (d *DotGit) readReferenceFrom(rd io.Reader, name string) (ref *plumbing.Ref
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(b) == 0 {
|
||||||
|
return nil, ErrEmptyRefFile
|
||||||
|
}
|
||||||
|
|
||||||
line := strings.TrimSpace(string(b))
|
line := strings.TrimSpace(string(b))
|
||||||
return plumbing.NewReferenceFromStrings(name, line), nil
|
return plumbing.NewReferenceFromStrings(name, line), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkReferenceAndTruncate reads the reference from the given file, or the `pack-refs` file if
|
||||||
|
// the file was empty. Then it checks that the old reference matches the stored reference and
|
||||||
|
// truncates the file.
|
||||||
func (d *DotGit) checkReferenceAndTruncate(f billy.File, old *plumbing.Reference) error {
|
func (d *DotGit) checkReferenceAndTruncate(f billy.File, old *plumbing.Reference) error {
|
||||||
if old == nil {
|
if old == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ref, err := d.readReferenceFrom(f, old.Name().String())
|
ref, err := d.readReferenceFrom(f, old.Name().String())
|
||||||
|
if errors.Is(err, ErrEmptyRefFile) {
|
||||||
|
// This may happen if the reference is being read from a newly created file.
|
||||||
|
// In that case, try getting the reference from the packed refs file.
|
||||||
|
ref, err = d.packedRef(old.Name())
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ref.Hash() != old.Hash() {
|
if ref.Hash() != old.Hash() {
|
||||||
return storage.ErrReferenceHasChanged
|
return storage.ErrReferenceHasChanged
|
||||||
}
|
}
|
||||||
@ -701,7 +719,11 @@ func (d *DotGit) SetRef(r, old *plumbing.Reference) error {
|
|||||||
// Symbolic references are resolved and included in the output.
|
// Symbolic references are resolved and included in the output.
|
||||||
func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
|
func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
|
||||||
var refs []*plumbing.Reference
|
var refs []*plumbing.Reference
|
||||||
var seen = make(map[plumbing.ReferenceName]bool)
|
seen := make(map[plumbing.ReferenceName]bool)
|
||||||
|
if err := d.addRefFromHEAD(&refs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
|
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -710,10 +732,6 @@ func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.addRefFromHEAD(&refs); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return refs, nil
|
return refs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,7 +833,8 @@ func (d *DotGit) addRefsFromPackedRefsFile(refs *[]*plumbing.Reference, f billy.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *DotGit) openAndLockPackedRefs(doCreate bool) (
|
func (d *DotGit) openAndLockPackedRefs(doCreate bool) (
|
||||||
pr billy.File, err error) {
|
pr billy.File, err error,
|
||||||
|
) {
|
||||||
var f billy.File
|
var f billy.File
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil && f != nil {
|
if err != nil && f != nil {
|
||||||
@ -1020,7 +1039,7 @@ func (d *DotGit) readReferenceFile(path, name string) (ref *plumbing.Reference,
|
|||||||
|
|
||||||
func (d *DotGit) CountLooseRefs() (int, error) {
|
func (d *DotGit) CountLooseRefs() (int, error) {
|
||||||
var refs []*plumbing.Reference
|
var refs []*plumbing.Reference
|
||||||
var seen = make(map[plumbing.ReferenceName]bool)
|
seen := make(map[plumbing.ReferenceName]bool)
|
||||||
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
|
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go
generated
vendored
@ -48,7 +48,7 @@ func (s *IndexStorage) Index() (i *index.Index, err error) {
|
|||||||
|
|
||||||
defer ioutil.CheckClose(f, &err)
|
defer ioutil.CheckClose(f, &err)
|
||||||
|
|
||||||
d := index.NewDecoder(bufio.NewReader(f))
|
d := index.NewDecoder(f)
|
||||||
err = d.Decode(idx)
|
err = d.Decode(idx)
|
||||||
return idx, err
|
return idx, err
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
generated
vendored
@ -431,13 +431,13 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb
|
|||||||
|
|
||||||
defer ioutil.CheckClose(w, &err)
|
defer ioutil.CheckClose(w, &err)
|
||||||
|
|
||||||
s.objectCache.Put(obj)
|
|
||||||
|
|
||||||
bufp := copyBufferPool.Get().(*[]byte)
|
bufp := copyBufferPool.Get().(*[]byte)
|
||||||
buf := *bufp
|
buf := *bufp
|
||||||
_, err = io.CopyBuffer(w, r, buf)
|
_, err = io.CopyBuffer(w, r, buf)
|
||||||
copyBufferPool.Put(bufp)
|
copyBufferPool.Put(bufp)
|
||||||
|
|
||||||
|
s.objectCache.Put(obj)
|
||||||
|
|
||||||
return obj, err
|
return obj, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
vendor/github.com/go-git/go-git/v5/submodule.go
generated
vendored
6
vendor/github.com/go-git/go-git/v5/submodule.go
generated
vendored
@ -214,10 +214,10 @@ func (s *Submodule) update(ctx context.Context, o *SubmoduleUpdateOptions, force
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.doRecursiveUpdate(r, o)
|
return s.doRecursiveUpdate(ctx, r, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Submodule) doRecursiveUpdate(r *Repository, o *SubmoduleUpdateOptions) error {
|
func (s *Submodule) doRecursiveUpdate(ctx context.Context, r *Repository, o *SubmoduleUpdateOptions) error {
|
||||||
if o.RecurseSubmodules == NoRecurseSubmodules {
|
if o.RecurseSubmodules == NoRecurseSubmodules {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -236,7 +236,7 @@ func (s *Submodule) doRecursiveUpdate(r *Repository, o *SubmoduleUpdateOptions)
|
|||||||
*new = *o
|
*new = *o
|
||||||
|
|
||||||
new.RecurseSubmodules--
|
new.RecurseSubmodules--
|
||||||
return l.Update(new)
|
return l.UpdateContext(ctx, new)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Submodule) fetchAndCheckout(
|
func (s *Submodule) fetchAndCheckout(
|
||||||
|
9
vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go
generated
vendored
9
vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go
generated
vendored
@ -1,12 +1,17 @@
|
|||||||
package merkletrie
|
package merkletrie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
|
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrEmptyFileName = errors.New("empty filename in tree entry")
|
||||||
|
)
|
||||||
|
|
||||||
// Action values represent the kind of things a Change can represent:
|
// Action values represent the kind of things a Change can represent:
|
||||||
// insertion, deletions or modifications of files.
|
// insertion, deletions or modifications of files.
|
||||||
type Action int
|
type Action int
|
||||||
@ -121,6 +126,10 @@ func (l *Changes) AddRecursiveDelete(root noder.Path) error {
|
|||||||
type noderToChangeFn func(noder.Path) Change // NewInsert or NewDelete
|
type noderToChangeFn func(noder.Path) Change // NewInsert or NewDelete
|
||||||
|
|
||||||
func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error {
|
func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error {
|
||||||
|
if root.String() == "" {
|
||||||
|
return ErrEmptyFileName
|
||||||
|
}
|
||||||
|
|
||||||
if !root.IsDir() {
|
if !root.IsDir() {
|
||||||
l.Add(ctor(root))
|
l.Add(ctor(root))
|
||||||
return nil
|
return nil
|
||||||
|
2
vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
generated
vendored
@ -11,7 +11,7 @@ package merkletrie
|
|||||||
// corresponding changes and move the iterators further over both
|
// corresponding changes and move the iterators further over both
|
||||||
// trees.
|
// trees.
|
||||||
//
|
//
|
||||||
// The table bellow show all the possible comparison results, along
|
// The table below shows all the possible comparison results, along
|
||||||
// with what changes should we produce and how to advance the
|
// with what changes should we produce and how to advance the
|
||||||
// iterators.
|
// iterators.
|
||||||
//
|
//
|
||||||
|
2
vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go
generated
vendored
@ -13,7 +13,7 @@ var bufioReader = sync.Pool{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetBufioReader returns a *bufio.Reader that is managed by a sync.Pool.
|
// GetBufioReader returns a *bufio.Reader that is managed by a sync.Pool.
|
||||||
// Returns a bufio.Reader that is resetted with reader and ready for use.
|
// Returns a bufio.Reader that is reset with reader and ready for use.
|
||||||
//
|
//
|
||||||
// After use, the *bufio.Reader should be put back into the sync.Pool
|
// After use, the *bufio.Reader should be put back into the sync.Pool
|
||||||
// by calling PutBufioReader.
|
// by calling PutBufioReader.
|
||||||
|
2
vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go
generated
vendored
2
vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go
generated
vendored
@ -35,7 +35,7 @@ func PutByteSlice(buf *[]byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetBytesBuffer returns a *bytes.Buffer that is managed by a sync.Pool.
|
// GetBytesBuffer returns a *bytes.Buffer that is managed by a sync.Pool.
|
||||||
// Returns a buffer that is resetted and ready for use.
|
// Returns a buffer that is reset and ready for use.
|
||||||
//
|
//
|
||||||
// After use, the *bytes.Buffer should be put back into the sync.Pool
|
// After use, the *bytes.Buffer should be put back into the sync.Pool
|
||||||
// by calling PutBytesBuffer.
|
// by calling PutBytesBuffer.
|
||||||
|
4
vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go
generated
vendored
4
vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go
generated
vendored
@ -35,7 +35,7 @@ type ZLibReader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetZlibReader returns a ZLibReader that is managed by a sync.Pool.
|
// GetZlibReader returns a ZLibReader that is managed by a sync.Pool.
|
||||||
// Returns a ZLibReader that is resetted using a dictionary that is
|
// Returns a ZLibReader that is reset using a dictionary that is
|
||||||
// also managed by a sync.Pool.
|
// also managed by a sync.Pool.
|
||||||
//
|
//
|
||||||
// After use, the ZLibReader should be put back into the sync.Pool
|
// After use, the ZLibReader should be put back into the sync.Pool
|
||||||
@ -58,7 +58,7 @@ func PutZlibReader(z ZLibReader) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetZlibWriter returns a *zlib.Writer that is managed by a sync.Pool.
|
// GetZlibWriter returns a *zlib.Writer that is managed by a sync.Pool.
|
||||||
// Returns a writer that is resetted with w and ready for use.
|
// Returns a writer that is reset with w and ready for use.
|
||||||
//
|
//
|
||||||
// After use, the *zlib.Writer should be put back into the sync.Pool
|
// After use, the *zlib.Writer should be put back into the sync.Pool
|
||||||
// by calling PutZlibWriter.
|
// by calling PutZlibWriter.
|
||||||
|
117
vendor/github.com/go-git/go-git/v5/worktree.go
generated
vendored
117
vendor/github.com/go-git/go-git/v5/worktree.go
generated
vendored
@ -25,11 +25,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrWorktreeNotClean = errors.New("worktree is not clean")
|
ErrWorktreeNotClean = errors.New("worktree is not clean")
|
||||||
ErrSubmoduleNotFound = errors.New("submodule not found")
|
ErrSubmoduleNotFound = errors.New("submodule not found")
|
||||||
ErrUnstagedChanges = errors.New("worktree contains unstaged changes")
|
ErrUnstagedChanges = errors.New("worktree contains unstaged changes")
|
||||||
ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink")
|
ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink")
|
||||||
ErrNonFastForwardUpdate = errors.New("non-fast-forward update")
|
ErrNonFastForwardUpdate = errors.New("non-fast-forward update")
|
||||||
|
ErrRestoreWorktreeOnlyNotSupported = errors.New("worktree only is not supported")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Worktree represents a git worktree.
|
// Worktree represents a git worktree.
|
||||||
@ -139,7 +140,7 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o.RecurseSubmodules != NoRecurseSubmodules {
|
if o.RecurseSubmodules != NoRecurseSubmodules {
|
||||||
return w.updateSubmodules(&SubmoduleUpdateOptions{
|
return w.updateSubmodules(ctx, &SubmoduleUpdateOptions{
|
||||||
RecurseSubmodules: o.RecurseSubmodules,
|
RecurseSubmodules: o.RecurseSubmodules,
|
||||||
Auth: o.Auth,
|
Auth: o.Auth,
|
||||||
})
|
})
|
||||||
@ -148,13 +149,13 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worktree) updateSubmodules(o *SubmoduleUpdateOptions) error {
|
func (w *Worktree) updateSubmodules(ctx context.Context, o *SubmoduleUpdateOptions) error {
|
||||||
s, err := w.Submodules()
|
s, err := w.Submodules()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.Init = true
|
o.Init = true
|
||||||
return s.Update(o)
|
return s.UpdateContext(ctx, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checkout switch branches or restore working tree files.
|
// Checkout switch branches or restore working tree files.
|
||||||
@ -307,13 +308,13 @@ func (w *Worktree) ResetSparsely(opts *ResetOptions, dirs []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if opts.Mode == MixedReset || opts.Mode == MergeReset || opts.Mode == HardReset {
|
if opts.Mode == MixedReset || opts.Mode == MergeReset || opts.Mode == HardReset {
|
||||||
if err := w.resetIndex(t, dirs); err != nil {
|
if err := w.resetIndex(t, dirs, opts.Files); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Mode == MergeReset || opts.Mode == HardReset {
|
if opts.Mode == MergeReset || opts.Mode == HardReset {
|
||||||
if err := w.resetWorktree(t); err != nil {
|
if err := w.resetWorktree(t, opts.Files); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -321,20 +322,52 @@ func (w *Worktree) ResetSparsely(opts *ResetOptions, dirs []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore restores specified files in the working tree or stage with contents from
|
||||||
|
// a restore source. If a path is tracked but does not exist in the restore,
|
||||||
|
// source, it will be removed to match the source.
|
||||||
|
//
|
||||||
|
// If Staged and Worktree are true, then the restore source will be the index.
|
||||||
|
// If only Staged is true, then the restore source will be HEAD.
|
||||||
|
// If only Worktree is true or neither Staged nor Worktree are true, will
|
||||||
|
// result in ErrRestoreWorktreeOnlyNotSupported because restoring the working
|
||||||
|
// tree while leaving the stage untouched is not currently supported.
|
||||||
|
//
|
||||||
|
// Restore with no files specified will return ErrNoRestorePaths.
|
||||||
|
func (w *Worktree) Restore(o *RestoreOptions) error {
|
||||||
|
if err := o.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Staged {
|
||||||
|
opts := &ResetOptions{
|
||||||
|
Files: o.Files,
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Worktree {
|
||||||
|
// If we are doing both Worktree and Staging then it is a hard reset
|
||||||
|
opts.Mode = HardReset
|
||||||
|
} else {
|
||||||
|
// If we are doing just staging then it is a mixed reset
|
||||||
|
opts.Mode = MixedReset
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.Reset(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrRestoreWorktreeOnlyNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
// Reset the worktree to a specified state.
|
// Reset the worktree to a specified state.
|
||||||
func (w *Worktree) Reset(opts *ResetOptions) error {
|
func (w *Worktree) Reset(opts *ResetOptions) error {
|
||||||
return w.ResetSparsely(opts, nil)
|
return w.ResetSparsely(opts, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
|
func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) error {
|
||||||
idx, err := w.r.Storer.Index()
|
idx, err := w.r.Storer.Index()
|
||||||
if len(dirs) > 0 {
|
|
||||||
idx.SkipUnless(dirs)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
b := newIndexBuilder(idx)
|
b := newIndexBuilder(idx)
|
||||||
|
|
||||||
changes, err := w.diffTreeWithStaging(t, true)
|
changes, err := w.diffTreeWithStaging(t, true)
|
||||||
@ -362,6 +395,13 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
|
|||||||
name = ch.From.String()
|
name = ch.From.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(files) > 0 {
|
||||||
|
contains := inFiles(files, name)
|
||||||
|
if !contains {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b.Remove(name)
|
b.Remove(name)
|
||||||
if e == nil {
|
if e == nil {
|
||||||
continue
|
continue
|
||||||
@ -376,10 +416,25 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.Write(idx)
|
b.Write(idx)
|
||||||
|
|
||||||
|
if len(dirs) > 0 {
|
||||||
|
idx.SkipUnless(dirs)
|
||||||
|
}
|
||||||
|
|
||||||
return w.r.Storer.SetIndex(idx)
|
return w.r.Storer.SetIndex(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worktree) resetWorktree(t *object.Tree) error {
|
func inFiles(files []string, v string) bool {
|
||||||
|
for _, s := range files {
|
||||||
|
if s == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Worktree) resetWorktree(t *object.Tree, files []string) error {
|
||||||
changes, err := w.diffStagingWithWorktree(true, false)
|
changes, err := w.diffStagingWithWorktree(true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -395,6 +450,25 @@ func (w *Worktree) resetWorktree(t *object.Tree) error {
|
|||||||
if err := w.validChange(ch); err != nil {
|
if err := w.validChange(ch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(files) > 0 {
|
||||||
|
file := ""
|
||||||
|
if ch.From != nil {
|
||||||
|
file = ch.From.String()
|
||||||
|
} else if ch.To != nil {
|
||||||
|
file = ch.To.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if file == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
contains := inFiles(files, file)
|
||||||
|
if !contains {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := w.checkoutChange(ch, t, b); err != nil {
|
if err := w.checkoutChange(ch, t, b); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -642,7 +716,7 @@ func (w *Worktree) checkoutChangeRegularFile(name string,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.addIndexFromFile(name, e.Hash, idx)
|
return w.addIndexFromFile(name, e.Hash, f.Mode, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -725,18 +799,13 @@ func (w *Worktree) addIndexFromTreeEntry(name string, f *object.TreeEntry, idx *
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *indexBuilder) error {
|
func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, mode filemode.FileMode, idx *indexBuilder) error {
|
||||||
idx.Remove(name)
|
idx.Remove(name)
|
||||||
fi, err := w.Filesystem.Lstat(name)
|
fi, err := w.Filesystem.Lstat(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mode, err := filemode.NewFromOSFileMode(fi.Mode())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
e := &index.Entry{
|
e := &index.Entry{
|
||||||
Hash: h,
|
Hash: h,
|
||||||
Name: name,
|
Name: name,
|
||||||
@ -1058,7 +1127,7 @@ func rmFileAndDirsIfEmpty(fs billy.Filesystem, name string) error {
|
|||||||
dir := filepath.Dir(name)
|
dir := filepath.Dir(name)
|
||||||
for {
|
for {
|
||||||
removed, err := removeDirIfEmpty(fs, dir)
|
removed, err := removeDirIfEmpty(fs, dir)
|
||||||
if err != nil {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
vendor/github.com/go-git/go-git/v5/worktree_commit.go
generated
vendored
43
vendor/github.com/go-git/go-git/v5/worktree_commit.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"path"
|
"path"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -23,6 +24,10 @@ var (
|
|||||||
// ErrEmptyCommit occurs when a commit is attempted using a clean
|
// ErrEmptyCommit occurs when a commit is attempted using a clean
|
||||||
// working tree, with no changes to be committed.
|
// working tree, with no changes to be committed.
|
||||||
ErrEmptyCommit = errors.New("cannot create empty commit: clean working tree")
|
ErrEmptyCommit = errors.New("cannot create empty commit: clean working tree")
|
||||||
|
|
||||||
|
// characters to be removed from user name and/or email before using them to build a commit object
|
||||||
|
// See https://git-scm.com/docs/git-commit#_commit_information
|
||||||
|
invalidCharactersRe = regexp.MustCompile(`[<>\n]`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Commit stores the current contents of the index in a new commit along with
|
// Commit stores the current contents of the index in a new commit along with
|
||||||
@ -38,8 +43,6 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var treeHash plumbing.Hash
|
|
||||||
|
|
||||||
if opts.Amend {
|
if opts.Amend {
|
||||||
head, err := w.r.Head()
|
head, err := w.r.Head()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -61,16 +64,34 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
|
|||||||
return plumbing.ZeroHash, err
|
return plumbing.ZeroHash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First handle the case of the first commit in the repository being empty.
|
||||||
|
if len(opts.Parents) == 0 && len(idx.Entries) == 0 && !opts.AllowEmptyCommits {
|
||||||
|
return plumbing.ZeroHash, ErrEmptyCommit
|
||||||
|
}
|
||||||
|
|
||||||
h := &buildTreeHelper{
|
h := &buildTreeHelper{
|
||||||
fs: w.Filesystem,
|
fs: w.Filesystem,
|
||||||
s: w.r.Storer,
|
s: w.r.Storer,
|
||||||
}
|
}
|
||||||
|
|
||||||
treeHash, err = h.BuildTree(idx, opts)
|
treeHash, err := h.BuildTree(idx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return plumbing.ZeroHash, err
|
return plumbing.ZeroHash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousTree := plumbing.ZeroHash
|
||||||
|
if len(opts.Parents) > 0 {
|
||||||
|
parentCommit, err := w.r.CommitObject(opts.Parents[0])
|
||||||
|
if err != nil {
|
||||||
|
return plumbing.ZeroHash, err
|
||||||
|
}
|
||||||
|
previousTree = parentCommit.TreeHash
|
||||||
|
}
|
||||||
|
|
||||||
|
if treeHash == previousTree && !opts.AllowEmptyCommits {
|
||||||
|
return plumbing.ZeroHash, ErrEmptyCommit
|
||||||
|
}
|
||||||
|
|
||||||
commit, err := w.buildCommitObject(msg, opts, treeHash)
|
commit, err := w.buildCommitObject(msg, opts, treeHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return plumbing.ZeroHash, err
|
return plumbing.ZeroHash, err
|
||||||
@ -121,8 +142,8 @@ func (w *Worktree) updateHEAD(commit plumbing.Hash) error {
|
|||||||
|
|
||||||
func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumbing.Hash) (plumbing.Hash, error) {
|
func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumbing.Hash) (plumbing.Hash, error) {
|
||||||
commit := &object.Commit{
|
commit := &object.Commit{
|
||||||
Author: *opts.Author,
|
Author: w.sanitize(*opts.Author),
|
||||||
Committer: *opts.Committer,
|
Committer: w.sanitize(*opts.Committer),
|
||||||
Message: msg,
|
Message: msg,
|
||||||
TreeHash: tree,
|
TreeHash: tree,
|
||||||
ParentHashes: opts.Parents,
|
ParentHashes: opts.Parents,
|
||||||
@ -148,6 +169,14 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
|
|||||||
return w.r.Storer.SetEncodedObject(obj)
|
return w.r.Storer.SetEncodedObject(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Worktree) sanitize(signature object.Signature) object.Signature {
|
||||||
|
return object.Signature{
|
||||||
|
Name: invalidCharactersRe.ReplaceAllString(signature.Name, ""),
|
||||||
|
Email: invalidCharactersRe.ReplaceAllString(signature.Email, ""),
|
||||||
|
When: signature.When,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type gpgSigner struct {
|
type gpgSigner struct {
|
||||||
key *openpgp.Entity
|
key *openpgp.Entity
|
||||||
cfg *packet.Config
|
cfg *packet.Config
|
||||||
@ -175,10 +204,6 @@ type buildTreeHelper struct {
|
|||||||
// BuildTree builds the tree objects and push its to the storer, the hash
|
// BuildTree builds the tree objects and push its to the storer, the hash
|
||||||
// of the root tree is returned.
|
// of the root tree is returned.
|
||||||
func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) {
|
func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) {
|
||||||
if len(idx.Entries) == 0 && (opts == nil || !opts.AllowEmptyCommits) {
|
|
||||||
return plumbing.ZeroHash, ErrEmptyCommit
|
|
||||||
}
|
|
||||||
|
|
||||||
const rootNode = ""
|
const rootNode = ""
|
||||||
h.trees = map[string]*object.Tree{rootNode: {}}
|
h.trees = map[string]*object.Tree{rootNode: {}}
|
||||||
h.entries = map[string]*object.TreeEntry{}
|
h.entries = map[string]*object.TreeEntry{}
|
||||||
|
3
vendor/github.com/go-git/go-git/v5/worktree_linux.go
generated
vendored
3
vendor/github.com/go-git/go-git/v5/worktree_linux.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package git
|
package git
|
||||||
@ -21,6 +22,6 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSymlinkWindowsNonAdmin(err error) bool {
|
func isSymlinkWindowsNonAdmin(_ error) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
34
vendor/github.com/go-git/go-git/v5/worktree_status.go
generated
vendored
34
vendor/github.com/go-git/go-git/v5/worktree_status.go
generated
vendored
@ -29,10 +29,23 @@ var (
|
|||||||
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
|
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
|
||||||
// files in the worktree.
|
// files in the worktree.
|
||||||
ErrGlobNoMatches = errors.New("glob pattern did not match any files")
|
ErrGlobNoMatches = errors.New("glob pattern did not match any files")
|
||||||
|
// ErrUnsupportedStatusStrategy occurs when an invalid StatusStrategy is used
|
||||||
|
// when processing the Worktree status.
|
||||||
|
ErrUnsupportedStatusStrategy = errors.New("unsupported status strategy")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Status returns the working tree status.
|
// Status returns the working tree status.
|
||||||
func (w *Worktree) Status() (Status, error) {
|
func (w *Worktree) Status() (Status, error) {
|
||||||
|
return w.StatusWithOptions(StatusOptions{Strategy: defaultStatusStrategy})
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatusOptions defines the options for Worktree.StatusWithOptions().
|
||||||
|
type StatusOptions struct {
|
||||||
|
Strategy StatusStrategy
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatusWithOptions returns the working tree status.
|
||||||
|
func (w *Worktree) StatusWithOptions(o StatusOptions) (Status, error) {
|
||||||
var hash plumbing.Hash
|
var hash plumbing.Hash
|
||||||
|
|
||||||
ref, err := w.r.Head()
|
ref, err := w.r.Head()
|
||||||
@ -44,11 +57,14 @@ func (w *Worktree) Status() (Status, error) {
|
|||||||
hash = ref.Hash()
|
hash = ref.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.status(hash)
|
return w.status(o.Strategy, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worktree) status(commit plumbing.Hash) (Status, error) {
|
func (w *Worktree) status(ss StatusStrategy, commit plumbing.Hash) (Status, error) {
|
||||||
s := make(Status)
|
s, err := ss.new(w)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
left, err := w.diffCommitWithStaging(commit, false)
|
left, err := w.diffCommitWithStaging(commit, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -488,7 +504,7 @@ func (w *Worktree) copyFileToStorage(path string) (hash plumbing.Hash, err error
|
|||||||
return w.r.Storer.SetEncodedObject(obj)
|
return w.r.Storer.SetEncodedObject(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, fi os.FileInfo) (err error) {
|
func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, _ os.FileInfo) (err error) {
|
||||||
src, err := w.Filesystem.Open(path)
|
src, err := w.Filesystem.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -503,7 +519,7 @@ func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, fi os.F
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, fi os.FileInfo) error {
|
func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, _ os.FileInfo) error {
|
||||||
target, err := w.Filesystem.Readlink(path)
|
target, err := w.Filesystem.Readlink(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -543,9 +559,11 @@ func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbi
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Mode.IsRegular() {
|
// The entry size must always reflect the current state, otherwise
|
||||||
e.Size = uint32(info.Size())
|
// it will cause go-git's Worktree.Status() to divert from "git status".
|
||||||
}
|
// The size of a symlink is the length of the path to the target.
|
||||||
|
// The size of Regular and Executable files is the size of the files.
|
||||||
|
e.Size = uint32(info.Size())
|
||||||
|
|
||||||
fillSystemInfo(e, info.Sys())
|
fillSystemInfo(e, info.Sys())
|
||||||
return nil
|
return nil
|
||||||
|
29
vendor/github.com/mmcloughlin/avo/LICENSE
generated
vendored
Normal file
29
vendor/github.com/mmcloughlin/avo/LICENSE
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2018, Michael McLoughlin
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
45
vendor/github.com/mmcloughlin/avo/attr/attr.go
generated
vendored
Normal file
45
vendor/github.com/mmcloughlin/avo/attr/attr.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Package attr provides attributes for text and data sections.
|
||||||
|
package attr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/bits"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Attribute represents TEXT or DATA flags.
|
||||||
|
type Attribute uint16
|
||||||
|
|
||||||
|
//go:generate go run make_textflag.go -output ztextflag.go
|
||||||
|
|
||||||
|
// Asm returns a representation of the attributes in assembly syntax. This may use macros from "textflags.h"; see ContainsTextFlags() to determine if this header is required.
|
||||||
|
func (a Attribute) Asm() string {
|
||||||
|
parts, rest := a.split()
|
||||||
|
if len(parts) == 0 || rest != 0 {
|
||||||
|
parts = append(parts, fmt.Sprintf("%d", rest))
|
||||||
|
}
|
||||||
|
return strings.Join(parts, "|")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsTextFlags returns whether the Asm() representation requires macros in "textflags.h".
|
||||||
|
func (a Attribute) ContainsTextFlags() bool {
|
||||||
|
flags, _ := a.split()
|
||||||
|
return len(flags) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// split splits a into known flags and any remaining bits.
|
||||||
|
func (a Attribute) split() ([]string, Attribute) {
|
||||||
|
var flags []string
|
||||||
|
var rest Attribute
|
||||||
|
for a != 0 {
|
||||||
|
i := uint(bits.TrailingZeros16(uint16(a)))
|
||||||
|
bit := Attribute(1) << i
|
||||||
|
if flag := attrname[bit]; flag != "" {
|
||||||
|
flags = append(flags, flag)
|
||||||
|
} else {
|
||||||
|
rest |= bit
|
||||||
|
}
|
||||||
|
a ^= bit
|
||||||
|
}
|
||||||
|
return flags, rest
|
||||||
|
}
|
39
vendor/github.com/mmcloughlin/avo/attr/textflag.h
generated
vendored
Normal file
39
vendor/github.com/mmcloughlin/avo/attr/textflag.h
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Code generated by downloading from https://github.com/golang/go/raw/go1.16.2/src/runtime/textflag.h. DO NOT EDIT.
|
||||||
|
|
||||||
|
// Copyright 2013 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 defines flags attached to various functions
|
||||||
|
// and data objects. The compilers, assemblers, and linker must
|
||||||
|
// all agree on these values.
|
||||||
|
//
|
||||||
|
// Keep in sync with src/cmd/internal/obj/textflag.go.
|
||||||
|
|
||||||
|
// Don't profile the marked routine. This flag is deprecated.
|
||||||
|
#define NOPROF 1
|
||||||
|
// It is ok for the linker to get multiple of these symbols. It will
|
||||||
|
// pick one of the duplicates to use.
|
||||||
|
#define DUPOK 2
|
||||||
|
// Don't insert stack check preamble.
|
||||||
|
#define NOSPLIT 4
|
||||||
|
// Put this data in a read-only section.
|
||||||
|
#define RODATA 8
|
||||||
|
// This data contains no pointers.
|
||||||
|
#define NOPTR 16
|
||||||
|
// This is a wrapper function and should not count as disabling 'recover'.
|
||||||
|
#define WRAPPER 32
|
||||||
|
// This function uses its incoming context register.
|
||||||
|
#define NEEDCTXT 64
|
||||||
|
// Allocate a word of thread local storage and store the offset from the
|
||||||
|
// thread local base to the thread local storage in this variable.
|
||||||
|
#define TLSBSS 256
|
||||||
|
// Do not insert instructions to allocate a stack frame for this function.
|
||||||
|
// Only valid on functions that declare a frame size of 0.
|
||||||
|
// TODO(mwhudson): only implemented for ppc64x at present.
|
||||||
|
#define NOFRAME 512
|
||||||
|
// Function can call reflect.Type.Method or reflect.Type.MethodByName.
|
||||||
|
#define REFLECTMETHOD 1024
|
||||||
|
// Function is the top of the call stack. Call stack unwinders should stop
|
||||||
|
// at this function.
|
||||||
|
#define TOPFRAME 2048
|
90
vendor/github.com/mmcloughlin/avo/attr/ztextflag.go
generated
vendored
Normal file
90
vendor/github.com/mmcloughlin/avo/attr/ztextflag.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// Code generated by make_textflag.go. DO NOT EDIT.
|
||||||
|
|
||||||
|
package attr
|
||||||
|
|
||||||
|
// Attribute values defined in textflag.h.
|
||||||
|
const (
|
||||||
|
// Don't profile the marked routine. This flag is deprecated.
|
||||||
|
NOPROF Attribute = 1
|
||||||
|
|
||||||
|
// It is ok for the linker to get multiple of these symbols. It will
|
||||||
|
// pick one of the duplicates to use.
|
||||||
|
DUPOK Attribute = 2
|
||||||
|
|
||||||
|
// Don't insert stack check preamble.
|
||||||
|
NOSPLIT Attribute = 4
|
||||||
|
|
||||||
|
// Put this data in a read-only section.
|
||||||
|
RODATA Attribute = 8
|
||||||
|
|
||||||
|
// This data contains no pointers.
|
||||||
|
NOPTR Attribute = 16
|
||||||
|
|
||||||
|
// This is a wrapper function and should not count as disabling 'recover'.
|
||||||
|
WRAPPER Attribute = 32
|
||||||
|
|
||||||
|
// This function uses its incoming context register.
|
||||||
|
NEEDCTXT Attribute = 64
|
||||||
|
|
||||||
|
// Allocate a word of thread local storage and store the offset from the
|
||||||
|
// thread local base to the thread local storage in this variable.
|
||||||
|
TLSBSS Attribute = 256
|
||||||
|
|
||||||
|
// Do not insert instructions to allocate a stack frame for this function.
|
||||||
|
// Only valid on functions that declare a frame size of 0.
|
||||||
|
NOFRAME Attribute = 512
|
||||||
|
|
||||||
|
// Function can call reflect.Type.Method or reflect.Type.MethodByName.
|
||||||
|
REFLECTMETHOD Attribute = 1024
|
||||||
|
|
||||||
|
// Function is the top of the call stack. Call stack unwinders should stop
|
||||||
|
// at this function.
|
||||||
|
TOPFRAME Attribute = 2048
|
||||||
|
)
|
||||||
|
|
||||||
|
var attrname = map[Attribute]string{
|
||||||
|
NOPROF: "NOPROF",
|
||||||
|
DUPOK: "DUPOK",
|
||||||
|
NOSPLIT: "NOSPLIT",
|
||||||
|
RODATA: "RODATA",
|
||||||
|
NOPTR: "NOPTR",
|
||||||
|
WRAPPER: "WRAPPER",
|
||||||
|
NEEDCTXT: "NEEDCTXT",
|
||||||
|
TLSBSS: "TLSBSS",
|
||||||
|
NOFRAME: "NOFRAME",
|
||||||
|
REFLECTMETHOD: "REFLECTMETHOD",
|
||||||
|
TOPFRAME: "TOPFRAME",
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOPROF reports whether the NOPROF flag is set.
|
||||||
|
func (a Attribute) NOPROF() bool { return (a & NOPROF) != 0 }
|
||||||
|
|
||||||
|
// DUPOK reports whether the DUPOK flag is set.
|
||||||
|
func (a Attribute) DUPOK() bool { return (a & DUPOK) != 0 }
|
||||||
|
|
||||||
|
// NOSPLIT reports whether the NOSPLIT flag is set.
|
||||||
|
func (a Attribute) NOSPLIT() bool { return (a & NOSPLIT) != 0 }
|
||||||
|
|
||||||
|
// RODATA reports whether the RODATA flag is set.
|
||||||
|
func (a Attribute) RODATA() bool { return (a & RODATA) != 0 }
|
||||||
|
|
||||||
|
// NOPTR reports whether the NOPTR flag is set.
|
||||||
|
func (a Attribute) NOPTR() bool { return (a & NOPTR) != 0 }
|
||||||
|
|
||||||
|
// WRAPPER reports whether the WRAPPER flag is set.
|
||||||
|
func (a Attribute) WRAPPER() bool { return (a & WRAPPER) != 0 }
|
||||||
|
|
||||||
|
// NEEDCTXT reports whether the NEEDCTXT flag is set.
|
||||||
|
func (a Attribute) NEEDCTXT() bool { return (a & NEEDCTXT) != 0 }
|
||||||
|
|
||||||
|
// TLSBSS reports whether the TLSBSS flag is set.
|
||||||
|
func (a Attribute) TLSBSS() bool { return (a & TLSBSS) != 0 }
|
||||||
|
|
||||||
|
// NOFRAME reports whether the NOFRAME flag is set.
|
||||||
|
func (a Attribute) NOFRAME() bool { return (a & NOFRAME) != 0 }
|
||||||
|
|
||||||
|
// REFLECTMETHOD reports whether the REFLECTMETHOD flag is set.
|
||||||
|
func (a Attribute) REFLECTMETHOD() bool { return (a & REFLECTMETHOD) != 0 }
|
||||||
|
|
||||||
|
// TOPFRAME reports whether the TOPFRAME flag is set.
|
||||||
|
func (a Attribute) TOPFRAME() bool { return (a & TOPFRAME) != 0 }
|
18
vendor/github.com/mmcloughlin/avo/build/attr.go
generated
vendored
Normal file
18
vendor/github.com/mmcloughlin/avo/build/attr.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import "github.com/mmcloughlin/avo/attr"
|
||||||
|
|
||||||
|
// TEXT and DATA attribute values included for convenience.
|
||||||
|
const (
|
||||||
|
NOPROF = attr.NOPROF
|
||||||
|
DUPOK = attr.DUPOK
|
||||||
|
NOSPLIT = attr.NOSPLIT
|
||||||
|
RODATA = attr.RODATA
|
||||||
|
NOPTR = attr.NOPTR
|
||||||
|
WRAPPER = attr.WRAPPER
|
||||||
|
NEEDCTXT = attr.NEEDCTXT
|
||||||
|
TLSBSS = attr.TLSBSS
|
||||||
|
NOFRAME = attr.NOFRAME
|
||||||
|
REFLECTMETHOD = attr.REFLECTMETHOD
|
||||||
|
TOPFRAME = attr.TOPFRAME
|
||||||
|
)
|
171
vendor/github.com/mmcloughlin/avo/build/cli.go
generated
vendored
Normal file
171
vendor/github.com/mmcloughlin/avo/build/cli.go
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"runtime/pprof"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/pass"
|
||||||
|
"github.com/mmcloughlin/avo/printer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config contains options for an avo main function.
|
||||||
|
type Config struct {
|
||||||
|
ErrOut io.Writer
|
||||||
|
MaxErrors int // max errors to report; 0 means unlimited
|
||||||
|
CPUProfile io.WriteCloser
|
||||||
|
Passes []pass.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main is the standard main function for an avo program. This extracts the
|
||||||
|
// result from the build Context (logging and exiting on error), and performs
|
||||||
|
// configured passes.
|
||||||
|
func Main(cfg *Config, context *Context) int {
|
||||||
|
diag := log.New(cfg.ErrOut, "", 0)
|
||||||
|
|
||||||
|
if cfg.CPUProfile != nil {
|
||||||
|
defer cfg.CPUProfile.Close()
|
||||||
|
if err := pprof.StartCPUProfile(cfg.CPUProfile); err != nil {
|
||||||
|
diag.Println("could not start CPU profile: ", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
defer pprof.StopCPUProfile()
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := context.Result()
|
||||||
|
if err != nil {
|
||||||
|
LogError(diag, err, cfg.MaxErrors)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
p := pass.Concat(cfg.Passes...)
|
||||||
|
if err := p.Execute(f); err != nil {
|
||||||
|
diag.Println(err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags represents CLI flags for an avo program.
|
||||||
|
type Flags struct {
|
||||||
|
errout *outputValue
|
||||||
|
allerrors bool
|
||||||
|
cpuprof *outputValue
|
||||||
|
pkg string
|
||||||
|
printers []*printerValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFlags initializes avo flags for the given FlagSet.
|
||||||
|
func NewFlags(fs *flag.FlagSet) *Flags {
|
||||||
|
f := &Flags{}
|
||||||
|
|
||||||
|
f.errout = newOutputValue(os.Stderr)
|
||||||
|
fs.Var(f.errout, "log", "diagnostics output")
|
||||||
|
|
||||||
|
fs.BoolVar(&f.allerrors, "e", false, "no limit on number of errors reported")
|
||||||
|
|
||||||
|
f.cpuprof = newOutputValue(nil)
|
||||||
|
fs.Var(f.cpuprof, "cpuprofile", "write cpu profile to `file`")
|
||||||
|
|
||||||
|
fs.StringVar(&f.pkg, "pkg", "", "package name (defaults to current directory name)")
|
||||||
|
|
||||||
|
goasm := newPrinterValue(printer.NewGoAsm, os.Stdout)
|
||||||
|
fs.Var(goasm, "out", "assembly output")
|
||||||
|
f.printers = append(f.printers, goasm)
|
||||||
|
|
||||||
|
stubs := newPrinterValue(printer.NewStubs, nil)
|
||||||
|
fs.Var(stubs, "stubs", "go stub file")
|
||||||
|
f.printers = append(f.printers, stubs)
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config builds a configuration object based on flag values.
|
||||||
|
func (f *Flags) Config() *Config {
|
||||||
|
pc := printer.NewGoRunConfig()
|
||||||
|
if f.pkg != "" {
|
||||||
|
pc.Pkg = f.pkg
|
||||||
|
}
|
||||||
|
passes := []pass.Interface{pass.Compile}
|
||||||
|
for _, pv := range f.printers {
|
||||||
|
p := pv.Build(pc)
|
||||||
|
if p != nil {
|
||||||
|
passes = append(passes, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := &Config{
|
||||||
|
ErrOut: f.errout.w,
|
||||||
|
MaxErrors: 10,
|
||||||
|
CPUProfile: f.cpuprof.w,
|
||||||
|
Passes: passes,
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.allerrors {
|
||||||
|
cfg.MaxErrors = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type outputValue struct {
|
||||||
|
w io.WriteCloser
|
||||||
|
filename string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOutputValue(dflt io.WriteCloser) *outputValue {
|
||||||
|
return &outputValue{w: dflt}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *outputValue) String() string {
|
||||||
|
if o == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return o.filename
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *outputValue) Set(s string) error {
|
||||||
|
o.filename = s
|
||||||
|
if s == "-" {
|
||||||
|
o.w = nopwritecloser{os.Stdout}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
f, err := os.Create(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.w = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type printerValue struct {
|
||||||
|
*outputValue
|
||||||
|
Builder printer.Builder
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPrinterValue(b printer.Builder, dflt io.WriteCloser) *printerValue {
|
||||||
|
return &printerValue{
|
||||||
|
outputValue: newOutputValue(dflt),
|
||||||
|
Builder: b,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *printerValue) Build(cfg printer.Config) pass.Interface {
|
||||||
|
if p.outputValue.w == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &pass.Output{
|
||||||
|
Writer: p.outputValue.w,
|
||||||
|
Printer: p.Builder(cfg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nopwritecloser wraps a Writer and provides a null implementation of Close().
|
||||||
|
type nopwritecloser struct {
|
||||||
|
io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nopwritecloser) Close() error { return nil }
|
224
vendor/github.com/mmcloughlin/avo/build/context.go
generated
vendored
Normal file
224
vendor/github.com/mmcloughlin/avo/build/context.go
generated
vendored
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/attr"
|
||||||
|
"github.com/mmcloughlin/avo/buildtags"
|
||||||
|
"github.com/mmcloughlin/avo/gotypes"
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate avogen -output zinstructions.go build
|
||||||
|
//go:generate avogen -output zinstructions_test.go buildtest
|
||||||
|
|
||||||
|
// Context maintains state for incrementally building an avo File.
|
||||||
|
type Context struct {
|
||||||
|
pkg *packages.Package
|
||||||
|
file *ir.File
|
||||||
|
function *ir.Function
|
||||||
|
global *ir.Global
|
||||||
|
errs ErrorList
|
||||||
|
reg.Collection
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContext initializes an empty build Context.
|
||||||
|
func NewContext() *Context {
|
||||||
|
return &Context{
|
||||||
|
file: ir.NewFile(),
|
||||||
|
Collection: *reg.NewCollection(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package sets the package the generated file will belong to. Required to be able to reference types in the package.
|
||||||
|
func (c *Context) Package(path string) {
|
||||||
|
cfg := &packages.Config{
|
||||||
|
Mode: packages.NeedTypes | packages.NeedDeps | packages.NeedImports,
|
||||||
|
}
|
||||||
|
pkgs, err := packages.Load(cfg, path)
|
||||||
|
if err != nil {
|
||||||
|
c.adderror(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pkg := pkgs[0]
|
||||||
|
if len(pkg.Errors) > 0 {
|
||||||
|
for _, err := range pkg.Errors {
|
||||||
|
c.adderror(err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.pkg = pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraints sets build constraints for the file.
|
||||||
|
func (c *Context) Constraints(t buildtags.ConstraintsConvertable) {
|
||||||
|
cs := t.ToConstraints()
|
||||||
|
if err := cs.Validate(); err != nil {
|
||||||
|
c.adderror(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.file.Constraints = cs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraint appends a constraint to the file's build constraints.
|
||||||
|
func (c *Context) Constraint(t buildtags.ConstraintConvertable) {
|
||||||
|
c.Constraints(append(c.file.Constraints, t.ToConstraint()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstraintExpr appends a constraint to the file's build constraints. The
|
||||||
|
// constraint to add is parsed from the given expression. The expression should
|
||||||
|
// look the same as the content following "// +build " in regular build
|
||||||
|
// constraint comments.
|
||||||
|
func (c *Context) ConstraintExpr(expr string) {
|
||||||
|
constraint, err := buildtags.ParseConstraint(expr)
|
||||||
|
if err != nil {
|
||||||
|
c.adderror(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Constraint(constraint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function starts building a new function with the given name.
|
||||||
|
func (c *Context) Function(name string) {
|
||||||
|
c.function = ir.NewFunction(name)
|
||||||
|
c.file.AddSection(c.function)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doc sets documentation comment lines for the currently active function.
|
||||||
|
func (c *Context) Doc(lines ...string) {
|
||||||
|
c.activefunc().Doc = lines
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pragma adds a compiler directive to the currently active function.
|
||||||
|
func (c *Context) Pragma(directive string, args ...string) {
|
||||||
|
c.activefunc().AddPragma(directive, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attributes sets function attributes for the currently active function.
|
||||||
|
func (c *Context) Attributes(a attr.Attribute) {
|
||||||
|
c.activefunc().Attributes = a
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signature sets the signature for the currently active function.
|
||||||
|
func (c *Context) Signature(s *gotypes.Signature) {
|
||||||
|
c.activefunc().SetSignature(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignatureExpr parses the signature expression and sets it as the active function's signature.
|
||||||
|
func (c *Context) SignatureExpr(expr string) {
|
||||||
|
s, err := gotypes.ParseSignatureInPackage(c.types(), expr)
|
||||||
|
if err != nil {
|
||||||
|
c.adderror(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Signature(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement starts building a function of the given name, whose type is
|
||||||
|
// specified by a stub in the containing package.
|
||||||
|
func (c *Context) Implement(name string) {
|
||||||
|
pkg := c.types()
|
||||||
|
if pkg == nil {
|
||||||
|
c.adderrormessage("no package specified")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s, err := gotypes.LookupSignature(pkg, name)
|
||||||
|
if err != nil {
|
||||||
|
c.adderror(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Function(name)
|
||||||
|
c.Signature(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) types() *types.Package {
|
||||||
|
if c.pkg == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.pkg.Types
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllocLocal allocates size bytes in the stack of the currently active function.
|
||||||
|
// Returns a reference to the base pointer for the newly allocated region.
|
||||||
|
func (c *Context) AllocLocal(size int) operand.Mem {
|
||||||
|
return c.activefunc().AllocLocal(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instruction adds an instruction to the active function.
|
||||||
|
func (c *Context) Instruction(i *ir.Instruction) {
|
||||||
|
c.activefunc().AddInstruction(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label adds a label to the active function.
|
||||||
|
func (c *Context) Label(name string) {
|
||||||
|
c.activefunc().AddLabel(ir.Label(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comment adds comment lines to the active function.
|
||||||
|
func (c *Context) Comment(lines ...string) {
|
||||||
|
c.activefunc().AddComment(lines...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commentf adds a formtted comment line.
|
||||||
|
func (c *Context) Commentf(format string, a ...any) {
|
||||||
|
c.Comment(fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) activefunc() *ir.Function {
|
||||||
|
if c.function == nil {
|
||||||
|
c.adderrormessage("no active function")
|
||||||
|
return ir.NewFunction("")
|
||||||
|
}
|
||||||
|
return c.function
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticGlobal adds a new static data section to the file and returns a pointer to it.
|
||||||
|
func (c *Context) StaticGlobal(name string) operand.Mem {
|
||||||
|
c.global = ir.NewStaticGlobal(name)
|
||||||
|
c.file.AddSection(c.global)
|
||||||
|
return c.global.Base()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataAttributes sets the attributes on the current active global data section.
|
||||||
|
func (c *Context) DataAttributes(a attr.Attribute) {
|
||||||
|
c.activeglobal().Attributes = a
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDatum adds constant v at offset to the current active global data section.
|
||||||
|
func (c *Context) AddDatum(offset int, v operand.Constant) {
|
||||||
|
if err := c.activeglobal().AddDatum(ir.NewDatum(offset, v)); err != nil {
|
||||||
|
c.adderror(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendDatum appends a constant to the current active global data section.
|
||||||
|
func (c *Context) AppendDatum(v operand.Constant) {
|
||||||
|
c.activeglobal().Append(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) activeglobal() *ir.Global {
|
||||||
|
if c.global == nil {
|
||||||
|
c.adderrormessage("no active global")
|
||||||
|
return ir.NewStaticGlobal("")
|
||||||
|
}
|
||||||
|
return c.global
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) adderror(err error) {
|
||||||
|
c.errs.addext(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) adderrormessage(msg string) {
|
||||||
|
c.adderror(errors.New(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result returns the built file and any accumulated errors.
|
||||||
|
func (c *Context) Result() (*ir.File, error) {
|
||||||
|
return c.file, c.errs.Err()
|
||||||
|
}
|
2
vendor/github.com/mmcloughlin/avo/build/doc.go
generated
vendored
Normal file
2
vendor/github.com/mmcloughlin/avo/build/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package build provides an assembly-like interface for incremental building of avo Files.
|
||||||
|
package build
|
91
vendor/github.com/mmcloughlin/avo/build/error.go
generated
vendored
Normal file
91
vendor/github.com/mmcloughlin/avo/build/error.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/internal/stack"
|
||||||
|
"github.com/mmcloughlin/avo/src"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error represents an error during building, optionally tagged with the position at which it happened.
|
||||||
|
type Error struct {
|
||||||
|
Position src.Position
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// exterr constructs an Error with position derived from the first frame in the
|
||||||
|
// call stack outside this package.
|
||||||
|
func exterr(err error) Error {
|
||||||
|
e := Error{Err: err}
|
||||||
|
if f := stack.ExternalCaller(); f != nil {
|
||||||
|
e.Position = src.FramePosition(*f).Relwd()
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Error) Error() string {
|
||||||
|
msg := e.Err.Error()
|
||||||
|
if e.Position.IsValid() {
|
||||||
|
return e.Position.String() + ": " + msg
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorList is a collection of errors for a source file.
|
||||||
|
type ErrorList []Error
|
||||||
|
|
||||||
|
// Add appends an error to the list.
|
||||||
|
func (e *ErrorList) Add(err Error) {
|
||||||
|
*e = append(*e, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAt appends an error at position p.
|
||||||
|
func (e *ErrorList) AddAt(p src.Position, err error) {
|
||||||
|
e.Add(Error{p, err})
|
||||||
|
}
|
||||||
|
|
||||||
|
// addext appends an error to the list, tagged with the first external position
|
||||||
|
// outside this package.
|
||||||
|
func (e *ErrorList) addext(err error) {
|
||||||
|
e.Add(exterr(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err returns an error equivalent to this error list.
|
||||||
|
// If the list is empty, Err returns nil.
|
||||||
|
func (e ErrorList) Err() error {
|
||||||
|
if len(e) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrorList) Error() string {
|
||||||
|
switch len(e) {
|
||||||
|
case 0:
|
||||||
|
return "no errors"
|
||||||
|
case 1:
|
||||||
|
return e[0].Error()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s (and %d more errors)", e[0], len(e)-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogError logs a list of errors, one error per line, if the err parameter is
|
||||||
|
// an ErrorList. Otherwise it just logs the err string. Reports at most max
|
||||||
|
// errors, or unlimited if max is 0.
|
||||||
|
func LogError(l *log.Logger, err error, max int) {
|
||||||
|
var list ErrorList
|
||||||
|
if errors.As(err, &list) {
|
||||||
|
for i, e := range list {
|
||||||
|
if max > 0 && i == max {
|
||||||
|
l.Print("too many errors")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l.Printf("%s\n", e)
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
l.Printf("%s\n", err)
|
||||||
|
}
|
||||||
|
}
|
163
vendor/github.com/mmcloughlin/avo/build/global.go
generated
vendored
Normal file
163
vendor/github.com/mmcloughlin/avo/build/global.go
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/attr"
|
||||||
|
"github.com/mmcloughlin/avo/buildtags"
|
||||||
|
"github.com/mmcloughlin/avo/gotypes"
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ctx provides a global build context.
|
||||||
|
var ctx = NewContext()
|
||||||
|
|
||||||
|
// TEXT starts building a new function called name, with attributes a, and sets its signature (see SignatureExpr).
|
||||||
|
func TEXT(name string, a attr.Attribute, signature string) {
|
||||||
|
ctx.Function(name)
|
||||||
|
ctx.Attributes(a)
|
||||||
|
ctx.SignatureExpr(signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLOBL declares a new static global data section with the given attributes.
|
||||||
|
func GLOBL(name string, a attr.Attribute) operand.Mem {
|
||||||
|
// TODO(mbm): should this be static?
|
||||||
|
g := ctx.StaticGlobal(name)
|
||||||
|
ctx.DataAttributes(a)
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// DATA adds a data value to the active data section.
|
||||||
|
func DATA(offset int, v operand.Constant) {
|
||||||
|
ctx.AddDatum(offset, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags = NewFlags(flag.CommandLine)
|
||||||
|
|
||||||
|
// Generate builds and compiles the avo file built with the global context. This
|
||||||
|
// should be the final line of any avo program. Configuration is determined from command-line flags.
|
||||||
|
func Generate() {
|
||||||
|
if !flag.Parsed() {
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
|
cfg := flags.Config()
|
||||||
|
|
||||||
|
status := Main(cfg, ctx)
|
||||||
|
|
||||||
|
// To record coverage of integration tests we wrap main() functions in a test
|
||||||
|
// functions. In this case we need the main function to terminate, therefore we
|
||||||
|
// only exit for failure status codes.
|
||||||
|
if status != 0 {
|
||||||
|
os.Exit(status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package sets the package the generated file will belong to. Required to be able to reference types in the package.
|
||||||
|
func Package(path string) { ctx.Package(path) }
|
||||||
|
|
||||||
|
// Constraints sets build constraints for the file.
|
||||||
|
func Constraints(t buildtags.ConstraintsConvertable) { ctx.Constraints(t) }
|
||||||
|
|
||||||
|
// Constraint appends a constraint to the file's build constraints.
|
||||||
|
func Constraint(t buildtags.ConstraintConvertable) { ctx.Constraint(t) }
|
||||||
|
|
||||||
|
// ConstraintExpr appends a constraint to the file's build constraints. The
|
||||||
|
// constraint to add is parsed from the given expression. The expression should
|
||||||
|
// look the same as the content following "// +build " in regular build
|
||||||
|
// constraint comments.
|
||||||
|
func ConstraintExpr(expr string) { ctx.ConstraintExpr(expr) }
|
||||||
|
|
||||||
|
// GP8L allocates and returns a general-purpose 8-bit register (low byte).
|
||||||
|
func GP8L() reg.GPVirtual { return ctx.GP8L() }
|
||||||
|
|
||||||
|
// GP8H allocates and returns a general-purpose 8-bit register (high byte).
|
||||||
|
func GP8H() reg.GPVirtual { return ctx.GP8H() }
|
||||||
|
|
||||||
|
// GP8 allocates and returns a general-purpose 8-bit register (low byte).
|
||||||
|
func GP8() reg.GPVirtual { return ctx.GP8() }
|
||||||
|
|
||||||
|
// GP16 allocates and returns a general-purpose 16-bit register.
|
||||||
|
func GP16() reg.GPVirtual { return ctx.GP16() }
|
||||||
|
|
||||||
|
// GP32 allocates and returns a general-purpose 32-bit register.
|
||||||
|
func GP32() reg.GPVirtual { return ctx.GP32() }
|
||||||
|
|
||||||
|
// GP64 allocates and returns a general-purpose 64-bit register.
|
||||||
|
func GP64() reg.GPVirtual { return ctx.GP64() }
|
||||||
|
|
||||||
|
// XMM allocates and returns a 128-bit vector register.
|
||||||
|
func XMM() reg.VecVirtual { return ctx.XMM() }
|
||||||
|
|
||||||
|
// YMM allocates and returns a 256-bit vector register.
|
||||||
|
func YMM() reg.VecVirtual { return ctx.YMM() }
|
||||||
|
|
||||||
|
// ZMM allocates and returns a 512-bit vector register.
|
||||||
|
func ZMM() reg.VecVirtual { return ctx.ZMM() }
|
||||||
|
|
||||||
|
// K allocates and returns an opmask register.
|
||||||
|
func K() reg.OpmaskVirtual { return ctx.K() }
|
||||||
|
|
||||||
|
// Param returns a the named argument of the active function.
|
||||||
|
func Param(name string) gotypes.Component { return ctx.Param(name) }
|
||||||
|
|
||||||
|
// ParamIndex returns the ith argument of the active function.
|
||||||
|
func ParamIndex(i int) gotypes.Component { return ctx.ParamIndex(i) }
|
||||||
|
|
||||||
|
// Return returns a the named return value of the active function.
|
||||||
|
func Return(name string) gotypes.Component { return ctx.Return(name) }
|
||||||
|
|
||||||
|
// ReturnIndex returns the ith argument of the active function.
|
||||||
|
func ReturnIndex(i int) gotypes.Component { return ctx.ReturnIndex(i) }
|
||||||
|
|
||||||
|
// Load the function argument src into register dst. Returns the destination
|
||||||
|
// register. This is syntactic sugar: it will attempt to select the right MOV
|
||||||
|
// instruction based on the types involved.
|
||||||
|
func Load(src gotypes.Component, dst reg.Register) reg.Register { return ctx.Load(src, dst) }
|
||||||
|
|
||||||
|
// Store register src into return value dst. This is syntactic sugar: it will
|
||||||
|
// attempt to select the right MOV instruction based on the types involved.
|
||||||
|
func Store(src reg.Register, dst gotypes.Component) { ctx.Store(src, dst) }
|
||||||
|
|
||||||
|
// Dereference loads a pointer and returns its element type.
|
||||||
|
func Dereference(ptr gotypes.Component) gotypes.Component { return ctx.Dereference(ptr) }
|
||||||
|
|
||||||
|
// Function starts building a new function with the given name.
|
||||||
|
func Function(name string) { ctx.Function(name) }
|
||||||
|
|
||||||
|
// Doc sets documentation comment lines for the currently active function.
|
||||||
|
func Doc(lines ...string) { ctx.Doc(lines...) }
|
||||||
|
|
||||||
|
// Pragma adds a compiler directive to the currently active function.
|
||||||
|
func Pragma(directive string, args ...string) { ctx.Pragma(directive, args...) }
|
||||||
|
|
||||||
|
// Attributes sets function attributes for the currently active function.
|
||||||
|
func Attributes(a attr.Attribute) { ctx.Attributes(a) }
|
||||||
|
|
||||||
|
// SignatureExpr parses the signature expression and sets it as the active function's signature.
|
||||||
|
func SignatureExpr(expr string) { ctx.SignatureExpr(expr) }
|
||||||
|
|
||||||
|
// Implement starts building a function of the given name, whose type is
|
||||||
|
// specified by a stub in the containing package.
|
||||||
|
func Implement(name string) { ctx.Implement(name) }
|
||||||
|
|
||||||
|
// AllocLocal allocates size bytes in the stack of the currently active function.
|
||||||
|
// Returns a reference to the base pointer for the newly allocated region.
|
||||||
|
func AllocLocal(size int) operand.Mem { return ctx.AllocLocal(size) }
|
||||||
|
|
||||||
|
// Label adds a label to the active function.
|
||||||
|
func Label(name string) { ctx.Label(name) }
|
||||||
|
|
||||||
|
// Comment adds comment lines to the active function.
|
||||||
|
func Comment(lines ...string) { ctx.Comment(lines...) }
|
||||||
|
|
||||||
|
// Commentf adds a formtted comment line.
|
||||||
|
func Commentf(format string, a ...any) { ctx.Commentf(format, a...) }
|
||||||
|
|
||||||
|
// ConstData builds a static data section containing just the given constant.
|
||||||
|
func ConstData(name string, v operand.Constant) operand.Mem { return ctx.ConstData(name, v) }
|
||||||
|
|
||||||
|
// Instruction adds an instruction to the active function.
|
||||||
|
func Instruction(i *ir.Instruction) { ctx.Instruction(i) }
|
69
vendor/github.com/mmcloughlin/avo/build/pseudo.go
generated
vendored
Normal file
69
vendor/github.com/mmcloughlin/avo/build/pseudo.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mmcloughlin/avo/attr"
|
||||||
|
"github.com/mmcloughlin/avo/gotypes"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate avogen -output zmov.go mov
|
||||||
|
|
||||||
|
// Param returns a the named argument of the active function.
|
||||||
|
func (c *Context) Param(name string) gotypes.Component {
|
||||||
|
return c.activefunc().Signature.Params().Lookup(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParamIndex returns the ith argument of the active function.
|
||||||
|
func (c *Context) ParamIndex(i int) gotypes.Component {
|
||||||
|
return c.activefunc().Signature.Params().At(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return returns a the named return value of the active function.
|
||||||
|
func (c *Context) Return(name string) gotypes.Component {
|
||||||
|
return c.activefunc().Signature.Results().Lookup(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReturnIndex returns the ith argument of the active function.
|
||||||
|
func (c *Context) ReturnIndex(i int) gotypes.Component {
|
||||||
|
return c.activefunc().Signature.Results().At(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the function argument src into register dst. Returns the destination
|
||||||
|
// register. This is syntactic sugar: it will attempt to select the right MOV
|
||||||
|
// instruction based on the types involved.
|
||||||
|
func (c *Context) Load(src gotypes.Component, dst reg.Register) reg.Register {
|
||||||
|
b, err := src.Resolve()
|
||||||
|
if err != nil {
|
||||||
|
c.adderror(err)
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
c.mov(b.Addr, dst, int(gotypes.Sizes.Sizeof(b.Type)), int(dst.Size()), b.Type)
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store register src into return value dst. This is syntactic sugar: it will
|
||||||
|
// attempt to select the right MOV instruction based on the types involved.
|
||||||
|
func (c *Context) Store(src reg.Register, dst gotypes.Component) {
|
||||||
|
b, err := dst.Resolve()
|
||||||
|
if err != nil {
|
||||||
|
c.adderror(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.mov(src, b.Addr, int(src.Size()), int(gotypes.Sizes.Sizeof(b.Type)), b.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dereference loads a pointer and returns its element type.
|
||||||
|
func (c *Context) Dereference(ptr gotypes.Component) gotypes.Component {
|
||||||
|
r := c.GP64()
|
||||||
|
c.Load(ptr, r)
|
||||||
|
return ptr.Dereference(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstData builds a static data section containing just the given constant.
|
||||||
|
func (c *Context) ConstData(name string, v operand.Constant) operand.Mem {
|
||||||
|
g := c.StaticGlobal(name)
|
||||||
|
c.DataAttributes(attr.RODATA | attr.NOPTR)
|
||||||
|
c.AppendDatum(v)
|
||||||
|
return g
|
||||||
|
}
|
86852
vendor/github.com/mmcloughlin/avo/build/zinstructions.go
generated
vendored
Normal file
86852
vendor/github.com/mmcloughlin/avo/build/zinstructions.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
294
vendor/github.com/mmcloughlin/avo/build/zmov.go
generated
vendored
Normal file
294
vendor/github.com/mmcloughlin/avo/build/zmov.go
generated
vendored
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
// Code generated by command: avogen -output zmov.go mov. DO NOT EDIT.
|
||||||
|
|
||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Context) mov(a, b operand.Op, an, bn int, t *types.Basic) {
|
||||||
|
switch {
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVB(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 1 && operand.IsM8(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVB(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVB(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVB(a, b)
|
||||||
|
case an == 4 && operand.IsR32(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVB(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVD(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 4 && operand.IsM32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVD(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVD(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVD(a, b)
|
||||||
|
case an == 4 && operand.IsR32(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVD(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 8 && operand.IsM64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsM64(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsR64(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVW(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 2 && operand.IsM16(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVW(a, b)
|
||||||
|
case an == 8 && operand.IsK(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVW(a, b)
|
||||||
|
case an == 2 && operand.IsM16(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVW(a, b)
|
||||||
|
case an == 4 && operand.IsR32(a) && bn == 8 && operand.IsK(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.KMOVW(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 1 && operand.IsR8(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVB(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 1 && operand.IsM8(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVB(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 1 && operand.IsR8(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVB(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVBLSX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVBLSX(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVBLZX(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 4 && operand.IsR32(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVBLZX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVBLZX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 4 && operand.IsR32(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVBLZX(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVBQSX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVBQSX(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVBQZX(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 8 && operand.IsR64(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVBQZX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVBQZX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 8 && operand.IsR64(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVBQZX(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 2 && operand.IsR16(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVBWSX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 2 && operand.IsR16(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVBWSX(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 2 && operand.IsR16(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVBWZX(a, b)
|
||||||
|
case an == 1 && operand.IsM8(a) && bn == 2 && operand.IsR16(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVBWZX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 2 && operand.IsR16(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVBWZX(a, b)
|
||||||
|
case an == 1 && operand.IsR8(a) && bn == 2 && operand.IsR16(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVBWZX(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVL(a, b)
|
||||||
|
case an == 4 && operand.IsR32(a) && bn == 4 && operand.IsM32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVL(a, b)
|
||||||
|
case an == 4 && operand.IsR32(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVL(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVLQSX(a, b)
|
||||||
|
case an == 4 && operand.IsR32(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVLQSX(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVLQZX(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 8 && operand.IsR64(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVLQZX(a, b)
|
||||||
|
case an == 16 && operand.IsM128(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVOU(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsM128(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVOU(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVOU(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsM64(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 4 && operand.IsR32(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsR64(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 4 && operand.IsM32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 8 && operand.IsM64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsM64(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsR64(a) && bn == 8 && operand.IsM64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsR64(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsM64(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.MOVSD(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 8 && operand.IsM64(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.MOVSD(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.MOVSD(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.MOVSS(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 4 && operand.IsM32(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.MOVSS(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.MOVSS(a, b)
|
||||||
|
case an == 2 && operand.IsM16(a) && bn == 2 && operand.IsR16(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVW(a, b)
|
||||||
|
case an == 2 && operand.IsR16(a) && bn == 2 && operand.IsM16(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVW(a, b)
|
||||||
|
case an == 2 && operand.IsR16(a) && bn == 2 && operand.IsR16(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.MOVW(a, b)
|
||||||
|
case an == 2 && operand.IsM16(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVWLSX(a, b)
|
||||||
|
case an == 2 && operand.IsR16(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVWLSX(a, b)
|
||||||
|
case an == 2 && operand.IsM16(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVWLZX(a, b)
|
||||||
|
case an == 2 && operand.IsM16(a) && bn == 4 && operand.IsR32(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVWLZX(a, b)
|
||||||
|
case an == 2 && operand.IsR16(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVWLZX(a, b)
|
||||||
|
case an == 2 && operand.IsR16(a) && bn == 4 && operand.IsR32(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVWLZX(a, b)
|
||||||
|
case an == 2 && operand.IsM16(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVWQSX(a, b)
|
||||||
|
case an == 2 && operand.IsR16(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == types.IsInteger:
|
||||||
|
c.MOVWQSX(a, b)
|
||||||
|
case an == 2 && operand.IsM16(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVWQZX(a, b)
|
||||||
|
case an == 2 && operand.IsM16(a) && bn == 8 && operand.IsR64(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVWQZX(a, b)
|
||||||
|
case an == 2 && operand.IsR16(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsUnsigned)) == (types.IsInteger|types.IsUnsigned):
|
||||||
|
c.MOVWQZX(a, b)
|
||||||
|
case an == 2 && operand.IsR16(a) && bn == 8 && operand.IsR64(b) && (t.Info()&types.IsBoolean) != 0:
|
||||||
|
c.MOVWQZX(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVD(a, b)
|
||||||
|
case an == 4 && operand.IsR32(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVD(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 4 && operand.IsM32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVD(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 4 && operand.IsR32(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVD(a, b)
|
||||||
|
case an == 16 && operand.IsM128(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU(a, b)
|
||||||
|
case an == 32 && operand.IsM256(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsM128(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsM256(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU(a, b)
|
||||||
|
case an == 16 && operand.IsM128(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 32 && operand.IsM256(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsM128(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsM256(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 64 && operand.IsM512(a) && bn == 64 && operand.IsZMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 64 && operand.IsZMM(a) && bn == 64 && operand.IsM512(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 64 && operand.IsZMM(a) && bn == 64 && operand.IsZMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU16(a, b)
|
||||||
|
case an == 16 && operand.IsM128(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 32 && operand.IsM256(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsM128(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsM256(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 64 && operand.IsM512(a) && bn == 64 && operand.IsZMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 64 && operand.IsZMM(a) && bn == 64 && operand.IsM512(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 64 && operand.IsZMM(a) && bn == 64 && operand.IsZMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU32(a, b)
|
||||||
|
case an == 16 && operand.IsM128(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 32 && operand.IsM256(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsM128(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsM256(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 64 && operand.IsM512(a) && bn == 64 && operand.IsZMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 64 && operand.IsZMM(a) && bn == 64 && operand.IsM512(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 64 && operand.IsZMM(a) && bn == 64 && operand.IsZMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU64(a, b)
|
||||||
|
case an == 16 && operand.IsM128(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 32 && operand.IsM256(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsM128(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsM256(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 32 && operand.IsYMM(a) && bn == 32 && operand.IsYMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 64 && operand.IsM512(a) && bn == 64 && operand.IsZMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 64 && operand.IsZMM(a) && bn == 64 && operand.IsM512(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 64 && operand.IsZMM(a) && bn == 64 && operand.IsZMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVDQU8(a, b)
|
||||||
|
case an == 8 && operand.IsM64(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsR64(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVQ(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 8 && operand.IsM64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVQ(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 8 && operand.IsR64(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVQ(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&(types.IsInteger|types.IsBoolean)) != 0:
|
||||||
|
c.VMOVQ(a, b)
|
||||||
|
case an == 8 && operand.IsM64(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.VMOVSD(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 8 && operand.IsM64(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.VMOVSD(a, b)
|
||||||
|
case an == 4 && operand.IsM32(a) && bn == 16 && operand.IsXMM(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.VMOVSS(a, b)
|
||||||
|
case an == 16 && operand.IsXMM(a) && bn == 4 && operand.IsM32(b) && (t.Info()&types.IsFloat) != 0:
|
||||||
|
c.VMOVSS(a, b)
|
||||||
|
default:
|
||||||
|
c.adderrormessage("could not deduce mov instruction")
|
||||||
|
}
|
||||||
|
}
|
312
vendor/github.com/mmcloughlin/avo/buildtags/buildtags.go
generated
vendored
Normal file
312
vendor/github.com/mmcloughlin/avo/buildtags/buildtags.go
generated
vendored
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
// Package buildtags provides types for representing and manipulating build constraints.
|
||||||
|
//
|
||||||
|
// In Go, build constraints are represented as comments in source code together with file naming conventions. For example
|
||||||
|
//
|
||||||
|
// // +build linux,386 darwin,!cgo
|
||||||
|
// // +build !purego
|
||||||
|
//
|
||||||
|
// Any terms provided in the filename can be thought of as an implicit extra
|
||||||
|
// constraint comment line. Collectively, these are referred to as
|
||||||
|
// “constraints”. Each line is a “constraint”. Within each constraint the
|
||||||
|
// space-separated terms are “options”, and within that the comma-separated
|
||||||
|
// items are “terms” which may be negated with at most one exclaimation mark.
|
||||||
|
//
|
||||||
|
// These represent a boolean formulae. The constraints are evaluated as the AND
|
||||||
|
// of constraint lines; a constraint is evaluated as the OR of its options and
|
||||||
|
// an option is evaluated as the AND of its terms. Overall build constraints are
|
||||||
|
// a boolean formula that is an AND of ORs of ANDs.
|
||||||
|
//
|
||||||
|
// This level of complexity is rarely used in Go programs. Therefore this
|
||||||
|
// package aims to provide access to all these layers of nesting if required,
|
||||||
|
// but make it easy to forget about for basic use cases too.
|
||||||
|
package buildtags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference: https://github.com/golang/go/blob/204a8f55dc2e0ac8d27a781dab0da609b98560da/src/go/build/doc.go#L73-L92
|
||||||
|
//
|
||||||
|
// // A build constraint is evaluated as the OR of space-separated options;
|
||||||
|
// // each option evaluates as the AND of its comma-separated terms;
|
||||||
|
// // and each term is an alphanumeric word or, preceded by !, its negation.
|
||||||
|
// // That is, the build constraint:
|
||||||
|
// //
|
||||||
|
// // // +build linux,386 darwin,!cgo
|
||||||
|
// //
|
||||||
|
// // corresponds to the boolean formula:
|
||||||
|
// //
|
||||||
|
// // (linux AND 386) OR (darwin AND (NOT cgo))
|
||||||
|
// //
|
||||||
|
// // A file may have multiple build constraints. The overall constraint is the AND
|
||||||
|
// // of the individual constraints. That is, the build constraints:
|
||||||
|
// //
|
||||||
|
// // // +build linux darwin
|
||||||
|
// // // +build 386
|
||||||
|
// //
|
||||||
|
// // corresponds to the boolean formula:
|
||||||
|
// //
|
||||||
|
// // (linux OR darwin) AND 386
|
||||||
|
//
|
||||||
|
|
||||||
|
// Interface represents a build constraint.
|
||||||
|
type Interface interface {
|
||||||
|
ConstraintsConvertable
|
||||||
|
fmt.GoStringer
|
||||||
|
Evaluate(v map[string]bool) bool
|
||||||
|
Validate() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstraintsConvertable can be converted to a Constraints object.
|
||||||
|
type ConstraintsConvertable interface {
|
||||||
|
ToConstraints() Constraints
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstraintConvertable can be converted to a Constraint.
|
||||||
|
type ConstraintConvertable interface {
|
||||||
|
ToConstraint() Constraint
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionConvertable can be converted to an Option.
|
||||||
|
type OptionConvertable interface {
|
||||||
|
ToOption() Option
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraints represents the AND of a list of Constraint lines.
|
||||||
|
type Constraints []Constraint
|
||||||
|
|
||||||
|
// And builds Constraints that will be true if all of its constraints are true.
|
||||||
|
func And(cs ...ConstraintConvertable) Constraints {
|
||||||
|
constraints := Constraints{}
|
||||||
|
for _, c := range cs {
|
||||||
|
constraints = append(constraints, c.ToConstraint())
|
||||||
|
}
|
||||||
|
return constraints
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToConstraints returns cs.
|
||||||
|
func (cs Constraints) ToConstraints() Constraints { return cs }
|
||||||
|
|
||||||
|
// Validate validates the constraints set.
|
||||||
|
func (cs Constraints) Validate() error {
|
||||||
|
for _, c := range cs {
|
||||||
|
if err := c.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate the boolean formula represented by cs under the given assignment of
|
||||||
|
// tag values. This is the AND of the values of the constituent Constraints.
|
||||||
|
func (cs Constraints) Evaluate(v map[string]bool) bool {
|
||||||
|
r := true
|
||||||
|
for _, c := range cs {
|
||||||
|
r = r && c.Evaluate(v)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoString represents Constraints as +build comment lines.
|
||||||
|
func (cs Constraints) GoString() string {
|
||||||
|
s := ""
|
||||||
|
for _, c := range cs {
|
||||||
|
s += c.GoString()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraint represents the OR of a list of Options.
|
||||||
|
type Constraint []Option
|
||||||
|
|
||||||
|
// Any builds a Constraint that will be true if any of its options are true.
|
||||||
|
func Any(opts ...OptionConvertable) Constraint {
|
||||||
|
c := Constraint{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
c = append(c, opt.ToOption())
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseConstraint parses a space-separated list of options.
|
||||||
|
func ParseConstraint(expr string) (Constraint, error) {
|
||||||
|
c := Constraint{}
|
||||||
|
for _, field := range strings.Fields(expr) {
|
||||||
|
opt, err := ParseOption(field)
|
||||||
|
if err != nil {
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
c = append(c, opt)
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToConstraints returns the list of constraints containing just c.
|
||||||
|
func (c Constraint) ToConstraints() Constraints { return Constraints{c} }
|
||||||
|
|
||||||
|
// ToConstraint returns c.
|
||||||
|
func (c Constraint) ToConstraint() Constraint { return c }
|
||||||
|
|
||||||
|
// Validate validates the constraint.
|
||||||
|
func (c Constraint) Validate() error {
|
||||||
|
for _, o := range c {
|
||||||
|
if err := o.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate the boolean formula represented by c under the given assignment of
|
||||||
|
// tag values. This is the OR of the values of the constituent Options.
|
||||||
|
func (c Constraint) Evaluate(v map[string]bool) bool {
|
||||||
|
r := false
|
||||||
|
for _, o := range c {
|
||||||
|
r = r || o.Evaluate(v)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoString represents the Constraint as one +build comment line.
|
||||||
|
func (c Constraint) GoString() string {
|
||||||
|
s := "// +build"
|
||||||
|
for _, o := range c {
|
||||||
|
s += " " + o.GoString()
|
||||||
|
}
|
||||||
|
return s + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option represents the AND of a list of Terms.
|
||||||
|
type Option []Term
|
||||||
|
|
||||||
|
// Opt builds an Option from the list of Terms.
|
||||||
|
func Opt(terms ...Term) Option {
|
||||||
|
return Option(terms)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseOption parses a comma-separated list of terms.
|
||||||
|
func ParseOption(expr string) (Option, error) {
|
||||||
|
opt := Option{}
|
||||||
|
for _, t := range strings.Split(expr, ",") {
|
||||||
|
opt = append(opt, Term(t))
|
||||||
|
}
|
||||||
|
return opt, opt.Validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToConstraints returns Constraints containing just this option.
|
||||||
|
func (o Option) ToConstraints() Constraints { return o.ToConstraint().ToConstraints() }
|
||||||
|
|
||||||
|
// ToConstraint returns a Constraint containing just this option.
|
||||||
|
func (o Option) ToConstraint() Constraint { return Constraint{o} }
|
||||||
|
|
||||||
|
// ToOption returns o.
|
||||||
|
func (o Option) ToOption() Option { return o }
|
||||||
|
|
||||||
|
// Validate validates o.
|
||||||
|
func (o Option) Validate() error {
|
||||||
|
for _, t := range o {
|
||||||
|
if err := t.Validate(); err != nil {
|
||||||
|
return fmt.Errorf("invalid term %q: %w", t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate the boolean formula represented by o under the given assignment of
|
||||||
|
// tag values. This is the AND of the values of the constituent Terms.
|
||||||
|
func (o Option) Evaluate(v map[string]bool) bool {
|
||||||
|
r := true
|
||||||
|
for _, t := range o {
|
||||||
|
r = r && t.Evaluate(v)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoString represents the Option as a comma-separated list of terms.
|
||||||
|
func (o Option) GoString() string {
|
||||||
|
var ts []string
|
||||||
|
for _, t := range o {
|
||||||
|
ts = append(ts, t.GoString())
|
||||||
|
}
|
||||||
|
return strings.Join(ts, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Term is an atomic term in a build constraint: an identifier or its negation.
|
||||||
|
type Term string
|
||||||
|
|
||||||
|
// Not returns a term for the negation of ident.
|
||||||
|
func Not(ident string) Term {
|
||||||
|
return Term("!" + ident)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToConstraints returns Constraints containing just this term.
|
||||||
|
func (t Term) ToConstraints() Constraints { return t.ToOption().ToConstraints() }
|
||||||
|
|
||||||
|
// ToConstraint returns a Constraint containing just this term.
|
||||||
|
func (t Term) ToConstraint() Constraint { return t.ToOption().ToConstraint() }
|
||||||
|
|
||||||
|
// ToOption returns an Option containing just this term.
|
||||||
|
func (t Term) ToOption() Option { return Option{t} }
|
||||||
|
|
||||||
|
// IsNegated reports whether t is the negation of an identifier.
|
||||||
|
func (t Term) IsNegated() bool { return strings.HasPrefix(string(t), "!") }
|
||||||
|
|
||||||
|
// Name returns the identifier for this term.
|
||||||
|
func (t Term) Name() string {
|
||||||
|
return strings.TrimPrefix(string(t), "!")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the term.
|
||||||
|
func (t Term) Validate() error {
|
||||||
|
// Reference: https://github.com/golang/go/blob/204a8f55dc2e0ac8d27a781dab0da609b98560da/src/cmd/go/internal/imports/build.go#L110-L112
|
||||||
|
//
|
||||||
|
// if strings.HasPrefix(name, "!!") { // bad syntax, reject always
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
if strings.HasPrefix(string(t), "!!") {
|
||||||
|
return errors.New("at most one '!' allowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(t.Name()) == 0 {
|
||||||
|
return errors.New("empty tag name")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference: https://github.com/golang/go/blob/204a8f55dc2e0ac8d27a781dab0da609b98560da/src/cmd/go/internal/imports/build.go#L121-L127
|
||||||
|
//
|
||||||
|
// // Tags must be letters, digits, underscores or dots.
|
||||||
|
// // Unlike in Go identifiers, all digits are fine (e.g., "386").
|
||||||
|
// for _, c := range name {
|
||||||
|
// if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
for _, c := range t.Name() {
|
||||||
|
if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
|
||||||
|
return fmt.Errorf("character '%c' disallowed in tags", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate the term under the given set of identifier values.
|
||||||
|
func (t Term) Evaluate(v map[string]bool) bool {
|
||||||
|
return (t.Validate() == nil) && (v[t.Name()] == !t.IsNegated())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoString returns t.
|
||||||
|
func (t Term) GoString() string { return string(t) }
|
||||||
|
|
||||||
|
// SetTags builds a set where the given list of identifiers are true.
|
||||||
|
func SetTags(idents ...string) map[string]bool {
|
||||||
|
v := map[string]bool{}
|
||||||
|
for _, ident := range idents {
|
||||||
|
v[ident] = true
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
46
vendor/github.com/mmcloughlin/avo/buildtags/syntax.go
generated
vendored
Normal file
46
vendor/github.com/mmcloughlin/avo/buildtags/syntax.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package buildtags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PlusBuildSyntaxSupported reports whether the current Go version supports the
|
||||||
|
// "// +build" constraint syntax.
|
||||||
|
func PlusBuildSyntaxSupported() bool { return plusbuild }
|
||||||
|
|
||||||
|
// GoBuildSyntaxSupported reports whether the current Go version supports the
|
||||||
|
// "//go:build" constraint syntax.
|
||||||
|
func GoBuildSyntaxSupported() bool { return gobuild }
|
||||||
|
|
||||||
|
// Format constraints according to the syntax supported by the current Go version.
|
||||||
|
func Format(t ConstraintsConvertable) (string, error) {
|
||||||
|
// Print build tags to minimal Go source that can be passed to go/format.
|
||||||
|
src := t.ToConstraints().GoString() + "\npackage stub"
|
||||||
|
|
||||||
|
// Format them.
|
||||||
|
formatted, err := format.Source([]byte(src))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("format build constraints: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the comment lines.
|
||||||
|
buf := bytes.NewReader(formatted)
|
||||||
|
scanner := bufio.NewScanner(buf)
|
||||||
|
output := ""
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
if (PlusBuildSyntaxSupported() && strings.HasPrefix(line, "// +build")) ||
|
||||||
|
(GoBuildSyntaxSupported() && strings.HasPrefix(line, "//go:build")) {
|
||||||
|
output += line + "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return "", fmt.Errorf("parse formatted build constraints: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output, nil
|
||||||
|
}
|
8
vendor/github.com/mmcloughlin/avo/buildtags/syntax_go116.go
generated
vendored
Normal file
8
vendor/github.com/mmcloughlin/avo/buildtags/syntax_go116.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//go:build !go1.17
|
||||||
|
|
||||||
|
package buildtags
|
||||||
|
|
||||||
|
const (
|
||||||
|
plusbuild = true
|
||||||
|
gobuild = false
|
||||||
|
)
|
8
vendor/github.com/mmcloughlin/avo/buildtags/syntax_go117.go
generated
vendored
Normal file
8
vendor/github.com/mmcloughlin/avo/buildtags/syntax_go117.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//go:build go1.17 && !go1.18
|
||||||
|
|
||||||
|
package buildtags
|
||||||
|
|
||||||
|
const (
|
||||||
|
plusbuild = true
|
||||||
|
gobuild = true
|
||||||
|
)
|
8
vendor/github.com/mmcloughlin/avo/buildtags/syntax_go118.go
generated
vendored
Normal file
8
vendor/github.com/mmcloughlin/avo/buildtags/syntax_go118.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//go:build go1.18
|
||||||
|
|
||||||
|
package buildtags
|
||||||
|
|
||||||
|
const (
|
||||||
|
plusbuild = false
|
||||||
|
gobuild = true
|
||||||
|
)
|
253
vendor/github.com/mmcloughlin/avo/gotypes/components.go
generated
vendored
Normal file
253
vendor/github.com/mmcloughlin/avo/gotypes/components.go
generated
vendored
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
package gotypes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sizes provides type sizes used by the standard Go compiler on amd64.
|
||||||
|
var Sizes = types.SizesFor("gc", "amd64")
|
||||||
|
|
||||||
|
// PointerSize is the size of a pointer on amd64.
|
||||||
|
var PointerSize = Sizes.Sizeof(types.Typ[types.UnsafePointer])
|
||||||
|
|
||||||
|
// Basic represents a primitive/basic type at a given memory address.
|
||||||
|
type Basic struct {
|
||||||
|
Addr operand.Mem
|
||||||
|
Type *types.Basic
|
||||||
|
}
|
||||||
|
|
||||||
|
// Component provides access to sub-components of a Go type.
|
||||||
|
type Component interface {
|
||||||
|
// When the component has no further sub-components, Resolve will return a
|
||||||
|
// reference to the components type and memory address. If there was an error
|
||||||
|
// during any previous calls to Component methods, they will be returned at
|
||||||
|
// resolution time.
|
||||||
|
Resolve() (*Basic, error)
|
||||||
|
Dereference(r reg.Register) Component // dereference a pointer
|
||||||
|
Base() Component // base pointer of a string or slice
|
||||||
|
Len() Component // length of a string or slice
|
||||||
|
Cap() Component // capacity of a slice
|
||||||
|
Real() Component // real part of a complex value
|
||||||
|
Imag() Component // imaginary part of a complex value
|
||||||
|
Index(int) Component // index into an array
|
||||||
|
Field(string) Component // access a struct field
|
||||||
|
}
|
||||||
|
|
||||||
|
// componenterr is an error that also provides a null implementation of the
|
||||||
|
// Component interface. This enables us to return an error from Component
|
||||||
|
// methods whilst also allowing method chaining to continue.
|
||||||
|
type componenterr string
|
||||||
|
|
||||||
|
func errorf(format string, args ...any) Component {
|
||||||
|
return componenterr(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c componenterr) Error() string { return string(c) }
|
||||||
|
func (c componenterr) Resolve() (*Basic, error) { return nil, c }
|
||||||
|
func (c componenterr) Dereference(r reg.Register) Component { return c }
|
||||||
|
func (c componenterr) Base() Component { return c }
|
||||||
|
func (c componenterr) Len() Component { return c }
|
||||||
|
func (c componenterr) Cap() Component { return c }
|
||||||
|
func (c componenterr) Real() Component { return c }
|
||||||
|
func (c componenterr) Imag() Component { return c }
|
||||||
|
func (c componenterr) Index(int) Component { return c }
|
||||||
|
func (c componenterr) Field(string) Component { return c }
|
||||||
|
|
||||||
|
type component struct {
|
||||||
|
typ types.Type
|
||||||
|
addr operand.Mem
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewComponent builds a component for the named type at the given address.
|
||||||
|
func NewComponent(t types.Type, addr operand.Mem) Component {
|
||||||
|
return &component{
|
||||||
|
typ: t,
|
||||||
|
addr: addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) Resolve() (*Basic, error) {
|
||||||
|
b := toprimitive(c.typ)
|
||||||
|
if b == nil {
|
||||||
|
return nil, errors.New("component is not primitive")
|
||||||
|
}
|
||||||
|
return &Basic{
|
||||||
|
Addr: c.addr,
|
||||||
|
Type: b,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) Dereference(r reg.Register) Component {
|
||||||
|
p, ok := c.typ.Underlying().(*types.Pointer)
|
||||||
|
if !ok {
|
||||||
|
return errorf("not pointer type")
|
||||||
|
}
|
||||||
|
return NewComponent(p.Elem(), operand.Mem{Base: r})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference: https://github.com/golang/go/blob/50bd1c4d4eb4fac8ddeb5f063c099daccfb71b26/src/reflect/value.go#L1800-L1804
|
||||||
|
//
|
||||||
|
// type SliceHeader struct {
|
||||||
|
// Data uintptr
|
||||||
|
// Len int
|
||||||
|
// Cap int
|
||||||
|
// }
|
||||||
|
var slicehdroffsets = Sizes.Offsetsof([]*types.Var{
|
||||||
|
types.NewField(token.NoPos, nil, "Data", types.Typ[types.Uintptr], false),
|
||||||
|
types.NewField(token.NoPos, nil, "Len", types.Typ[types.Int], false),
|
||||||
|
types.NewField(token.NoPos, nil, "Cap", types.Typ[types.Int], false),
|
||||||
|
})
|
||||||
|
|
||||||
|
func (c *component) Base() Component {
|
||||||
|
if !isslice(c.typ) && !isstring(c.typ) {
|
||||||
|
return errorf("only slices and strings have base pointers")
|
||||||
|
}
|
||||||
|
return c.sub("_base", int(slicehdroffsets[0]), types.Typ[types.Uintptr])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) Len() Component {
|
||||||
|
if !isslice(c.typ) && !isstring(c.typ) {
|
||||||
|
return errorf("only slices and strings have length fields")
|
||||||
|
}
|
||||||
|
return c.sub("_len", int(slicehdroffsets[1]), types.Typ[types.Int])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) Cap() Component {
|
||||||
|
if !isslice(c.typ) {
|
||||||
|
return errorf("only slices have capacity fields")
|
||||||
|
}
|
||||||
|
return c.sub("_cap", int(slicehdroffsets[2]), types.Typ[types.Int])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) Real() Component {
|
||||||
|
if !iscomplex(c.typ) {
|
||||||
|
return errorf("only complex types have real values")
|
||||||
|
}
|
||||||
|
f := complextofloat(c.typ)
|
||||||
|
return c.sub("_real", 0, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) Imag() Component {
|
||||||
|
if !iscomplex(c.typ) {
|
||||||
|
return errorf("only complex types have imaginary values")
|
||||||
|
}
|
||||||
|
f := complextofloat(c.typ)
|
||||||
|
return c.sub("_imag", int(Sizes.Sizeof(f)), f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) Index(i int) Component {
|
||||||
|
a, ok := c.typ.Underlying().(*types.Array)
|
||||||
|
if !ok {
|
||||||
|
return errorf("not array type")
|
||||||
|
}
|
||||||
|
if int64(i) >= a.Len() {
|
||||||
|
return errorf("array index out of bounds")
|
||||||
|
}
|
||||||
|
// Reference: https://github.com/golang/tools/blob/bcd4e47d02889ebbc25c9f4bf3d27e4124b0bf9d/go/analysis/passes/asmdecl/asmdecl.go#L482-L494
|
||||||
|
//
|
||||||
|
// case asmArray:
|
||||||
|
// tu := t.Underlying().(*types.Array)
|
||||||
|
// elem := tu.Elem()
|
||||||
|
// // Calculate offset of each element array.
|
||||||
|
// fields := []*types.Var{
|
||||||
|
// types.NewVar(token.NoPos, nil, "fake0", elem),
|
||||||
|
// types.NewVar(token.NoPos, nil, "fake1", elem),
|
||||||
|
// }
|
||||||
|
// offsets := arch.sizes.Offsetsof(fields)
|
||||||
|
// elemoff := int(offsets[1])
|
||||||
|
// for i := 0; i < int(tu.Len()); i++ {
|
||||||
|
// cc = appendComponentsRecursive(arch, elem, cc, suffix+"_"+strconv.Itoa(i), i*elemoff)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
elem := a.Elem()
|
||||||
|
elemsize := int(Sizes.Sizeof(types.NewArray(elem, 2)) - Sizes.Sizeof(types.NewArray(elem, 1)))
|
||||||
|
return c.sub("_"+strconv.Itoa(i), i*elemsize, elem)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) Field(n string) Component {
|
||||||
|
s, ok := c.typ.Underlying().(*types.Struct)
|
||||||
|
if !ok {
|
||||||
|
return errorf("not struct type")
|
||||||
|
}
|
||||||
|
// Reference: https://github.com/golang/tools/blob/13ba8ad772dfbf0f451b5dd0679e9c5605afc05d/go/analysis/passes/asmdecl/asmdecl.go#L471-L480
|
||||||
|
//
|
||||||
|
// case asmStruct:
|
||||||
|
// tu := t.Underlying().(*types.Struct)
|
||||||
|
// fields := make([]*types.Var, tu.NumFields())
|
||||||
|
// for i := 0; i < tu.NumFields(); i++ {
|
||||||
|
// fields[i] = tu.Field(i)
|
||||||
|
// }
|
||||||
|
// offsets := arch.sizes.Offsetsof(fields)
|
||||||
|
// for i, f := range fields {
|
||||||
|
// cc = appendComponentsRecursive(arch, f.Type(), cc, suffix+"_"+f.Name(), off+int(offsets[i]))
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
fields := make([]*types.Var, s.NumFields())
|
||||||
|
for i := 0; i < s.NumFields(); i++ {
|
||||||
|
fields[i] = s.Field(i)
|
||||||
|
}
|
||||||
|
offsets := Sizes.Offsetsof(fields)
|
||||||
|
for i, f := range fields {
|
||||||
|
if f.Name() == n {
|
||||||
|
return c.sub("_"+n, int(offsets[i]), f.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorf("struct does not have field '%s'", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *component) sub(suffix string, offset int, t types.Type) *component {
|
||||||
|
s := *c
|
||||||
|
if s.addr.Symbol.Name != "" {
|
||||||
|
s.addr.Symbol.Name += suffix
|
||||||
|
}
|
||||||
|
s.addr = s.addr.Offset(offset)
|
||||||
|
s.typ = t
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|
||||||
|
func isslice(t types.Type) bool {
|
||||||
|
_, ok := t.Underlying().(*types.Slice)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func isstring(t types.Type) bool {
|
||||||
|
b, ok := t.Underlying().(*types.Basic)
|
||||||
|
return ok && b.Kind() == types.String
|
||||||
|
}
|
||||||
|
|
||||||
|
func iscomplex(t types.Type) bool {
|
||||||
|
b, ok := t.Underlying().(*types.Basic)
|
||||||
|
return ok && (b.Info()&types.IsComplex) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func complextofloat(t types.Type) types.Type {
|
||||||
|
switch Sizes.Sizeof(t) {
|
||||||
|
case 16:
|
||||||
|
return types.Typ[types.Float64]
|
||||||
|
case 8:
|
||||||
|
return types.Typ[types.Float32]
|
||||||
|
}
|
||||||
|
panic("bad")
|
||||||
|
}
|
||||||
|
|
||||||
|
// toprimitive determines whether t is primitive (cannot be reduced into
|
||||||
|
// components). If it is, it returns the basic type for t, otherwise returns
|
||||||
|
// nil.
|
||||||
|
func toprimitive(t types.Type) *types.Basic {
|
||||||
|
switch b := t.(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
if (b.Info() & (types.IsString | types.IsComplex)) == 0 {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
case *types.Pointer:
|
||||||
|
return types.Typ[types.Uintptr]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
2
vendor/github.com/mmcloughlin/avo/gotypes/doc.go
generated
vendored
Normal file
2
vendor/github.com/mmcloughlin/avo/gotypes/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package gotypes provides helpers for interacting with Go types within avo functions.
|
||||||
|
package gotypes
|
193
vendor/github.com/mmcloughlin/avo/gotypes/signature.go
generated
vendored
Normal file
193
vendor/github.com/mmcloughlin/avo/gotypes/signature.go
generated
vendored
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
package gotypes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Signature represents a Go function signature.
|
||||||
|
type Signature struct {
|
||||||
|
pkg *types.Package
|
||||||
|
sig *types.Signature
|
||||||
|
params *Tuple
|
||||||
|
results *Tuple
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSignature constructs a Signature.
|
||||||
|
func NewSignature(pkg *types.Package, sig *types.Signature) *Signature {
|
||||||
|
s := &Signature{
|
||||||
|
pkg: pkg,
|
||||||
|
sig: sig,
|
||||||
|
}
|
||||||
|
s.init()
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSignatureVoid builds the void signature "func()".
|
||||||
|
func NewSignatureVoid() *Signature {
|
||||||
|
return NewSignature(nil, types.NewSignatureType(nil, nil, nil, nil, nil, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupSignature returns the signature of the named function in the provided package.
|
||||||
|
func LookupSignature(pkg *types.Package, name string) (*Signature, error) {
|
||||||
|
scope := pkg.Scope()
|
||||||
|
obj := scope.Lookup(name)
|
||||||
|
if obj == nil {
|
||||||
|
return nil, fmt.Errorf("could not find function \"%s\"", name)
|
||||||
|
}
|
||||||
|
s, ok := obj.Type().(*types.Signature)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("object \"%s\" does not have signature type", name)
|
||||||
|
}
|
||||||
|
return NewSignature(pkg, s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseSignature builds a Signature by parsing a Go function type expression.
|
||||||
|
// The function type must reference builtin types only; see
|
||||||
|
// ParseSignatureInPackage if custom types are required.
|
||||||
|
func ParseSignature(expr string) (*Signature, error) {
|
||||||
|
return ParseSignatureInPackage(nil, expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseSignatureInPackage builds a Signature by parsing a Go function type
|
||||||
|
// expression. The expression may reference types in the provided package.
|
||||||
|
func ParseSignatureInPackage(pkg *types.Package, expr string) (*Signature, error) {
|
||||||
|
tv, err := types.Eval(token.NewFileSet(), pkg, token.NoPos, expr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if tv.Value != nil {
|
||||||
|
return nil, errors.New("signature expression should have nil value")
|
||||||
|
}
|
||||||
|
s, ok := tv.Type.(*types.Signature)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("provided type is not a function signature")
|
||||||
|
}
|
||||||
|
return NewSignature(pkg, s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Params returns the function signature argument types.
|
||||||
|
func (s *Signature) Params() *Tuple { return s.params }
|
||||||
|
|
||||||
|
// Results returns the function return types.
|
||||||
|
func (s *Signature) Results() *Tuple { return s.results }
|
||||||
|
|
||||||
|
// Bytes returns the total size of the function arguments and return values.
|
||||||
|
func (s *Signature) Bytes() int { return s.Params().Bytes() + s.Results().Bytes() }
|
||||||
|
|
||||||
|
// String writes Signature as a string. This does not include the "func" keyword.
|
||||||
|
func (s *Signature) String() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
types.WriteSignature(&buf, s.sig, func(pkg *types.Package) string {
|
||||||
|
if pkg == s.pkg {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return pkg.Name()
|
||||||
|
})
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signature) init() {
|
||||||
|
p := s.sig.Params()
|
||||||
|
r := s.sig.Results()
|
||||||
|
|
||||||
|
// Compute parameter offsets. Note that if the function has results,
|
||||||
|
// additional padding up to max align is inserted between parameters and
|
||||||
|
// results.
|
||||||
|
vs := tuplevars(p)
|
||||||
|
vs = append(vs, types.NewParam(token.NoPos, nil, "sentinel", types.Typ[types.Uint64]))
|
||||||
|
paramsoffsets := Sizes.Offsetsof(vs)
|
||||||
|
paramssize := paramsoffsets[p.Len()]
|
||||||
|
if r.Len() == 0 {
|
||||||
|
paramssize = structsize(vs[:p.Len()])
|
||||||
|
}
|
||||||
|
s.params = newTuple(p, paramsoffsets, paramssize, "arg")
|
||||||
|
|
||||||
|
// Result offsets.
|
||||||
|
vs = tuplevars(r)
|
||||||
|
resultsoffsets := Sizes.Offsetsof(vs)
|
||||||
|
resultssize := structsize(vs)
|
||||||
|
for i := range resultsoffsets {
|
||||||
|
resultsoffsets[i] += paramssize
|
||||||
|
}
|
||||||
|
s.results = newTuple(r, resultsoffsets, resultssize, "ret")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tuple represents a tuple of variables, such as function arguments or results.
|
||||||
|
type Tuple struct {
|
||||||
|
components []Component
|
||||||
|
byname map[string]Component
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTuple(t *types.Tuple, offsets []int64, size int64, defaultprefix string) *Tuple {
|
||||||
|
tuple := &Tuple{
|
||||||
|
byname: map[string]Component{},
|
||||||
|
size: int(size),
|
||||||
|
}
|
||||||
|
for i := 0; i < t.Len(); i++ {
|
||||||
|
v := t.At(i)
|
||||||
|
name := v.Name()
|
||||||
|
if name == "" {
|
||||||
|
name = defaultprefix
|
||||||
|
if i > 0 {
|
||||||
|
name += strconv.Itoa(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addr := operand.NewParamAddr(name, int(offsets[i]))
|
||||||
|
c := NewComponent(v.Type(), addr)
|
||||||
|
tuple.components = append(tuple.components, c)
|
||||||
|
if v.Name() != "" {
|
||||||
|
tuple.byname[v.Name()] = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tuple
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup returns the variable with the given name.
|
||||||
|
func (t *Tuple) Lookup(name string) Component {
|
||||||
|
e := t.byname[name]
|
||||||
|
if e == nil {
|
||||||
|
return errorf("unknown variable \"%s\"", name)
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// At returns the variable at index i.
|
||||||
|
func (t *Tuple) At(i int) Component {
|
||||||
|
if i >= len(t.components) {
|
||||||
|
return errorf("index out of range")
|
||||||
|
}
|
||||||
|
return t.components[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the size of the Tuple. This may include additional padding.
|
||||||
|
func (t *Tuple) Bytes() int { return t.size }
|
||||||
|
|
||||||
|
func tuplevars(t *types.Tuple) []*types.Var {
|
||||||
|
vs := make([]*types.Var, t.Len())
|
||||||
|
for i := 0; i < t.Len(); i++ {
|
||||||
|
vs[i] = t.At(i)
|
||||||
|
}
|
||||||
|
return vs
|
||||||
|
}
|
||||||
|
|
||||||
|
// structsize computes the size of a struct containing the given variables as
|
||||||
|
// fields. It would be equivalent to calculating the size of types.NewStruct(vs,
|
||||||
|
// nil), apart from the fact that NewStruct panics if multiple fields have the
|
||||||
|
// same name, and this happens for example if the variables represent return
|
||||||
|
// types from a function.
|
||||||
|
func structsize(vs []*types.Var) int64 {
|
||||||
|
n := len(vs)
|
||||||
|
if n == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
offsets := Sizes.Offsetsof(vs)
|
||||||
|
return offsets[n-1] + Sizes.Sizeof(vs[n-1].Type())
|
||||||
|
}
|
101
vendor/github.com/mmcloughlin/avo/internal/prnt/printer.go
generated
vendored
Normal file
101
vendor/github.com/mmcloughlin/avo/internal/prnt/printer.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Package prnt provides common functionality for code generators.
|
||||||
|
package prnt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/build/constraint"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generator provides convenience methods for code generators. In particular it
|
||||||
|
// provides fmt-like methods which print to an internal buffer. It also allows
|
||||||
|
// any errors to be stored so they can be checked at the end, rather than having
|
||||||
|
// error checks obscuring the code generation.
|
||||||
|
type Generator struct {
|
||||||
|
buf bytes.Buffer
|
||||||
|
level int // current indentation level
|
||||||
|
indent string // indentation string
|
||||||
|
pending bool // if there's a pending indentation
|
||||||
|
err error // saved error from printing
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw provides direct access to the underlying output stream.
|
||||||
|
func (g *Generator) Raw() io.Writer {
|
||||||
|
return &g.buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIndentString sets the string used for one level of indentation. Use
|
||||||
|
// Indent() and Dedent() to control indent level.
|
||||||
|
func (g *Generator) SetIndentString(indent string) {
|
||||||
|
g.indent = indent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indent increments the indent level.
|
||||||
|
func (g *Generator) Indent() {
|
||||||
|
g.level++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dedent decrements the indent level.
|
||||||
|
func (g *Generator) Dedent() {
|
||||||
|
g.level--
|
||||||
|
}
|
||||||
|
|
||||||
|
// Linef prints formatted output terminated with a new line.
|
||||||
|
func (g *Generator) Linef(format string, args ...any) {
|
||||||
|
g.Printf(format, args...)
|
||||||
|
g.NL()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printf prints to the internal buffer.
|
||||||
|
func (g *Generator) Printf(format string, args ...any) {
|
||||||
|
if g.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if g.pending {
|
||||||
|
indent := strings.Repeat(g.indent, g.level)
|
||||||
|
format = indent + format
|
||||||
|
g.pending = false
|
||||||
|
}
|
||||||
|
_, err := fmt.Fprintf(&g.buf, format, args...)
|
||||||
|
g.AddError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NL prints a new line.
|
||||||
|
func (g *Generator) NL() {
|
||||||
|
g.Printf("\n")
|
||||||
|
g.pending = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comment writes comment lines prefixed with "// ".
|
||||||
|
func (g *Generator) Comment(lines ...string) {
|
||||||
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace("// " + line)
|
||||||
|
g.Printf("%s\n", line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildConstraint outputs a build constraint.
|
||||||
|
func (g *Generator) BuildConstraint(expr string) {
|
||||||
|
line := fmt.Sprintf("//go:build %s", expr)
|
||||||
|
if _, err := constraint.Parse(line); err != nil {
|
||||||
|
g.AddError(err)
|
||||||
|
}
|
||||||
|
g.Linef(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddError records an error in code generation. The first non-nil error will
|
||||||
|
// prevent printing operations from writing anything else, and the error will be
|
||||||
|
// returned from Result().
|
||||||
|
func (g *Generator) AddError(err error) {
|
||||||
|
if err != nil && g.err == nil {
|
||||||
|
g.err = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result returns the printed bytes. If any error was recorded with AddError
|
||||||
|
// during code generation, the first such error will be returned here.
|
||||||
|
func (g *Generator) Result() ([]byte, error) {
|
||||||
|
return g.buf.Bytes(), g.err
|
||||||
|
}
|
73
vendor/github.com/mmcloughlin/avo/internal/stack/stack.go
generated
vendored
Normal file
73
vendor/github.com/mmcloughlin/avo/internal/stack/stack.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// Package stack provides helpers for querying the callstack.
|
||||||
|
package stack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Frames returns at most max callstack Frames, starting with its caller and
|
||||||
|
// skipping skip Frames.
|
||||||
|
func Frames(skip, max int) []runtime.Frame {
|
||||||
|
pc := make([]uintptr, max)
|
||||||
|
n := runtime.Callers(skip+2, pc)
|
||||||
|
if n == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
pc = pc[:n]
|
||||||
|
frames := runtime.CallersFrames(pc)
|
||||||
|
var fs []runtime.Frame
|
||||||
|
for {
|
||||||
|
f, more := frames.Next()
|
||||||
|
fs = append(fs, f)
|
||||||
|
if !more {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match returns the first stack frame for which the predicate function returns
|
||||||
|
// true. Returns nil if no match is found. Starts matching after skip frames,
|
||||||
|
// starting with its caller.
|
||||||
|
func Match(skip int, predicate func(runtime.Frame) bool) *runtime.Frame {
|
||||||
|
i, n := skip+1, 16
|
||||||
|
for {
|
||||||
|
fs := Frames(i, n)
|
||||||
|
for j, f := range fs {
|
||||||
|
if predicate(f) {
|
||||||
|
return &fs[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(fs) < n {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i += n
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main returns the main() function Frame.
|
||||||
|
func Main() *runtime.Frame {
|
||||||
|
return Match(1, func(f runtime.Frame) bool {
|
||||||
|
return f.Function == "main.main"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalCaller returns the first frame outside the callers package.
|
||||||
|
func ExternalCaller() *runtime.Frame {
|
||||||
|
var first *runtime.Frame
|
||||||
|
return Match(1, func(f runtime.Frame) bool {
|
||||||
|
if first == nil {
|
||||||
|
first = &f
|
||||||
|
}
|
||||||
|
return pkg(first.Function) != pkg(f.Function)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func pkg(ident string) string {
|
||||||
|
dir, name := path.Split(ident)
|
||||||
|
parts := strings.Split(name, ".")
|
||||||
|
return dir + parts[0]
|
||||||
|
}
|
2
vendor/github.com/mmcloughlin/avo/ir/doc.go
generated
vendored
Normal file
2
vendor/github.com/mmcloughlin/avo/ir/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package ir provides the intermediate representation of avo programs.
|
||||||
|
package ir
|
365
vendor/github.com/mmcloughlin/avo/ir/ir.go
generated
vendored
Normal file
365
vendor/github.com/mmcloughlin/avo/ir/ir.go
generated
vendored
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
package ir
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/attr"
|
||||||
|
"github.com/mmcloughlin/avo/buildtags"
|
||||||
|
"github.com/mmcloughlin/avo/gotypes"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Node is a part of a Function.
|
||||||
|
type Node interface {
|
||||||
|
node()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label within a function.
|
||||||
|
type Label string
|
||||||
|
|
||||||
|
func (l Label) node() {}
|
||||||
|
|
||||||
|
// Comment represents a multi-line comment.
|
||||||
|
type Comment struct {
|
||||||
|
Lines []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Comment) node() {}
|
||||||
|
|
||||||
|
// NewComment builds a Comment consisting of the provided lines.
|
||||||
|
func NewComment(lines ...string) *Comment {
|
||||||
|
return &Comment{
|
||||||
|
Lines: lines,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instruction is a single instruction in a function.
|
||||||
|
type Instruction struct {
|
||||||
|
Opcode string
|
||||||
|
Suffixes []string
|
||||||
|
Operands []operand.Op
|
||||||
|
|
||||||
|
Inputs []operand.Op
|
||||||
|
Outputs []operand.Op
|
||||||
|
|
||||||
|
IsTerminal bool
|
||||||
|
IsBranch bool
|
||||||
|
IsConditional bool
|
||||||
|
CancellingInputs bool
|
||||||
|
|
||||||
|
// ISA is the list of required instruction set extensions.
|
||||||
|
ISA []string
|
||||||
|
|
||||||
|
// CFG.
|
||||||
|
Pred []*Instruction
|
||||||
|
Succ []*Instruction
|
||||||
|
|
||||||
|
// LiveIn/LiveOut are sets of live register IDs pre/post execution.
|
||||||
|
LiveIn reg.MaskSet
|
||||||
|
LiveOut reg.MaskSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Instruction) node() {}
|
||||||
|
|
||||||
|
// OpcodeWithSuffixes returns the full opcode, including dot-separated suffixes.
|
||||||
|
func (i *Instruction) OpcodeWithSuffixes() string {
|
||||||
|
opcode := i.Opcode
|
||||||
|
for _, s := range i.Suffixes {
|
||||||
|
opcode += "." + s
|
||||||
|
}
|
||||||
|
return opcode
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUnconditionalBranch reports whether i is an unconditional branch.
|
||||||
|
func (i Instruction) IsUnconditionalBranch() bool {
|
||||||
|
return i.IsBranch && !i.IsConditional
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetLabel returns the label referenced by this instruction. Returns nil if
|
||||||
|
// no label is referenced.
|
||||||
|
func (i Instruction) TargetLabel() *Label {
|
||||||
|
if !i.IsBranch {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(i.Operands) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if ref, ok := i.Operands[0].(operand.LabelRef); ok {
|
||||||
|
lbl := Label(ref)
|
||||||
|
return &lbl
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers returns all registers involved in the instruction.
|
||||||
|
func (i Instruction) Registers() []reg.Register {
|
||||||
|
var rs []reg.Register
|
||||||
|
for _, op := range i.Operands {
|
||||||
|
rs = append(rs, operand.Registers(op)...)
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
// InputRegisters returns all registers read by this instruction.
|
||||||
|
func (i Instruction) InputRegisters() []reg.Register {
|
||||||
|
var rs []reg.Register
|
||||||
|
for _, op := range i.Inputs {
|
||||||
|
rs = append(rs, operand.Registers(op)...)
|
||||||
|
}
|
||||||
|
if i.CancellingInputs && rs[0] == rs[1] {
|
||||||
|
rs = []reg.Register{}
|
||||||
|
}
|
||||||
|
for _, op := range i.Outputs {
|
||||||
|
if operand.IsMem(op) {
|
||||||
|
rs = append(rs, operand.Registers(op)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutputRegisters returns all registers written by this instruction.
|
||||||
|
func (i Instruction) OutputRegisters() []reg.Register {
|
||||||
|
var rs []reg.Register
|
||||||
|
for _, op := range i.Outputs {
|
||||||
|
if r, ok := op.(reg.Register); ok {
|
||||||
|
rs = append(rs, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section is a part of a file.
|
||||||
|
type Section interface {
|
||||||
|
section()
|
||||||
|
}
|
||||||
|
|
||||||
|
// File represents an assembly file.
|
||||||
|
type File struct {
|
||||||
|
Constraints buildtags.Constraints
|
||||||
|
Includes []string
|
||||||
|
Sections []Section
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFile initializes an empty file.
|
||||||
|
func NewFile() *File {
|
||||||
|
return &File{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSection appends a Section to the file.
|
||||||
|
func (f *File) AddSection(s Section) {
|
||||||
|
f.Sections = append(f.Sections, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions returns all functions in the file.
|
||||||
|
func (f *File) Functions() []*Function {
|
||||||
|
var fns []*Function
|
||||||
|
for _, s := range f.Sections {
|
||||||
|
if fn, ok := s.(*Function); ok {
|
||||||
|
fns = append(fns, fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fns
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pragma represents a function compiler directive.
|
||||||
|
type Pragma struct {
|
||||||
|
Directive string
|
||||||
|
Arguments []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function represents an assembly function.
|
||||||
|
type Function struct {
|
||||||
|
Name string
|
||||||
|
Attributes attr.Attribute
|
||||||
|
Pragmas []Pragma
|
||||||
|
Doc []string
|
||||||
|
Signature *gotypes.Signature
|
||||||
|
LocalSize int
|
||||||
|
|
||||||
|
Nodes []Node
|
||||||
|
|
||||||
|
// LabelTarget maps from label name to the following instruction.
|
||||||
|
LabelTarget map[Label]*Instruction
|
||||||
|
|
||||||
|
// Register allocation.
|
||||||
|
Allocation reg.Allocation
|
||||||
|
|
||||||
|
// ISA is the list of required instruction set extensions.
|
||||||
|
ISA []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Function) section() {}
|
||||||
|
|
||||||
|
// NewFunction builds an empty function of the given name.
|
||||||
|
func NewFunction(name string) *Function {
|
||||||
|
return &Function{
|
||||||
|
Name: name,
|
||||||
|
Signature: gotypes.NewSignatureVoid(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPragma adds a pragma to this function.
|
||||||
|
func (f *Function) AddPragma(directive string, args ...string) {
|
||||||
|
f.Pragmas = append(f.Pragmas, Pragma{
|
||||||
|
Directive: directive,
|
||||||
|
Arguments: args,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSignature sets the function signature.
|
||||||
|
func (f *Function) SetSignature(s *gotypes.Signature) {
|
||||||
|
f.Signature = s
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllocLocal allocates size bytes in this function's stack.
|
||||||
|
// Returns a reference to the base pointer for the newly allocated region.
|
||||||
|
func (f *Function) AllocLocal(size int) operand.Mem {
|
||||||
|
ptr := operand.NewStackAddr(f.LocalSize)
|
||||||
|
f.LocalSize += size
|
||||||
|
return ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddInstruction appends an instruction to f.
|
||||||
|
func (f *Function) AddInstruction(i *Instruction) {
|
||||||
|
f.AddNode(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLabel appends a label to f.
|
||||||
|
func (f *Function) AddLabel(l Label) {
|
||||||
|
f.AddNode(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddComment adds comment lines to f.
|
||||||
|
func (f *Function) AddComment(lines ...string) {
|
||||||
|
f.AddNode(NewComment(lines...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNode appends a Node to f.
|
||||||
|
func (f *Function) AddNode(n Node) {
|
||||||
|
f.Nodes = append(f.Nodes, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instructions returns just the list of instruction nodes.
|
||||||
|
func (f *Function) Instructions() []*Instruction {
|
||||||
|
var is []*Instruction
|
||||||
|
for _, n := range f.Nodes {
|
||||||
|
i, ok := n.(*Instruction)
|
||||||
|
if ok {
|
||||||
|
is = append(is, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return is
|
||||||
|
}
|
||||||
|
|
||||||
|
// Labels returns just the list of label nodes.
|
||||||
|
func (f *Function) Labels() []Label {
|
||||||
|
var lbls []Label
|
||||||
|
for _, n := range f.Nodes {
|
||||||
|
lbl, ok := n.(Label)
|
||||||
|
if ok {
|
||||||
|
lbls = append(lbls, lbl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lbls
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stub returns the Go function declaration.
|
||||||
|
func (f *Function) Stub() string {
|
||||||
|
return "func " + f.Name + f.Signature.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrameBytes returns the size of the stack frame in bytes.
|
||||||
|
func (f *Function) FrameBytes() int {
|
||||||
|
return f.LocalSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArgumentBytes returns the size of the arguments in bytes.
|
||||||
|
func (f *Function) ArgumentBytes() int {
|
||||||
|
return f.Signature.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Datum represents a data element at a particular offset of a data section.
|
||||||
|
type Datum struct {
|
||||||
|
Offset int
|
||||||
|
Value operand.Constant
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDatum builds a Datum from the given constant.
|
||||||
|
func NewDatum(offset int, v operand.Constant) Datum {
|
||||||
|
return Datum{
|
||||||
|
Offset: offset,
|
||||||
|
Value: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interval returns the range of bytes this datum will occupy within its section.
|
||||||
|
func (d Datum) Interval() (int, int) {
|
||||||
|
return d.Offset, d.Offset + d.Value.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overlaps returns whether d overlaps with other.
|
||||||
|
func (d Datum) Overlaps(other Datum) bool {
|
||||||
|
s, e := d.Interval()
|
||||||
|
so, eo := other.Interval()
|
||||||
|
return !(eo <= s || e <= so)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global represents a DATA section.
|
||||||
|
type Global struct {
|
||||||
|
Symbol operand.Symbol
|
||||||
|
Attributes attr.Attribute
|
||||||
|
Data []Datum
|
||||||
|
Size int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGlobal constructs an empty DATA section.
|
||||||
|
func NewGlobal(sym operand.Symbol) *Global {
|
||||||
|
return &Global{
|
||||||
|
Symbol: sym,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStaticGlobal is a convenience for building a static DATA section.
|
||||||
|
func NewStaticGlobal(name string) *Global {
|
||||||
|
return NewGlobal(operand.NewStaticSymbol(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Global) section() {}
|
||||||
|
|
||||||
|
// Base returns a pointer to the start of the data section.
|
||||||
|
func (g *Global) Base() operand.Mem {
|
||||||
|
return operand.NewDataAddr(g.Symbol, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grow ensures that the data section has at least the given size.
|
||||||
|
func (g *Global) Grow(size int) {
|
||||||
|
if g.Size < size {
|
||||||
|
g.Size = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDatum adds d to this data section, growing it if necessary. Errors if the datum overlaps with existing data.
|
||||||
|
func (g *Global) AddDatum(d Datum) error {
|
||||||
|
for _, other := range g.Data {
|
||||||
|
if d.Overlaps(other) {
|
||||||
|
return errors.New("overlaps existing datum")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.add(d)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the constant to the end of the data section.
|
||||||
|
func (g *Global) Append(v operand.Constant) {
|
||||||
|
g.add(Datum{
|
||||||
|
Offset: g.Size,
|
||||||
|
Value: v,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Global) add(d Datum) {
|
||||||
|
_, end := d.Interval()
|
||||||
|
g.Grow(end)
|
||||||
|
g.Data = append(g.Data, d)
|
||||||
|
}
|
282
vendor/github.com/mmcloughlin/avo/operand/checks.go
generated
vendored
Normal file
282
vendor/github.com/mmcloughlin/avo/operand/checks.go
generated
vendored
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
package operand
|
||||||
|
|
||||||
|
import "github.com/mmcloughlin/avo/reg"
|
||||||
|
|
||||||
|
// Pure type assertion checks:
|
||||||
|
|
||||||
|
// IsRegister returns whether op has type reg.Register.
|
||||||
|
func IsRegister(op Op) bool { _, ok := op.(reg.Register); return ok }
|
||||||
|
|
||||||
|
// IsMem returns whether op has type Mem.
|
||||||
|
func IsMem(op Op) bool { _, ok := op.(Mem); return ok }
|
||||||
|
|
||||||
|
// IsRel returns whether op has type Rel.
|
||||||
|
func IsRel(op Op) bool { _, ok := op.(Rel); return ok }
|
||||||
|
|
||||||
|
// Checks corresponding to specific operand types in the Intel Manual:
|
||||||
|
|
||||||
|
// Is1 returns true if op is the immediate constant 1.
|
||||||
|
func Is1(op Op) bool {
|
||||||
|
i, ok := op.(U8)
|
||||||
|
return ok && i == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is3 returns true if op is the immediate constant 3.
|
||||||
|
func Is3(op Op) bool {
|
||||||
|
i, ok := op.(U8)
|
||||||
|
return ok && i == 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIMM2U returns true if op is a 2-bit unsigned immediate (less than 4).
|
||||||
|
func IsIMM2U(op Op) bool {
|
||||||
|
i, ok := op.(U8)
|
||||||
|
return ok && i < 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIMM8 returns true is op is an 8-bit immediate.
|
||||||
|
func IsIMM8(op Op) bool {
|
||||||
|
_, uok := op.(U8)
|
||||||
|
_, iok := op.(I8)
|
||||||
|
return uok || iok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIMM16 returns true is op is a 16-bit immediate.
|
||||||
|
func IsIMM16(op Op) bool {
|
||||||
|
_, uok := op.(U16)
|
||||||
|
_, iok := op.(I16)
|
||||||
|
return uok || iok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIMM32 returns true is op is a 32-bit immediate.
|
||||||
|
func IsIMM32(op Op) bool {
|
||||||
|
_, uok := op.(U32)
|
||||||
|
_, iok := op.(I32)
|
||||||
|
return uok || iok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIMM64 returns true is op is a 64-bit immediate.
|
||||||
|
func IsIMM64(op Op) bool {
|
||||||
|
_, uok := op.(U64)
|
||||||
|
_, iok := op.(I64)
|
||||||
|
return uok || iok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAL returns true if op is the AL register.
|
||||||
|
func IsAL(op Op) bool {
|
||||||
|
return op == reg.AL
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCL returns true if op is the CL register.
|
||||||
|
func IsCL(op Op) bool {
|
||||||
|
return op == reg.CL
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAX returns true if op is the 16-bit AX register.
|
||||||
|
func IsAX(op Op) bool {
|
||||||
|
return op == reg.AX
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEAX returns true if op is the 32-bit EAX register.
|
||||||
|
func IsEAX(op Op) bool {
|
||||||
|
return op == reg.EAX
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRAX returns true if op is the 64-bit RAX register.
|
||||||
|
func IsRAX(op Op) bool {
|
||||||
|
return op == reg.RAX
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsR8 returns true if op is an 8-bit general-purpose register.
|
||||||
|
func IsR8(op Op) bool {
|
||||||
|
return IsGP(op, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsR16 returns true if op is a 16-bit general-purpose register.
|
||||||
|
func IsR16(op Op) bool {
|
||||||
|
return IsGP(op, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsR32 returns true if op is a 32-bit general-purpose register.
|
||||||
|
func IsR32(op Op) bool {
|
||||||
|
return IsGP(op, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsR64 returns true if op is a 64-bit general-purpose register.
|
||||||
|
func IsR64(op Op) bool {
|
||||||
|
return IsGP(op, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPseudo returns true if op is a pseudo register.
|
||||||
|
func IsPseudo(op Op) bool {
|
||||||
|
return IsRegisterKind(op, reg.KindPseudo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsGP returns true if op is a general-purpose register of size n bytes.
|
||||||
|
func IsGP(op Op, n uint) bool {
|
||||||
|
return IsRegisterKindSize(op, reg.KindGP, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsXMM0 returns true if op is the X0 register.
|
||||||
|
func IsXMM0(op Op) bool {
|
||||||
|
return op == reg.X0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsXMM returns true if op is a 128-bit XMM register.
|
||||||
|
func IsXMM(op Op) bool {
|
||||||
|
return IsRegisterKindSize(op, reg.KindVector, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsYMM returns true if op is a 256-bit YMM register.
|
||||||
|
func IsYMM(op Op) bool {
|
||||||
|
return IsRegisterKindSize(op, reg.KindVector, 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZMM returns true if op is a 512-bit ZMM register.
|
||||||
|
func IsZMM(op Op) bool {
|
||||||
|
return IsRegisterKindSize(op, reg.KindVector, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsK returns true if op is an Opmask register.
|
||||||
|
func IsK(op Op) bool {
|
||||||
|
return IsRegisterKind(op, reg.KindOpmask)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRegisterKindSize returns true if op is a register of the given kind and size in bytes.
|
||||||
|
func IsRegisterKindSize(op Op, k reg.Kind, n uint) bool {
|
||||||
|
r, ok := op.(reg.Register)
|
||||||
|
return ok && r.Kind() == k && r.Size() == n
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRegisterKind returns true if op is a register of the given kind.
|
||||||
|
func IsRegisterKind(op Op, k reg.Kind) bool {
|
||||||
|
r, ok := op.(reg.Register)
|
||||||
|
return ok && r.Kind() == k
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsM returns true if op is a 16-, 32- or 64-bit memory operand.
|
||||||
|
func IsM(op Op) bool {
|
||||||
|
// TODO(mbm): confirm "m" check is defined correctly
|
||||||
|
// Intel manual: "A 16-, 32- or 64-bit operand in memory."
|
||||||
|
return IsM16(op) || IsM32(op) || IsM64(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsM8 returns true if op is an 8-bit memory operand.
|
||||||
|
func IsM8(op Op) bool {
|
||||||
|
// TODO(mbm): confirm "m8" check is defined correctly
|
||||||
|
// Intel manual: "A byte operand in memory, usually expressed as a variable or
|
||||||
|
// array name, but pointed to by the DS:(E)SI or ES:(E)DI registers. In 64-bit
|
||||||
|
// mode, it is pointed to by the RSI or RDI registers."
|
||||||
|
return IsMSize(op, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsM16 returns true if op is a 16-bit memory operand.
|
||||||
|
func IsM16(op Op) bool {
|
||||||
|
return IsMSize(op, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsM32 returns true if op is a 16-bit memory operand.
|
||||||
|
func IsM32(op Op) bool {
|
||||||
|
return IsMSize(op, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsM64 returns true if op is a 64-bit memory operand.
|
||||||
|
func IsM64(op Op) bool {
|
||||||
|
return IsMSize(op, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMSize returns true if op is a memory operand using general-purpose address
|
||||||
|
// registers of the given size in bytes.
|
||||||
|
func IsMSize(op Op, n uint) bool {
|
||||||
|
// TODO(mbm): should memory operands have a size attribute as well?
|
||||||
|
// TODO(mbm): m8,m16,m32,m64 checks do not actually check size
|
||||||
|
m, ok := op.(Mem)
|
||||||
|
return ok && IsMReg(m.Base) && (m.Index == nil || IsMReg(m.Index))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMReg returns true if op is a register that can be used in a memory operand.
|
||||||
|
func IsMReg(op Op) bool {
|
||||||
|
return IsPseudo(op) || IsRegisterKind(op, reg.KindGP)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsM128 returns true if op is a 128-bit memory operand.
|
||||||
|
func IsM128(op Op) bool {
|
||||||
|
// TODO(mbm): should "m128" be the same as "m64"?
|
||||||
|
return IsM64(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsM256 returns true if op is a 256-bit memory operand.
|
||||||
|
func IsM256(op Op) bool {
|
||||||
|
// TODO(mbm): should "m256" be the same as "m64"?
|
||||||
|
return IsM64(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsM512 returns true if op is a 512-bit memory operand.
|
||||||
|
func IsM512(op Op) bool {
|
||||||
|
// TODO(mbm): should "m512" be the same as "m64"?
|
||||||
|
return IsM64(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVM32X returns true if op is a vector memory operand with 32-bit XMM index.
|
||||||
|
func IsVM32X(op Op) bool {
|
||||||
|
return IsVmx(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVM64X returns true if op is a vector memory operand with 64-bit XMM index.
|
||||||
|
func IsVM64X(op Op) bool {
|
||||||
|
return IsVmx(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVmx returns true if op is a vector memory operand with XMM index.
|
||||||
|
func IsVmx(op Op) bool {
|
||||||
|
return isvm(op, IsXMM)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVM32Y returns true if op is a vector memory operand with 32-bit YMM index.
|
||||||
|
func IsVM32Y(op Op) bool {
|
||||||
|
return IsVmy(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVM64Y returns true if op is a vector memory operand with 64-bit YMM index.
|
||||||
|
func IsVM64Y(op Op) bool {
|
||||||
|
return IsVmy(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVmy returns true if op is a vector memory operand with YMM index.
|
||||||
|
func IsVmy(op Op) bool {
|
||||||
|
return isvm(op, IsYMM)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVM32Z returns true if op is a vector memory operand with 32-bit ZMM index.
|
||||||
|
func IsVM32Z(op Op) bool {
|
||||||
|
return IsVmz(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVM64Z returns true if op is a vector memory operand with 64-bit ZMM index.
|
||||||
|
func IsVM64Z(op Op) bool {
|
||||||
|
return IsVmz(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVmz returns true if op is a vector memory operand with ZMM index.
|
||||||
|
func IsVmz(op Op) bool {
|
||||||
|
return isvm(op, IsZMM)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isvm(op Op, idx func(Op) bool) bool {
|
||||||
|
m, ok := op.(Mem)
|
||||||
|
return ok && IsR64(m.Base) && idx(m.Index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsREL8 returns true if op is an 8-bit offset relative to instruction pointer.
|
||||||
|
func IsREL8(op Op) bool {
|
||||||
|
r, ok := op.(Rel)
|
||||||
|
return ok && r == Rel(int8(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsREL32 returns true if op is an offset relative to instruction pointer, or a
|
||||||
|
// label reference.
|
||||||
|
func IsREL32(op Op) bool {
|
||||||
|
// TODO(mbm): should labels be considered separately?
|
||||||
|
_, rel := op.(Rel)
|
||||||
|
_, label := op.(LabelRef)
|
||||||
|
return rel || label
|
||||||
|
}
|
64
vendor/github.com/mmcloughlin/avo/operand/const.go
generated
vendored
Normal file
64
vendor/github.com/mmcloughlin/avo/operand/const.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package operand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constant represents a constant literal.
|
||||||
|
type Constant interface {
|
||||||
|
Op
|
||||||
|
Bytes() int
|
||||||
|
constant()
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate go run make_const.go -output zconst.go
|
||||||
|
|
||||||
|
// Special cases for floating point string representation.
|
||||||
|
//
|
||||||
|
// Issue 387 pointed out that floating point values that happen to be integers
|
||||||
|
// need to have a decimal point to be parsed correctly.
|
||||||
|
|
||||||
|
// String returns a representation the 32-bit float which is guaranteed to be
|
||||||
|
// parsed as a floating point constant by the Go assembler.
|
||||||
|
func (f F32) String() string { return asmfloat(float64(f), 32) }
|
||||||
|
|
||||||
|
// String returns a representation the 64-bit float which is guaranteed to be
|
||||||
|
// parsed as a floating point constant by the Go assembler.
|
||||||
|
func (f F64) String() string { return asmfloat(float64(f), 64) }
|
||||||
|
|
||||||
|
// asmfloat represents x as a string such that the assembler scanner will always
|
||||||
|
// recognize it as a float. Specifically, ensure that when x is an integral
|
||||||
|
// value, the result will still have a decimal point.
|
||||||
|
func asmfloat(x float64, bits int) string {
|
||||||
|
s := strconv.FormatFloat(x, 'f', -1, bits)
|
||||||
|
if !strings.ContainsRune(s, '.') {
|
||||||
|
s += ".0"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// String is a string constant.
|
||||||
|
type String string
|
||||||
|
|
||||||
|
// Asm returns an assembly syntax representation of the string s.
|
||||||
|
func (s String) Asm() string { return fmt.Sprintf("$%q", s) }
|
||||||
|
|
||||||
|
// Bytes returns the length of s.
|
||||||
|
func (s String) Bytes() int { return len(s) }
|
||||||
|
|
||||||
|
func (s String) constant() {}
|
||||||
|
|
||||||
|
// Imm returns an unsigned integer constant with size guessed from x.
|
||||||
|
func Imm(x uint64) Constant {
|
||||||
|
switch {
|
||||||
|
case uint64(uint8(x)) == x:
|
||||||
|
return U8(x)
|
||||||
|
case uint64(uint16(x)) == x:
|
||||||
|
return U16(x)
|
||||||
|
case uint64(uint32(x)) == x:
|
||||||
|
return U32(x)
|
||||||
|
}
|
||||||
|
return U64(x)
|
||||||
|
}
|
2
vendor/github.com/mmcloughlin/avo/operand/doc.go
generated
vendored
Normal file
2
vendor/github.com/mmcloughlin/avo/operand/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package operand provides types for instruction operands.
|
||||||
|
package operand
|
151
vendor/github.com/mmcloughlin/avo/operand/types.go
generated
vendored
Normal file
151
vendor/github.com/mmcloughlin/avo/operand/types.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package operand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Op is an operand.
|
||||||
|
type Op interface {
|
||||||
|
Asm() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Symbol represents a symbol name.
|
||||||
|
type Symbol struct {
|
||||||
|
Name string
|
||||||
|
Static bool // only visible in current source file
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStaticSymbol builds a static Symbol. Static symbols are only visible in the current source file.
|
||||||
|
func NewStaticSymbol(name string) Symbol {
|
||||||
|
return Symbol{Name: name, Static: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Symbol) String() string {
|
||||||
|
n := s.Name
|
||||||
|
if s.Static {
|
||||||
|
n += "<>"
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mem represents a memory reference.
|
||||||
|
type Mem struct {
|
||||||
|
Symbol Symbol
|
||||||
|
Disp int
|
||||||
|
Base reg.Register
|
||||||
|
Index reg.Register
|
||||||
|
Scale uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewParamAddr is a convenience to build a Mem operand pointing to a function
|
||||||
|
// parameter, which is a named offset from the frame pointer pseudo register.
|
||||||
|
func NewParamAddr(name string, offset int) Mem {
|
||||||
|
return Mem{
|
||||||
|
Symbol: Symbol{
|
||||||
|
Name: name,
|
||||||
|
Static: false,
|
||||||
|
},
|
||||||
|
Disp: offset,
|
||||||
|
Base: reg.FramePointer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStackAddr returns a memory reference relative to the stack pointer.
|
||||||
|
func NewStackAddr(offset int) Mem {
|
||||||
|
return Mem{
|
||||||
|
Disp: offset,
|
||||||
|
Base: reg.StackPointer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDataAddr returns a memory reference relative to the named data symbol.
|
||||||
|
func NewDataAddr(sym Symbol, offset int) Mem {
|
||||||
|
return Mem{
|
||||||
|
Symbol: sym,
|
||||||
|
Disp: offset,
|
||||||
|
Base: reg.StaticBase,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset returns a reference to m plus idx bytes.
|
||||||
|
func (m Mem) Offset(idx int) Mem {
|
||||||
|
a := m
|
||||||
|
a.Disp += idx
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// Idx returns a new memory reference with (Index, Scale) set to (r, s).
|
||||||
|
func (m Mem) Idx(r reg.Register, s uint8) Mem {
|
||||||
|
a := m
|
||||||
|
a.Index = r
|
||||||
|
a.Scale = s
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// Asm returns an assembly syntax representation of m.
|
||||||
|
func (m Mem) Asm() string {
|
||||||
|
a := m.Symbol.String()
|
||||||
|
if a != "" {
|
||||||
|
a += fmt.Sprintf("%+d", m.Disp)
|
||||||
|
} else if m.Disp != 0 {
|
||||||
|
a += fmt.Sprintf("%d", m.Disp)
|
||||||
|
}
|
||||||
|
if m.Base != nil {
|
||||||
|
a += fmt.Sprintf("(%s)", m.Base.Asm())
|
||||||
|
}
|
||||||
|
if m.Index != nil && m.Scale != 0 {
|
||||||
|
a += fmt.Sprintf("(%s*%d)", m.Index.Asm(), m.Scale)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rel is an offset relative to the instruction pointer.
|
||||||
|
type Rel int32
|
||||||
|
|
||||||
|
// Asm returns an assembly syntax representation of r.
|
||||||
|
func (r Rel) Asm() string {
|
||||||
|
return fmt.Sprintf(".%+d", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LabelRef is a reference to a label.
|
||||||
|
type LabelRef string
|
||||||
|
|
||||||
|
// Asm returns an assembly syntax representation of l.
|
||||||
|
func (l LabelRef) Asm() string {
|
||||||
|
return string(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers returns the list of all operands involved in the given operand.
|
||||||
|
func Registers(op Op) []reg.Register {
|
||||||
|
switch op := op.(type) {
|
||||||
|
case reg.Register:
|
||||||
|
return []reg.Register{op}
|
||||||
|
case Mem:
|
||||||
|
var r []reg.Register
|
||||||
|
if op.Base != nil {
|
||||||
|
r = append(r, op.Base)
|
||||||
|
}
|
||||||
|
if op.Index != nil {
|
||||||
|
r = append(r, op.Index)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
case Constant, Rel, LabelRef:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
panic("unknown operand type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyAllocation returns an operand with allocated registers replaced. Registers missing from the allocation are left alone.
|
||||||
|
func ApplyAllocation(op Op, a reg.Allocation) Op {
|
||||||
|
switch op := op.(type) {
|
||||||
|
case reg.Register:
|
||||||
|
return a.LookupRegisterDefault(op)
|
||||||
|
case Mem:
|
||||||
|
op.Base = a.LookupRegisterDefault(op.Base)
|
||||||
|
op.Index = a.LookupRegisterDefault(op.Index)
|
||||||
|
return op
|
||||||
|
}
|
||||||
|
return op
|
||||||
|
}
|
75
vendor/github.com/mmcloughlin/avo/operand/zconst.go
generated
vendored
Normal file
75
vendor/github.com/mmcloughlin/avo/operand/zconst.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Code generated by make_const.go. DO NOT EDIT.
|
||||||
|
|
||||||
|
package operand
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// I8 is a 8-bit signed integer constant.
|
||||||
|
type I8 int8
|
||||||
|
|
||||||
|
func (i I8) Asm() string { return fmt.Sprintf("$%+d", i) }
|
||||||
|
func (i I8) Bytes() int { return 1 }
|
||||||
|
func (i I8) constant() {}
|
||||||
|
|
||||||
|
// U8 is a 8-bit unsigned integer constant.
|
||||||
|
type U8 uint8
|
||||||
|
|
||||||
|
func (u U8) Asm() string { return fmt.Sprintf("$%#02x", u) }
|
||||||
|
func (u U8) Bytes() int { return 1 }
|
||||||
|
func (u U8) constant() {}
|
||||||
|
|
||||||
|
// I16 is a 16-bit signed integer constant.
|
||||||
|
type I16 int16
|
||||||
|
|
||||||
|
func (i I16) Asm() string { return fmt.Sprintf("$%+d", i) }
|
||||||
|
func (i I16) Bytes() int { return 2 }
|
||||||
|
func (i I16) constant() {}
|
||||||
|
|
||||||
|
// U16 is a 16-bit unsigned integer constant.
|
||||||
|
type U16 uint16
|
||||||
|
|
||||||
|
func (u U16) Asm() string { return fmt.Sprintf("$%#04x", u) }
|
||||||
|
func (u U16) Bytes() int { return 2 }
|
||||||
|
func (u U16) constant() {}
|
||||||
|
|
||||||
|
// F32 is a 32-bit floating point constant.
|
||||||
|
type F32 float32
|
||||||
|
|
||||||
|
func (f F32) Asm() string { return fmt.Sprintf("$(%s)", f) }
|
||||||
|
func (f F32) Bytes() int { return 4 }
|
||||||
|
func (f F32) constant() {}
|
||||||
|
|
||||||
|
// I32 is a 32-bit signed integer constant.
|
||||||
|
type I32 int32
|
||||||
|
|
||||||
|
func (i I32) Asm() string { return fmt.Sprintf("$%+d", i) }
|
||||||
|
func (i I32) Bytes() int { return 4 }
|
||||||
|
func (i I32) constant() {}
|
||||||
|
|
||||||
|
// U32 is a 32-bit unsigned integer constant.
|
||||||
|
type U32 uint32
|
||||||
|
|
||||||
|
func (u U32) Asm() string { return fmt.Sprintf("$%#08x", u) }
|
||||||
|
func (u U32) Bytes() int { return 4 }
|
||||||
|
func (u U32) constant() {}
|
||||||
|
|
||||||
|
// F64 is a 64-bit floating point constant.
|
||||||
|
type F64 float64
|
||||||
|
|
||||||
|
func (f F64) Asm() string { return fmt.Sprintf("$(%s)", f) }
|
||||||
|
func (f F64) Bytes() int { return 8 }
|
||||||
|
func (f F64) constant() {}
|
||||||
|
|
||||||
|
// I64 is a 64-bit signed integer constant.
|
||||||
|
type I64 int64
|
||||||
|
|
||||||
|
func (i I64) Asm() string { return fmt.Sprintf("$%+d", i) }
|
||||||
|
func (i I64) Bytes() int { return 8 }
|
||||||
|
func (i I64) constant() {}
|
||||||
|
|
||||||
|
// U64 is a 64-bit unsigned integer constant.
|
||||||
|
type U64 uint64
|
||||||
|
|
||||||
|
func (u U64) Asm() string { return fmt.Sprintf("$%#016x", u) }
|
||||||
|
func (u U64) Bytes() int { return 8 }
|
||||||
|
func (u U64) constant() {}
|
213
vendor/github.com/mmcloughlin/avo/pass/alloc.go
generated
vendored
Normal file
213
vendor/github.com/mmcloughlin/avo/pass/alloc.go
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// edge is an edge of the interference graph, indicating that registers X and Y
|
||||||
|
// must be in non-conflicting registers.
|
||||||
|
type edge struct {
|
||||||
|
X, Y reg.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocator is a graph-coloring register allocator.
|
||||||
|
type Allocator struct {
|
||||||
|
registers []reg.ID
|
||||||
|
priority map[reg.ID]int
|
||||||
|
allocation reg.Allocation
|
||||||
|
edges []*edge
|
||||||
|
possible map[reg.ID][]reg.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAllocator builds an allocator for the given physical registers.
|
||||||
|
func NewAllocator(rs []reg.Physical) (*Allocator, error) {
|
||||||
|
// Set of IDs, excluding restricted registers.
|
||||||
|
idset := map[reg.ID]bool{}
|
||||||
|
for _, r := range rs {
|
||||||
|
if (r.Info() & reg.Restricted) != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
idset[r.ID()] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(idset) == 0 {
|
||||||
|
return nil, errors.New("no allocatable registers")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produce slice of unique register IDs.
|
||||||
|
var ids []reg.ID
|
||||||
|
for id := range idset {
|
||||||
|
ids = append(ids, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
a := &Allocator{
|
||||||
|
registers: ids,
|
||||||
|
priority: map[reg.ID]int{},
|
||||||
|
allocation: reg.NewEmptyAllocation(),
|
||||||
|
possible: map[reg.ID][]reg.ID{},
|
||||||
|
}
|
||||||
|
a.sortregisters()
|
||||||
|
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAllocatorForKind builds an allocator for the given kind of registers.
|
||||||
|
func NewAllocatorForKind(k reg.Kind) (*Allocator, error) {
|
||||||
|
f := reg.FamilyOfKind(k)
|
||||||
|
if f == nil {
|
||||||
|
return nil, errors.New("unknown register family")
|
||||||
|
}
|
||||||
|
return NewAllocator(f.Registers())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPriority sets the priority of the given regiser to p. Higher priority
|
||||||
|
// registers are preferred in allocations. By default all registers have 0
|
||||||
|
// priority. Priority will only apply to subsequent Add() calls, therefore
|
||||||
|
// typically all SetPriority calls should happen at allocator initialization.
|
||||||
|
func (a *Allocator) SetPriority(id reg.ID, p int) {
|
||||||
|
a.priority[id] = p
|
||||||
|
a.sortregisters()
|
||||||
|
}
|
||||||
|
|
||||||
|
// sortregisters sorts the list of available registers: higher priority first,
|
||||||
|
// falling back to sorting by ID.
|
||||||
|
func (a *Allocator) sortregisters() {
|
||||||
|
sort.Slice(a.registers, func(i, j int) bool {
|
||||||
|
ri, rj := a.registers[i], a.registers[j]
|
||||||
|
pi, pj := a.priority[ri], a.priority[rj]
|
||||||
|
return (pi > pj) || (pi == pj && ri < rj)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddInterferenceSet records that r interferes with every register in s. Convenience wrapper around AddInterference.
|
||||||
|
func (a *Allocator) AddInterferenceSet(r reg.Register, s reg.MaskSet) {
|
||||||
|
for id, mask := range s {
|
||||||
|
if (r.Mask() & mask) != 0 {
|
||||||
|
a.AddInterference(r.ID(), id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddInterference records that x and y must be assigned to non-conflicting physical registers.
|
||||||
|
func (a *Allocator) AddInterference(x, y reg.ID) {
|
||||||
|
a.Add(x)
|
||||||
|
a.Add(y)
|
||||||
|
a.edges = append(a.edges, &edge{X: x, Y: y})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds a register to be allocated. Does nothing if the register has already been added.
|
||||||
|
func (a *Allocator) Add(v reg.ID) {
|
||||||
|
if !v.IsVirtual() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, found := a.possible[v]; found {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.possible[v] = a.possibleregisters(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate allocates physical registers.
|
||||||
|
func (a *Allocator) Allocate() (reg.Allocation, error) {
|
||||||
|
for {
|
||||||
|
if err := a.update(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.remaining() == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
v := a.mostrestricted()
|
||||||
|
if err := a.alloc(v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a.allocation, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// update possible allocations based on edges.
|
||||||
|
func (a *Allocator) update() error {
|
||||||
|
var rem []*edge
|
||||||
|
for _, e := range a.edges {
|
||||||
|
x := a.allocation.LookupDefault(e.X)
|
||||||
|
y := a.allocation.LookupDefault(e.Y)
|
||||||
|
switch {
|
||||||
|
case x.IsVirtual() && y.IsVirtual():
|
||||||
|
rem = append(rem, e)
|
||||||
|
continue
|
||||||
|
case x.IsPhysical() && y.IsPhysical():
|
||||||
|
if x == y {
|
||||||
|
return errors.New("impossible register allocation")
|
||||||
|
}
|
||||||
|
case x.IsPhysical() && y.IsVirtual():
|
||||||
|
a.discardconflicting(y, x)
|
||||||
|
case x.IsVirtual() && y.IsPhysical():
|
||||||
|
a.discardconflicting(x, y)
|
||||||
|
default:
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a.edges = rem
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mostrestricted returns the virtual register with the least possibilities.
|
||||||
|
func (a *Allocator) mostrestricted() reg.ID {
|
||||||
|
n := int(math.MaxInt32)
|
||||||
|
var v reg.ID
|
||||||
|
for w, p := range a.possible {
|
||||||
|
// On a tie, choose the smallest ID in numeric order. This avoids
|
||||||
|
// non-deterministic allocations due to map iteration order.
|
||||||
|
if len(p) < n || (len(p) == n && w < v) {
|
||||||
|
n = len(p)
|
||||||
|
v = w
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// discardconflicting removes registers from vs possible list that conflict with p.
|
||||||
|
func (a *Allocator) discardconflicting(v, p reg.ID) {
|
||||||
|
a.possible[v] = filterregisters(a.possible[v], func(r reg.ID) bool {
|
||||||
|
return r != p
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// alloc attempts to allocate a register to v.
|
||||||
|
func (a *Allocator) alloc(v reg.ID) error {
|
||||||
|
ps := a.possible[v]
|
||||||
|
if len(ps) == 0 {
|
||||||
|
return errors.New("failed to allocate registers")
|
||||||
|
}
|
||||||
|
p := ps[0]
|
||||||
|
a.allocation[v] = p
|
||||||
|
delete(a.possible, v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// remaining returns the number of unallocated registers.
|
||||||
|
func (a *Allocator) remaining() int {
|
||||||
|
return len(a.possible)
|
||||||
|
}
|
||||||
|
|
||||||
|
// possibleregisters returns all allocate-able registers for the given virtual.
|
||||||
|
func (a *Allocator) possibleregisters(v reg.ID) []reg.ID {
|
||||||
|
return filterregisters(a.registers, func(r reg.ID) bool {
|
||||||
|
return v.Kind() == r.Kind()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterregisters(in []reg.ID, predicate func(reg.ID) bool) []reg.ID {
|
||||||
|
var rs []reg.ID
|
||||||
|
for _, r := range in {
|
||||||
|
if predicate(r) {
|
||||||
|
rs = append(rs, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
81
vendor/github.com/mmcloughlin/avo/pass/cfg.go
generated
vendored
Normal file
81
vendor/github.com/mmcloughlin/avo/pass/cfg.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LabelTarget populates the LabelTarget of the given function. This maps from
|
||||||
|
// label name to the following instruction.
|
||||||
|
func LabelTarget(fn *ir.Function) error {
|
||||||
|
target := map[ir.Label]*ir.Instruction{}
|
||||||
|
var pending []ir.Label
|
||||||
|
for _, node := range fn.Nodes {
|
||||||
|
switch n := node.(type) {
|
||||||
|
case ir.Label:
|
||||||
|
if _, found := target[n]; found {
|
||||||
|
return fmt.Errorf("duplicate label \"%s\"", n)
|
||||||
|
}
|
||||||
|
pending = append(pending, n)
|
||||||
|
case *ir.Instruction:
|
||||||
|
for _, label := range pending {
|
||||||
|
target[label] = n
|
||||||
|
}
|
||||||
|
pending = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(pending) != 0 {
|
||||||
|
return errors.New("function ends with label")
|
||||||
|
}
|
||||||
|
fn.LabelTarget = target
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CFG constructs the call-flow-graph for the function.
|
||||||
|
func CFG(fn *ir.Function) error {
|
||||||
|
is := fn.Instructions()
|
||||||
|
n := len(is)
|
||||||
|
|
||||||
|
// Populate successors.
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
cur := is[i]
|
||||||
|
var nxt *ir.Instruction
|
||||||
|
if i+1 < n {
|
||||||
|
nxt = is[i+1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's a branch, locate the target.
|
||||||
|
if cur.IsBranch {
|
||||||
|
lbl := cur.TargetLabel()
|
||||||
|
if lbl == nil {
|
||||||
|
return errors.New("no label for branch instruction")
|
||||||
|
}
|
||||||
|
target, found := fn.LabelTarget[*lbl]
|
||||||
|
if !found {
|
||||||
|
return fmt.Errorf("unknown label %q", *lbl)
|
||||||
|
}
|
||||||
|
cur.Succ = append(cur.Succ, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, could continue to the following instruction.
|
||||||
|
switch {
|
||||||
|
case cur.IsTerminal:
|
||||||
|
case cur.IsUnconditionalBranch():
|
||||||
|
default:
|
||||||
|
cur.Succ = append(cur.Succ, nxt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate predecessors.
|
||||||
|
for _, i := range is {
|
||||||
|
for _, s := range i.Succ {
|
||||||
|
if s != nil {
|
||||||
|
s.Pred = append(s.Pred, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
123
vendor/github.com/mmcloughlin/avo/pass/cleanup.go
generated
vendored
Normal file
123
vendor/github.com/mmcloughlin/avo/pass/cleanup.go
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PruneJumpToFollowingLabel removes jump instructions that target an
|
||||||
|
// immediately following label.
|
||||||
|
func PruneJumpToFollowingLabel(fn *ir.Function) error {
|
||||||
|
for i := 0; i+1 < len(fn.Nodes); i++ {
|
||||||
|
node := fn.Nodes[i]
|
||||||
|
next := fn.Nodes[i+1]
|
||||||
|
|
||||||
|
// This node is an unconditional jump.
|
||||||
|
inst, ok := node.(*ir.Instruction)
|
||||||
|
if !ok || !inst.IsBranch || inst.IsConditional {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
target := inst.TargetLabel()
|
||||||
|
if target == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// And the jump target is the immediately following node.
|
||||||
|
lbl, ok := next.(ir.Label)
|
||||||
|
if !ok || lbl != *target {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then the jump is unnecessary and can be removed.
|
||||||
|
fn.Nodes = deletenode(fn.Nodes, i)
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PruneDanglingLabels removes labels that are not referenced by any branches.
|
||||||
|
func PruneDanglingLabels(fn *ir.Function) error {
|
||||||
|
// Count label references.
|
||||||
|
count := map[ir.Label]int{}
|
||||||
|
for _, n := range fn.Nodes {
|
||||||
|
i, ok := n.(*ir.Instruction)
|
||||||
|
if !ok || !i.IsBranch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
target := i.TargetLabel()
|
||||||
|
if target == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
count[*target]++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for labels with no references.
|
||||||
|
for i := 0; i < len(fn.Nodes); i++ {
|
||||||
|
node := fn.Nodes[i]
|
||||||
|
lbl, ok := node.(ir.Label)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if count[lbl] == 0 {
|
||||||
|
fn.Nodes = deletenode(fn.Nodes, i)
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PruneSelfMoves removes move instructions from one register to itself.
|
||||||
|
func PruneSelfMoves(fn *ir.Function) error {
|
||||||
|
return removeinstructions(fn, func(i *ir.Instruction) bool {
|
||||||
|
switch i.Opcode {
|
||||||
|
case "MOVB", "MOVW", "MOVL", "MOVQ":
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return operand.IsRegister(i.Operands[0]) && operand.IsRegister(i.Operands[1]) && i.Operands[0] == i.Operands[1]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeinstructions deletes instructions from the given function which match predicate.
|
||||||
|
func removeinstructions(fn *ir.Function, predicate func(*ir.Instruction) bool) error {
|
||||||
|
// Removal of instructions has the potential to invalidate CFG structures.
|
||||||
|
// Clear them to prevent accidental use of stale structures after this pass.
|
||||||
|
invalidatecfg(fn)
|
||||||
|
|
||||||
|
for i := 0; i < len(fn.Nodes); i++ {
|
||||||
|
n := fn.Nodes[i]
|
||||||
|
|
||||||
|
inst, ok := n.(*ir.Instruction)
|
||||||
|
if !ok || !predicate(inst) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fn.Nodes = deletenode(fn.Nodes, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// deletenode deletes node i from nodes and returns the resulting slice.
|
||||||
|
func deletenode(nodes []ir.Node, i int) []ir.Node {
|
||||||
|
n := len(nodes)
|
||||||
|
copy(nodes[i:], nodes[i+1:])
|
||||||
|
nodes[n-1] = nil
|
||||||
|
return nodes[:n-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// invalidatecfg clears CFG structures.
|
||||||
|
func invalidatecfg(fn *ir.Function) {
|
||||||
|
fn.LabelTarget = nil
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
i.Pred = nil
|
||||||
|
i.Succ = nil
|
||||||
|
}
|
||||||
|
}
|
31
vendor/github.com/mmcloughlin/avo/pass/isa.go
generated
vendored
Normal file
31
vendor/github.com/mmcloughlin/avo/pass/isa.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RequiredISAExtensions determines ISA extensions required for the given
|
||||||
|
// function. Populates the ISA field.
|
||||||
|
func RequiredISAExtensions(fn *ir.Function) error {
|
||||||
|
// Collect ISA set.
|
||||||
|
set := map[string]bool{}
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
for _, isa := range i.ISA {
|
||||||
|
set[isa] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(set) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the function's ISA field with the unique sorted list.
|
||||||
|
for isa := range set {
|
||||||
|
fn.ISA = append(fn.ISA, isa)
|
||||||
|
}
|
||||||
|
sort.Strings(fn.ISA)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
101
vendor/github.com/mmcloughlin/avo/pass/pass.go
generated
vendored
Normal file
101
vendor/github.com/mmcloughlin/avo/pass/pass.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Package pass implements processing passes on avo Files.
|
||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
"github.com/mmcloughlin/avo/printer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Compile pass compiles an avo file. Upon successful completion the avo file
|
||||||
|
// may be printed to Go assembly.
|
||||||
|
var Compile = Concat(
|
||||||
|
Verify,
|
||||||
|
FunctionPass(PruneJumpToFollowingLabel),
|
||||||
|
FunctionPass(PruneDanglingLabels),
|
||||||
|
FunctionPass(LabelTarget),
|
||||||
|
FunctionPass(CFG),
|
||||||
|
InstructionPass(ZeroExtend32BitOutputs),
|
||||||
|
FunctionPass(Liveness),
|
||||||
|
FunctionPass(AllocateRegisters),
|
||||||
|
FunctionPass(BindRegisters),
|
||||||
|
FunctionPass(VerifyAllocation),
|
||||||
|
FunctionPass(EnsureBasePointerCalleeSaved),
|
||||||
|
Func(IncludeTextFlagHeader),
|
||||||
|
FunctionPass(PruneSelfMoves),
|
||||||
|
FunctionPass(RequiredISAExtensions),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface for a processing pass.
|
||||||
|
type Interface interface {
|
||||||
|
Execute(*ir.File) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func adapts a function to the pass Interface.
|
||||||
|
type Func func(*ir.File) error
|
||||||
|
|
||||||
|
// Execute calls p.
|
||||||
|
func (p Func) Execute(f *ir.File) error {
|
||||||
|
return p(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FunctionPass is a convenience for implementing a full file pass with a
|
||||||
|
// function that operates on each avo Function independently.
|
||||||
|
type FunctionPass func(*ir.Function) error
|
||||||
|
|
||||||
|
// Execute calls p on every function in the file. Exits on the first error.
|
||||||
|
func (p FunctionPass) Execute(f *ir.File) error {
|
||||||
|
for _, fn := range f.Functions() {
|
||||||
|
if err := p(fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstructionPass is a convenience for implementing a full file pass with a
|
||||||
|
// function that operates on each Instruction independently.
|
||||||
|
type InstructionPass func(*ir.Instruction) error
|
||||||
|
|
||||||
|
// Execute calls p on every instruction in the file. Exits on the first error.
|
||||||
|
func (p InstructionPass) Execute(f *ir.File) error {
|
||||||
|
for _, fn := range f.Functions() {
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
if err := p(i); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Concat returns a pass that executes the given passes in order, stopping on the first error.
|
||||||
|
func Concat(passes ...Interface) Interface {
|
||||||
|
return Func(func(f *ir.File) error {
|
||||||
|
for _, p := range passes {
|
||||||
|
if err := p.Execute(f); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output pass prints a file.
|
||||||
|
type Output struct {
|
||||||
|
Writer io.WriteCloser
|
||||||
|
Printer printer.Printer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute prints f with the configured Printer and writes output to Writer.
|
||||||
|
func (o *Output) Execute(f *ir.File) error {
|
||||||
|
b, err := o.Printer.Print(f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err = o.Writer.Write(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return o.Writer.Close()
|
||||||
|
}
|
223
vendor/github.com/mmcloughlin/avo/pass/reg.go
generated
vendored
Normal file
223
vendor/github.com/mmcloughlin/avo/pass/reg.go
generated
vendored
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/gotypes"
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ZeroExtend32BitOutputs applies the rule that "32-bit operands generate a
|
||||||
|
// 32-bit result, zero-extended to a 64-bit result in the destination
|
||||||
|
// general-purpose register" (Intel Software Developer’s Manual, Volume 1,
|
||||||
|
// 3.4.1.1).
|
||||||
|
func ZeroExtend32BitOutputs(i *ir.Instruction) error {
|
||||||
|
for j, op := range i.Outputs {
|
||||||
|
if !operand.IsR32(op) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r, ok := op.(reg.GP)
|
||||||
|
if !ok {
|
||||||
|
panic("r32 operand should satisfy reg.GP")
|
||||||
|
}
|
||||||
|
i.Outputs[j] = r.As64()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liveness computes register liveness.
|
||||||
|
func Liveness(fn *ir.Function) error {
|
||||||
|
// Note this implementation is initially naive so as to be "obviously correct".
|
||||||
|
// There are a well-known optimizations we can apply if necessary.
|
||||||
|
|
||||||
|
is := fn.Instructions()
|
||||||
|
|
||||||
|
// Process instructions in reverse: poor approximation to topological sort.
|
||||||
|
// TODO(mbm): process instructions in topological sort order
|
||||||
|
for l, r := 0, len(is)-1; l < r; l, r = l+1, r-1 {
|
||||||
|
is[l], is[r] = is[r], is[l]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize.
|
||||||
|
for _, i := range is {
|
||||||
|
i.LiveIn = reg.NewMaskSetFromRegisters(i.InputRegisters())
|
||||||
|
i.LiveOut = reg.NewEmptyMaskSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterative dataflow analysis.
|
||||||
|
for {
|
||||||
|
changes := false
|
||||||
|
|
||||||
|
for _, i := range is {
|
||||||
|
// out[n] = UNION[s IN succ[n]] in[s]
|
||||||
|
for _, s := range i.Succ {
|
||||||
|
if s == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
changes = i.LiveOut.Update(s.LiveIn) || changes
|
||||||
|
}
|
||||||
|
|
||||||
|
// in[n] = use[n] UNION (out[n] - def[n])
|
||||||
|
def := reg.NewMaskSetFromRegisters(i.OutputRegisters())
|
||||||
|
changes = i.LiveIn.Update(i.LiveOut.Difference(def)) || changes
|
||||||
|
}
|
||||||
|
|
||||||
|
if !changes {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllocateRegisters performs register allocation.
|
||||||
|
func AllocateRegisters(fn *ir.Function) error {
|
||||||
|
// Initialize one allocator per kind.
|
||||||
|
as := map[reg.Kind]*Allocator{}
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
for _, r := range i.Registers() {
|
||||||
|
k := r.Kind()
|
||||||
|
if _, found := as[k]; !found {
|
||||||
|
a, err := NewAllocatorForKind(k)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
as[k] = a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-prioritize the base pointer register. This can be used as a general
|
||||||
|
// purpose register, but it's callee-save so needs to be saved/restored if
|
||||||
|
// it is clobbered. For this reason we prefer to avoid using it unless
|
||||||
|
// forced to by register pressure.
|
||||||
|
for k, a := range as {
|
||||||
|
f := reg.FamilyOfKind(k)
|
||||||
|
for _, r := range f.Registers() {
|
||||||
|
if (r.Info() & reg.BasePointer) != 0 {
|
||||||
|
// Negative priority penalizes this register relative to all
|
||||||
|
// others (having default zero priority).
|
||||||
|
a.SetPriority(r.ID(), -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate registers to be allocated.
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
for _, r := range i.Registers() {
|
||||||
|
as[r.Kind()].Add(r.ID())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record register interferences.
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
for _, d := range i.OutputRegisters() {
|
||||||
|
k := d.Kind()
|
||||||
|
out := i.LiveOut.OfKind(k)
|
||||||
|
out.DiscardRegister(d)
|
||||||
|
as[k].AddInterferenceSet(d, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute register allocation.
|
||||||
|
fn.Allocation = reg.NewEmptyAllocation()
|
||||||
|
for _, a := range as {
|
||||||
|
al, err := a.Allocate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := fn.Allocation.Merge(al); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindRegisters applies the result of register allocation, replacing all virtual registers with their assigned physical registers.
|
||||||
|
func BindRegisters(fn *ir.Function) error {
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
for idx := range i.Operands {
|
||||||
|
i.Operands[idx] = operand.ApplyAllocation(i.Operands[idx], fn.Allocation)
|
||||||
|
}
|
||||||
|
for idx := range i.Inputs {
|
||||||
|
i.Inputs[idx] = operand.ApplyAllocation(i.Inputs[idx], fn.Allocation)
|
||||||
|
}
|
||||||
|
for idx := range i.Outputs {
|
||||||
|
i.Outputs[idx] = operand.ApplyAllocation(i.Outputs[idx], fn.Allocation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyAllocation performs sanity checks following register allocation.
|
||||||
|
func VerifyAllocation(fn *ir.Function) error {
|
||||||
|
// All registers should be physical.
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
for _, r := range i.Registers() {
|
||||||
|
if reg.ToPhysical(r) == nil {
|
||||||
|
return errors.New("non physical register found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnsureBasePointerCalleeSaved ensures that the base pointer register will be
|
||||||
|
// saved and restored if it has been clobbered by the function.
|
||||||
|
func EnsureBasePointerCalleeSaved(fn *ir.Function) error {
|
||||||
|
// Check to see if the base pointer is written to.
|
||||||
|
clobbered := false
|
||||||
|
for _, i := range fn.Instructions() {
|
||||||
|
for _, r := range i.OutputRegisters() {
|
||||||
|
if p := reg.ToPhysical(r); p != nil && (p.Info()®.BasePointer) != 0 {
|
||||||
|
clobbered = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !clobbered {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function clobbers the base pointer register so we need to ensure it
|
||||||
|
// will be saved and restored. The Go assembler will do this automatically,
|
||||||
|
// with a few exceptions detailed below. In summary, we can usually ensure
|
||||||
|
// this happens by ensuring the function is not frameless (apart from
|
||||||
|
// NOFRAME functions).
|
||||||
|
//
|
||||||
|
// Reference: https://github.com/golang/go/blob/3f4977bd5800beca059defb5de4dc64cd758cbb9/src/cmd/internal/obj/x86/obj6.go#L591-L609
|
||||||
|
//
|
||||||
|
// var bpsize int
|
||||||
|
// if ctxt.Arch.Family == sys.AMD64 &&
|
||||||
|
// !p.From.Sym.NoFrame() && // (1) below
|
||||||
|
// !(autoffset == 0 && p.From.Sym.NoSplit()) && // (2) below
|
||||||
|
// !(autoffset == 0 && !hasCall) { // (3) below
|
||||||
|
// // Make room to save a base pointer.
|
||||||
|
// // There are 2 cases we must avoid:
|
||||||
|
// // 1) If noframe is set (which we do for functions which tail call).
|
||||||
|
// // 2) Scary runtime internals which would be all messed up by frame pointers.
|
||||||
|
// // We detect these using a heuristic: frameless nosplit functions.
|
||||||
|
// // TODO: Maybe someday we label them all with NOFRAME and get rid of this heuristic.
|
||||||
|
// // For performance, we also want to avoid:
|
||||||
|
// // 3) Frameless leaf functions
|
||||||
|
// bpsize = ctxt.Arch.PtrSize
|
||||||
|
// autoffset += int32(bpsize)
|
||||||
|
// p.To.Offset += int64(bpsize)
|
||||||
|
// } else {
|
||||||
|
// bpsize = 0
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
if fn.Attributes.NOFRAME() {
|
||||||
|
return errors.New("NOFRAME function clobbers base pointer register")
|
||||||
|
}
|
||||||
|
|
||||||
|
if fn.LocalSize == 0 {
|
||||||
|
fn.AllocLocal(int(gotypes.PointerSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
42
vendor/github.com/mmcloughlin/avo/pass/textflag.go
generated
vendored
Normal file
42
vendor/github.com/mmcloughlin/avo/pass/textflag.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mmcloughlin/avo/attr"
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IncludeTextFlagHeader includes textflag.h if necessary.
|
||||||
|
func IncludeTextFlagHeader(f *ir.File) error {
|
||||||
|
const textflagheader = "textflag.h"
|
||||||
|
|
||||||
|
// Check if we already have it.
|
||||||
|
for _, path := range f.Includes {
|
||||||
|
if path == textflagheader {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add it if necessary.
|
||||||
|
if requirestextflags(f) {
|
||||||
|
f.Includes = append(f.Includes, textflagheader)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// requirestextflags returns whether the file uses flags in the textflags.h header.
|
||||||
|
func requirestextflags(f *ir.File) bool {
|
||||||
|
for _, s := range f.Sections {
|
||||||
|
var a attr.Attribute
|
||||||
|
switch s := s.(type) {
|
||||||
|
case *ir.Function:
|
||||||
|
a = s.Attributes
|
||||||
|
case *ir.Global:
|
||||||
|
a = s.Attributes
|
||||||
|
}
|
||||||
|
if a.ContainsTextFlags() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
32
vendor/github.com/mmcloughlin/avo/pass/verify.go
generated
vendored
Normal file
32
vendor/github.com/mmcloughlin/avo/pass/verify.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package pass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Verify pass validates an avo file.
|
||||||
|
var Verify = Concat(
|
||||||
|
InstructionPass(VerifyMemOperands),
|
||||||
|
)
|
||||||
|
|
||||||
|
// VerifyMemOperands checks the instruction's memory operands.
|
||||||
|
func VerifyMemOperands(i *ir.Instruction) error {
|
||||||
|
for _, op := range i.Operands {
|
||||||
|
m, ok := op.(operand.Mem)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Base == nil {
|
||||||
|
return errors.New("bad memory operand: missing base register")
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Index != nil && m.Scale == 0 {
|
||||||
|
return errors.New("bad memory operand: index register with scale 0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
192
vendor/github.com/mmcloughlin/avo/printer/goasm.go
generated
vendored
Normal file
192
vendor/github.com/mmcloughlin/avo/printer/goasm.go
generated
vendored
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
package printer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/buildtags"
|
||||||
|
"github.com/mmcloughlin/avo/internal/prnt"
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// dot is the pesky unicode dot used in Go assembly.
|
||||||
|
const dot = "\u00b7"
|
||||||
|
|
||||||
|
type goasm struct {
|
||||||
|
cfg Config
|
||||||
|
prnt.Generator
|
||||||
|
|
||||||
|
instructions []*ir.Instruction
|
||||||
|
clear bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGoAsm constructs a printer for writing Go assembly files.
|
||||||
|
func NewGoAsm(cfg Config) Printer {
|
||||||
|
return &goasm{cfg: cfg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *goasm) Print(f *ir.File) ([]byte, error) {
|
||||||
|
p.header(f)
|
||||||
|
for _, s := range f.Sections {
|
||||||
|
switch s := s.(type) {
|
||||||
|
case *ir.Function:
|
||||||
|
p.function(s)
|
||||||
|
case *ir.Global:
|
||||||
|
p.global(s)
|
||||||
|
default:
|
||||||
|
panic("unknown section type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *goasm) header(f *ir.File) {
|
||||||
|
p.Comment(p.cfg.GeneratedWarning())
|
||||||
|
|
||||||
|
if len(f.Constraints) > 0 {
|
||||||
|
constraints, err := buildtags.Format(f.Constraints)
|
||||||
|
if err != nil {
|
||||||
|
p.AddError(err)
|
||||||
|
}
|
||||||
|
p.NL()
|
||||||
|
p.Printf(constraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(f.Includes) > 0 {
|
||||||
|
p.NL()
|
||||||
|
p.includes(f.Includes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *goasm) includes(paths []string) {
|
||||||
|
for _, path := range paths {
|
||||||
|
p.Printf("#include \"%s\"\n", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *goasm) function(f *ir.Function) {
|
||||||
|
p.NL()
|
||||||
|
p.Comment(f.Stub())
|
||||||
|
|
||||||
|
if len(f.ISA) > 0 {
|
||||||
|
p.Comment("Requires: " + strings.Join(f.ISA, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference: https://github.com/golang/go/blob/b115207baf6c2decc3820ada4574ef4e5ad940ec/src/cmd/internal/obj/util.go#L166-L176
|
||||||
|
//
|
||||||
|
// if p.As == ATEXT {
|
||||||
|
// // If there are attributes, print them. Otherwise, skip the comma.
|
||||||
|
// // In short, print one of these two:
|
||||||
|
// // TEXT foo(SB), DUPOK|NOSPLIT, $0
|
||||||
|
// // TEXT foo(SB), $0
|
||||||
|
// s := p.From.Sym.Attribute.TextAttrString()
|
||||||
|
// if s != "" {
|
||||||
|
// fmt.Fprintf(&buf, "%s%s", sep, s)
|
||||||
|
// sep = ", "
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
p.Printf("TEXT %s%s(SB)", dot, f.Name)
|
||||||
|
if f.Attributes != 0 {
|
||||||
|
p.Printf(", %s", f.Attributes.Asm())
|
||||||
|
}
|
||||||
|
p.Printf(", %s\n", textsize(f))
|
||||||
|
|
||||||
|
p.clear = true
|
||||||
|
for _, node := range f.Nodes {
|
||||||
|
switch n := node.(type) {
|
||||||
|
case *ir.Instruction:
|
||||||
|
p.instruction(n)
|
||||||
|
if n.IsTerminal || n.IsUnconditionalBranch() {
|
||||||
|
p.flush()
|
||||||
|
}
|
||||||
|
case ir.Label:
|
||||||
|
p.flush()
|
||||||
|
p.ensureclear()
|
||||||
|
p.Printf("%s:\n", n)
|
||||||
|
case *ir.Comment:
|
||||||
|
p.flush()
|
||||||
|
p.ensureclear()
|
||||||
|
for _, line := range n.Lines {
|
||||||
|
p.Printf("\t// %s\n", line)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unexpected node type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *goasm) instruction(i *ir.Instruction) {
|
||||||
|
p.instructions = append(p.instructions, i)
|
||||||
|
p.clear = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *goasm) flush() {
|
||||||
|
if len(p.instructions) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine instruction width. Instructions with no operands are not
|
||||||
|
// considered in this calculation.
|
||||||
|
width := 0
|
||||||
|
for _, i := range p.instructions {
|
||||||
|
opcode := i.OpcodeWithSuffixes()
|
||||||
|
if len(i.Operands) > 0 && len(opcode) > width {
|
||||||
|
width = len(opcode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output instruction block.
|
||||||
|
for _, i := range p.instructions {
|
||||||
|
if len(i.Operands) > 0 {
|
||||||
|
p.Printf("\t%-*s%s\n", width+1, i.OpcodeWithSuffixes(), joinOperands(i.Operands))
|
||||||
|
} else {
|
||||||
|
p.Printf("\t%s\n", i.OpcodeWithSuffixes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.instructions = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *goasm) ensureclear() {
|
||||||
|
if !p.clear {
|
||||||
|
p.NL()
|
||||||
|
p.clear = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *goasm) global(g *ir.Global) {
|
||||||
|
p.NL()
|
||||||
|
for _, d := range g.Data {
|
||||||
|
a := operand.NewDataAddr(g.Symbol, d.Offset)
|
||||||
|
p.Printf("DATA %s/%d, %s\n", a.Asm(), d.Value.Bytes(), d.Value.Asm())
|
||||||
|
}
|
||||||
|
p.Printf("GLOBL %s(SB), %s, $%d\n", g.Symbol, g.Attributes.Asm(), g.Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func textsize(f *ir.Function) string {
|
||||||
|
// Reference: https://github.com/golang/go/blob/b115207baf6c2decc3820ada4574ef4e5ad940ec/src/cmd/internal/obj/util.go#L260-L265
|
||||||
|
//
|
||||||
|
// case TYPE_TEXTSIZE:
|
||||||
|
// if a.Val.(int32) == objabi.ArgsSizeUnknown {
|
||||||
|
// str = fmt.Sprintf("$%d", a.Offset)
|
||||||
|
// } else {
|
||||||
|
// str = fmt.Sprintf("$%d-%d", a.Offset, a.Val.(int32))
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
s := "$" + strconv.Itoa(f.FrameBytes())
|
||||||
|
if argsize := f.ArgumentBytes(); argsize > 0 {
|
||||||
|
return s + "-" + strconv.Itoa(argsize)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func joinOperands(operands []operand.Op) string {
|
||||||
|
asm := make([]string, len(operands))
|
||||||
|
for i, op := range operands {
|
||||||
|
asm[i] = op.Asm()
|
||||||
|
}
|
||||||
|
return strings.Join(asm, ", ")
|
||||||
|
}
|
98
vendor/github.com/mmcloughlin/avo/printer/printer.go
generated
vendored
Normal file
98
vendor/github.com/mmcloughlin/avo/printer/printer.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
// Package printer implements printing of avo files in various formats.
|
||||||
|
package printer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/internal/stack"
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Printer can produce output for an avo File.
|
||||||
|
type Printer interface {
|
||||||
|
Print(*ir.File) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builder can construct a printer.
|
||||||
|
type Builder func(Config) Printer
|
||||||
|
|
||||||
|
// Config represents general printing configuration.
|
||||||
|
type Config struct {
|
||||||
|
// Command-line arguments passed to the generator. If provided, this will be
|
||||||
|
// included in a code generation warning.
|
||||||
|
Argv []string
|
||||||
|
|
||||||
|
// Name of the code generator.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Name of Go package the generated code will belong to.
|
||||||
|
Pkg string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDefaultConfig produces a config with Name "avo".
|
||||||
|
// The package name is guessed from the current directory.
|
||||||
|
func NewDefaultConfig() Config {
|
||||||
|
return Config{
|
||||||
|
Name: "avo",
|
||||||
|
Pkg: pkg(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewArgvConfig constructs a Config from os.Args.
|
||||||
|
// The package name is guessed from the current directory.
|
||||||
|
func NewArgvConfig() Config {
|
||||||
|
return Config{
|
||||||
|
Argv: os.Args,
|
||||||
|
Pkg: pkg(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGoRunConfig produces a Config for a generator that's expected to be
|
||||||
|
// executed via "go run ...".
|
||||||
|
func NewGoRunConfig() Config {
|
||||||
|
path := mainfile()
|
||||||
|
if path == "" {
|
||||||
|
return NewDefaultConfig()
|
||||||
|
}
|
||||||
|
argv := []string{"go", "run", filepath.Base(path)}
|
||||||
|
if len(os.Args) > 1 {
|
||||||
|
argv = append(argv, os.Args[1:]...)
|
||||||
|
}
|
||||||
|
return Config{
|
||||||
|
Argv: argv,
|
||||||
|
Pkg: pkg(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GeneratedBy returns a description of the code generator.
|
||||||
|
func (c Config) GeneratedBy() string {
|
||||||
|
if c.Argv == nil {
|
||||||
|
return c.Name
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("command: %s", strings.Join(c.Argv, " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GeneratedWarning returns text for a code generation warning. Conforms to https://golang.org/s/generatedcode.
|
||||||
|
func (c Config) GeneratedWarning() string {
|
||||||
|
return fmt.Sprintf("Code generated by %s. DO NOT EDIT.", c.GeneratedBy())
|
||||||
|
}
|
||||||
|
|
||||||
|
// mainfile attempts to determine the file path of the main function by
|
||||||
|
// inspecting the stack. Returns empty string on failure.
|
||||||
|
func mainfile() string {
|
||||||
|
if m := stack.Main(); m != nil {
|
||||||
|
return m.File
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// pkg guesses the name of the package from the working directory.
|
||||||
|
func pkg() string {
|
||||||
|
if cwd, err := os.Getwd(); err == nil {
|
||||||
|
return filepath.Base(cwd)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
61
vendor/github.com/mmcloughlin/avo/printer/stubs.go
generated
vendored
Normal file
61
vendor/github.com/mmcloughlin/avo/printer/stubs.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package printer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/format"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/buildtags"
|
||||||
|
"github.com/mmcloughlin/avo/internal/prnt"
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stubs struct {
|
||||||
|
cfg Config
|
||||||
|
prnt.Generator
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStubs constructs a printer for writing stub function declarations.
|
||||||
|
func NewStubs(cfg Config) Printer {
|
||||||
|
return &stubs{cfg: cfg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubs) Print(f *ir.File) ([]byte, error) {
|
||||||
|
s.Comment(s.cfg.GeneratedWarning())
|
||||||
|
|
||||||
|
if len(f.Constraints) > 0 {
|
||||||
|
constraints, err := buildtags.Format(f.Constraints)
|
||||||
|
if err != nil {
|
||||||
|
s.AddError(err)
|
||||||
|
}
|
||||||
|
s.NL()
|
||||||
|
s.Printf(constraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.NL()
|
||||||
|
s.Printf("package %s\n", s.cfg.Pkg)
|
||||||
|
for _, fn := range f.Functions() {
|
||||||
|
s.NL()
|
||||||
|
s.Comment(fn.Doc...)
|
||||||
|
for _, pragma := range fn.Pragmas {
|
||||||
|
s.pragma(pragma)
|
||||||
|
}
|
||||||
|
s.Printf("%s\n", fn.Stub())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply formatting to the result. This is the simplest way to ensure
|
||||||
|
// comment formatting rules introduced in Go 1.19 are applied. See
|
||||||
|
// https://go.dev/doc/comment.
|
||||||
|
src, err := s.Result()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return format.Source(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubs) pragma(p ir.Pragma) {
|
||||||
|
s.Printf("//go:%s", p.Directive)
|
||||||
|
for _, arg := range p.Arguments {
|
||||||
|
s.Printf(" %s", arg)
|
||||||
|
}
|
||||||
|
s.NL()
|
||||||
|
}
|
57
vendor/github.com/mmcloughlin/avo/reg/collection.go
generated
vendored
Normal file
57
vendor/github.com/mmcloughlin/avo/reg/collection.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package reg
|
||||||
|
|
||||||
|
// Collection represents a collection of virtual registers. This is primarily
|
||||||
|
// useful for allocating virtual registers with distinct IDs.
|
||||||
|
type Collection struct {
|
||||||
|
idx map[Kind]Index
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCollection builds an empty register collection.
|
||||||
|
func NewCollection() *Collection {
|
||||||
|
return &Collection{
|
||||||
|
idx: map[Kind]Index{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualRegister allocates and returns a new virtual register of the given kind and width.
|
||||||
|
func (c *Collection) VirtualRegister(k Kind, s Spec) Virtual {
|
||||||
|
idx := c.idx[k]
|
||||||
|
c.idx[k]++
|
||||||
|
return NewVirtual(idx, k, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GP8L allocates and returns a general-purpose 8-bit register (low byte).
|
||||||
|
func (c *Collection) GP8L() GPVirtual { return c.GP(S8L) }
|
||||||
|
|
||||||
|
// GP8H allocates and returns a general-purpose 8-bit register (high byte).
|
||||||
|
func (c *Collection) GP8H() GPVirtual { return c.GP(S8H) }
|
||||||
|
|
||||||
|
// GP8 allocates and returns a general-purpose 8-bit register (low byte).
|
||||||
|
func (c *Collection) GP8() GPVirtual { return c.GP8L() }
|
||||||
|
|
||||||
|
// GP16 allocates and returns a general-purpose 16-bit register.
|
||||||
|
func (c *Collection) GP16() GPVirtual { return c.GP(S16) }
|
||||||
|
|
||||||
|
// GP32 allocates and returns a general-purpose 32-bit register.
|
||||||
|
func (c *Collection) GP32() GPVirtual { return c.GP(S32) }
|
||||||
|
|
||||||
|
// GP64 allocates and returns a general-purpose 64-bit register.
|
||||||
|
func (c *Collection) GP64() GPVirtual { return c.GP(S64) }
|
||||||
|
|
||||||
|
// GP allocates and returns a general-purpose register of the given width.
|
||||||
|
func (c *Collection) GP(s Spec) GPVirtual { return newgpv(c.VirtualRegister(KindGP, s)) }
|
||||||
|
|
||||||
|
// XMM allocates and returns a 128-bit vector register.
|
||||||
|
func (c *Collection) XMM() VecVirtual { return c.Vec(S128) }
|
||||||
|
|
||||||
|
// YMM allocates and returns a 256-bit vector register.
|
||||||
|
func (c *Collection) YMM() VecVirtual { return c.Vec(S256) }
|
||||||
|
|
||||||
|
// ZMM allocates and returns a 512-bit vector register.
|
||||||
|
func (c *Collection) ZMM() VecVirtual { return c.Vec(S512) }
|
||||||
|
|
||||||
|
// Vec allocates and returns a vector register of the given width.
|
||||||
|
func (c *Collection) Vec(s Spec) VecVirtual { return newvecv(c.VirtualRegister(KindVector, s)) }
|
||||||
|
|
||||||
|
// K allocates and returns an opmask register.
|
||||||
|
func (c *Collection) K() OpmaskVirtual { return newopmaskv(c.VirtualRegister(KindOpmask, S64)) }
|
2
vendor/github.com/mmcloughlin/avo/reg/doc.go
generated
vendored
Normal file
2
vendor/github.com/mmcloughlin/avo/reg/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package reg provides types for physical and virtual registers, and definitions of x86-64 register families.
|
||||||
|
package reg
|
112
vendor/github.com/mmcloughlin/avo/reg/set.go
generated
vendored
Normal file
112
vendor/github.com/mmcloughlin/avo/reg/set.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package reg
|
||||||
|
|
||||||
|
// MaskSet maps register IDs to masks.
|
||||||
|
type MaskSet map[ID]uint16
|
||||||
|
|
||||||
|
// NewEmptyMaskSet builds an empty register mask set.
|
||||||
|
func NewEmptyMaskSet() MaskSet {
|
||||||
|
return MaskSet{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMaskSetFromRegisters forms a mask set from the given register list.
|
||||||
|
func NewMaskSetFromRegisters(rs []Register) MaskSet {
|
||||||
|
s := NewEmptyMaskSet()
|
||||||
|
for _, r := range rs {
|
||||||
|
s.AddRegister(r)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone returns a copy of s.
|
||||||
|
func (s MaskSet) Clone() MaskSet {
|
||||||
|
c := NewEmptyMaskSet()
|
||||||
|
for id, mask := range s {
|
||||||
|
c.Add(id, mask)
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add mask to the given register ID.
|
||||||
|
// Reports whether this made any change to the set.
|
||||||
|
func (s MaskSet) Add(id ID, mask uint16) bool {
|
||||||
|
if (s[id] & mask) == mask {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s[id] |= mask
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRegister is a convenience for adding the register's (ID, mask) to the set.
|
||||||
|
// Reports whether this made any change to the set.
|
||||||
|
func (s MaskSet) AddRegister(r Register) bool {
|
||||||
|
return s.Add(r.ID(), r.Mask())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard clears masked bits from register ID.
|
||||||
|
// Reports whether this made any change to the set.
|
||||||
|
func (s MaskSet) Discard(id ID, mask uint16) bool {
|
||||||
|
if curr, found := s[id]; !found || (curr&mask) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s[id] &^= mask
|
||||||
|
if s[id] == 0 {
|
||||||
|
delete(s, id)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscardRegister is a convenience for discarding the register's (ID, mask) from the set.
|
||||||
|
// Reports whether this made any change to the set.
|
||||||
|
func (s MaskSet) DiscardRegister(r Register) bool {
|
||||||
|
return s.Discard(r.ID(), r.Mask())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update adds masks in t to s.
|
||||||
|
// Reports whether this made any change to the set.
|
||||||
|
func (s MaskSet) Update(t MaskSet) bool {
|
||||||
|
change := false
|
||||||
|
for id, mask := range t {
|
||||||
|
change = s.Add(id, mask) || change
|
||||||
|
}
|
||||||
|
return change
|
||||||
|
}
|
||||||
|
|
||||||
|
// Difference returns the set of registers in s but not t.
|
||||||
|
func (s MaskSet) Difference(t MaskSet) MaskSet {
|
||||||
|
d := s.Clone()
|
||||||
|
d.DifferenceUpdate(t)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// DifferenceUpdate removes every element of t from s.
|
||||||
|
func (s MaskSet) DifferenceUpdate(t MaskSet) bool {
|
||||||
|
change := false
|
||||||
|
for id, mask := range t {
|
||||||
|
change = s.Discard(id, mask) || change
|
||||||
|
}
|
||||||
|
return change
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equals returns true if s and t contain the same masks.
|
||||||
|
func (s MaskSet) Equals(t MaskSet) bool {
|
||||||
|
if len(s) != len(t) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for id, mask := range s {
|
||||||
|
if _, found := t[id]; !found || mask != t[id] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// OfKind returns the set of elements of s with kind k.
|
||||||
|
func (s MaskSet) OfKind(k Kind) MaskSet {
|
||||||
|
t := NewEmptyMaskSet()
|
||||||
|
for id, mask := range s {
|
||||||
|
if id.Kind() == k {
|
||||||
|
t.Add(id, mask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
305
vendor/github.com/mmcloughlin/avo/reg/types.go
generated
vendored
Normal file
305
vendor/github.com/mmcloughlin/avo/reg/types.go
generated
vendored
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
package reg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Kind is a class of registers.
|
||||||
|
type Kind uint8
|
||||||
|
|
||||||
|
// Index of a register within a kind.
|
||||||
|
type Index uint16
|
||||||
|
|
||||||
|
// Family is a collection of Physical registers of a common kind.
|
||||||
|
type Family struct {
|
||||||
|
Kind Kind
|
||||||
|
registers []Physical
|
||||||
|
}
|
||||||
|
|
||||||
|
// define builds a register and adds it to the Family.
|
||||||
|
func (f *Family) define(s Spec, idx Index, name string, flags ...Info) Physical {
|
||||||
|
r := newregister(f, s, idx, name, flags...)
|
||||||
|
f.add(r)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// add r to the family.
|
||||||
|
func (f *Family) add(r Physical) {
|
||||||
|
if r.Kind() != f.Kind {
|
||||||
|
panic("bad kind")
|
||||||
|
}
|
||||||
|
f.registers = append(f.registers, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Virtual returns a virtual register from this family's kind.
|
||||||
|
func (f *Family) Virtual(idx Index, s Spec) Virtual {
|
||||||
|
return NewVirtual(idx, f.Kind, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers returns the registers in this family.
|
||||||
|
func (f *Family) Registers() []Physical {
|
||||||
|
return append([]Physical(nil), f.registers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup returns the register with given physical index and spec. Returns nil if no such register exists.
|
||||||
|
func (f *Family) Lookup(idx Index, s Spec) Physical {
|
||||||
|
for _, r := range f.registers {
|
||||||
|
if r.PhysicalIndex() == idx && r.Mask() == s.Mask() {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID is a register identifier.
|
||||||
|
type ID uint32
|
||||||
|
|
||||||
|
// newid builds a new register ID from the virtual flag v, kind and index.
|
||||||
|
func newid(v uint8, kind Kind, idx Index) ID {
|
||||||
|
return ID(v) | (ID(kind) << 8) | (ID(idx) << 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVirtual reports whether this is an ID for a virtual register.
|
||||||
|
func (id ID) IsVirtual() bool { return (id & 1) == 1 }
|
||||||
|
|
||||||
|
// IsPhysical reports whether this is an ID for a physical register.
|
||||||
|
func (id ID) IsPhysical() bool { return !id.IsVirtual() }
|
||||||
|
|
||||||
|
// Kind extracts the kind from the register ID.
|
||||||
|
func (id ID) Kind() Kind { return Kind(id >> 8) }
|
||||||
|
|
||||||
|
// Index extracts the index from the register ID.
|
||||||
|
func (id ID) Index() Index { return Index(id >> 16) }
|
||||||
|
|
||||||
|
// Register represents a virtual or physical register.
|
||||||
|
type Register interface {
|
||||||
|
ID() ID
|
||||||
|
Kind() Kind
|
||||||
|
Size() uint
|
||||||
|
Mask() uint16
|
||||||
|
Asm() string
|
||||||
|
as(Spec) Register
|
||||||
|
spec() Spec
|
||||||
|
register()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal reports whether a and b are equal registers.
|
||||||
|
func Equal(a, b Register) bool {
|
||||||
|
return (a.ID() == b.ID()) && (a.Mask() == b.Mask())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Virtual is a register of a given type and size, not yet allocated to a physical register.
|
||||||
|
type Virtual interface {
|
||||||
|
VirtualIndex() Index
|
||||||
|
Register
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToVirtual converts r to Virtual if possible, otherwise returns nil.
|
||||||
|
func ToVirtual(r Register) Virtual {
|
||||||
|
if v, ok := r.(Virtual); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type virtual struct {
|
||||||
|
idx Index
|
||||||
|
kind Kind
|
||||||
|
Spec
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVirtual builds a Virtual register.
|
||||||
|
func NewVirtual(idx Index, k Kind, s Spec) Virtual {
|
||||||
|
return virtual{
|
||||||
|
idx: idx,
|
||||||
|
kind: k,
|
||||||
|
Spec: s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v virtual) ID() ID { return newid(1, v.kind, v.idx) }
|
||||||
|
func (v virtual) VirtualIndex() Index { return v.idx }
|
||||||
|
func (v virtual) Kind() Kind { return v.kind }
|
||||||
|
|
||||||
|
func (v virtual) Asm() string {
|
||||||
|
// TODO(mbm): decide on virtual register syntax
|
||||||
|
return fmt.Sprintf("<virtual:%v:%v:%v>", v.idx, v.Kind(), v.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v virtual) as(s Spec) Register {
|
||||||
|
return virtual{
|
||||||
|
idx: v.idx,
|
||||||
|
kind: v.kind,
|
||||||
|
Spec: s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v virtual) spec() Spec { return v.Spec }
|
||||||
|
func (v virtual) register() {}
|
||||||
|
|
||||||
|
// Info is a bitmask of register properties.
|
||||||
|
type Info uint8
|
||||||
|
|
||||||
|
// Defined register Info flags.
|
||||||
|
const (
|
||||||
|
None Info = 0
|
||||||
|
Restricted Info = 1 << iota
|
||||||
|
BasePointer
|
||||||
|
)
|
||||||
|
|
||||||
|
// Physical is a concrete register.
|
||||||
|
type Physical interface {
|
||||||
|
PhysicalIndex() Index
|
||||||
|
Info() Info
|
||||||
|
Register
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToPhysical converts r to Physical if possible, otherwise returns nil.
|
||||||
|
func ToPhysical(r Register) Physical {
|
||||||
|
if p, ok := r.(Physical); ok {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// register implements Physical.
|
||||||
|
type register struct {
|
||||||
|
family *Family
|
||||||
|
idx Index
|
||||||
|
name string
|
||||||
|
info Info
|
||||||
|
Spec
|
||||||
|
}
|
||||||
|
|
||||||
|
func newregister(f *Family, s Spec, idx Index, name string, flags ...Info) register {
|
||||||
|
r := register{
|
||||||
|
family: f,
|
||||||
|
idx: idx,
|
||||||
|
name: name,
|
||||||
|
info: None,
|
||||||
|
Spec: s,
|
||||||
|
}
|
||||||
|
for _, flag := range flags {
|
||||||
|
r.info |= flag
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r register) ID() ID { return newid(0, r.Kind(), r.idx) }
|
||||||
|
func (r register) PhysicalIndex() Index { return r.idx }
|
||||||
|
func (r register) Kind() Kind { return r.family.Kind }
|
||||||
|
func (r register) Asm() string { return r.name }
|
||||||
|
func (r register) Info() Info { return r.info }
|
||||||
|
|
||||||
|
func (r register) as(s Spec) Register {
|
||||||
|
return r.family.Lookup(r.PhysicalIndex(), s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r register) spec() Spec { return r.Spec }
|
||||||
|
func (r register) register() {}
|
||||||
|
|
||||||
|
// Spec defines the size of a register as well as the bit ranges it occupies in
|
||||||
|
// an underlying physical register.
|
||||||
|
type Spec uint16
|
||||||
|
|
||||||
|
// Spec values required for x86-64.
|
||||||
|
const (
|
||||||
|
S0 Spec = 0x0 // zero value reserved for pseudo registers
|
||||||
|
S8L Spec = 0x1
|
||||||
|
S8H Spec = 0x2
|
||||||
|
S8 = S8L
|
||||||
|
S16 Spec = 0x3
|
||||||
|
S32 Spec = 0x7
|
||||||
|
S64 Spec = 0xf
|
||||||
|
S128 Spec = 0x1f
|
||||||
|
S256 Spec = 0x3f
|
||||||
|
S512 Spec = 0x7f
|
||||||
|
)
|
||||||
|
|
||||||
|
// Mask returns a mask representing which bytes of an underlying register are
|
||||||
|
// used by this register. This is almost always the low bytes, except for the
|
||||||
|
// case of the high-byte registers. If bit n of the mask is set, this means
|
||||||
|
// bytes 2^(n-1) to 2^n-1 are used.
|
||||||
|
func (s Spec) Mask() uint16 {
|
||||||
|
return uint16(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the register width in bytes.
|
||||||
|
func (s Spec) Size() uint {
|
||||||
|
x := uint(s)
|
||||||
|
return (x >> 1) + (x & 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupPhysical returns the physical register with the given parameters, or nil if not found.
|
||||||
|
func LookupPhysical(k Kind, idx Index, s Spec) Physical {
|
||||||
|
f := FamilyOfKind(k)
|
||||||
|
if f == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return f.Lookup(idx, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupID returns the physical register with the given id and spec, or nil if not found.
|
||||||
|
func LookupID(id ID, s Spec) Physical {
|
||||||
|
if id.IsVirtual() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return LookupPhysical(id.Kind(), id.Index(), s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocation records a register allocation.
|
||||||
|
type Allocation map[ID]ID
|
||||||
|
|
||||||
|
// NewEmptyAllocation builds an empty register allocation.
|
||||||
|
func NewEmptyAllocation() Allocation {
|
||||||
|
return Allocation{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge allocations from b into a. Errors if there is disagreement on a common
|
||||||
|
// register.
|
||||||
|
func (a Allocation) Merge(b Allocation) error {
|
||||||
|
for id, p := range b {
|
||||||
|
if alt, found := a[id]; found && alt != p {
|
||||||
|
return errors.New("disagreement on overlapping register")
|
||||||
|
}
|
||||||
|
a[id] = p
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupDefault returns the register ID assigned by this allocation, returning
|
||||||
|
// id if none is found.
|
||||||
|
func (a Allocation) LookupDefault(id ID) ID {
|
||||||
|
if _, found := a[id]; found {
|
||||||
|
return a[id]
|
||||||
|
}
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupRegister the allocation for register r, or return nil if there is none.
|
||||||
|
func (a Allocation) LookupRegister(r Register) Physical {
|
||||||
|
// Return immediately if it is already a physical register.
|
||||||
|
if p := ToPhysical(r); p != nil {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup an allocation for this virtual ID.
|
||||||
|
id, found := a[r.ID()]
|
||||||
|
if !found {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return LookupID(id, r.spec())
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupRegisterDefault returns the register assigned to r, or r itself if there is none.
|
||||||
|
func (a Allocation) LookupRegisterDefault(r Register) Register {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if p := a.LookupRegister(r); p != nil {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
383
vendor/github.com/mmcloughlin/avo/reg/x86.go
generated
vendored
Normal file
383
vendor/github.com/mmcloughlin/avo/reg/x86.go
generated
vendored
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
package reg
|
||||||
|
|
||||||
|
// Register kinds.
|
||||||
|
const (
|
||||||
|
KindPseudo Kind = iota
|
||||||
|
KindGP
|
||||||
|
KindVector
|
||||||
|
KindOpmask
|
||||||
|
)
|
||||||
|
|
||||||
|
// Declare register families.
|
||||||
|
var (
|
||||||
|
Pseudo = &Family{Kind: KindPseudo}
|
||||||
|
GeneralPurpose = &Family{Kind: KindGP}
|
||||||
|
Vector = &Family{Kind: KindVector}
|
||||||
|
Opmask = &Family{Kind: KindOpmask}
|
||||||
|
|
||||||
|
Families = []*Family{
|
||||||
|
Pseudo,
|
||||||
|
GeneralPurpose,
|
||||||
|
Vector,
|
||||||
|
Opmask,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var familiesByKind = map[Kind]*Family{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for _, f := range Families {
|
||||||
|
familiesByKind[f.Kind] = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FamilyOfKind returns the Family of registers of the given kind, or nil if not found.
|
||||||
|
func FamilyOfKind(k Kind) *Family {
|
||||||
|
return familiesByKind[k]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pseudo registers.
|
||||||
|
var (
|
||||||
|
FramePointer = Pseudo.define(S0, 0, "FP")
|
||||||
|
ProgramCounter = Pseudo.define(S0, 0, "PC")
|
||||||
|
StaticBase = Pseudo.define(S0, 0, "SB")
|
||||||
|
StackPointer = Pseudo.define(S0, 0, "SP")
|
||||||
|
)
|
||||||
|
|
||||||
|
// GP provides additional methods for general purpose registers.
|
||||||
|
type GP interface {
|
||||||
|
As8() Register
|
||||||
|
As8L() Register
|
||||||
|
As8H() Register
|
||||||
|
As16() Register
|
||||||
|
As32() Register
|
||||||
|
As64() Register
|
||||||
|
}
|
||||||
|
|
||||||
|
// GPPhysical is a general-purpose physical register.
|
||||||
|
type GPPhysical interface {
|
||||||
|
Physical
|
||||||
|
GP
|
||||||
|
}
|
||||||
|
|
||||||
|
type gpp struct {
|
||||||
|
Physical
|
||||||
|
}
|
||||||
|
|
||||||
|
func newgpp(r Physical) GPPhysical { return gpp{Physical: r} }
|
||||||
|
|
||||||
|
func (p gpp) As8() Register { return newgpp(p.as(S8).(Physical)) }
|
||||||
|
func (p gpp) As8L() Register { return newgpp(p.as(S8L).(Physical)) }
|
||||||
|
func (p gpp) As8H() Register { return newgpp(p.as(S8H).(Physical)) }
|
||||||
|
func (p gpp) As16() Register { return newgpp(p.as(S16).(Physical)) }
|
||||||
|
func (p gpp) As32() Register { return newgpp(p.as(S32).(Physical)) }
|
||||||
|
func (p gpp) As64() Register { return newgpp(p.as(S64).(Physical)) }
|
||||||
|
|
||||||
|
// GPVirtual is a general-purpose virtual register.
|
||||||
|
type GPVirtual interface {
|
||||||
|
Virtual
|
||||||
|
GP
|
||||||
|
}
|
||||||
|
|
||||||
|
type gpv struct {
|
||||||
|
Virtual
|
||||||
|
}
|
||||||
|
|
||||||
|
func newgpv(v Virtual) GPVirtual { return gpv{Virtual: v} }
|
||||||
|
|
||||||
|
func (v gpv) As8() Register { return newgpv(v.as(S8).(Virtual)) }
|
||||||
|
func (v gpv) As8L() Register { return newgpv(v.as(S8L).(Virtual)) }
|
||||||
|
func (v gpv) As8H() Register { return newgpv(v.as(S8H).(Virtual)) }
|
||||||
|
func (v gpv) As16() Register { return newgpv(v.as(S16).(Virtual)) }
|
||||||
|
func (v gpv) As32() Register { return newgpv(v.as(S32).(Virtual)) }
|
||||||
|
func (v gpv) As64() Register { return newgpv(v.as(S64).(Virtual)) }
|
||||||
|
|
||||||
|
func gp(s Spec, id Index, name string, flags ...Info) GPPhysical {
|
||||||
|
r := newgpp(newregister(GeneralPurpose, s, id, name, flags...))
|
||||||
|
GeneralPurpose.add(r)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// General purpose registers.
|
||||||
|
var (
|
||||||
|
// Low byte.
|
||||||
|
AL = gp(S8L, 0, "AL")
|
||||||
|
CL = gp(S8L, 1, "CL")
|
||||||
|
DL = gp(S8L, 2, "DL")
|
||||||
|
BL = gp(S8L, 3, "BL")
|
||||||
|
|
||||||
|
// High byte.
|
||||||
|
AH = gp(S8H, 0, "AH")
|
||||||
|
CH = gp(S8H, 1, "CH")
|
||||||
|
DH = gp(S8H, 2, "DH")
|
||||||
|
BH = gp(S8H, 3, "BH")
|
||||||
|
|
||||||
|
// 8-bit.
|
||||||
|
SPB = gp(S8, 4, "SP", Restricted)
|
||||||
|
BPB = gp(S8, 5, "BP", BasePointer)
|
||||||
|
SIB = gp(S8, 6, "SI")
|
||||||
|
DIB = gp(S8, 7, "DI")
|
||||||
|
R8B = gp(S8, 8, "R8")
|
||||||
|
R9B = gp(S8, 9, "R9")
|
||||||
|
R10B = gp(S8, 10, "R10")
|
||||||
|
R11B = gp(S8, 11, "R11")
|
||||||
|
R12B = gp(S8, 12, "R12")
|
||||||
|
R13B = gp(S8, 13, "R13")
|
||||||
|
R14B = gp(S8, 14, "R14")
|
||||||
|
R15B = gp(S8, 15, "R15")
|
||||||
|
|
||||||
|
// 16-bit.
|
||||||
|
AX = gp(S16, 0, "AX")
|
||||||
|
CX = gp(S16, 1, "CX")
|
||||||
|
DX = gp(S16, 2, "DX")
|
||||||
|
BX = gp(S16, 3, "BX")
|
||||||
|
SP = gp(S16, 4, "SP", Restricted)
|
||||||
|
BP = gp(S16, 5, "BP", BasePointer)
|
||||||
|
SI = gp(S16, 6, "SI")
|
||||||
|
DI = gp(S16, 7, "DI")
|
||||||
|
R8W = gp(S16, 8, "R8")
|
||||||
|
R9W = gp(S16, 9, "R9")
|
||||||
|
R10W = gp(S16, 10, "R10")
|
||||||
|
R11W = gp(S16, 11, "R11")
|
||||||
|
R12W = gp(S16, 12, "R12")
|
||||||
|
R13W = gp(S16, 13, "R13")
|
||||||
|
R14W = gp(S16, 14, "R14")
|
||||||
|
R15W = gp(S16, 15, "R15")
|
||||||
|
|
||||||
|
// 32-bit.
|
||||||
|
EAX = gp(S32, 0, "AX")
|
||||||
|
ECX = gp(S32, 1, "CX")
|
||||||
|
EDX = gp(S32, 2, "DX")
|
||||||
|
EBX = gp(S32, 3, "BX")
|
||||||
|
ESP = gp(S32, 4, "SP", Restricted)
|
||||||
|
EBP = gp(S32, 5, "BP", BasePointer)
|
||||||
|
ESI = gp(S32, 6, "SI")
|
||||||
|
EDI = gp(S32, 7, "DI")
|
||||||
|
R8L = gp(S32, 8, "R8")
|
||||||
|
R9L = gp(S32, 9, "R9")
|
||||||
|
R10L = gp(S32, 10, "R10")
|
||||||
|
R11L = gp(S32, 11, "R11")
|
||||||
|
R12L = gp(S32, 12, "R12")
|
||||||
|
R13L = gp(S32, 13, "R13")
|
||||||
|
R14L = gp(S32, 14, "R14")
|
||||||
|
R15L = gp(S32, 15, "R15")
|
||||||
|
|
||||||
|
// 64-bit.
|
||||||
|
RAX = gp(S64, 0, "AX")
|
||||||
|
RCX = gp(S64, 1, "CX")
|
||||||
|
RDX = gp(S64, 2, "DX")
|
||||||
|
RBX = gp(S64, 3, "BX")
|
||||||
|
RSP = gp(S64, 4, "SP", Restricted)
|
||||||
|
RBP = gp(S64, 5, "BP", BasePointer)
|
||||||
|
RSI = gp(S64, 6, "SI")
|
||||||
|
RDI = gp(S64, 7, "DI")
|
||||||
|
R8 = gp(S64, 8, "R8")
|
||||||
|
R9 = gp(S64, 9, "R9")
|
||||||
|
R10 = gp(S64, 10, "R10")
|
||||||
|
R11 = gp(S64, 11, "R11")
|
||||||
|
R12 = gp(S64, 12, "R12")
|
||||||
|
R13 = gp(S64, 13, "R13")
|
||||||
|
R14 = gp(S64, 14, "R14")
|
||||||
|
R15 = gp(S64, 15, "R15")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Vec provides methods for vector registers.
|
||||||
|
type Vec interface {
|
||||||
|
AsX() Register
|
||||||
|
AsY() Register
|
||||||
|
AsZ() Register
|
||||||
|
}
|
||||||
|
|
||||||
|
// VecPhysical is a physical vector register.
|
||||||
|
type VecPhysical interface {
|
||||||
|
Physical
|
||||||
|
Vec
|
||||||
|
}
|
||||||
|
|
||||||
|
type vecp struct {
|
||||||
|
Physical
|
||||||
|
Vec
|
||||||
|
}
|
||||||
|
|
||||||
|
func newvecp(r Physical) VecPhysical { return vecp{Physical: r} }
|
||||||
|
|
||||||
|
func (p vecp) AsX() Register { return newvecp(p.as(S128).(Physical)) }
|
||||||
|
func (p vecp) AsY() Register { return newvecp(p.as(S256).(Physical)) }
|
||||||
|
func (p vecp) AsZ() Register { return newvecp(p.as(S512).(Physical)) }
|
||||||
|
|
||||||
|
// VecVirtual is a virtual vector register.
|
||||||
|
type VecVirtual interface {
|
||||||
|
Virtual
|
||||||
|
Vec
|
||||||
|
}
|
||||||
|
|
||||||
|
type vecv struct {
|
||||||
|
Virtual
|
||||||
|
Vec
|
||||||
|
}
|
||||||
|
|
||||||
|
func newvecv(v Virtual) VecVirtual { return vecv{Virtual: v} }
|
||||||
|
|
||||||
|
func (v vecv) AsX() Register { return newvecv(v.as(S128).(Virtual)) }
|
||||||
|
func (v vecv) AsY() Register { return newvecv(v.as(S256).(Virtual)) }
|
||||||
|
func (v vecv) AsZ() Register { return newvecv(v.as(S512).(Virtual)) }
|
||||||
|
|
||||||
|
func vec(s Spec, id Index, name string, flags ...Info) VecPhysical {
|
||||||
|
r := newvecp(newregister(Vector, s, id, name, flags...))
|
||||||
|
Vector.add(r)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vector registers.
|
||||||
|
var (
|
||||||
|
// 128-bit.
|
||||||
|
X0 = vec(S128, 0, "X0")
|
||||||
|
X1 = vec(S128, 1, "X1")
|
||||||
|
X2 = vec(S128, 2, "X2")
|
||||||
|
X3 = vec(S128, 3, "X3")
|
||||||
|
X4 = vec(S128, 4, "X4")
|
||||||
|
X5 = vec(S128, 5, "X5")
|
||||||
|
X6 = vec(S128, 6, "X6")
|
||||||
|
X7 = vec(S128, 7, "X7")
|
||||||
|
X8 = vec(S128, 8, "X8")
|
||||||
|
X9 = vec(S128, 9, "X9")
|
||||||
|
X10 = vec(S128, 10, "X10")
|
||||||
|
X11 = vec(S128, 11, "X11")
|
||||||
|
X12 = vec(S128, 12, "X12")
|
||||||
|
X13 = vec(S128, 13, "X13")
|
||||||
|
X14 = vec(S128, 14, "X14")
|
||||||
|
X15 = vec(S128, 15, "X15")
|
||||||
|
X16 = vec(S128, 16, "X16")
|
||||||
|
X17 = vec(S128, 17, "X17")
|
||||||
|
X18 = vec(S128, 18, "X18")
|
||||||
|
X19 = vec(S128, 19, "X19")
|
||||||
|
X20 = vec(S128, 20, "X20")
|
||||||
|
X21 = vec(S128, 21, "X21")
|
||||||
|
X22 = vec(S128, 22, "X22")
|
||||||
|
X23 = vec(S128, 23, "X23")
|
||||||
|
X24 = vec(S128, 24, "X24")
|
||||||
|
X25 = vec(S128, 25, "X25")
|
||||||
|
X26 = vec(S128, 26, "X26")
|
||||||
|
X27 = vec(S128, 27, "X27")
|
||||||
|
X28 = vec(S128, 28, "X28")
|
||||||
|
X29 = vec(S128, 29, "X29")
|
||||||
|
X30 = vec(S128, 30, "X30")
|
||||||
|
X31 = vec(S128, 31, "X31")
|
||||||
|
|
||||||
|
// 256-bit.
|
||||||
|
Y0 = vec(S256, 0, "Y0")
|
||||||
|
Y1 = vec(S256, 1, "Y1")
|
||||||
|
Y2 = vec(S256, 2, "Y2")
|
||||||
|
Y3 = vec(S256, 3, "Y3")
|
||||||
|
Y4 = vec(S256, 4, "Y4")
|
||||||
|
Y5 = vec(S256, 5, "Y5")
|
||||||
|
Y6 = vec(S256, 6, "Y6")
|
||||||
|
Y7 = vec(S256, 7, "Y7")
|
||||||
|
Y8 = vec(S256, 8, "Y8")
|
||||||
|
Y9 = vec(S256, 9, "Y9")
|
||||||
|
Y10 = vec(S256, 10, "Y10")
|
||||||
|
Y11 = vec(S256, 11, "Y11")
|
||||||
|
Y12 = vec(S256, 12, "Y12")
|
||||||
|
Y13 = vec(S256, 13, "Y13")
|
||||||
|
Y14 = vec(S256, 14, "Y14")
|
||||||
|
Y15 = vec(S256, 15, "Y15")
|
||||||
|
Y16 = vec(S256, 16, "Y16")
|
||||||
|
Y17 = vec(S256, 17, "Y17")
|
||||||
|
Y18 = vec(S256, 18, "Y18")
|
||||||
|
Y19 = vec(S256, 19, "Y19")
|
||||||
|
Y20 = vec(S256, 20, "Y20")
|
||||||
|
Y21 = vec(S256, 21, "Y21")
|
||||||
|
Y22 = vec(S256, 22, "Y22")
|
||||||
|
Y23 = vec(S256, 23, "Y23")
|
||||||
|
Y24 = vec(S256, 24, "Y24")
|
||||||
|
Y25 = vec(S256, 25, "Y25")
|
||||||
|
Y26 = vec(S256, 26, "Y26")
|
||||||
|
Y27 = vec(S256, 27, "Y27")
|
||||||
|
Y28 = vec(S256, 28, "Y28")
|
||||||
|
Y29 = vec(S256, 29, "Y29")
|
||||||
|
Y30 = vec(S256, 30, "Y30")
|
||||||
|
Y31 = vec(S256, 31, "Y31")
|
||||||
|
|
||||||
|
// 512-bit.
|
||||||
|
Z0 = vec(S512, 0, "Z0")
|
||||||
|
Z1 = vec(S512, 1, "Z1")
|
||||||
|
Z2 = vec(S512, 2, "Z2")
|
||||||
|
Z3 = vec(S512, 3, "Z3")
|
||||||
|
Z4 = vec(S512, 4, "Z4")
|
||||||
|
Z5 = vec(S512, 5, "Z5")
|
||||||
|
Z6 = vec(S512, 6, "Z6")
|
||||||
|
Z7 = vec(S512, 7, "Z7")
|
||||||
|
Z8 = vec(S512, 8, "Z8")
|
||||||
|
Z9 = vec(S512, 9, "Z9")
|
||||||
|
Z10 = vec(S512, 10, "Z10")
|
||||||
|
Z11 = vec(S512, 11, "Z11")
|
||||||
|
Z12 = vec(S512, 12, "Z12")
|
||||||
|
Z13 = vec(S512, 13, "Z13")
|
||||||
|
Z14 = vec(S512, 14, "Z14")
|
||||||
|
Z15 = vec(S512, 15, "Z15")
|
||||||
|
Z16 = vec(S512, 16, "Z16")
|
||||||
|
Z17 = vec(S512, 17, "Z17")
|
||||||
|
Z18 = vec(S512, 18, "Z18")
|
||||||
|
Z19 = vec(S512, 19, "Z19")
|
||||||
|
Z20 = vec(S512, 20, "Z20")
|
||||||
|
Z21 = vec(S512, 21, "Z21")
|
||||||
|
Z22 = vec(S512, 22, "Z22")
|
||||||
|
Z23 = vec(S512, 23, "Z23")
|
||||||
|
Z24 = vec(S512, 24, "Z24")
|
||||||
|
Z25 = vec(S512, 25, "Z25")
|
||||||
|
Z26 = vec(S512, 26, "Z26")
|
||||||
|
Z27 = vec(S512, 27, "Z27")
|
||||||
|
Z28 = vec(S512, 28, "Z28")
|
||||||
|
Z29 = vec(S512, 29, "Z29")
|
||||||
|
Z30 = vec(S512, 30, "Z30")
|
||||||
|
Z31 = vec(S512, 31, "Z31")
|
||||||
|
)
|
||||||
|
|
||||||
|
// OpmaskPhysical is a opmask physical register.
|
||||||
|
type OpmaskPhysical interface {
|
||||||
|
Physical
|
||||||
|
}
|
||||||
|
|
||||||
|
type opmaskp struct {
|
||||||
|
Physical
|
||||||
|
}
|
||||||
|
|
||||||
|
func newopmaskp(r Physical) OpmaskPhysical { return opmaskp{Physical: r} }
|
||||||
|
|
||||||
|
// OpmaskVirtual is a virtual opmask register.
|
||||||
|
type OpmaskVirtual interface {
|
||||||
|
Virtual
|
||||||
|
}
|
||||||
|
|
||||||
|
type opmaskv struct {
|
||||||
|
Virtual
|
||||||
|
}
|
||||||
|
|
||||||
|
func newopmaskv(v Virtual) OpmaskVirtual { return opmaskv{Virtual: v} }
|
||||||
|
|
||||||
|
func opmask(s Spec, id Index, name string, flags ...Info) OpmaskPhysical {
|
||||||
|
r := newopmaskp(newregister(Opmask, s, id, name, flags...))
|
||||||
|
Opmask.add(r)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opmask registers.
|
||||||
|
//
|
||||||
|
// Note that while K0 is a physical opmask register (it is a valid opmask source
|
||||||
|
// and destination operand), it cannot be used as an opmask predicate value
|
||||||
|
// because in that context K0 means "all true" or "no mask" regardless of the
|
||||||
|
// actual contents of the physical register. For that reason, K0 should never be
|
||||||
|
// assigned as a "general purpose" opmask register. However, it can be
|
||||||
|
// explicitly operated upon by name as non-predicate operand, for example to
|
||||||
|
// hold a constant or temporary value during calculations on other opmask
|
||||||
|
// registers.
|
||||||
|
var (
|
||||||
|
K0 = opmask(S64, 0, "K0", Restricted)
|
||||||
|
K1 = opmask(S64, 1, "K1")
|
||||||
|
K2 = opmask(S64, 2, "K2")
|
||||||
|
K3 = opmask(S64, 3, "K3")
|
||||||
|
K4 = opmask(S64, 4, "K4")
|
||||||
|
K5 = opmask(S64, 5, "K5")
|
||||||
|
K6 = opmask(S64, 6, "K6")
|
||||||
|
K7 = opmask(S64, 7, "K7")
|
||||||
|
)
|
62
vendor/github.com/mmcloughlin/avo/src/src.go
generated
vendored
Normal file
62
vendor/github.com/mmcloughlin/avo/src/src.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Package src provides types for working with source files.
|
||||||
|
package src
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Position represents a position in a source file.
|
||||||
|
type Position struct {
|
||||||
|
Filename string
|
||||||
|
Line int // 1-up
|
||||||
|
}
|
||||||
|
|
||||||
|
// FramePosition returns the Position of the given stack frame.
|
||||||
|
func FramePosition(f runtime.Frame) Position {
|
||||||
|
return Position{
|
||||||
|
Filename: f.File,
|
||||||
|
Line: f.Line,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid reports whether the position is valid: Line must be positive, but
|
||||||
|
// Filename may be empty.
|
||||||
|
func (p Position) IsValid() bool {
|
||||||
|
return p.Line > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// String represents Position as a string.
|
||||||
|
func (p Position) String() string {
|
||||||
|
if !p.IsValid() {
|
||||||
|
return "-"
|
||||||
|
}
|
||||||
|
var s string
|
||||||
|
if p.Filename != "" {
|
||||||
|
s += p.Filename + ":"
|
||||||
|
}
|
||||||
|
s += strconv.Itoa(p.Line)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rel returns Position relative to basepath. If the given filename cannot be
|
||||||
|
// expressed relative to basepath the position will be returned unchanged.
|
||||||
|
func (p Position) Rel(basepath string) Position {
|
||||||
|
q := p
|
||||||
|
if rel, err := filepath.Rel(basepath, q.Filename); err == nil {
|
||||||
|
q.Filename = rel
|
||||||
|
}
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relwd returns Position relative to the current working directory. Returns p
|
||||||
|
// unchanged if the working directory cannot be determined, or the filename
|
||||||
|
// cannot be expressed relative to the working directory.
|
||||||
|
func (p Position) Relwd() Position {
|
||||||
|
if wd, err := os.Getwd(); err == nil {
|
||||||
|
return p.Rel(wd)
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
2
vendor/github.com/mmcloughlin/avo/x86/doc.go
generated
vendored
Normal file
2
vendor/github.com/mmcloughlin/avo/x86/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package x86 provides constructors for all x86-64 instructions.
|
||||||
|
package x86
|
5
vendor/github.com/mmcloughlin/avo/x86/gen.go
generated
vendored
Normal file
5
vendor/github.com/mmcloughlin/avo/x86/gen.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package x86
|
||||||
|
|
||||||
|
//go:generate avogen -output zoptab.go optab
|
||||||
|
//go:generate avogen -output zctors.go ctors
|
||||||
|
//go:generate avogen -output zctors_test.go ctorstest
|
130
vendor/github.com/mmcloughlin/avo/x86/optab.go
generated
vendored
Normal file
130
vendor/github.com/mmcloughlin/avo/x86/optab.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package x86
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/mmcloughlin/avo/ir"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// build constructs an instruction object from a list of acceptable forms, and
|
||||||
|
// given input operands and suffixes.
|
||||||
|
func build(forms []form, suffixes sffxs, ops []operand.Op) (*ir.Instruction, error) {
|
||||||
|
for i := range forms {
|
||||||
|
f := &forms[i]
|
||||||
|
if f.match(suffixes, ops) {
|
||||||
|
return f.build(suffixes, ops), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errors.New("bad operands")
|
||||||
|
}
|
||||||
|
|
||||||
|
// form represents an instruction form.
|
||||||
|
type form struct {
|
||||||
|
Opcode opc
|
||||||
|
SuffixesClass sffxscls
|
||||||
|
Features feature
|
||||||
|
ISAs isas
|
||||||
|
Arity uint8
|
||||||
|
Operands oprnds
|
||||||
|
}
|
||||||
|
|
||||||
|
// feature is a flags enumeration type representing instruction properties.
|
||||||
|
type feature uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
featureTerminal feature = 1 << iota
|
||||||
|
featureBranch
|
||||||
|
featureConditionalBranch
|
||||||
|
featureCancellingInputs
|
||||||
|
)
|
||||||
|
|
||||||
|
// oprnds is a list of explicit and implicit operands of an instruction form.
|
||||||
|
// The size of the array is output by optab generator.
|
||||||
|
type oprnds [maxoperands]oprnd
|
||||||
|
|
||||||
|
// oprnd represents an explicit or implicit operand to an instruction form.
|
||||||
|
type oprnd struct {
|
||||||
|
Type uint8
|
||||||
|
Implicit bool
|
||||||
|
Action action
|
||||||
|
}
|
||||||
|
|
||||||
|
// action an instruction form applies to an operand.
|
||||||
|
type action uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
actionN action = iota
|
||||||
|
actionR
|
||||||
|
actionW
|
||||||
|
actionRW action = actionR | actionW
|
||||||
|
)
|
||||||
|
|
||||||
|
// Read reports if the action includes read.
|
||||||
|
func (a action) Read() bool { return (a & actionR) != 0 }
|
||||||
|
|
||||||
|
// Read reports if the action includes write.
|
||||||
|
func (a action) Write() bool { return (a & actionW) != 0 }
|
||||||
|
|
||||||
|
// match reports whether this form matches the given suffixes and operand
|
||||||
|
// list.
|
||||||
|
func (f *form) match(suffixes sffxs, ops []operand.Op) bool {
|
||||||
|
// Match suffix.
|
||||||
|
accept := f.SuffixesClass.SuffixesSet()
|
||||||
|
if !accept[suffixes] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match operands.
|
||||||
|
if len(ops) != int(f.Arity) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, op := range ops {
|
||||||
|
t := oprndtype(f.Operands[i].Type)
|
||||||
|
if !t.Match(op) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the full instruction object for this form and the given suffixes and
|
||||||
|
// operands. Assumes the form already matches the inputs.
|
||||||
|
func (f *form) build(suffixes sffxs, ops []operand.Op) *ir.Instruction {
|
||||||
|
// Base instruction properties.
|
||||||
|
i := &ir.Instruction{
|
||||||
|
Opcode: f.Opcode.String(),
|
||||||
|
Suffixes: suffixes.Strings(),
|
||||||
|
Operands: ops,
|
||||||
|
IsTerminal: (f.Features & featureTerminal) != 0,
|
||||||
|
IsBranch: (f.Features & featureBranch) != 0,
|
||||||
|
IsConditional: (f.Features & featureConditionalBranch) != 0,
|
||||||
|
CancellingInputs: (f.Features & featureCancellingInputs) != 0,
|
||||||
|
ISA: f.ISAs.List(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input/output operands.
|
||||||
|
for _, spec := range f.Operands {
|
||||||
|
if spec.Type == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
var op operand.Op
|
||||||
|
if spec.Implicit {
|
||||||
|
op = implreg(spec.Type).Register()
|
||||||
|
} else {
|
||||||
|
op, ops = ops[0], ops[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.Action.Read() {
|
||||||
|
i.Inputs = append(i.Inputs, op)
|
||||||
|
}
|
||||||
|
if spec.Action.Write() {
|
||||||
|
i.Outputs = append(i.Outputs, op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
38615
vendor/github.com/mmcloughlin/avo/x86/zctors.go
generated
vendored
Normal file
38615
vendor/github.com/mmcloughlin/avo/x86/zctors.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16385
vendor/github.com/mmcloughlin/avo/x86/zoptab.go
generated
vendored
Normal file
16385
vendor/github.com/mmcloughlin/avo/x86/zoptab.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user