internal/load: use alias slice for determinism

Previously aliases were stored in a map which was causing
non-deterministic code generation (see recent build failures). This diff
changes to a slice to avoid this problem.

Updates #50
This commit is contained in:
Michael McLoughlin
2019-01-20 23:06:42 -08:00
parent 2d7a9ddb6c
commit 02ecaad4e4
4 changed files with 61 additions and 53 deletions

View File

@@ -12,7 +12,7 @@ arch=${GOROOT}/src/cmd/asm/internal/arch/arch.go
echo echo
echo 'package load' echo 'package load'
echo echo
echo 'var annoyingaliases = map[string]string{' echo 'var annoyingaliases = []alias{'
awk ' awk '
/archX86/ { x86=1 } /archX86/ { x86=1 }
@@ -27,7 +27,7 @@ arch=${GOROOT}/src/cmd/asm/internal/arch/arch.go
sub(/x86\.A/, "", to) sub(/x86\.A/, "", to)
if(from != to) { if(from != to) {
printf("\t\"%s\": \"%s\",\n", from, to) printf("\t{\"%s\", \"%s\"},\n", from, to)
} }
} }
' ${arch} ' ${arch}

View File

@@ -74,15 +74,19 @@ func (l *Loader) Load() ([]inst.Instruction, error) {
im[e.Opcode] = e im[e.Opcode] = e
} }
// Apply list of aliases. // Merge aliased forms. This is primarily for MOVQ (issue #50).
for from, to := range aliases { for _, a := range aliases {
if existing, found := im[from]; found { if existing, found := im[a.From]; found {
im[to].Forms = append(im[to].Forms, existing.Forms...) im[a.To].Forms = append(im[a.To].Forms, existing.Forms...)
} }
cpy := *im[to] }
cpy.Opcode = from
cpy.AliasOf = to // Apply list of aliases.
im[from] = &cpy for _, a := range aliases {
cpy := *im[a.To]
cpy.Opcode = a.From
cpy.AliasOf = a.To
im[a.From] = &cpy
} }
// Dedupe forms. // Dedupe forms.

View File

@@ -4,9 +4,15 @@ import (
"github.com/mmcloughlin/avo/internal/inst" "github.com/mmcloughlin/avo/internal/inst"
) )
// alias defines an opcode alias.
type alias struct {
From string
To string
}
// aliases defines a list of opcode aliases. Where possible these are extracted // aliases defines a list of opcode aliases. Where possible these are extracted
// from the code (see note below). // from the code (see note below).
var aliases = map[string]string{ var aliases = []alias{
// The PSHUFD/PSHUFL alias is not recorded in the list of "Annoying aliases" below. However the instructions are identical. // The PSHUFD/PSHUFL alias is not recorded in the list of "Annoying aliases" below. However the instructions are identical.
// //
// Reference: https://github.com/golang/go/blob/048c9164a0c5572df18325e377473e7893dbfb07/src/cmd/internal/obj/x86/asm6.go#L1365 // Reference: https://github.com/golang/go/blob/048c9164a0c5572df18325e377473e7893dbfb07/src/cmd/internal/obj/x86/asm6.go#L1365
@@ -17,7 +23,7 @@ var aliases = map[string]string{
// //
// {APSHUFD, yxshuf, Pq, opBytes{0x70, 0}}, // {APSHUFD, yxshuf, Pq, opBytes{0x70, 0}},
// //
"PSHUFD": "PSHUFL", {"PSHUFD", "PSHUFL"},
} }
// Go contains a list of self-proclaimed "Annoying aliases", as follows. We use // Go contains a list of self-proclaimed "Annoying aliases", as follows. We use
@@ -88,9 +94,7 @@ var aliases = map[string]string{
//go:generate ./annoyingaliases.sh zannoyingaliases.go //go:generate ./annoyingaliases.sh zannoyingaliases.go
func init() { func init() {
for from, to := range annoyingaliases { aliases = append(aliases, annoyingaliases...)
aliases[from] = to
}
} }
// extras is simply a list of extra instructions to add to the database. // extras is simply a list of extra instructions to add to the database.

View File

@@ -2,42 +2,42 @@
package load package load
var annoyingaliases = map[string]string{ var annoyingaliases = []alias{
"JA": "JHI", {"JA", "JHI"},
"JAE": "JCC", {"JAE", "JCC"},
"JB": "JCS", {"JB", "JCS"},
"JBE": "JLS", {"JBE", "JLS"},
"JC": "JCS", {"JC", "JCS"},
"JE": "JEQ", {"JE", "JEQ"},
"JG": "JGT", {"JG", "JGT"},
"JHS": "JCC", {"JHS", "JCC"},
"JL": "JLT", {"JL", "JLT"},
"JLO": "JCS", {"JLO", "JCS"},
"JNA": "JLS", {"JNA", "JLS"},
"JNAE": "JCS", {"JNAE", "JCS"},
"JNB": "JCC", {"JNB", "JCC"},
"JNBE": "JHI", {"JNBE", "JHI"},
"JNC": "JCC", {"JNC", "JCC"},
"JNG": "JLE", {"JNG", "JLE"},
"JNGE": "JLT", {"JNGE", "JLT"},
"JNL": "JGE", {"JNL", "JGE"},
"JNLE": "JGT", {"JNLE", "JGT"},
"JNO": "JOC", {"JNO", "JOC"},
"JNP": "JPC", {"JNP", "JPC"},
"JNS": "JPL", {"JNS", "JPL"},
"JNZ": "JNE", {"JNZ", "JNE"},
"JO": "JOS", {"JO", "JOS"},
"JP": "JPS", {"JP", "JPS"},
"JPE": "JPS", {"JPE", "JPS"},
"JPO": "JPC", {"JPO", "JPC"},
"JS": "JMI", {"JS", "JMI"},
"JZ": "JEQ", {"JZ", "JEQ"},
"MASKMOVDQU": "MASKMOVOU", {"MASKMOVDQU", "MASKMOVOU"},
"MOVD": "MOVQ", {"MOVD", "MOVQ"},
"MOVDQ2Q": "MOVQ", {"MOVDQ2Q", "MOVQ"},
"MOVNTDQ": "MOVNTO", {"MOVNTDQ", "MOVNTO"},
"MOVOA": "MOVO", {"MOVOA", "MOVO"},
"PSLLDQ": "PSLLO", {"PSLLDQ", "PSLLO"},
"PSRLDQ": "PSRLO", {"PSRLDQ", "PSRLO"},
"PADDD": "PADDL", {"PADDD", "PADDL"},
} }