mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: I81b64fe503bf07b4d7bd823286b83e663b5c0f76
This commit is contained in:
commit
0007017f96
487 changed files with 30207 additions and 4496 deletions
|
|
@ -740,6 +740,7 @@ The ARM64 port is in an experimental state.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<code>R18</code> is the "platform register", reserved on the Apple platform.
|
<code>R18</code> is the "platform register", reserved on the Apple platform.
|
||||||
|
To prevent accidental misuse, the register is named <code>R18_PLATFORM</code>.
|
||||||
<code>R27</code> and <code>R28</code> are reserved by the compiler and linker.
|
<code>R27</code> and <code>R28</code> are reserved by the compiler and linker.
|
||||||
<code>R29</code> is the frame pointer.
|
<code>R29</code> is the frame pointer.
|
||||||
<code>R30</code> is the link register.
|
<code>R30</code> is the link register.
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ func Test25143(t *testing.T) { test25143(t) }
|
||||||
func Test23356(t *testing.T) { test23356(t) }
|
func Test23356(t *testing.T) { test23356(t) }
|
||||||
func Test26066(t *testing.T) { test26066(t) }
|
func Test26066(t *testing.T) { test26066(t) }
|
||||||
func Test26213(t *testing.T) { test26213(t) }
|
func Test26213(t *testing.T) { test26213(t) }
|
||||||
|
func Test27660(t *testing.T) { test27660(t) }
|
||||||
|
|
||||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||||
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
|
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
|
||||||
|
|
|
||||||
54
misc/cgo/test/test27660.go
Normal file
54
misc/cgo/test/test27660.go
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Stress the interaction between the race detector and cgo in an
|
||||||
|
// attempt to reproduce the memory corruption described in #27660.
|
||||||
|
// The bug was very timing sensitive; at the time of writing this
|
||||||
|
// test would only trigger the bug about once out of every five runs.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
// #include <unistd.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func test27660(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
ints := make([]int, 100)
|
||||||
|
locks := make([]sync.Mutex, 100)
|
||||||
|
// Slowly create threads so that ThreadSanitizer is forced to
|
||||||
|
// frequently resize its SyncClocks.
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
go func() {
|
||||||
|
for ctx.Err() == nil {
|
||||||
|
// Sleep in C for long enough that it is likely that the runtime
|
||||||
|
// will retake this goroutine's currently wired P.
|
||||||
|
C.usleep(1000 /* 1ms */)
|
||||||
|
runtime.Gosched() // avoid starvation (see #28701)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
// Trigger lots of synchronization and memory reads/writes to
|
||||||
|
// increase the likelihood that the race described in #27660
|
||||||
|
// results in corruption of ThreadSanitizer's internal state
|
||||||
|
// and thus an assertion failure or segfault.
|
||||||
|
for ctx.Err() == nil {
|
||||||
|
j := rand.Intn(100)
|
||||||
|
locks[j].Lock()
|
||||||
|
ints[j]++
|
||||||
|
locks[j].Unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,6 +50,9 @@ go src=..
|
||||||
google
|
google
|
||||||
pprof
|
pprof
|
||||||
internal
|
internal
|
||||||
|
binutils
|
||||||
|
testdata
|
||||||
|
+
|
||||||
driver
|
driver
|
||||||
testdata
|
testdata
|
||||||
+
|
+
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,10 @@
|
||||||
console.warn("exit code:", code);
|
console.warn("exit code:", code);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this._exitPromise = new Promise((resolve) => {
|
||||||
|
this._resolveExitPromise = resolve;
|
||||||
|
});
|
||||||
|
this._pendingCallback = null;
|
||||||
this._callbackTimeouts = new Map();
|
this._callbackTimeouts = new Map();
|
||||||
this._nextCallbackTimeoutID = 1;
|
this._nextCallbackTimeoutID = 1;
|
||||||
|
|
||||||
|
|
@ -194,6 +198,11 @@
|
||||||
const timeOrigin = Date.now() - performance.now();
|
const timeOrigin = Date.now() - performance.now();
|
||||||
this.importObject = {
|
this.importObject = {
|
||||||
go: {
|
go: {
|
||||||
|
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
|
||||||
|
// may trigger a synchronous callback to Go. This makes Go code get executed in the middle of the imported
|
||||||
|
// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
|
||||||
|
// This changes the SP, thus we have to update the SP used by the imported function.
|
||||||
|
|
||||||
// func wasmExit(code int32)
|
// func wasmExit(code int32)
|
||||||
"runtime.wasmExit": (sp) => {
|
"runtime.wasmExit": (sp) => {
|
||||||
const code = mem().getInt32(sp + 8, true);
|
const code = mem().getInt32(sp + 8, true);
|
||||||
|
|
@ -229,7 +238,7 @@
|
||||||
const id = this._nextCallbackTimeoutID;
|
const id = this._nextCallbackTimeoutID;
|
||||||
this._nextCallbackTimeoutID++;
|
this._nextCallbackTimeoutID++;
|
||||||
this._callbackTimeouts.set(id, setTimeout(
|
this._callbackTimeouts.set(id, setTimeout(
|
||||||
() => { this._resolveCallbackPromise(); },
|
() => { this._resume(); },
|
||||||
getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
|
getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
|
||||||
));
|
));
|
||||||
mem().setInt32(sp + 16, id, true);
|
mem().setInt32(sp + 16, id, true);
|
||||||
|
|
@ -254,7 +263,9 @@
|
||||||
|
|
||||||
// func valueGet(v ref, p string) ref
|
// func valueGet(v ref, p string) ref
|
||||||
"syscall/js.valueGet": (sp) => {
|
"syscall/js.valueGet": (sp) => {
|
||||||
storeValue(sp + 32, Reflect.get(loadValue(sp + 8), loadString(sp + 16)));
|
const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
|
||||||
|
sp = this._inst.exports.getsp(); // see comment above
|
||||||
|
storeValue(sp + 32, result);
|
||||||
},
|
},
|
||||||
|
|
||||||
// func valueSet(v ref, p string, x ref)
|
// func valueSet(v ref, p string, x ref)
|
||||||
|
|
@ -278,7 +289,9 @@
|
||||||
const v = loadValue(sp + 8);
|
const v = loadValue(sp + 8);
|
||||||
const m = Reflect.get(v, loadString(sp + 16));
|
const m = Reflect.get(v, loadString(sp + 16));
|
||||||
const args = loadSliceOfValues(sp + 32);
|
const args = loadSliceOfValues(sp + 32);
|
||||||
storeValue(sp + 56, Reflect.apply(m, v, args));
|
const result = Reflect.apply(m, v, args);
|
||||||
|
sp = this._inst.exports.getsp(); // see comment above
|
||||||
|
storeValue(sp + 56, result);
|
||||||
mem().setUint8(sp + 64, 1);
|
mem().setUint8(sp + 64, 1);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
storeValue(sp + 56, err);
|
storeValue(sp + 56, err);
|
||||||
|
|
@ -291,7 +304,9 @@
|
||||||
try {
|
try {
|
||||||
const v = loadValue(sp + 8);
|
const v = loadValue(sp + 8);
|
||||||
const args = loadSliceOfValues(sp + 16);
|
const args = loadSliceOfValues(sp + 16);
|
||||||
storeValue(sp + 40, Reflect.apply(v, undefined, args));
|
const result = Reflect.apply(v, undefined, args);
|
||||||
|
sp = this._inst.exports.getsp(); // see comment above
|
||||||
|
storeValue(sp + 40, result);
|
||||||
mem().setUint8(sp + 48, 1);
|
mem().setUint8(sp + 48, 1);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
storeValue(sp + 40, err);
|
storeValue(sp + 40, err);
|
||||||
|
|
@ -304,7 +319,9 @@
|
||||||
try {
|
try {
|
||||||
const v = loadValue(sp + 8);
|
const v = loadValue(sp + 8);
|
||||||
const args = loadSliceOfValues(sp + 16);
|
const args = loadSliceOfValues(sp + 16);
|
||||||
storeValue(sp + 40, Reflect.construct(v, args));
|
const result = Reflect.construct(v, args);
|
||||||
|
sp = this._inst.exports.getsp(); // see comment above
|
||||||
|
storeValue(sp + 40, result);
|
||||||
mem().setUint8(sp + 48, 1);
|
mem().setUint8(sp + 48, 1);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
storeValue(sp + 40, err);
|
storeValue(sp + 40, err);
|
||||||
|
|
@ -355,7 +372,6 @@
|
||||||
this,
|
this,
|
||||||
];
|
];
|
||||||
this._refs = new Map();
|
this._refs = new Map();
|
||||||
this._callbackShutdown = false;
|
|
||||||
this.exited = false;
|
this.exited = false;
|
||||||
|
|
||||||
const mem = new DataView(this._inst.exports.mem.buffer)
|
const mem = new DataView(this._inst.exports.mem.buffer)
|
||||||
|
|
@ -390,42 +406,30 @@
|
||||||
offset += 8;
|
offset += 8;
|
||||||
});
|
});
|
||||||
|
|
||||||
while (true) {
|
this._inst.exports.run(argc, argv);
|
||||||
const callbackPromise = new Promise((resolve) => {
|
if (this.exited) {
|
||||||
this._resolveCallbackPromise = () => {
|
this._resolveExitPromise();
|
||||||
|
}
|
||||||
|
await this._exitPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
_resume() {
|
||||||
if (this.exited) {
|
if (this.exited) {
|
||||||
throw new Error("bad callback: Go program has already exited");
|
throw new Error("bad callback: Go program has already exited");
|
||||||
}
|
}
|
||||||
setTimeout(resolve, 0); // make sure it is asynchronous
|
this._inst.exports.resume();
|
||||||
};
|
|
||||||
});
|
|
||||||
this._inst.exports.run(argc, argv);
|
|
||||||
if (this.exited) {
|
if (this.exited) {
|
||||||
break;
|
this._resolveExitPromise();
|
||||||
}
|
|
||||||
await callbackPromise;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static _makeCallbackHelper(id, pendingCallbacks, go) {
|
_makeCallbackHelper(id) {
|
||||||
|
const go = this;
|
||||||
return function () {
|
return function () {
|
||||||
pendingCallbacks.push({ id: id, args: arguments });
|
const cb = { id: id, this: this, args: arguments };
|
||||||
go._resolveCallbackPromise();
|
go._pendingCallback = cb;
|
||||||
};
|
go._resume();
|
||||||
}
|
return cb.result;
|
||||||
|
|
||||||
static _makeEventCallbackHelper(preventDefault, stopPropagation, stopImmediatePropagation, fn) {
|
|
||||||
return function (event) {
|
|
||||||
if (preventDefault) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
if (stopPropagation) {
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
if (stopImmediatePropagation) {
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
fn(event);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -444,8 +448,8 @@
|
||||||
process.on("exit", (code) => { // Node.js exits if no callback is pending
|
process.on("exit", (code) => { // Node.js exits if no callback is pending
|
||||||
if (code === 0 && !go.exited) {
|
if (code === 0 && !go.exited) {
|
||||||
// deadlock, make Go print error and stack traces
|
// deadlock, make Go print error and stack traces
|
||||||
go._callbackShutdown = true;
|
go._pendingCallback = { id: 0 };
|
||||||
go._inst.exports.run();
|
go._resume();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return go.run(result.instance);
|
return go.run(result.instance);
|
||||||
|
|
|
||||||
|
|
@ -550,7 +550,7 @@ func TestWriter(t *testing.T) {
|
||||||
t.Errorf("%s: %d bytes written", context, len(written))
|
t.Errorf("%s: %d bytes written", context, len(written))
|
||||||
}
|
}
|
||||||
for l := 0; l < len(written); l++ {
|
for l := 0; l < len(written); l++ {
|
||||||
if written[i] != data[i] {
|
if written[l] != data[l] {
|
||||||
t.Errorf("wrong bytes written")
|
t.Errorf("wrong bytes written")
|
||||||
t.Errorf("want=%q", data[0:len(written)])
|
t.Errorf("want=%q", data[0:len(written)])
|
||||||
t.Errorf("have=%q", written)
|
t.Errorf("have=%q", written)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,13 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Equal returns a boolean reporting whether a and b
|
||||||
|
// are the same length and contain the same bytes.
|
||||||
|
// A nil argument is equivalent to an empty slice.
|
||||||
|
func Equal(a, b []byte) bool {
|
||||||
|
return bytealg.Equal(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
func equalPortable(a, b []byte) bool {
|
func equalPortable(a, b []byte) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
|
|
@ -24,6 +31,13 @@ func equalPortable(a, b []byte) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare returns an integer comparing two byte slices lexicographically.
|
||||||
|
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
|
||||||
|
// A nil argument is equivalent to an empty slice.
|
||||||
|
func Compare(a, b []byte) int {
|
||||||
|
return bytealg.Compare(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
// explode splits s into a slice of UTF-8 sequences, one per Unicode code point (still slices of bytes),
|
// explode splits s into a slice of UTF-8 sequences, one per Unicode code point (still slices of bytes),
|
||||||
// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
|
// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
|
||||||
func explode(s []byte, n int) [][]byte {
|
func explode(s []byte, n int) [][]byte {
|
||||||
|
|
@ -83,6 +97,11 @@ func ContainsRune(b []byte, r rune) bool {
|
||||||
return IndexRune(b, r) >= 0
|
return IndexRune(b, r) >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IndexByte returns the index of the first instance of c in b, or -1 if c is not present in b.
|
||||||
|
func IndexByte(b []byte, c byte) int {
|
||||||
|
return bytealg.IndexByte(b, c)
|
||||||
|
}
|
||||||
|
|
||||||
func indexBytePortable(s []byte, c byte) int {
|
func indexBytePortable(s []byte, c byte) int {
|
||||||
for i, b := range s {
|
for i, b := range s {
|
||||||
if b == c {
|
if b == c {
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package bytes
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
// IndexByte returns the index of the first instance of c in b, or -1 if c is not present in b.
|
|
||||||
func IndexByte(b []byte, c byte) int // in internal/bytealg
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
// Equal returns a boolean reporting whether a and b
|
|
||||||
// are the same length and contain the same bytes.
|
|
||||||
// A nil argument is equivalent to an empty slice.
|
|
||||||
func Equal(a, b []byte) bool // in internal/bytealg
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
// Compare returns an integer comparing two byte slices lexicographically.
|
|
||||||
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
|
|
||||||
// A nil argument is equivalent to an empty slice.
|
|
||||||
func Compare(a, b []byte) int // in internal/bytealg
|
|
||||||
|
|
@ -61,6 +61,7 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
tab, err := f.PCLineTable()
|
tab, err := f.PCLineTable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,9 @@ func archArm64() *Arch {
|
||||||
for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
|
for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
|
||||||
register[obj.Rconv(i)] = int16(i)
|
register[obj.Rconv(i)] = int16(i)
|
||||||
}
|
}
|
||||||
|
// Rename R18 to R18_PLATFORM to avoid accidental use.
|
||||||
|
register["R18_PLATFORM"] = register["R18"]
|
||||||
|
delete(register, "R18")
|
||||||
for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
|
for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
|
||||||
register[obj.Rconv(i)] = int16(i)
|
register[obj.Rconv(i)] = int16(i)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -607,6 +607,7 @@ var arm64OperandTests = []operandTest{
|
||||||
{"R0", "R0"},
|
{"R0", "R0"},
|
||||||
{"R10", "R10"},
|
{"R10", "R10"},
|
||||||
{"R11", "R11"},
|
{"R11", "R11"},
|
||||||
|
{"R18_PLATFORM", "R18"},
|
||||||
{"$4503601774854144.0", "$(4503601774854144.0)"},
|
{"$4503601774854144.0", "$(4503601774854144.0)"},
|
||||||
{"$runtime·badsystemstack(SB)", "$runtime.badsystemstack(SB)"},
|
{"$runtime·badsystemstack(SB)", "$runtime.badsystemstack(SB)"},
|
||||||
{"ZR", "ZR"},
|
{"ZR", "ZR"},
|
||||||
|
|
|
||||||
36
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
36
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
|
@ -47,8 +47,8 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
ADD R2.SXTX<<1, RSP, RSP // ffe7228b
|
ADD R2.SXTX<<1, RSP, RSP // ffe7228b
|
||||||
ADD ZR.SXTX<<1, R2, R3 // 43e43f8b
|
ADD ZR.SXTX<<1, R2, R3 // 43e43f8b
|
||||||
ADDW R2.SXTW, R10, R12 // 4cc1220b
|
ADDW R2.SXTW, R10, R12 // 4cc1220b
|
||||||
ADD R18.UXTX, R14, R17 // d161328b
|
ADD R19.UXTX, R14, R17 // d161338b
|
||||||
ADDSW R18.UXTW, R14, R17 // d141322b
|
ADDSW R19.UXTW, R14, R17 // d141332b
|
||||||
ADDS R12.SXTX, R3, R1 // 61e02cab
|
ADDS R12.SXTX, R3, R1 // 61e02cab
|
||||||
SUB R19.UXTH<<4, R2, R21 // 553033cb
|
SUB R19.UXTH<<4, R2, R21 // 553033cb
|
||||||
SUBW R1.UXTX<<1, R3, R2 // 6264214b
|
SUBW R1.UXTX<<1, R3, R2 // 6264214b
|
||||||
|
|
@ -144,7 +144,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
||||||
MOVD (R3)(R6), R5 // MOVD (R3)(R6*1), R5 // 656866f8
|
MOVD (R3)(R6), R5 // MOVD (R3)(R6*1), R5 // 656866f8
|
||||||
MOVD (R2)(R6), R4 // MOVD (R2)(R6*1), R4 // 446866f8
|
MOVD (R2)(R6), R4 // MOVD (R2)(R6*1), R4 // 446866f8
|
||||||
MOVWU (R19)(R18<<2), R18 // 727a72b8
|
MOVWU (R19)(R20<<2), R20 // 747a74b8
|
||||||
MOVD (R2)(R6<<3), R4 // 447866f8
|
MOVD (R2)(R6<<3), R4 // 447866f8
|
||||||
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
|
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
|
||||||
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
|
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
|
||||||
|
|
@ -154,7 +154,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
MOVHU (R1)(R2<<1), R5 // 25786278
|
MOVHU (R1)(R2<<1), R5 // 25786278
|
||||||
MOVB (R9)(R3.UXTW), R6 // 2649a338
|
MOVB (R9)(R3.UXTW), R6 // 2649a338
|
||||||
MOVB (R10)(R6), R15 // MOVB (R10)(R6*1), R15 // 4f69a638
|
MOVB (R10)(R6), R15 // MOVB (R10)(R6*1), R15 // 4f69a638
|
||||||
MOVH (R5)(R7.SXTX<<1), R18 // b2f8a778
|
MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778
|
||||||
MOVH (R8)(R4<<1), R10 // 0a79a478
|
MOVH (R8)(R4<<1), R10 // 0a79a478
|
||||||
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
|
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
|
||||||
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
|
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
|
||||||
|
|
@ -195,6 +195,11 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
CMPW $27745, R2 // 3b8c8d525f001b6b
|
CMPW $27745, R2 // 3b8c8d525f001b6b
|
||||||
CMNW $0x3fffffc0, R2 // CMNW $1073741760, R2 // fb5f1a325f001b2b
|
CMNW $0x3fffffc0, R2 // CMNW $1073741760, R2 // fb5f1a325f001b2b
|
||||||
CMPW $0xffff0, R1 // CMPW $1048560, R1 // fb3f1c323f001b6b
|
CMPW $0xffff0, R1 // CMPW $1048560, R1 // fb3f1c323f001b6b
|
||||||
|
CMP $0xffffffffffa0, R3 // CMP $281474976710560, R3 // fb0b80921b00e0f27f001beb
|
||||||
|
CMP $0xf4240, R1 // CMP $1000000, R1 // 1b4888d2fb01a0f23f001beb
|
||||||
|
ADD $0x186a0, R2, R5 // ADD $100000, R2, R5 // 45801a91a5604091
|
||||||
|
SUB $0xe7791f700, R3, R1 // SUB $62135596800, R3, R1 // 1be09ed23bf2aef2db01c0f261001bcb
|
||||||
|
CMP $3343198598084851058, R3 // 5bae8ed2db8daef23badcdf2bbcce5f27f001beb
|
||||||
ADD $0x3fffffffc000, R5 // ADD $70368744161280, R5 // fb7f72b2a5001b8b
|
ADD $0x3fffffffc000, R5 // ADD $70368744161280, R5 // fb7f72b2a5001b8b
|
||||||
// LTYPE1 imsr ',' spreg ','
|
// LTYPE1 imsr ',' spreg ','
|
||||||
// {
|
// {
|
||||||
|
|
@ -222,6 +227,13 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
EOR $(1<<63), R1 // EOR $-9223372036854775808, R1 // 210041d2
|
EOR $(1<<63), R1 // EOR $-9223372036854775808, R1 // 210041d2
|
||||||
EOR $(1<<63-1), R1 // EOR $9223372036854775807, R1 // 21f840d2
|
EOR $(1<<63-1), R1 // EOR $9223372036854775807, R1 // 21f840d2
|
||||||
|
|
||||||
|
ANDW $0x3ff00000, R2 // ANDW $1072693248, R2 // 42240c12
|
||||||
|
BICW $0x3ff00000, R2 // BICW $1072693248, R2 // 42540212
|
||||||
|
ORRW $0x3ff00000, R2 // ORRW $1072693248, R2 // 42240c32
|
||||||
|
ORNW $0x3ff00000, R2 // ORNW $1072693248, R2 // 42540232
|
||||||
|
EORW $0x3ff00000, R2 // EORW $1072693248, R2 // 42240c52
|
||||||
|
EONW $0x3ff00000, R2 // EONW $1072693248, R2 // 42540252
|
||||||
|
|
||||||
AND $0x22220000, R3, R4 // AND $572653568, R3, R4 // 5b44a4d264001b8a
|
AND $0x22220000, R3, R4 // AND $572653568, R3, R4 // 5b44a4d264001b8a
|
||||||
ORR $0x22220000, R3, R4 // ORR $572653568, R3, R4 // 5b44a4d264001baa
|
ORR $0x22220000, R3, R4 // ORR $572653568, R3, R4 // 5b44a4d264001baa
|
||||||
EOR $0x22220000, R3, R4 // EOR $572653568, R3, R4 // 5b44a4d264001bca
|
EOR $0x22220000, R3, R4 // EOR $572653568, R3, R4 // 5b44a4d264001bca
|
||||||
|
|
@ -233,12 +245,21 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
|
|
||||||
EOR $0xe03fffffffffffff, R20, R22 // EOR $-2287828610704211969, R20, R22 // 96e243d2
|
EOR $0xe03fffffffffffff, R20, R22 // EOR $-2287828610704211969, R20, R22 // 96e243d2
|
||||||
TSTW $0x600000006, R1 // TSTW $25769803782, R1 // 3f041f72
|
TSTW $0x600000006, R1 // TSTW $25769803782, R1 // 3f041f72
|
||||||
|
TST $0x4900000049, R0 // TST $313532612681, R0 // 3b0980d23b09c0f21f001bea
|
||||||
|
ORR $0x170000, R2, R1 // ORR $1507328, R2, R1 // fb02a0d241001baa
|
||||||
|
AND $0xff00ff, R2 // AND $16711935, R2 // fb1f80d2fb1fa0f242001b8a
|
||||||
|
AND $0xff00ffff, R1 // AND $4278255615, R1 // fbff9fd21be0bff221001b8a
|
||||||
ANDS $0xffff, R2 // ANDS $65535, R2 // 423c40f2
|
ANDS $0xffff, R2 // ANDS $65535, R2 // 423c40f2
|
||||||
AND $0x7fffffff, R3 // AND $2147483647, R3 // 63784092
|
AND $0x7fffffff, R3 // AND $2147483647, R3 // 63784092
|
||||||
ANDS $0x0ffffffff80000000, R2 // ANDS $-2147483648, R2 // 428061f2
|
ANDS $0x0ffffffff80000000, R2 // ANDS $-2147483648, R2 // 428061f2
|
||||||
AND $0xfffff, R2 // AND $1048575, R2 // 424c4092
|
AND $0xfffff, R2 // AND $1048575, R2 // 424c4092
|
||||||
ANDW $0xf00fffff, R1 // ANDW $4027580415, R1 // 215c0412
|
ANDW $0xf00fffff, R1 // ANDW $4027580415, R1 // 215c0412
|
||||||
ANDSW $0xff00ffff, R1 // ANDSW $4278255615, R1 // 215c0872
|
ANDSW $0xff00ffff, R1 // ANDSW $4278255615, R1 // 215c0872
|
||||||
|
TST $0x11223344, R2 // TST $287454020, R2 // 9b6886d25b24a2f25f001bea
|
||||||
|
TSTW $0xa000, R3 // TSTW $40960, R3 // 1b0094527f001b6a
|
||||||
|
BICW $0xa000, R3 // BICW $40960, R3 // 1b00945263003b0a
|
||||||
|
ORRW $0x1b000, R2, R3 // ORRW $110592, R2, R3 // 1b0096523b00a07243001b2a
|
||||||
|
TSTW $0x500000, R1 // TSTW $5242880, R1 // 1b0aa0523f001b6a
|
||||||
TSTW $0xff00ff, R1 // TSTW $16711935, R1 // 3f9c0072
|
TSTW $0xff00ff, R1 // TSTW $16711935, R1 // 3f9c0072
|
||||||
|
|
||||||
AND $8, R0, RSP // 1f007d92
|
AND $8, R0, RSP // 1f007d92
|
||||||
|
|
@ -249,13 +270,20 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
EON $8, R0, RSP // 1ff87cd2
|
EON $8, R0, RSP // 1ff87cd2
|
||||||
|
|
||||||
MOVD $0x3fffffffc000, R0 // MOVD $70368744161280, R0 // e07f72b2
|
MOVD $0x3fffffffc000, R0 // MOVD $70368744161280, R0 // e07f72b2
|
||||||
|
MOVW $1000000, R4 // 04488852e401a072
|
||||||
MOVW $0xaaaa0000, R1 // MOVW $2863267840, R1 // 4155b552
|
MOVW $0xaaaa0000, R1 // MOVW $2863267840, R1 // 4155b552
|
||||||
MOVW $0xaaaaffff, R1 // MOVW $2863333375, R1 // a1aaaa12
|
MOVW $0xaaaaffff, R1 // MOVW $2863333375, R1 // a1aaaa12
|
||||||
MOVW $0xaaaa, R1 // MOVW $43690, R1 // 41559552
|
MOVW $0xaaaa, R1 // MOVW $43690, R1 // 41559552
|
||||||
MOVW $0xffffaaaa, R1 // MOVW $4294945450, R1 // a1aa8a12
|
MOVW $0xffffaaaa, R1 // MOVW $4294945450, R1 // a1aa8a12
|
||||||
MOVW $0xffff0000, R1 // MOVW $4294901760, R1 // e1ffbf52
|
MOVW $0xffff0000, R1 // MOVW $4294901760, R1 // e1ffbf52
|
||||||
MOVD $0xffff00000000000, R1 // MOVD $1152903912420802560, R1 // e13f54b2
|
MOVD $0xffff00000000000, R1 // MOVD $1152903912420802560, R1 // e13f54b2
|
||||||
|
MOVD $0x1111000000001111, R1 // MOVD $1229764173248860433, R1 // 212282d22122e2f2
|
||||||
|
MOVD $0x1111ffff1111ffff, R1 // MOVD $1230045644216991743, R1 // c1ddbd922122e2f2
|
||||||
|
MOVD $0x1111222233334444, R1 // MOVD $1229801703532086340, R1 // 818888d26166a6f24144c4f22122e2f2
|
||||||
|
MOVD $0xaaaaffff, R1 // MOVD $2863333375, R1 // e1ff9fd24155b5f2
|
||||||
MOVD $0x11110000, R1 // MOVD $286326784, R1 // 2122a2d2
|
MOVD $0x11110000, R1 // MOVD $286326784, R1 // 2122a2d2
|
||||||
|
MOVD $0xaaaa0000aaaa1111, R1 // MOVD $-6149102338357718767, R1 // 212282d24155b5f24155f5f2
|
||||||
|
MOVD $0x1111ffff1111aaaa, R1 // MOVD $1230045644216969898, R1 // a1aa8a922122a2f22122e2f2
|
||||||
MOVD $0, R1 // 010080d2
|
MOVD $0, R1 // 010080d2
|
||||||
MOVD $-1, R1 // 01008092
|
MOVD $-1, R1 // 01008092
|
||||||
MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2
|
MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2
|
||||||
|
|
|
||||||
54
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
54
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
|
|
@ -56,7 +56,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
BFXILW $3, R27, $23, R14 // 6e670333
|
BFXILW $3, R27, $23, R14 // 6e670333
|
||||||
BFXIL $26, R8, $16, R20 // 14a55ab3
|
BFXIL $26, R8, $16, R20 // 14a55ab3
|
||||||
BICW R7@>15, R5, R16 // b03ce70a
|
BICW R7@>15, R5, R16 // b03ce70a
|
||||||
BIC R12@>13, R12, R18 // 9235ec8a
|
BIC R12@>13, R12, R19 // 9335ec8a
|
||||||
BICSW R25->20, R3, R20 // 7450b96a
|
BICSW R25->20, R3, R20 // 7450b96a
|
||||||
BICS R19->12, R1, R23 // 3730b3ea
|
BICS R19->12, R1, R23 // 3730b3ea
|
||||||
BICS R19, R1, R23 // 370033ea
|
BICS R19, R1, R23 // 370033ea
|
||||||
|
|
@ -76,7 +76,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
CCMN LE, R30, R12, $6 // c6d34cba
|
CCMN LE, R30, R12, $6 // c6d34cba
|
||||||
CCMPW VS, R29, $15, $7 // a76b4f7a
|
CCMPW VS, R29, $15, $7 // a76b4f7a
|
||||||
CCMP LE, R7, $19, $3 // e3d853fa
|
CCMP LE, R7, $19, $3 // e3d853fa
|
||||||
CCMPW HS, R18, R6, $0 // 4022467a
|
CCMPW HS, R19, R6, $0 // 6022467a
|
||||||
CCMP LT, R30, R6, $7 // c7b346fa
|
CCMP LT, R30, R6, $7 // c7b346fa
|
||||||
CCMN MI, ZR, R1, $4 // e44341ba
|
CCMN MI, ZR, R1, $4 // e44341ba
|
||||||
CSINCW HS, ZR, R27, R14 // ee279b1a
|
CSINCW HS, ZR, R27, R14 // ee279b1a
|
||||||
|
|
@ -118,7 +118,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
CRC32H R3, R21, R27 // bb46c31a
|
CRC32H R3, R21, R27 // bb46c31a
|
||||||
CRC32W R22, R30, R9 // c94bd61a
|
CRC32W R22, R30, R9 // c94bd61a
|
||||||
CRC32X R20, R4, R15 // 8f4cd49a
|
CRC32X R20, R4, R15 // 8f4cd49a
|
||||||
CRC32CB R18, R27, R22 // 7653d21a
|
CRC32CB R19, R27, R22 // 7653d31a
|
||||||
CRC32CH R21, R0, R20 // 1454d51a
|
CRC32CH R21, R0, R20 // 1454d51a
|
||||||
CRC32CW R9, R3, R21 // 7558c91a
|
CRC32CW R9, R3, R21 // 7558c91a
|
||||||
CRC32CX R11, R0, R24 // 185ccb9a
|
CRC32CX R11, R0, R24 // 185ccb9a
|
||||||
|
|
@ -133,7 +133,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
CSINVW AL, R23, R21, R5 // e5e2955a
|
CSINVW AL, R23, R21, R5 // e5e2955a
|
||||||
CSINV LO, R2, R11, R14 // 4e308bda
|
CSINV LO, R2, R11, R14 // 4e308bda
|
||||||
CSNEGW HS, R16, R29, R10 // 0a269d5a
|
CSNEGW HS, R16, R29, R10 // 0a269d5a
|
||||||
CSNEG NE, R21, R18, R11 // ab1692da
|
CSNEG NE, R21, R19, R11 // ab1693da
|
||||||
//TODO DC
|
//TODO DC
|
||||||
DCPS1 $11378 // 418ea5d4
|
DCPS1 $11378 // 418ea5d4
|
||||||
DCPS2 $10699 // 6239a5d4
|
DCPS2 $10699 // 6239a5d4
|
||||||
|
|
@ -185,23 +185,23 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
MOVBU.P 42(R2), R12 // 4ca44238
|
MOVBU.P 42(R2), R12 // 4ca44238
|
||||||
MOVBU.W -27(R2), R14 // 4e5c5e38
|
MOVBU.W -27(R2), R14 // 4e5c5e38
|
||||||
MOVBU 2916(R24), R3 // 03936d39
|
MOVBU 2916(R24), R3 // 03936d39
|
||||||
MOVBU (R18)(R14<<0), R23 // 577a6e38
|
MOVBU (R19)(R14<<0), R23 // 777a6e38
|
||||||
MOVBU (R2)(R8.SXTX), R19 // 53e86838
|
MOVBU (R2)(R8.SXTX), R19 // 53e86838
|
||||||
MOVBU (R27)(R23), R14 // MOVBU (R27)(R23*1), R14 // 6e6b7738
|
MOVBU (R27)(R23), R14 // MOVBU (R27)(R23*1), R14 // 6e6b7738
|
||||||
MOVHU.P 107(R14), R13 // cdb54678
|
MOVHU.P 107(R14), R13 // cdb54678
|
||||||
MOVHU.W 192(R3), R2 // 620c4c78
|
MOVHU.W 192(R3), R2 // 620c4c78
|
||||||
MOVHU 6844(R4), R18 // 92787579
|
MOVHU 6844(R4), R19 // 93787579
|
||||||
MOVHU (R5)(R25.SXTW), R15 // afc87978
|
MOVHU (R5)(R25.SXTW), R15 // afc87978
|
||||||
//TODO MOVBW.P 77(R18), R11 // 4bd6c438
|
//TODO MOVBW.P 77(R19), R11 // 6bd6c438
|
||||||
MOVB.P 36(RSP), R27 // fb478238
|
MOVB.P 36(RSP), R27 // fb478238
|
||||||
//TODO MOVBW.W -57(R18), R13 // 4d7edc38
|
//TODO MOVBW.W -57(R19), R13 // 6d7edc38
|
||||||
MOVB.W -178(R16), R24 // 18ee9438
|
MOVB.W -178(R16), R24 // 18ee9438
|
||||||
//TODO MOVBW 430(R8), R22 // 16b9c639
|
//TODO MOVBW 430(R8), R22 // 16b9c639
|
||||||
MOVB 997(R9), R23 // 37958f39
|
MOVB 997(R9), R23 // 37958f39
|
||||||
//TODO MOVBW (R2<<1)(R21), R15 // af7ae238
|
//TODO MOVBW (R2<<1)(R21), R15 // af7ae238
|
||||||
//TODO MOVBW (R26)(R0), R21 // 1568fa38
|
//TODO MOVBW (R26)(R0), R21 // 1568fa38
|
||||||
MOVB (R5)(R15), R16 // MOVB (R5)(R15*1), R16 // b068af38
|
MOVB (R5)(R15), R16 // MOVB (R5)(R15*1), R16 // b068af38
|
||||||
MOVB (R18)(R26.SXTW), R19 // 53caba38
|
MOVB (R19)(R26.SXTW), R19 // 73caba38
|
||||||
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
||||||
//TODO MOVHW.P 218(R22), R25 // d9a6cd78
|
//TODO MOVHW.P 218(R22), R25 // d9a6cd78
|
||||||
MOVH.P 179(R23), R5 // e5368b78
|
MOVH.P 179(R23), R5 // e5368b78
|
||||||
|
|
@ -212,7 +212,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
//TODO MOVHW (R22)(R24.SXTX), R4 // c4eaf878
|
//TODO MOVHW (R22)(R24.SXTX), R4 // c4eaf878
|
||||||
MOVH (R26)(R30.UXTW<<1), ZR // 5f5bbe78
|
MOVH (R26)(R30.UXTW<<1), ZR // 5f5bbe78
|
||||||
MOVW.P -58(R16), R2 // 02669cb8
|
MOVW.P -58(R16), R2 // 02669cb8
|
||||||
MOVW.W -216(R18), R8 // 488e92b8
|
MOVW.W -216(R19), R8 // 688e92b8
|
||||||
MOVW 4764(R23), R10 // ea9e92b9
|
MOVW 4764(R23), R10 // ea9e92b9
|
||||||
MOVW (R8)(R3.UXTW), R17 // 1149a3b8
|
MOVW (R8)(R3.UXTW), R17 // 1149a3b8
|
||||||
//TODO LDTR -0x1e(R3), R4 // 64285eb8
|
//TODO LDTR -0x1e(R3), R4 // 64285eb8
|
||||||
|
|
@ -297,7 +297,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
RET // c0035fd6
|
RET // c0035fd6
|
||||||
REVW R8, R10 // 0a09c05a
|
REVW R8, R10 // 0a09c05a
|
||||||
REV R1, R2 // 220cc0da
|
REV R1, R2 // 220cc0da
|
||||||
REV16W R21, R18 // b206c05a
|
REV16W R21, R19 // b306c05a
|
||||||
REV16 R25, R4 // 2407c0da
|
REV16 R25, R4 // 2407c0da
|
||||||
REV32 R27, R21 // 750bc0da
|
REV32 R27, R21 // 750bc0da
|
||||||
EXTRW $27, R4, R25, R19 // 336f8413
|
EXTRW $27, R4, R25, R19 // 336f8413
|
||||||
|
|
@ -308,7 +308,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
ROR R0, R23, R2 // e22ec09a
|
ROR R0, R23, R2 // e22ec09a
|
||||||
SBCW R4, R8, R24 // 1801045a
|
SBCW R4, R8, R24 // 1801045a
|
||||||
SBC R25, R10, R26 // 5a0119da
|
SBC R25, R10, R26 // 5a0119da
|
||||||
SBCSW R27, R18, R18 // 52021b7a
|
SBCSW R27, R19, R19 // 73021b7a
|
||||||
SBCS R5, R9, R5 // 250105fa
|
SBCS R5, R9, R5 // 250105fa
|
||||||
SBFIZW $9, R10, $18, R22 // 56451713
|
SBFIZW $9, R10, $18, R22 // 56451713
|
||||||
SBFIZ $6, R11, $15, R20 // 74397a93
|
SBFIZ $6, R11, $15, R20 // 74397a93
|
||||||
|
|
@ -337,7 +337,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
//TODO STNPW 44(R1), R3, R10 // 2a8c0528
|
//TODO STNPW 44(R1), R3, R10 // 2a8c0528
|
||||||
//TODO STNP 0x108(R3), ZR, R7 // 67fc10a8
|
//TODO STNP 0x108(R3), ZR, R7 // 67fc10a8
|
||||||
LDP.P -384(R3), (R22, R26) // 7668e8a8
|
LDP.P -384(R3), (R22, R26) // 7668e8a8
|
||||||
LDP.W 280(R8), (R18, R11) // 12add1a9
|
LDP.W 280(R8), (R19, R11) // 13add1a9
|
||||||
STP.P (R22, R27), 352(R0) // 166c96a8
|
STP.P (R22, R27), 352(R0) // 166c96a8
|
||||||
STP.W (R17, R11), 96(R8) // 112d86a9
|
STP.W (R17, R11), 96(R8) // 112d86a9
|
||||||
MOVW.P R20, -28(R1) // 34441eb8
|
MOVW.P R20, -28(R1) // 34441eb8
|
||||||
|
|
@ -360,22 +360,22 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
MOVB R2, (R29)(R26) // MOVB R2, (R29)(R26*1) // a26b3a38
|
MOVB R2, (R29)(R26) // MOVB R2, (R29)(R26*1) // a26b3a38
|
||||||
MOVH R11, -80(R23) // eb021b78
|
MOVH R11, -80(R23) // eb021b78
|
||||||
MOVH R11, (R27)(R14.SXTW<<1) // 6bdb2e78
|
MOVH R11, (R27)(R14.SXTW<<1) // 6bdb2e78
|
||||||
MOVB R18, (R0)(R4) // MOVB R18, (R0)(R4*1) // 12682438
|
MOVB R19, (R0)(R4) // MOVB R19, (R0)(R4*1) // 13682438
|
||||||
MOVB R1, (R6)(R4) // MOVB R1, (R6)(R4*1) // c1682438
|
MOVB R1, (R6)(R4) // MOVB R1, (R6)(R4*1) // c1682438
|
||||||
MOVH R3, (R11)(R13<<1) // 63792d78
|
MOVH R3, (R11)(R13<<1) // 63792d78
|
||||||
//TODO STTR 55(R4), R29 // 9d7803b8
|
//TODO STTR 55(R4), R29 // 9d7803b8
|
||||||
//TODO STTR 124(R5), R25 // b9c807f8
|
//TODO STTR 124(R5), R25 // b9c807f8
|
||||||
//TODO STTRB -28(R23), R16 // f04a1e38
|
//TODO STTRB -28(R23), R16 // f04a1e38
|
||||||
//TODO STTRH 9(R10), R18 // 52990078
|
//TODO STTRH 9(R10), R19 // 53990078
|
||||||
STXP (R1, R2), (R3), R10 // 61082ac8
|
STXP (R1, R2), (R3), R10 // 61082ac8
|
||||||
STXP (R1, R2), (RSP), R10 // e10b2ac8
|
STXP (R1, R2), (RSP), R10 // e10b2ac8
|
||||||
STXPW (R1, R2), (R3), R10 // 61082a88
|
STXPW (R1, R2), (R3), R10 // 61082a88
|
||||||
STXPW (R1, R2), (RSP), R10 // e10b2a88
|
STXPW (R1, R2), (RSP), R10 // e10b2a88
|
||||||
STXRW R2, (R19), R18 // 627e1288
|
STXRW R2, (R19), R20 // 627e1488
|
||||||
STXR R15, (R21), R13 // af7e0dc8
|
STXR R15, (R21), R13 // af7e0dc8
|
||||||
STXRB R7, (R9), R24 // 277d1808
|
STXRB R7, (R9), R24 // 277d1808
|
||||||
STXRH R12, (R3), R8 // 6c7c0848
|
STXRH R12, (R3), R8 // 6c7c0848
|
||||||
SUBW R20.UXTW<<2, R23, R18 // f24a344b
|
SUBW R20.UXTW<<2, R23, R19 // f34a344b
|
||||||
SUB R5.SXTW<<2, R1, R26 // 3ac825cb
|
SUB R5.SXTW<<2, R1, R26 // 3ac825cb
|
||||||
SUB $(1923<<12), R4, R27 // SUB $7876608, R4, R27 // 9b0c5ed1
|
SUB $(1923<<12), R4, R27 // SUB $7876608, R4, R27 // 9b0c5ed1
|
||||||
SUBW $(1923<<12), R4, R27 // SUBW $7876608, R4, R27 // 9b0c5e51
|
SUBW $(1923<<12), R4, R27 // SUBW $7876608, R4, R27 // 9b0c5e51
|
||||||
|
|
@ -410,12 +410,12 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
UBFXW $3, R7, $20, R15 // ef580353
|
UBFXW $3, R7, $20, R15 // ef580353
|
||||||
UBFX $33, R17, $25, R5 // 25e661d3
|
UBFX $33, R17, $25, R5 // 25e661d3
|
||||||
UDIVW R8, R21, R15 // af0ac81a
|
UDIVW R8, R21, R15 // af0ac81a
|
||||||
UDIV R2, R18, R21 // 550ac29a
|
UDIV R2, R19, R21 // 750ac29a
|
||||||
UMADDL R0, R20, R17, R17 // 3152a09b
|
UMADDL R0, R20, R17, R17 // 3152a09b
|
||||||
UMSUBL R22, R4, R3, R7 // 6790b69b
|
UMSUBL R22, R4, R3, R7 // 6790b69b
|
||||||
UMNEGL R3, R18, R1 // 41fea39b
|
UMNEGL R3, R19, R1 // 61fea39b
|
||||||
UMULH R24, R20, R24 // 987ed89b
|
UMULH R24, R20, R24 // 987ed89b
|
||||||
UMULL R18, R22, R19 // d37eb29b
|
UMULL R19, R22, R19 // d37eb39b
|
||||||
UXTBW R2, R6 // 461c0053
|
UXTBW R2, R6 // 461c0053
|
||||||
UXTHW R7, R20 // f43c0053
|
UXTHW R7, R20 // f43c0053
|
||||||
VCNT V0.B8, V0.B8 // 0058200e
|
VCNT V0.B8, V0.B8 // 0058200e
|
||||||
|
|
@ -471,7 +471,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
//TODO FCVTAS F27, R7 // 6703241e
|
//TODO FCVTAS F27, R7 // 6703241e
|
||||||
//TODO FCVTAS F19, R26 // 7a02249e
|
//TODO FCVTAS F19, R26 // 7a02249e
|
||||||
//TODO FCVTAS F4, R0 // 8000641e
|
//TODO FCVTAS F4, R0 // 8000641e
|
||||||
//TODO FCVTAS F3, R18 // 7200649e
|
//TODO FCVTAS F3, R19 // 7300649e
|
||||||
//TODO FCVTAU F18, F28 // 5cca217e
|
//TODO FCVTAU F18, F28 // 5cca217e
|
||||||
//TODO VFCVTAU V30.S4, V27.S4 // dbcb216e
|
//TODO VFCVTAU V30.S4, V27.S4 // dbcb216e
|
||||||
//TODO FCVTAU F0, R2 // 0200251e
|
//TODO FCVTAU F0, R2 // 0200251e
|
||||||
|
|
@ -482,16 +482,16 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
//TODO VFCVTL2 V15.H8, V25.S4 // f979214e
|
//TODO VFCVTL2 V15.H8, V25.S4 // f979214e
|
||||||
//TODO FCVTMS F21, F28 // bcba215e
|
//TODO FCVTMS F21, F28 // bcba215e
|
||||||
//TODO VFCVTMS V5.D2, V2.D2 // a2b8614e
|
//TODO VFCVTMS V5.D2, V2.D2 // a2b8614e
|
||||||
//TODO FCVTMS F31, R18 // f203301e
|
//TODO FCVTMS F31, R19 // f303301e
|
||||||
//TODO FCVTMS F23, R16 // f002309e
|
//TODO FCVTMS F23, R16 // f002309e
|
||||||
//TODO FCVTMS F16, R22 // 1602701e
|
//TODO FCVTMS F16, R22 // 1602701e
|
||||||
//TODO FCVTMS F14, R19 // d301709e
|
//TODO FCVTMS F14, R19 // d301709e
|
||||||
//TODO FCVTMU F14, F8 // c8b9217e
|
//TODO FCVTMU F14, F8 // c8b9217e
|
||||||
//TODO VFCVTMU V7.D2, V1.D2 // e1b8616e
|
//TODO VFCVTMU V7.D2, V1.D2 // e1b8616e
|
||||||
//TODO FCVTMU F2, R0 // 4000311e
|
//TODO FCVTMU F2, R0 // 4000311e
|
||||||
//TODO FCVTMU F23, R18 // f202319e
|
//TODO FCVTMU F23, R19 // f302319e
|
||||||
//TODO FCVTMU F16, R17 // 1102711e
|
//TODO FCVTMU F16, R17 // 1102711e
|
||||||
//TODO FCVTMU F12, R18 // 9201719e
|
//TODO FCVTMU F12, R19 // 9301719e
|
||||||
//TODO VFCVTN V23.D2, V26.S2 // fa6a610e
|
//TODO VFCVTN V23.D2, V26.S2 // fa6a610e
|
||||||
//TODO VFCVTN2 V2.D2, V31.S4 // 5f68614e
|
//TODO VFCVTN2 V2.D2, V31.S4 // 5f68614e
|
||||||
//TODO FCVTNS F3, F27 // 7ba8215e
|
//TODO FCVTNS F3, F27 // 7ba8215e
|
||||||
|
|
@ -540,7 +540,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
//TODO FCVTZU $14, F24, R20 // 14cb191e
|
//TODO FCVTZU $14, F24, R20 // 14cb191e
|
||||||
//TODO FCVTZU $6, F25, R17 // 31eb199e
|
//TODO FCVTZU $6, F25, R17 // 31eb199e
|
||||||
//TODO FCVTZU $5, F17, R10 // 2aee591e
|
//TODO FCVTZU $5, F17, R10 // 2aee591e
|
||||||
//TODO FCVTZU $6, F7, R18 // f2e8599e
|
//TODO FCVTZU $6, F7, R19 // f3e8599e
|
||||||
FCVTZUSW F2, R9 // 4900391e
|
FCVTZUSW F2, R9 // 4900391e
|
||||||
FCVTZUS F12, R29 // 9d01399e
|
FCVTZUS F12, R29 // 9d01399e
|
||||||
FCVTZUDW F27, R22 // 7603791e
|
FCVTZUDW F27, R22 // 7603791e
|
||||||
|
|
@ -682,11 +682,11 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
VLD1.P (R19)(R4), [V24.B8, V25.B8] // VLD1.P (R19)(R4*1), [V24.B8, V25.B8] // 78a2c40c
|
VLD1.P (R19)(R4), [V24.B8, V25.B8] // VLD1.P (R19)(R4*1), [V24.B8, V25.B8] // 78a2c40c
|
||||||
VLD1.P (R20)(R8), [V7.H8, V8.H8, V9.H8] // VLD1.P (R20)(R8*1), [V7.H8, V8.H8, V9.H8] // 8766c84c
|
VLD1.P (R20)(R8), [V7.H8, V8.H8, V9.H8] // VLD1.P (R20)(R8*1), [V7.H8, V8.H8, V9.H8] // 8766c84c
|
||||||
VLD1.P 32(R30), [V5.B8, V6.B8, V7.B8, V8.B8] // c523df0c
|
VLD1.P 32(R30), [V5.B8, V6.B8, V7.B8, V8.B8] // c523df0c
|
||||||
VLD1 (R18), V14.B[15] // 4e1e404d
|
VLD1 (R19), V14.B[15] // 6e1e404d
|
||||||
VLD1 (R29), V0.H[1] // a04b400d
|
VLD1 (R29), V0.H[1] // a04b400d
|
||||||
VLD1 (R27), V2.S[0] // 6283400d
|
VLD1 (R27), V2.S[0] // 6283400d
|
||||||
VLD1 (R21), V5.D[1] // a586404d
|
VLD1 (R21), V5.D[1] // a586404d
|
||||||
VLD1.P 1(R18), V10.B[14] // 4a1adf4d
|
VLD1.P 1(R19), V10.B[14] // 6a1adf4d
|
||||||
VLD1.P (R3)(R14), V16.B[11] // VLD1.P (R3)(R14*1), V16.B[11] // 700cce4d
|
VLD1.P (R3)(R14), V16.B[11] // VLD1.P (R3)(R14*1), V16.B[11] // 700cce4d
|
||||||
VLD1.P 2(R1), V28.H[2] // 3c50df0d
|
VLD1.P 2(R1), V28.H[2] // 3c50df0d
|
||||||
VLD1.P (R13)(R20), V9.H[2] // VLD1.P (R13)(R20*1), V9.H[2] // a951d40d
|
VLD1.P (R13)(R20), V9.H[2] // VLD1.P (R13)(R20*1), V9.H[2] // a951d40d
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ func (in *Input) Text() string {
|
||||||
return in.text
|
return in.text
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash processes a # preprocessor directive. It returns true iff it completes.
|
// hash processes a # preprocessor directive. It reports whether it completes.
|
||||||
func (in *Input) hash() bool {
|
func (in *Input) hash() bool {
|
||||||
// We have a '#'; it must be followed by a known word (define, include, etc.).
|
// We have a '#'; it must be followed by a known word (define, include, etc.).
|
||||||
tok := in.Stack.Next()
|
tok := in.Stack.Next()
|
||||||
|
|
|
||||||
|
|
@ -827,6 +827,10 @@ The directives are:
|
||||||
possibly version in the dynamic library, and the optional "<library>"
|
possibly version in the dynamic library, and the optional "<library>"
|
||||||
names the specific library where the symbol should be found.
|
names the specific library where the symbol should be found.
|
||||||
|
|
||||||
|
On AIX, the library pattern is slightly different. It must be
|
||||||
|
"lib.a/obj.o" with obj.o the member of this library exporting
|
||||||
|
this symbol.
|
||||||
|
|
||||||
In the <remote>, # or @ can be used to introduce a symbol version.
|
In the <remote>, # or @ can be used to introduce a symbol version.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,22 @@ func (p *Package) writeDefs() {
|
||||||
|
|
||||||
init := gccgoInit.String()
|
init := gccgoInit.String()
|
||||||
if init != "" {
|
if init != "" {
|
||||||
fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));")
|
// The init function does nothing but simple
|
||||||
|
// assignments, so it won't use much stack space, so
|
||||||
|
// it's OK to not split the stack. Splitting the stack
|
||||||
|
// can run into a bug in clang (as of 2018-11-09):
|
||||||
|
// this is a leaf function, and when clang sees a leaf
|
||||||
|
// function it won't emit the split stack prologue for
|
||||||
|
// the function. However, if this function refers to a
|
||||||
|
// non-split-stack function, which will happen if the
|
||||||
|
// cgo code refers to a C function not compiled with
|
||||||
|
// -fsplit-stack, then the linker will think that it
|
||||||
|
// needs to adjust the split stack prologue, but there
|
||||||
|
// won't be one. Marking the function explicitly
|
||||||
|
// no_split_stack works around this problem by telling
|
||||||
|
// the linker that it's OK if there is no split stack
|
||||||
|
// prologue.
|
||||||
|
fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor, no_split_stack));")
|
||||||
fmt.Fprintln(fc, "static void init(void) {")
|
fmt.Fprintln(fc, "static void init(void) {")
|
||||||
fmt.Fprint(fc, init)
|
fmt.Fprint(fc, init)
|
||||||
fmt.Fprintln(fc, "}")
|
fmt.Fprintln(fc, "}")
|
||||||
|
|
|
||||||
|
|
@ -587,6 +587,7 @@ var knownFormats = map[string]string{
|
||||||
"*cmd/compile/internal/types.Sym %S": "",
|
"*cmd/compile/internal/types.Sym %S": "",
|
||||||
"*cmd/compile/internal/types.Sym %p": "",
|
"*cmd/compile/internal/types.Sym %p": "",
|
||||||
"*cmd/compile/internal/types.Sym %v": "",
|
"*cmd/compile/internal/types.Sym %v": "",
|
||||||
|
"*cmd/compile/internal/types.Type %#L": "",
|
||||||
"*cmd/compile/internal/types.Type %#v": "",
|
"*cmd/compile/internal/types.Type %#v": "",
|
||||||
"*cmd/compile/internal/types.Type %+v": "",
|
"*cmd/compile/internal/types.Type %+v": "",
|
||||||
"*cmd/compile/internal/types.Type %-S": "",
|
"*cmd/compile/internal/types.Type %-S": "",
|
||||||
|
|
@ -598,6 +599,7 @@ var knownFormats = map[string]string{
|
||||||
"*cmd/compile/internal/types.Type %v": "",
|
"*cmd/compile/internal/types.Type %v": "",
|
||||||
"*cmd/internal/obj.Addr %v": "",
|
"*cmd/internal/obj.Addr %v": "",
|
||||||
"*cmd/internal/obj.LSym %v": "",
|
"*cmd/internal/obj.LSym %v": "",
|
||||||
|
"*math/big.Float %f": "",
|
||||||
"*math/big.Int %#x": "",
|
"*math/big.Int %#x": "",
|
||||||
"*math/big.Int %s": "",
|
"*math/big.Int %s": "",
|
||||||
"*math/big.Int %v": "",
|
"*math/big.Int %v": "",
|
||||||
|
|
@ -658,6 +660,7 @@ var knownFormats = map[string]string{
|
||||||
"cmd/compile/internal/ssa.rbrank %d": "",
|
"cmd/compile/internal/ssa.rbrank %d": "",
|
||||||
"cmd/compile/internal/ssa.regMask %d": "",
|
"cmd/compile/internal/ssa.regMask %d": "",
|
||||||
"cmd/compile/internal/ssa.register %d": "",
|
"cmd/compile/internal/ssa.register %d": "",
|
||||||
|
"cmd/compile/internal/syntax.Error %q": "",
|
||||||
"cmd/compile/internal/syntax.Expr %#v": "",
|
"cmd/compile/internal/syntax.Expr %#v": "",
|
||||||
"cmd/compile/internal/syntax.Node %T": "",
|
"cmd/compile/internal/syntax.Node %T": "",
|
||||||
"cmd/compile/internal/syntax.Operator %s": "",
|
"cmd/compile/internal/syntax.Operator %s": "",
|
||||||
|
|
@ -705,6 +708,7 @@ var knownFormats = map[string]string{
|
||||||
"interface{} %v": "",
|
"interface{} %v": "",
|
||||||
"map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "",
|
"map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "",
|
||||||
"map[cmd/compile/internal/ssa.ID]uint32 %v": "",
|
"map[cmd/compile/internal/ssa.ID]uint32 %v": "",
|
||||||
|
"math/big.Accuracy %s": "",
|
||||||
"reflect.Type %s": "",
|
"reflect.Type %s": "",
|
||||||
"rune %#U": "",
|
"rune %#U": "",
|
||||||
"rune %c": "",
|
"rune %c": "",
|
||||||
|
|
|
||||||
|
|
@ -51,110 +51,105 @@ var runtimeDecls = [...]struct {
|
||||||
{"decoderune", funcTag, 50},
|
{"decoderune", funcTag, 50},
|
||||||
{"countrunes", funcTag, 51},
|
{"countrunes", funcTag, 51},
|
||||||
{"convI2I", funcTag, 52},
|
{"convI2I", funcTag, 52},
|
||||||
{"convT2E", funcTag, 53},
|
{"convT16", funcTag, 54},
|
||||||
{"convT2E16", funcTag, 52},
|
{"convT32", funcTag, 54},
|
||||||
{"convT2E32", funcTag, 52},
|
{"convT64", funcTag, 54},
|
||||||
{"convT2E64", funcTag, 52},
|
{"convTstring", funcTag, 54},
|
||||||
{"convT2Estring", funcTag, 52},
|
{"convTslice", funcTag, 54},
|
||||||
{"convT2Eslice", funcTag, 52},
|
{"convT2E", funcTag, 55},
|
||||||
{"convT2Enoptr", funcTag, 53},
|
{"convT2Enoptr", funcTag, 55},
|
||||||
{"convT2I", funcTag, 53},
|
{"convT2I", funcTag, 55},
|
||||||
{"convT2I16", funcTag, 52},
|
{"convT2Inoptr", funcTag, 55},
|
||||||
{"convT2I32", funcTag, 52},
|
|
||||||
{"convT2I64", funcTag, 52},
|
|
||||||
{"convT2Istring", funcTag, 52},
|
|
||||||
{"convT2Islice", funcTag, 52},
|
|
||||||
{"convT2Inoptr", funcTag, 53},
|
|
||||||
{"assertE2I", funcTag, 52},
|
{"assertE2I", funcTag, 52},
|
||||||
{"assertE2I2", funcTag, 54},
|
{"assertE2I2", funcTag, 56},
|
||||||
{"assertI2I", funcTag, 52},
|
{"assertI2I", funcTag, 52},
|
||||||
{"assertI2I2", funcTag, 54},
|
{"assertI2I2", funcTag, 56},
|
||||||
{"panicdottypeE", funcTag, 55},
|
{"panicdottypeE", funcTag, 57},
|
||||||
{"panicdottypeI", funcTag, 55},
|
{"panicdottypeI", funcTag, 57},
|
||||||
{"panicnildottype", funcTag, 56},
|
{"panicnildottype", funcTag, 58},
|
||||||
{"ifaceeq", funcTag, 59},
|
{"ifaceeq", funcTag, 60},
|
||||||
{"efaceeq", funcTag, 59},
|
{"efaceeq", funcTag, 60},
|
||||||
{"fastrand", funcTag, 61},
|
{"fastrand", funcTag, 62},
|
||||||
{"makemap64", funcTag, 63},
|
{"makemap64", funcTag, 64},
|
||||||
{"makemap", funcTag, 64},
|
{"makemap", funcTag, 65},
|
||||||
{"makemap_small", funcTag, 65},
|
{"makemap_small", funcTag, 66},
|
||||||
{"mapaccess1", funcTag, 66},
|
{"mapaccess1", funcTag, 67},
|
||||||
{"mapaccess1_fast32", funcTag, 67},
|
{"mapaccess1_fast32", funcTag, 68},
|
||||||
{"mapaccess1_fast64", funcTag, 67},
|
{"mapaccess1_fast64", funcTag, 68},
|
||||||
{"mapaccess1_faststr", funcTag, 67},
|
{"mapaccess1_faststr", funcTag, 68},
|
||||||
{"mapaccess1_fat", funcTag, 68},
|
{"mapaccess1_fat", funcTag, 69},
|
||||||
{"mapaccess2", funcTag, 69},
|
{"mapaccess2", funcTag, 70},
|
||||||
{"mapaccess2_fast32", funcTag, 70},
|
{"mapaccess2_fast32", funcTag, 71},
|
||||||
{"mapaccess2_fast64", funcTag, 70},
|
{"mapaccess2_fast64", funcTag, 71},
|
||||||
{"mapaccess2_faststr", funcTag, 70},
|
{"mapaccess2_faststr", funcTag, 71},
|
||||||
{"mapaccess2_fat", funcTag, 71},
|
{"mapaccess2_fat", funcTag, 72},
|
||||||
{"mapassign", funcTag, 66},
|
{"mapassign", funcTag, 67},
|
||||||
{"mapassign_fast32", funcTag, 67},
|
{"mapassign_fast32", funcTag, 68},
|
||||||
{"mapassign_fast32ptr", funcTag, 67},
|
{"mapassign_fast32ptr", funcTag, 68},
|
||||||
{"mapassign_fast64", funcTag, 67},
|
{"mapassign_fast64", funcTag, 68},
|
||||||
{"mapassign_fast64ptr", funcTag, 67},
|
{"mapassign_fast64ptr", funcTag, 68},
|
||||||
{"mapassign_faststr", funcTag, 67},
|
{"mapassign_faststr", funcTag, 68},
|
||||||
{"mapiterinit", funcTag, 72},
|
{"mapiterinit", funcTag, 73},
|
||||||
{"mapdelete", funcTag, 72},
|
{"mapdelete", funcTag, 73},
|
||||||
{"mapdelete_fast32", funcTag, 73},
|
{"mapdelete_fast32", funcTag, 74},
|
||||||
{"mapdelete_fast64", funcTag, 73},
|
{"mapdelete_fast64", funcTag, 74},
|
||||||
{"mapdelete_faststr", funcTag, 73},
|
{"mapdelete_faststr", funcTag, 74},
|
||||||
{"mapiternext", funcTag, 74},
|
{"mapiternext", funcTag, 75},
|
||||||
{"mapclear", funcTag, 75},
|
{"mapclear", funcTag, 76},
|
||||||
{"makechan64", funcTag, 77},
|
{"makechan64", funcTag, 78},
|
||||||
{"makechan", funcTag, 78},
|
{"makechan", funcTag, 79},
|
||||||
{"chanrecv1", funcTag, 80},
|
{"chanrecv1", funcTag, 81},
|
||||||
{"chanrecv2", funcTag, 81},
|
{"chanrecv2", funcTag, 82},
|
||||||
{"chansend1", funcTag, 83},
|
{"chansend1", funcTag, 84},
|
||||||
{"closechan", funcTag, 23},
|
{"closechan", funcTag, 23},
|
||||||
{"writeBarrier", varTag, 85},
|
{"writeBarrier", varTag, 86},
|
||||||
{"typedmemmove", funcTag, 86},
|
{"typedmemmove", funcTag, 87},
|
||||||
{"typedmemclr", funcTag, 87},
|
{"typedmemclr", funcTag, 88},
|
||||||
{"typedslicecopy", funcTag, 88},
|
{"typedslicecopy", funcTag, 89},
|
||||||
{"selectnbsend", funcTag, 89},
|
{"selectnbsend", funcTag, 90},
|
||||||
{"selectnbrecv", funcTag, 90},
|
{"selectnbrecv", funcTag, 91},
|
||||||
{"selectnbrecv2", funcTag, 92},
|
{"selectnbrecv2", funcTag, 93},
|
||||||
{"selectsetpc", funcTag, 56},
|
{"selectsetpc", funcTag, 58},
|
||||||
{"selectgo", funcTag, 93},
|
{"selectgo", funcTag, 94},
|
||||||
{"block", funcTag, 5},
|
{"block", funcTag, 5},
|
||||||
{"makeslice", funcTag, 94},
|
{"makeslice", funcTag, 95},
|
||||||
{"makeslice64", funcTag, 95},
|
{"makeslice64", funcTag, 96},
|
||||||
{"growslice", funcTag, 97},
|
{"growslice", funcTag, 98},
|
||||||
{"memmove", funcTag, 98},
|
{"memmove", funcTag, 99},
|
||||||
{"memclrNoHeapPointers", funcTag, 99},
|
{"memclrNoHeapPointers", funcTag, 100},
|
||||||
{"memclrHasPointers", funcTag, 99},
|
{"memclrHasPointers", funcTag, 100},
|
||||||
{"memequal", funcTag, 100},
|
{"memequal", funcTag, 101},
|
||||||
{"memequal8", funcTag, 101},
|
{"memequal8", funcTag, 102},
|
||||||
{"memequal16", funcTag, 101},
|
{"memequal16", funcTag, 102},
|
||||||
{"memequal32", funcTag, 101},
|
{"memequal32", funcTag, 102},
|
||||||
{"memequal64", funcTag, 101},
|
{"memequal64", funcTag, 102},
|
||||||
{"memequal128", funcTag, 101},
|
{"memequal128", funcTag, 102},
|
||||||
{"int64div", funcTag, 102},
|
{"int64div", funcTag, 103},
|
||||||
{"uint64div", funcTag, 103},
|
{"uint64div", funcTag, 104},
|
||||||
{"int64mod", funcTag, 102},
|
{"int64mod", funcTag, 103},
|
||||||
{"uint64mod", funcTag, 103},
|
{"uint64mod", funcTag, 104},
|
||||||
{"float64toint64", funcTag, 104},
|
{"float64toint64", funcTag, 105},
|
||||||
{"float64touint64", funcTag, 105},
|
{"float64touint64", funcTag, 106},
|
||||||
{"float64touint32", funcTag, 106},
|
{"float64touint32", funcTag, 107},
|
||||||
{"int64tofloat64", funcTag, 107},
|
{"int64tofloat64", funcTag, 108},
|
||||||
{"uint64tofloat64", funcTag, 108},
|
{"uint64tofloat64", funcTag, 109},
|
||||||
{"uint32tofloat64", funcTag, 109},
|
{"uint32tofloat64", funcTag, 110},
|
||||||
{"complex128div", funcTag, 110},
|
{"complex128div", funcTag, 111},
|
||||||
{"racefuncenter", funcTag, 111},
|
{"racefuncenter", funcTag, 112},
|
||||||
{"racefuncenterfp", funcTag, 5},
|
{"racefuncenterfp", funcTag, 5},
|
||||||
{"racefuncexit", funcTag, 5},
|
{"racefuncexit", funcTag, 5},
|
||||||
{"raceread", funcTag, 111},
|
{"raceread", funcTag, 112},
|
||||||
{"racewrite", funcTag, 111},
|
{"racewrite", funcTag, 112},
|
||||||
{"racereadrange", funcTag, 112},
|
{"racereadrange", funcTag, 113},
|
||||||
{"racewriterange", funcTag, 112},
|
{"racewriterange", funcTag, 113},
|
||||||
{"msanread", funcTag, 112},
|
{"msanread", funcTag, 113},
|
||||||
{"msanwrite", funcTag, 112},
|
{"msanwrite", funcTag, 113},
|
||||||
{"support_popcnt", varTag, 11},
|
{"support_popcnt", varTag, 11},
|
||||||
{"support_sse41", varTag, 11},
|
{"support_sse41", varTag, 11},
|
||||||
}
|
}
|
||||||
|
|
||||||
func runtimeTypes() []*types.Type {
|
func runtimeTypes() []*types.Type {
|
||||||
var typs [113]*types.Type
|
var typs [114]*types.Type
|
||||||
typs[0] = types.Bytetype
|
typs[0] = types.Bytetype
|
||||||
typs[1] = types.NewPtr(typs[0])
|
typs[1] = types.NewPtr(typs[0])
|
||||||
typs[2] = types.Types[TANY]
|
typs[2] = types.Types[TANY]
|
||||||
|
|
@ -208,65 +203,66 @@ func runtimeTypes() []*types.Type {
|
||||||
typs[50] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[32])}, []*Node{anonfield(typs[40]), anonfield(typs[32])})
|
typs[50] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[32])}, []*Node{anonfield(typs[40]), anonfield(typs[32])})
|
||||||
typs[51] = functype(nil, []*Node{anonfield(typs[21])}, []*Node{anonfield(typs[32])})
|
typs[51] = functype(nil, []*Node{anonfield(typs[21])}, []*Node{anonfield(typs[32])})
|
||||||
typs[52] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
|
typs[52] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
|
||||||
typs[53] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
|
typs[53] = types.Types[TUNSAFEPTR]
|
||||||
typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])})
|
typs[54] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[53])})
|
||||||
typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
|
typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
|
||||||
typs[56] = functype(nil, []*Node{anonfield(typs[1])}, nil)
|
typs[56] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])})
|
||||||
typs[57] = types.NewPtr(typs[47])
|
typs[57] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
|
||||||
typs[58] = types.Types[TUNSAFEPTR]
|
typs[58] = functype(nil, []*Node{anonfield(typs[1])}, nil)
|
||||||
typs[59] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[58]), anonfield(typs[58])}, []*Node{anonfield(typs[11])})
|
typs[59] = types.NewPtr(typs[47])
|
||||||
typs[60] = types.Types[TUINT32]
|
typs[60] = functype(nil, []*Node{anonfield(typs[59]), anonfield(typs[53]), anonfield(typs[53])}, []*Node{anonfield(typs[11])})
|
||||||
typs[61] = functype(nil, nil, []*Node{anonfield(typs[60])})
|
typs[61] = types.Types[TUINT32]
|
||||||
typs[62] = types.NewMap(typs[2], typs[2])
|
typs[62] = functype(nil, nil, []*Node{anonfield(typs[61])})
|
||||||
typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[62])})
|
typs[63] = types.NewMap(typs[2], typs[2])
|
||||||
typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[3])}, []*Node{anonfield(typs[62])})
|
typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[63])})
|
||||||
typs[65] = functype(nil, nil, []*Node{anonfield(typs[62])})
|
typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[3])}, []*Node{anonfield(typs[63])})
|
||||||
typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
|
typs[66] = functype(nil, nil, []*Node{anonfield(typs[63])})
|
||||||
typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
|
typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
|
||||||
typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
|
typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
|
||||||
typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
|
typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
|
||||||
typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
|
typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
|
||||||
typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
|
typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
|
||||||
typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, nil)
|
typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
|
||||||
typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, nil)
|
typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3])}, nil)
|
||||||
typs[74] = functype(nil, []*Node{anonfield(typs[3])}, nil)
|
typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[2])}, nil)
|
||||||
typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62])}, nil)
|
typs[75] = functype(nil, []*Node{anonfield(typs[3])}, nil)
|
||||||
typs[76] = types.NewChan(typs[2], types.Cboth)
|
typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63])}, nil)
|
||||||
typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[76])})
|
typs[77] = types.NewChan(typs[2], types.Cboth)
|
||||||
typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[76])})
|
typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[77])})
|
||||||
typs[79] = types.NewChan(typs[2], types.Crecv)
|
typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[77])})
|
||||||
typs[80] = functype(nil, []*Node{anonfield(typs[79]), anonfield(typs[3])}, nil)
|
typs[80] = types.NewChan(typs[2], types.Crecv)
|
||||||
typs[81] = functype(nil, []*Node{anonfield(typs[79]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
typs[81] = functype(nil, []*Node{anonfield(typs[80]), anonfield(typs[3])}, nil)
|
||||||
typs[82] = types.NewChan(typs[2], types.Csend)
|
typs[82] = functype(nil, []*Node{anonfield(typs[80]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||||
typs[83] = functype(nil, []*Node{anonfield(typs[82]), anonfield(typs[3])}, nil)
|
typs[83] = types.NewChan(typs[2], types.Csend)
|
||||||
typs[84] = types.NewArray(typs[0], 3)
|
typs[84] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, nil)
|
||||||
typs[85] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[84]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])})
|
typs[85] = types.NewArray(typs[0], 3)
|
||||||
typs[86] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
|
typs[86] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[85]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])})
|
||||||
typs[87] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
|
typs[87] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
|
||||||
typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
|
typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
|
||||||
typs[89] = functype(nil, []*Node{anonfield(typs[82]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
|
||||||
typs[90] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
|
typs[90] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||||
typs[91] = types.NewPtr(typs[11])
|
typs[91] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[80])}, []*Node{anonfield(typs[11])})
|
||||||
typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
|
typs[92] = types.NewPtr(typs[11])
|
||||||
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
|
typs[93] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[92]), anonfield(typs[80])}, []*Node{anonfield(typs[11])})
|
||||||
typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[58])})
|
typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
|
||||||
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[58])})
|
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[53])})
|
||||||
typs[96] = types.NewSlice(typs[2])
|
typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[53])})
|
||||||
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[96]), anonfield(typs[32])}, []*Node{anonfield(typs[96])})
|
typs[97] = types.NewSlice(typs[2])
|
||||||
typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
|
typs[98] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[97]), anonfield(typs[32])}, []*Node{anonfield(typs[97])})
|
||||||
typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil)
|
typs[99] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
|
||||||
typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])})
|
typs[100] = functype(nil, []*Node{anonfield(typs[53]), anonfield(typs[47])}, nil)
|
||||||
typs[101] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
typs[101] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])})
|
||||||
typs[102] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
|
typs[102] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||||
typs[103] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
|
typs[103] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
|
||||||
typs[104] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])})
|
typs[104] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
|
||||||
typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
|
typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])})
|
||||||
typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[60])})
|
typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
|
||||||
typs[107] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
|
typs[107] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[61])})
|
||||||
typs[108] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
|
typs[108] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
|
||||||
typs[109] = functype(nil, []*Node{anonfield(typs[60])}, []*Node{anonfield(typs[13])})
|
typs[109] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
|
||||||
typs[110] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
|
typs[110] = functype(nil, []*Node{anonfield(typs[61])}, []*Node{anonfield(typs[13])})
|
||||||
typs[111] = functype(nil, []*Node{anonfield(typs[47])}, nil)
|
typs[111] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
|
||||||
typs[112] = functype(nil, []*Node{anonfield(typs[47]), anonfield(typs[47])}, nil)
|
typs[112] = functype(nil, []*Node{anonfield(typs[47])}, nil)
|
||||||
|
typs[113] = functype(nil, []*Node{anonfield(typs[47]), anonfield(typs[47])}, nil)
|
||||||
return typs[:]
|
return typs[:]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,23 +61,23 @@ func slicestringcopy(to any, fr any) int
|
||||||
func decoderune(string, int) (retv rune, retk int)
|
func decoderune(string, int) (retv rune, retk int)
|
||||||
func countrunes(string) int
|
func countrunes(string) int
|
||||||
|
|
||||||
// interface conversions
|
// Non-empty-interface to non-empty-interface conversion.
|
||||||
func convI2I(typ *byte, elem any) (ret any)
|
func convI2I(typ *byte, elem any) (ret any)
|
||||||
|
|
||||||
|
// Specialized type-to-interface conversion.
|
||||||
|
// These return only a data pointer.
|
||||||
|
func convT16(val any) unsafe.Pointer // val must be uint16-like (same size and alignment as a uint16)
|
||||||
|
func convT32(val any) unsafe.Pointer // val must be uint32-like (same size and alignment as a uint32)
|
||||||
|
func convT64(val any) unsafe.Pointer // val must be uint64-like (same size and alignment as a uint64 and contains no pointers)
|
||||||
|
func convTstring(val any) unsafe.Pointer // val must be a string
|
||||||
|
func convTslice(val any) unsafe.Pointer // val must be a slice
|
||||||
|
|
||||||
|
// Type to empty-interface conversion.
|
||||||
func convT2E(typ *byte, elem *any) (ret any)
|
func convT2E(typ *byte, elem *any) (ret any)
|
||||||
func convT2E16(typ *byte, val any) (ret any)
|
|
||||||
func convT2E32(typ *byte, val any) (ret any)
|
|
||||||
func convT2E64(typ *byte, val any) (ret any)
|
|
||||||
func convT2Estring(typ *byte, val any) (ret any) // val must be a string
|
|
||||||
func convT2Eslice(typ *byte, val any) (ret any) // val must be a slice
|
|
||||||
func convT2Enoptr(typ *byte, elem *any) (ret any)
|
func convT2Enoptr(typ *byte, elem *any) (ret any)
|
||||||
|
|
||||||
|
// Type to non-empty-interface conversion.
|
||||||
func convT2I(tab *byte, elem *any) (ret any)
|
func convT2I(tab *byte, elem *any) (ret any)
|
||||||
func convT2I16(tab *byte, val any) (ret any)
|
|
||||||
func convT2I32(tab *byte, val any) (ret any)
|
|
||||||
func convT2I64(tab *byte, val any) (ret any)
|
|
||||||
func convT2Istring(tab *byte, val any) (ret any) // val must be a string
|
|
||||||
func convT2Islice(tab *byte, val any) (ret any) // val must be a slice
|
|
||||||
func convT2Inoptr(tab *byte, elem *any) (ret any)
|
func convT2Inoptr(tab *byte, elem *any) (ret any)
|
||||||
|
|
||||||
// interface type assertions x.(T)
|
// interface type assertions x.(T)
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@ func transformclosure(xfunc *Node) {
|
||||||
lineno = lno
|
lineno = lno
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasemptycvars returns true iff closure clo has an
|
// hasemptycvars reports whether closure clo has an
|
||||||
// empty list of captured vars.
|
// empty list of captured vars.
|
||||||
func hasemptycvars(clo *Node) bool {
|
func hasemptycvars(clo *Node) bool {
|
||||||
xfunc := clo.Func.Closure
|
xfunc := clo.Func.Closure
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,7 @@ func beginRange(calls []dwarf.InlCall, p *obj.Prog, ii int, imap map[int]int) *d
|
||||||
}
|
}
|
||||||
callIdx, found := imap[ii]
|
callIdx, found := imap[ii]
|
||||||
if !found {
|
if !found {
|
||||||
Fatalf("internal error: can't find inlIndex %d in imap for prog at %d\n", ii, p.Pc)
|
Fatalf("can't find inlIndex %d in imap for prog at %d\n", ii, p.Pc)
|
||||||
}
|
}
|
||||||
call := &calls[callIdx]
|
call := &calls[callIdx]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1114,6 +1114,7 @@ var opprec = []int{
|
||||||
OSLICEARR: 8,
|
OSLICEARR: 8,
|
||||||
OSLICE3: 8,
|
OSLICE3: 8,
|
||||||
OSLICE3ARR: 8,
|
OSLICE3ARR: 8,
|
||||||
|
OSLICEHEADER: 8,
|
||||||
ODOTINTER: 8,
|
ODOTINTER: 8,
|
||||||
ODOTMETH: 8,
|
ODOTMETH: 8,
|
||||||
ODOTPTR: 8,
|
ODOTPTR: 8,
|
||||||
|
|
@ -1393,6 +1394,12 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
||||||
}
|
}
|
||||||
fmt.Fprint(s, "]")
|
fmt.Fprint(s, "]")
|
||||||
|
|
||||||
|
case OSLICEHEADER:
|
||||||
|
if n.List.Len() != 2 {
|
||||||
|
Fatalf("bad OSLICEHEADER list length %d", n.List.Len())
|
||||||
|
}
|
||||||
|
mode.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left, n.List.First(), n.List.Second())
|
||||||
|
|
||||||
case OCOPY, OCOMPLEX:
|
case OCOPY, OCOMPLEX:
|
||||||
mode.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right)
|
mode.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,6 @@ var asmhdr string
|
||||||
var simtype [NTYPE]types.EType
|
var simtype [NTYPE]types.EType
|
||||||
|
|
||||||
var (
|
var (
|
||||||
isforw [NTYPE]bool
|
|
||||||
isInt [NTYPE]bool
|
isInt [NTYPE]bool
|
||||||
isFloat [NTYPE]bool
|
isFloat [NTYPE]bool
|
||||||
isComplex [NTYPE]bool
|
isComplex [NTYPE]bool
|
||||||
|
|
|
||||||
|
|
@ -185,24 +185,6 @@ func (pp *Progs) settext(fn *Node) {
|
||||||
ptxt.From.Type = obj.TYPE_MEM
|
ptxt.From.Type = obj.TYPE_MEM
|
||||||
ptxt.From.Name = obj.NAME_EXTERN
|
ptxt.From.Name = obj.NAME_EXTERN
|
||||||
ptxt.From.Sym = fn.Func.lsym
|
ptxt.From.Sym = fn.Func.lsym
|
||||||
|
|
||||||
p := pp.Prog(obj.AFUNCDATA)
|
|
||||||
Addrconst(&p.From, objabi.FUNCDATA_ArgsPointerMaps)
|
|
||||||
p.To.Type = obj.TYPE_MEM
|
|
||||||
p.To.Name = obj.NAME_EXTERN
|
|
||||||
p.To.Sym = &fn.Func.lsym.Func.GCArgs
|
|
||||||
|
|
||||||
p = pp.Prog(obj.AFUNCDATA)
|
|
||||||
Addrconst(&p.From, objabi.FUNCDATA_LocalsPointerMaps)
|
|
||||||
p.To.Type = obj.TYPE_MEM
|
|
||||||
p.To.Name = obj.NAME_EXTERN
|
|
||||||
p.To.Sym = &fn.Func.lsym.Func.GCLocals
|
|
||||||
|
|
||||||
p = pp.Prog(obj.AFUNCDATA)
|
|
||||||
Addrconst(&p.From, objabi.FUNCDATA_RegPointerMaps)
|
|
||||||
p.To.Type = obj.TYPE_MEM
|
|
||||||
p.To.Name = obj.NAME_EXTERN
|
|
||||||
p.To.Sym = &fn.Func.lsym.Func.GCRegs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Func) initLSym() {
|
func (f *Func) initLSym() {
|
||||||
|
|
|
||||||
|
|
@ -909,7 +909,7 @@ func (w *exportWriter) mpfloat(f *big.Float, typ *types.Type) {
|
||||||
|
|
||||||
manti, acc := mant.Int(nil)
|
manti, acc := mant.Int(nil)
|
||||||
if acc != big.Exact {
|
if acc != big.Exact {
|
||||||
Fatalf("exporter: internal error")
|
Fatalf("mantissa scaling failed for %f (%s)", f, acc)
|
||||||
}
|
}
|
||||||
w.mpint(manti, typ)
|
w.mpint(manti, typ)
|
||||||
if manti.Sign() != 0 {
|
if manti.Sign() != 0 {
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@ import (
|
||||||
const (
|
const (
|
||||||
inlineMaxBudget = 80
|
inlineMaxBudget = 80
|
||||||
inlineExtraAppendCost = 0
|
inlineExtraAppendCost = 0
|
||||||
inlineExtraCallCost = inlineMaxBudget // default is do not inline, -l=4 enables by using 1 instead.
|
// default is to inline if there's at most one call. -l=4 overrides this by using 1 instead.
|
||||||
|
inlineExtraCallCost = inlineMaxBudget * 3 / 4
|
||||||
inlineExtraPanicCost = 1 // do not penalize inlining panics.
|
inlineExtraPanicCost = 1 // do not penalize inlining panics.
|
||||||
inlineExtraThrowCost = inlineMaxBudget // with current (2018-05/1.11) code, inlining runtime.throw does not help.
|
inlineExtraThrowCost = inlineMaxBudget // with current (2018-05/1.11) code, inlining runtime.throw does not help.
|
||||||
|
|
||||||
|
|
@ -141,6 +142,13 @@ func caninl(fn *Node) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If marked as "go:uintptrescapes", don't inline, since the
|
||||||
|
// escape information is lost during inlining.
|
||||||
|
if fn.Func.Pragma&UintptrEscapes != 0 {
|
||||||
|
reason = "marked as having an escaping uintptr argument"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// The nowritebarrierrec checker currently works at function
|
// The nowritebarrierrec checker currently works at function
|
||||||
// granularity, so inlining yeswritebarrierrec functions can
|
// granularity, so inlining yeswritebarrierrec functions can
|
||||||
// confuse it (#22342). As a workaround, disallow inlining
|
// confuse it (#22342). As a workaround, disallow inlining
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ func TestIntendedInlining(t *testing.T) {
|
||||||
"isDirectIface",
|
"isDirectIface",
|
||||||
"itabHashFunc",
|
"itabHashFunc",
|
||||||
"noescape",
|
"noescape",
|
||||||
|
"pcvalueCacheKey",
|
||||||
"readUnaligned32",
|
"readUnaligned32",
|
||||||
"readUnaligned64",
|
"readUnaligned64",
|
||||||
"releasem",
|
"releasem",
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,14 @@ func (p *noder) pragcgo(pos syntax.Pos, text string) {
|
||||||
case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]):
|
case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]):
|
||||||
case len(f) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(f[3]):
|
case len(f) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(f[3]):
|
||||||
f[3] = strings.Trim(f[3], `"`)
|
f[3] = strings.Trim(f[3], `"`)
|
||||||
|
if objabi.GOOS == "aix" && f[3] != "" {
|
||||||
|
// On Aix, library pattern must be "lib.a/object.o"
|
||||||
|
n := strings.Split(f[3], "/")
|
||||||
|
if len(n) != 2 || !strings.HasSuffix(n[0], ".a") || !strings.HasSuffix(n[1], ".o") {
|
||||||
|
p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["lib.a/object.o"]]`})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`})
|
p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`})
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package gc
|
||||||
import (
|
import (
|
||||||
"cmd/compile/internal/syntax"
|
"cmd/compile/internal/syntax"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -49,10 +50,12 @@ func TestPragmaFields(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPragcgo(t *testing.T) {
|
func TestPragcgo(t *testing.T) {
|
||||||
var tests = []struct {
|
type testStruct struct {
|
||||||
in string
|
in string
|
||||||
want []string
|
want []string
|
||||||
}{
|
}
|
||||||
|
|
||||||
|
var tests = []testStruct{
|
||||||
{`go:cgo_export_dynamic local`, []string{`cgo_export_dynamic`, `local`}},
|
{`go:cgo_export_dynamic local`, []string{`cgo_export_dynamic`, `local`}},
|
||||||
{`go:cgo_export_dynamic local remote`, []string{`cgo_export_dynamic`, `local`, `remote`}},
|
{`go:cgo_export_dynamic local remote`, []string{`cgo_export_dynamic`, `local`, `remote`}},
|
||||||
{`go:cgo_export_dynamic local' remote'`, []string{`cgo_export_dynamic`, `local'`, `remote'`}},
|
{`go:cgo_export_dynamic local' remote'`, []string{`cgo_export_dynamic`, `local'`, `remote'`}},
|
||||||
|
|
@ -61,8 +64,6 @@ func TestPragcgo(t *testing.T) {
|
||||||
{`go:cgo_export_static local' remote'`, []string{`cgo_export_static`, `local'`, `remote'`}},
|
{`go:cgo_export_static local' remote'`, []string{`cgo_export_static`, `local'`, `remote'`}},
|
||||||
{`go:cgo_import_dynamic local`, []string{`cgo_import_dynamic`, `local`}},
|
{`go:cgo_import_dynamic local`, []string{`cgo_import_dynamic`, `local`}},
|
||||||
{`go:cgo_import_dynamic local remote`, []string{`cgo_import_dynamic`, `local`, `remote`}},
|
{`go:cgo_import_dynamic local remote`, []string{`cgo_import_dynamic`, `local`, `remote`}},
|
||||||
{`go:cgo_import_dynamic local remote "library"`, []string{`cgo_import_dynamic`, `local`, `remote`, `library`}},
|
|
||||||
{`go:cgo_import_dynamic local' remote' "lib rary"`, []string{`cgo_import_dynamic`, `local'`, `remote'`, `lib rary`}},
|
|
||||||
{`go:cgo_import_static local`, []string{`cgo_import_static`, `local`}},
|
{`go:cgo_import_static local`, []string{`cgo_import_static`, `local`}},
|
||||||
{`go:cgo_import_static local'`, []string{`cgo_import_static`, `local'`}},
|
{`go:cgo_import_static local'`, []string{`cgo_import_static`, `local'`}},
|
||||||
{`go:cgo_dynamic_linker "/path/"`, []string{`cgo_dynamic_linker`, `/path/`}},
|
{`go:cgo_dynamic_linker "/path/"`, []string{`cgo_dynamic_linker`, `/path/`}},
|
||||||
|
|
@ -71,17 +72,50 @@ func TestPragcgo(t *testing.T) {
|
||||||
{`go:cgo_ldflag "a rg"`, []string{`cgo_ldflag`, `a rg`}},
|
{`go:cgo_ldflag "a rg"`, []string{`cgo_ldflag`, `a rg`}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS != "aix" {
|
||||||
|
tests = append(tests, []testStruct{
|
||||||
|
{`go:cgo_import_dynamic local remote "library"`, []string{`cgo_import_dynamic`, `local`, `remote`, `library`}},
|
||||||
|
{`go:cgo_import_dynamic local' remote' "lib rary"`, []string{`cgo_import_dynamic`, `local'`, `remote'`, `lib rary`}},
|
||||||
|
}...)
|
||||||
|
} else {
|
||||||
|
// cgo_import_dynamic with a library is slightly different on AIX
|
||||||
|
// as the library field must follow the pattern [libc.a/object.o].
|
||||||
|
tests = append(tests, []testStruct{
|
||||||
|
{`go:cgo_import_dynamic local remote "lib.a/obj.o"`, []string{`cgo_import_dynamic`, `local`, `remote`, `lib.a/obj.o`}},
|
||||||
|
// This test must fail.
|
||||||
|
{`go:cgo_import_dynamic local' remote' "library"`, []string{`<unknown position>: usage: //go:cgo_import_dynamic local [remote ["lib.a/object.o"]]`}},
|
||||||
|
}...)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
var p noder
|
var p noder
|
||||||
var nopos syntax.Pos
|
var nopos syntax.Pos
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
||||||
|
p.err = make(chan syntax.Error)
|
||||||
|
gotch := make(chan [][]string)
|
||||||
|
go func() {
|
||||||
p.pragcgobuf = nil
|
p.pragcgobuf = nil
|
||||||
p.pragcgo(nopos, tt.in)
|
p.pragcgo(nopos, tt.in)
|
||||||
|
if p.pragcgobuf != nil {
|
||||||
|
gotch <- p.pragcgobuf
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
got := p.pragcgobuf
|
select {
|
||||||
|
case e := <-p.err:
|
||||||
|
want := tt.want[0]
|
||||||
|
if e.Error() != want {
|
||||||
|
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, e, want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case got := <-gotch:
|
||||||
want := [][]string{tt.want}
|
want := [][]string{tt.want}
|
||||||
if !reflect.DeepEqual(got, want) {
|
if !reflect.DeepEqual(got, want) {
|
||||||
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, got, want)
|
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, got, want)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,9 @@ func Main(archInit func(*Arch)) {
|
||||||
flag.BoolVar(&flag_race, "race", false, "enable race detector")
|
flag.BoolVar(&flag_race, "race", false, "enable race detector")
|
||||||
}
|
}
|
||||||
objabi.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s'])
|
objabi.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s'])
|
||||||
|
if enableTrace {
|
||||||
|
flag.BoolVar(&trace, "t", false, "trace type-checking")
|
||||||
|
}
|
||||||
flag.StringVar(&pathPrefix, "trimpath", "", "remove `prefix` from recorded source file paths")
|
flag.StringVar(&pathPrefix, "trimpath", "", "remove `prefix` from recorded source file paths")
|
||||||
flag.BoolVar(&Debug_vlog, "v", false, "increase debug verbosity")
|
flag.BoolVar(&Debug_vlog, "v", false, "increase debug verbosity")
|
||||||
objabi.Flagcount("w", "debug type checking", &Debug['w'])
|
objabi.Flagcount("w", "debug type checking", &Debug['w'])
|
||||||
|
|
@ -488,13 +491,17 @@ func Main(archInit func(*Arch)) {
|
||||||
// Phase 1: const, type, and names and types of funcs.
|
// Phase 1: const, type, and names and types of funcs.
|
||||||
// This will gather all the information about types
|
// This will gather all the information about types
|
||||||
// and methods but doesn't depend on any of it.
|
// and methods but doesn't depend on any of it.
|
||||||
|
//
|
||||||
|
// We also defer type alias declarations until phase 2
|
||||||
|
// to avoid cycles like #18640.
|
||||||
|
// TODO(gri) Remove this again once we have a fix for #25838.
|
||||||
defercheckwidth()
|
defercheckwidth()
|
||||||
|
|
||||||
// Don't use range--typecheck can add closures to xtop.
|
// Don't use range--typecheck can add closures to xtop.
|
||||||
timings.Start("fe", "typecheck", "top1")
|
timings.Start("fe", "typecheck", "top1")
|
||||||
for i := 0; i < len(xtop); i++ {
|
for i := 0; i < len(xtop); i++ {
|
||||||
n := xtop[i]
|
n := xtop[i]
|
||||||
if op := n.Op; op != ODCL && op != OAS && op != OAS2 {
|
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
|
||||||
xtop[i] = typecheck(n, Etop)
|
xtop[i] = typecheck(n, Etop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -506,7 +513,7 @@ func Main(archInit func(*Arch)) {
|
||||||
timings.Start("fe", "typecheck", "top2")
|
timings.Start("fe", "typecheck", "top2")
|
||||||
for i := 0; i < len(xtop); i++ {
|
for i := 0; i < len(xtop); i++ {
|
||||||
n := xtop[i]
|
n := xtop[i]
|
||||||
if op := n.Op; op == ODCL || op == OAS || op == OAS2 {
|
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
|
||||||
xtop[i] = typecheck(n, Etop)
|
xtop[i] = typecheck(n, Etop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -273,22 +273,18 @@ func dumpglobls() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.
|
// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.
|
||||||
// It takes care not to add any duplicates.
|
//
|
||||||
// Though the object file format handles duplicates efficiently,
|
// This is done during the sequential phase after compilation, since
|
||||||
// storing only a single copy of the data,
|
// global symbols can't be declared during parallel compilation.
|
||||||
// failure to remove these duplicates adds a few percent to object file size.
|
|
||||||
func addGCLocals() {
|
func addGCLocals() {
|
||||||
seen := make(map[string]bool)
|
|
||||||
for _, s := range Ctxt.Text {
|
for _, s := range Ctxt.Text {
|
||||||
if s.Func == nil {
|
if s.Func == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, gcsym := range []*obj.LSym{&s.Func.GCArgs, &s.Func.GCLocals, &s.Func.GCRegs} {
|
for _, gcsym := range []*obj.LSym{s.Func.GCArgs, s.Func.GCLocals, s.Func.GCRegs} {
|
||||||
if seen[gcsym.Name] {
|
if gcsym != nil && !gcsym.OnList() {
|
||||||
continue
|
ggloblsym(gcsym, int32(len(gcsym.P)), obj.RODATA|obj.DUPOK)
|
||||||
}
|
}
|
||||||
Ctxt.Data = append(Ctxt.Data, gcsym)
|
|
||||||
seen[gcsym.Name] = true
|
|
||||||
}
|
}
|
||||||
if x := s.Func.StackObjects; x != nil {
|
if x := s.Func.StackObjects; x != nil {
|
||||||
ggloblsym(x, int32(len(x.P)), obj.RODATA|obj.LOCAL)
|
ggloblsym(x, int32(len(x.P)), obj.RODATA|obj.LOCAL)
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ package gc
|
||||||
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICEHEADERSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
|
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
|
||||||
|
|
||||||
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 555, 561, 570, 577, 581, 588, 595, 603, 607, 611, 615, 622, 629, 637, 643, 648, 653, 657, 662, 670, 675, 680, 684, 687, 695, 699, 701, 706, 710, 715, 721, 727, 733, 739, 744, 748, 755, 761, 766, 772, 775, 781, 788, 793, 797, 802, 806, 816, 821, 829, 835, 842, 849, 857, 863, 867, 870}
|
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 550, 559, 570, 577, 581, 588, 595, 603, 607, 611, 615, 622, 629, 637, 643, 648, 653, 657, 662, 670, 675, 680, 684, 687, 695, 699, 701, 706, 710, 715, 721, 727, 733, 739, 744, 748, 755, 761, 766, 772, 775, 781, 788, 793, 797, 802, 806, 816, 821, 829, 835, 842, 849, 857, 863, 867, 870}
|
||||||
|
|
||||||
func (i Op) String() string {
|
func (i Op) String() string {
|
||||||
if i >= Op(len(_Op_index)-1) {
|
if i >= Op(len(_Op_index)-1) {
|
||||||
|
|
|
||||||
|
|
@ -1019,7 +1019,7 @@ func (lv *Liveness) epilogue() {
|
||||||
live := lv.livevars[index]
|
live := lv.livevars[index]
|
||||||
if v.Op.IsCall() && live.regs != 0 {
|
if v.Op.IsCall() && live.regs != 0 {
|
||||||
lv.printDebug()
|
lv.printDebug()
|
||||||
v.Fatalf("internal error: %v register %s recorded as live at call", lv.fn.Func.Nname, live.regs.niceString(lv.f.Config))
|
v.Fatalf("%v register %s recorded as live at call", lv.fn.Func.Nname, live.regs.niceString(lv.f.Config))
|
||||||
}
|
}
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
|
|
@ -1038,7 +1038,7 @@ func (lv *Liveness) epilogue() {
|
||||||
// input parameters.
|
// input parameters.
|
||||||
for j, n := range lv.vars {
|
for j, n := range lv.vars {
|
||||||
if n.Class() != PPARAM && lv.stackMaps[0].Get(int32(j)) {
|
if n.Class() != PPARAM && lv.stackMaps[0].Get(int32(j)) {
|
||||||
Fatalf("internal error: %v %L recorded as live on entry", lv.fn.Func.Nname, n)
|
lv.f.Fatalf("%v %L recorded as live on entry", lv.fn.Func.Nname, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check that no registers are live at function entry.
|
// Check that no registers are live at function entry.
|
||||||
|
|
@ -1047,7 +1047,7 @@ func (lv *Liveness) epilogue() {
|
||||||
// so it doesn't appear live at entry.
|
// so it doesn't appear live at entry.
|
||||||
if regs := lv.regMaps[0]; regs != 0 {
|
if regs := lv.regMaps[0]; regs != 0 {
|
||||||
lv.printDebug()
|
lv.printDebug()
|
||||||
lv.f.Fatalf("internal error: %v register %s recorded as live on entry", lv.fn.Func.Nname, regs.niceString(lv.f.Config))
|
lv.f.Fatalf("%v register %s recorded as live on entry", lv.fn.Func.Nname, regs.niceString(lv.f.Config))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1461,7 +1461,7 @@ func (lv *Liveness) printDebug() {
|
||||||
// first word dumped is the total number of bitmaps. The second word is the
|
// first word dumped is the total number of bitmaps. The second word is the
|
||||||
// length of the bitmaps. All bitmaps are assumed to be of equal length. The
|
// length of the bitmaps. All bitmaps are assumed to be of equal length. The
|
||||||
// remaining bytes are the raw bitmaps.
|
// remaining bytes are the raw bitmaps.
|
||||||
func (lv *Liveness) emit(argssym, livesym, regssym *obj.LSym) {
|
func (lv *Liveness) emit() (argsSym, liveSym, regsSym *obj.LSym) {
|
||||||
// Size args bitmaps to be just large enough to hold the largest pointer.
|
// Size args bitmaps to be just large enough to hold the largest pointer.
|
||||||
// First, find the largest Xoffset node we care about.
|
// First, find the largest Xoffset node we care about.
|
||||||
// (Nodes without pointers aren't in lv.vars; see livenessShouldTrack.)
|
// (Nodes without pointers aren't in lv.vars; see livenessShouldTrack.)
|
||||||
|
|
@ -1489,13 +1489,16 @@ func (lv *Liveness) emit(argssym, livesym, regssym *obj.LSym) {
|
||||||
// This would require shifting all bitmaps.
|
// This would require shifting all bitmaps.
|
||||||
maxLocals := lv.stkptrsize
|
maxLocals := lv.stkptrsize
|
||||||
|
|
||||||
|
// Temporary symbols for encoding bitmaps.
|
||||||
|
var argsSymTmp, liveSymTmp, regsSymTmp obj.LSym
|
||||||
|
|
||||||
args := bvalloc(int32(maxArgs / int64(Widthptr)))
|
args := bvalloc(int32(maxArgs / int64(Widthptr)))
|
||||||
aoff := duint32(argssym, 0, uint32(len(lv.stackMaps))) // number of bitmaps
|
aoff := duint32(&argsSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
|
||||||
aoff = duint32(argssym, aoff, uint32(args.n)) // number of bits in each bitmap
|
aoff = duint32(&argsSymTmp, aoff, uint32(args.n)) // number of bits in each bitmap
|
||||||
|
|
||||||
locals := bvalloc(int32(maxLocals / int64(Widthptr)))
|
locals := bvalloc(int32(maxLocals / int64(Widthptr)))
|
||||||
loff := duint32(livesym, 0, uint32(len(lv.stackMaps))) // number of bitmaps
|
loff := duint32(&liveSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
|
||||||
loff = duint32(livesym, loff, uint32(locals.n)) // number of bits in each bitmap
|
loff = duint32(&liveSymTmp, loff, uint32(locals.n)) // number of bits in each bitmap
|
||||||
|
|
||||||
for _, live := range lv.stackMaps {
|
for _, live := range lv.stackMaps {
|
||||||
args.Clear()
|
args.Clear()
|
||||||
|
|
@ -1503,13 +1506,13 @@ func (lv *Liveness) emit(argssym, livesym, regssym *obj.LSym) {
|
||||||
|
|
||||||
lv.pointerMap(live, lv.vars, args, locals)
|
lv.pointerMap(live, lv.vars, args, locals)
|
||||||
|
|
||||||
aoff = dbvec(argssym, aoff, args)
|
aoff = dbvec(&argsSymTmp, aoff, args)
|
||||||
loff = dbvec(livesym, loff, locals)
|
loff = dbvec(&liveSymTmp, loff, locals)
|
||||||
}
|
}
|
||||||
|
|
||||||
regs := bvalloc(lv.usedRegs())
|
regs := bvalloc(lv.usedRegs())
|
||||||
roff := duint32(regssym, 0, uint32(len(lv.regMaps))) // number of bitmaps
|
roff := duint32(®sSymTmp, 0, uint32(len(lv.regMaps))) // number of bitmaps
|
||||||
roff = duint32(regssym, roff, uint32(regs.n)) // number of bits in each bitmap
|
roff = duint32(®sSymTmp, roff, uint32(regs.n)) // number of bits in each bitmap
|
||||||
if regs.n > 32 {
|
if regs.n > 32 {
|
||||||
// Our uint32 conversion below won't work.
|
// Our uint32 conversion below won't work.
|
||||||
Fatalf("GP registers overflow uint32")
|
Fatalf("GP registers overflow uint32")
|
||||||
|
|
@ -1519,25 +1522,29 @@ func (lv *Liveness) emit(argssym, livesym, regssym *obj.LSym) {
|
||||||
for _, live := range lv.regMaps {
|
for _, live := range lv.regMaps {
|
||||||
regs.Clear()
|
regs.Clear()
|
||||||
regs.b[0] = uint32(live)
|
regs.b[0] = uint32(live)
|
||||||
roff = dbvec(regssym, roff, regs)
|
roff = dbvec(®sSymTmp, roff, regs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give these LSyms content-addressable names,
|
// Give these LSyms content-addressable names,
|
||||||
// so that they can be de-duplicated.
|
// so that they can be de-duplicated.
|
||||||
// This provides significant binary size savings.
|
// This provides significant binary size savings.
|
||||||
// It is safe to rename these LSyms because
|
//
|
||||||
// they are tracked separately from ctxt.hash.
|
// These symbols will be added to Ctxt.Data by addGCLocals
|
||||||
argssym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(argssym.P))
|
// after parallel compilation is done.
|
||||||
livesym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(livesym.P))
|
makeSym := func(tmpSym *obj.LSym) *obj.LSym {
|
||||||
regssym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(regssym.P))
|
return Ctxt.LookupInit(fmt.Sprintf("gclocals·%x", md5.Sum(tmpSym.P)), func(lsym *obj.LSym) {
|
||||||
|
lsym.P = tmpSym.P
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return makeSym(&argsSymTmp), makeSym(&liveSymTmp), makeSym(®sSymTmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entry pointer for liveness analysis. Solves for the liveness of
|
// Entry pointer for liveness analysis. Solves for the liveness of
|
||||||
// pointer variables in the function and emits a runtime data
|
// pointer variables in the function and emits a runtime data
|
||||||
// structure read by the garbage collector.
|
// structure read by the garbage collector.
|
||||||
// Returns a map from GC safe points to their corresponding stack map index.
|
// Returns a map from GC safe points to their corresponding stack map index.
|
||||||
func liveness(e *ssafn, f *ssa.Func) LivenessMap {
|
func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap {
|
||||||
// Construct the global liveness state.
|
// Construct the global liveness state.
|
||||||
vars, idx := getvariables(e.curfn)
|
vars, idx := getvariables(e.curfn)
|
||||||
lv := newliveness(e.curfn, f, vars, idx, e.stkptrsize)
|
lv := newliveness(e.curfn, f, vars, idx, e.stkptrsize)
|
||||||
|
|
@ -1577,7 +1584,25 @@ func liveness(e *ssafn, f *ssa.Func) LivenessMap {
|
||||||
|
|
||||||
// Emit the live pointer map data structures
|
// Emit the live pointer map data structures
|
||||||
if ls := e.curfn.Func.lsym; ls != nil {
|
if ls := e.curfn.Func.lsym; ls != nil {
|
||||||
lv.emit(&ls.Func.GCArgs, &ls.Func.GCLocals, &ls.Func.GCRegs)
|
ls.Func.GCArgs, ls.Func.GCLocals, ls.Func.GCRegs = lv.emit()
|
||||||
|
|
||||||
|
p := pp.Prog(obj.AFUNCDATA)
|
||||||
|
Addrconst(&p.From, objabi.FUNCDATA_ArgsPointerMaps)
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Name = obj.NAME_EXTERN
|
||||||
|
p.To.Sym = ls.Func.GCArgs
|
||||||
|
|
||||||
|
p = pp.Prog(obj.AFUNCDATA)
|
||||||
|
Addrconst(&p.From, objabi.FUNCDATA_LocalsPointerMaps)
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Name = obj.NAME_EXTERN
|
||||||
|
p.To.Sym = ls.Func.GCLocals
|
||||||
|
|
||||||
|
p = pp.Prog(obj.AFUNCDATA)
|
||||||
|
Addrconst(&p.From, objabi.FUNCDATA_RegPointerMaps)
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Name = obj.NAME_EXTERN
|
||||||
|
p.To.Sym = ls.Func.GCRegs
|
||||||
}
|
}
|
||||||
return lv.livenessMap
|
return lv.livenessMap
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -812,7 +812,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
|
||||||
|
|
||||||
sptrWeak := true
|
sptrWeak := true
|
||||||
var sptr *obj.LSym
|
var sptr *obj.LSym
|
||||||
if !t.IsPtr() || t.PtrBase != nil {
|
if !t.IsPtr() || t.IsPtrElem() {
|
||||||
tptr := types.NewPtr(t)
|
tptr := types.NewPtr(t)
|
||||||
if t.Sym != nil || methods(tptr) != nil {
|
if t.Sym != nil || methods(tptr) != nil {
|
||||||
sptrWeak = false
|
sptrWeak = false
|
||||||
|
|
@ -1137,7 +1137,7 @@ func dtypesym(t *types.Type) *obj.LSym {
|
||||||
return lsym
|
return lsym
|
||||||
}
|
}
|
||||||
// TODO(mdempsky): Investigate whether this can happen.
|
// TODO(mdempsky): Investigate whether this can happen.
|
||||||
if isforw[tbase.Etype] {
|
if tbase.Etype == TFORW {
|
||||||
return lsym
|
return lsym
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5051,7 +5051,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
||||||
|
|
||||||
e := f.Frontend().(*ssafn)
|
e := f.Frontend().(*ssafn)
|
||||||
|
|
||||||
s.livenessMap = liveness(e, f)
|
s.livenessMap = liveness(e, f, pp)
|
||||||
emitStackObjects(e, pp)
|
emitStackObjects(e, pp)
|
||||||
|
|
||||||
// Remember where each block starts.
|
// Remember where each block starts.
|
||||||
|
|
|
||||||
|
|
@ -929,7 +929,7 @@ type nodeQueue struct {
|
||||||
head, tail int
|
head, tail int
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty returns true if q contains no Nodes.
|
// empty reports whether q contains no Nodes.
|
||||||
func (q *nodeQueue) empty() bool {
|
func (q *nodeQueue) empty() bool {
|
||||||
return q.head == q.tail
|
return q.head == q.tail
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,50 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// To enable tracing support (-t flag), set enableTrace to true.
|
||||||
|
const enableTrace = false
|
||||||
|
|
||||||
|
var trace bool
|
||||||
|
var traceIndent []byte
|
||||||
|
|
||||||
|
func tracePrint(title string, n *Node) func(np **Node) {
|
||||||
|
indent := traceIndent
|
||||||
|
|
||||||
|
// guard against nil
|
||||||
|
var pos, op string
|
||||||
|
var tc uint8
|
||||||
|
if n != nil {
|
||||||
|
pos = linestr(n.Pos)
|
||||||
|
op = n.Op.String()
|
||||||
|
tc = n.Typecheck()
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s: %s%s %p %s %v tc=%d\n", pos, indent, title, n, op, n, tc)
|
||||||
|
traceIndent = append(traceIndent, ". "...)
|
||||||
|
|
||||||
|
return func(np **Node) {
|
||||||
|
traceIndent = traceIndent[:len(traceIndent)-2]
|
||||||
|
|
||||||
|
// if we have a result, use that
|
||||||
|
if np != nil {
|
||||||
|
n = *np
|
||||||
|
}
|
||||||
|
|
||||||
|
// guard against nil
|
||||||
|
// use outer pos, op so we don't get empty pos/op if n == nil (nicer output)
|
||||||
|
var tc uint8
|
||||||
|
var typ *types.Type
|
||||||
|
if n != nil {
|
||||||
|
pos = linestr(n.Pos)
|
||||||
|
op = n.Op.String()
|
||||||
|
tc = n.Typecheck()
|
||||||
|
typ = n.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s: %s=> %p %s %v tc=%d type=%#L\n", pos, indent, n, op, n, tc, typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Etop = 1 << iota // evaluated at statement level
|
Etop = 1 << iota // evaluated at statement level
|
||||||
Erv // evaluated in value context
|
Erv // evaluated in value context
|
||||||
|
|
@ -31,11 +75,16 @@ const (
|
||||||
var typecheckdefstack []*Node
|
var typecheckdefstack []*Node
|
||||||
|
|
||||||
// resolve ONONAME to definition, if any.
|
// resolve ONONAME to definition, if any.
|
||||||
func resolve(n *Node) *Node {
|
func resolve(n *Node) (res *Node) {
|
||||||
if n == nil || n.Op != ONONAME {
|
if n == nil || n.Op != ONONAME {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only trace if there's work to do
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("resolve", n)(&res)
|
||||||
|
}
|
||||||
|
|
||||||
if n.Sym.Pkg != localpkg {
|
if n.Sym.Pkg != localpkg {
|
||||||
if inimport {
|
if inimport {
|
||||||
Fatalf("recursive inimport")
|
Fatalf("recursive inimport")
|
||||||
|
|
@ -150,7 +199,7 @@ var typecheck_tcstack []*Node
|
||||||
// typecheck type checks node n.
|
// typecheck type checks node n.
|
||||||
// The result of typecheck MUST be assigned back to n, e.g.
|
// The result of typecheck MUST be assigned back to n, e.g.
|
||||||
// n.Left = typecheck(n.Left, top)
|
// n.Left = typecheck(n.Left, top)
|
||||||
func typecheck(n *Node, top int) *Node {
|
func typecheck(n *Node, top int) (res *Node) {
|
||||||
// cannot type check until all the source has been parsed
|
// cannot type check until all the source has been parsed
|
||||||
if !typecheckok {
|
if !typecheckok {
|
||||||
Fatalf("early typecheck")
|
Fatalf("early typecheck")
|
||||||
|
|
@ -160,6 +209,11 @@ func typecheck(n *Node, top int) *Node {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only trace if there's work to do
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheck", n)(&res)
|
||||||
|
}
|
||||||
|
|
||||||
lno := setlineno(n)
|
lno := setlineno(n)
|
||||||
|
|
||||||
// Skip over parens.
|
// Skip over parens.
|
||||||
|
|
@ -201,8 +255,16 @@ func typecheck(n *Node, top int) *Node {
|
||||||
// since it would expand indefinitely when aliases
|
// since it would expand indefinitely when aliases
|
||||||
// are substituted.
|
// are substituted.
|
||||||
cycle := cycleFor(n)
|
cycle := cycleFor(n)
|
||||||
for _, n := range cycle {
|
for _, n1 := range cycle {
|
||||||
if n.Name != nil && !n.Name.Param.Alias {
|
if n1.Name != nil && !n1.Name.Param.Alias {
|
||||||
|
// Cycle is ok. But if n is an alias type and doesn't
|
||||||
|
// have a type yet, we have a recursive type declaration
|
||||||
|
// with aliases that we can't handle properly yet.
|
||||||
|
// Report an error rather than crashing later.
|
||||||
|
if n.Name != nil && n.Name.Param.Alias && n.Type == nil {
|
||||||
|
lineno = n.Pos
|
||||||
|
Fatalf("cannot handle alias type declaration (issue #25838): %v", n)
|
||||||
|
}
|
||||||
lineno = lno
|
lineno = lno
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +356,11 @@ func indexlit(n *Node) *Node {
|
||||||
|
|
||||||
// The result of typecheck1 MUST be assigned back to n, e.g.
|
// The result of typecheck1 MUST be assigned back to n, e.g.
|
||||||
// n.Left = typecheck1(n.Left, top)
|
// n.Left = typecheck1(n.Left, top)
|
||||||
func typecheck1(n *Node, top int) *Node {
|
func typecheck1(n *Node, top int) (res *Node) {
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheck1", n)(&res)
|
||||||
|
}
|
||||||
|
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OLITERAL, ONAME, ONONAME, OTYPE:
|
case OLITERAL, ONAME, ONONAME, OTYPE:
|
||||||
if n.Sym == nil {
|
if n.Sym == nil {
|
||||||
|
|
@ -1094,11 +1160,15 @@ func typecheck1(n *Node, top int) *Node {
|
||||||
ok |= Erv
|
ok |= Erv
|
||||||
|
|
||||||
t := n.Type
|
t := n.Type
|
||||||
|
if t == nil {
|
||||||
|
Fatalf("no type specified for OSLICEHEADER")
|
||||||
|
}
|
||||||
|
|
||||||
if !t.IsSlice() {
|
if !t.IsSlice() {
|
||||||
Fatalf("invalid type %v for OSLICEHEADER", n.Type)
|
Fatalf("invalid type %v for OSLICEHEADER", n.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !n.Left.Type.IsUnsafePtr() {
|
if n.Left == nil || n.Left.Type == nil || !n.Left.Type.IsUnsafePtr() {
|
||||||
Fatalf("need unsafe.Pointer for OSLICEHEADER")
|
Fatalf("need unsafe.Pointer for OSLICEHEADER")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2381,7 +2451,11 @@ func lookdot1(errnode *Node, s *types.Sym, t *types.Type, fs *types.Fields, dost
|
||||||
|
|
||||||
// typecheckMethodExpr checks selector expressions (ODOT) where the
|
// typecheckMethodExpr checks selector expressions (ODOT) where the
|
||||||
// base expression is a type expression (OTYPE).
|
// base expression is a type expression (OTYPE).
|
||||||
func typecheckMethodExpr(n *Node) *Node {
|
func typecheckMethodExpr(n *Node) (res *Node) {
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheckMethodExpr", n)(&res)
|
||||||
|
}
|
||||||
|
|
||||||
t := n.Left.Type
|
t := n.Left.Type
|
||||||
|
|
||||||
// Compute the method set for t.
|
// Compute the method set for t.
|
||||||
|
|
@ -2924,7 +2998,11 @@ func pushtype(n *Node, t *types.Type) {
|
||||||
|
|
||||||
// The result of typecheckcomplit MUST be assigned back to n, e.g.
|
// The result of typecheckcomplit MUST be assigned back to n, e.g.
|
||||||
// n.Left = typecheckcomplit(n.Left)
|
// n.Left = typecheckcomplit(n.Left)
|
||||||
func typecheckcomplit(n *Node) *Node {
|
func typecheckcomplit(n *Node) (res *Node) {
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheckcomplit", n)(&res)
|
||||||
|
}
|
||||||
|
|
||||||
lno := lineno
|
lno := lineno
|
||||||
defer func() {
|
defer func() {
|
||||||
lineno = lno
|
lineno = lno
|
||||||
|
|
@ -3337,6 +3415,10 @@ func samesafeexpr(l *Node, r *Node) bool {
|
||||||
// if this assignment is the definition of a var on the left side,
|
// if this assignment is the definition of a var on the left side,
|
||||||
// fill in the var's type.
|
// fill in the var's type.
|
||||||
func typecheckas(n *Node) {
|
func typecheckas(n *Node) {
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheckas", n)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
// delicate little dance.
|
// delicate little dance.
|
||||||
// the definition of n may refer to this assignment
|
// the definition of n may refer to this assignment
|
||||||
// as its definition, in which case it will call typecheckas.
|
// as its definition, in which case it will call typecheckas.
|
||||||
|
|
@ -3393,6 +3475,10 @@ func checkassignto(src *types.Type, dst *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckas2(n *Node) {
|
func typecheckas2(n *Node) {
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheckas2", n)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
ls := n.List.Slice()
|
ls := n.List.Slice()
|
||||||
for i1, n1 := range ls {
|
for i1, n1 := range ls {
|
||||||
// delicate little dance.
|
// delicate little dance.
|
||||||
|
|
@ -3521,6 +3607,10 @@ out:
|
||||||
|
|
||||||
// type check function definition
|
// type check function definition
|
||||||
func typecheckfunc(n *Node) {
|
func typecheckfunc(n *Node) {
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheckfunc", n)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
for _, ln := range n.Func.Dcl {
|
for _, ln := range n.Func.Dcl {
|
||||||
if ln.Op == ONAME && (ln.Class() == PPARAM || ln.Class() == PPARAMOUT) {
|
if ln.Op == ONAME && (ln.Class() == PPARAM || ln.Class() == PPARAMOUT) {
|
||||||
ln.Name.Decldepth = 1
|
ln.Name.Decldepth = 1
|
||||||
|
|
@ -3593,8 +3683,7 @@ func copytype(n *Node, t *types.Type) {
|
||||||
embedlineno := n.Type.ForwardType().Embedlineno
|
embedlineno := n.Type.ForwardType().Embedlineno
|
||||||
l := n.Type.ForwardType().Copyto
|
l := n.Type.ForwardType().Copyto
|
||||||
|
|
||||||
ptrBase := n.Type.PtrBase
|
cache := n.Type.Cache
|
||||||
sliceOf := n.Type.SliceOf
|
|
||||||
|
|
||||||
// TODO(mdempsky): Fix Type rekinding.
|
// TODO(mdempsky): Fix Type rekinding.
|
||||||
*n.Type = *t
|
*n.Type = *t
|
||||||
|
|
@ -3615,8 +3704,7 @@ func copytype(n *Node, t *types.Type) {
|
||||||
|
|
||||||
t.Nod = asTypesNode(n)
|
t.Nod = asTypesNode(n)
|
||||||
t.SetDeferwidth(false)
|
t.SetDeferwidth(false)
|
||||||
t.PtrBase = ptrBase
|
t.Cache = cache
|
||||||
t.SliceOf = sliceOf
|
|
||||||
|
|
||||||
// Propagate go:notinheap pragma from the Name to the Type.
|
// Propagate go:notinheap pragma from the Name to the Type.
|
||||||
if n.Name != nil && n.Name.Param != nil && n.Name.Param.Pragma&NotInHeap != 0 {
|
if n.Name != nil && n.Name.Param != nil && n.Name.Param.Pragma&NotInHeap != 0 {
|
||||||
|
|
@ -3637,6 +3725,10 @@ func copytype(n *Node, t *types.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckdeftype(n *Node) {
|
func typecheckdeftype(n *Node) {
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheckdeftype", n)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
n.Type.Sym = n.Sym
|
n.Type.Sym = n.Sym
|
||||||
n.SetTypecheck(1)
|
n.SetTypecheck(1)
|
||||||
n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
|
n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
|
||||||
|
|
@ -3654,6 +3746,10 @@ func typecheckdeftype(n *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckdef(n *Node) {
|
func typecheckdef(n *Node) {
|
||||||
|
if enableTrace && trace {
|
||||||
|
defer tracePrint("typecheckdef", n)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
lno := setlineno(n)
|
lno := setlineno(n)
|
||||||
|
|
||||||
if n.Op == ONONAME {
|
if n.Op == ONONAME {
|
||||||
|
|
@ -3992,6 +4088,12 @@ func deadcode(fn *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func deadcodeslice(nn Nodes) {
|
func deadcodeslice(nn Nodes) {
|
||||||
|
var lastLabel = -1
|
||||||
|
for i, n := range nn.Slice() {
|
||||||
|
if n != nil && n.Op == OLABEL {
|
||||||
|
lastLabel = i
|
||||||
|
}
|
||||||
|
}
|
||||||
for i, n := range nn.Slice() {
|
for i, n := range nn.Slice() {
|
||||||
// Cut is set to true when all nodes after i'th position
|
// Cut is set to true when all nodes after i'th position
|
||||||
// should be removed.
|
// should be removed.
|
||||||
|
|
@ -4014,14 +4116,18 @@ func deadcodeslice(nn Nodes) {
|
||||||
// If "then" or "else" branch ends with panic or return statement,
|
// If "then" or "else" branch ends with panic or return statement,
|
||||||
// it is safe to remove all statements after this node.
|
// it is safe to remove all statements after this node.
|
||||||
// isterminating is not used to avoid goto-related complications.
|
// isterminating is not used to avoid goto-related complications.
|
||||||
|
// We must be careful not to deadcode-remove labels, as they
|
||||||
|
// might be the target of a goto. See issue 28616.
|
||||||
if body := body.Slice(); len(body) != 0 {
|
if body := body.Slice(); len(body) != 0 {
|
||||||
switch body[(len(body) - 1)].Op {
|
switch body[(len(body) - 1)].Op {
|
||||||
case ORETURN, ORETJMP, OPANIC:
|
case ORETURN, ORETJMP, OPANIC:
|
||||||
|
if i > lastLabel {
|
||||||
cut = true
|
cut = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deadcodeslice(n.Ninit)
|
deadcodeslice(n.Ninit)
|
||||||
deadcodeslice(n.Nbody)
|
deadcodeslice(n.Nbody)
|
||||||
|
|
|
||||||
|
|
@ -200,8 +200,6 @@ func typeinit() {
|
||||||
isComplex[TCOMPLEX64] = true
|
isComplex[TCOMPLEX64] = true
|
||||||
isComplex[TCOMPLEX128] = true
|
isComplex[TCOMPLEX128] = true
|
||||||
|
|
||||||
isforw[TFORW] = true
|
|
||||||
|
|
||||||
// initialize okfor
|
// initialize okfor
|
||||||
for et := types.EType(0); et < NTYPE; et++ {
|
for et := types.EType(0); et < NTYPE; et++ {
|
||||||
if isInt[et] || et == TIDEAL {
|
if isInt[et] || et == TIDEAL {
|
||||||
|
|
|
||||||
|
|
@ -384,41 +384,31 @@ func convFuncName(from, to *types.Type) (fnname string, needsaddr bool) {
|
||||||
tkind := to.Tie()
|
tkind := to.Tie()
|
||||||
switch from.Tie() {
|
switch from.Tie() {
|
||||||
case 'I':
|
case 'I':
|
||||||
switch tkind {
|
if tkind == 'I' {
|
||||||
case 'I':
|
|
||||||
return "convI2I", false
|
return "convI2I", false
|
||||||
}
|
}
|
||||||
case 'T':
|
case 'T':
|
||||||
switch tkind {
|
|
||||||
case 'E':
|
|
||||||
switch {
|
switch {
|
||||||
case from.Size() == 2 && from.Align == 2:
|
case from.Size() == 2 && from.Align == 2:
|
||||||
return "convT2E16", false
|
return "convT16", false
|
||||||
case from.Size() == 4 && from.Align == 4 && !types.Haspointers(from):
|
case from.Size() == 4 && from.Align == 4 && !types.Haspointers(from):
|
||||||
return "convT2E32", false
|
return "convT32", false
|
||||||
case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !types.Haspointers(from):
|
case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !types.Haspointers(from):
|
||||||
return "convT2E64", false
|
return "convT64", false
|
||||||
case from.IsString():
|
case from.IsString():
|
||||||
return "convT2Estring", false
|
return "convTstring", false
|
||||||
case from.IsSlice():
|
case from.IsSlice():
|
||||||
return "convT2Eslice", false
|
return "convTslice", false
|
||||||
case !types.Haspointers(from):
|
}
|
||||||
|
|
||||||
|
switch tkind {
|
||||||
|
case 'E':
|
||||||
|
if !types.Haspointers(from) {
|
||||||
return "convT2Enoptr", true
|
return "convT2Enoptr", true
|
||||||
}
|
}
|
||||||
return "convT2E", true
|
return "convT2E", true
|
||||||
case 'I':
|
case 'I':
|
||||||
switch {
|
if !types.Haspointers(from) {
|
||||||
case from.Size() == 2 && from.Align == 2:
|
|
||||||
return "convT2I16", false
|
|
||||||
case from.Size() == 4 && from.Align == 4 && !types.Haspointers(from):
|
|
||||||
return "convT2I32", false
|
|
||||||
case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !types.Haspointers(from):
|
|
||||||
return "convT2I64", false
|
|
||||||
case from.IsString():
|
|
||||||
return "convT2Istring", false
|
|
||||||
case from.IsSlice():
|
|
||||||
return "convT2Islice", false
|
|
||||||
case !types.Haspointers(from):
|
|
||||||
return "convT2Inoptr", true
|
return "convT2Inoptr", true
|
||||||
}
|
}
|
||||||
return "convT2I", true
|
return "convT2I", true
|
||||||
|
|
@ -496,7 +486,7 @@ opswitch:
|
||||||
OIND, OSPTR, OITAB, OIDATA, OADDR:
|
OIND, OSPTR, OITAB, OIDATA, OADDR:
|
||||||
n.Left = walkexpr(n.Left, init)
|
n.Left = walkexpr(n.Left, init)
|
||||||
|
|
||||||
case OEFACE, OAND, OSUB, OMUL, OADD, OOR, OXOR:
|
case OEFACE, OAND, OSUB, OMUL, OADD, OOR, OXOR, OLSH, ORSH:
|
||||||
n.Left = walkexpr(n.Left, init)
|
n.Left = walkexpr(n.Left, init)
|
||||||
n.Right = walkexpr(n.Right, init)
|
n.Right = walkexpr(n.Right, init)
|
||||||
|
|
||||||
|
|
@ -548,15 +538,6 @@ opswitch:
|
||||||
n.SetTypecheck(1)
|
n.SetTypecheck(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
case OLSH, ORSH:
|
|
||||||
n.Left = walkexpr(n.Left, init)
|
|
||||||
n.Right = walkexpr(n.Right, init)
|
|
||||||
t := n.Left.Type
|
|
||||||
n.SetBounded(bounded(n.Right, 8*t.Width))
|
|
||||||
if Debug['m'] != 0 && n.Bounded() && !Isconst(n.Right, CTINT) {
|
|
||||||
Warn("shift bounds check elided")
|
|
||||||
}
|
|
||||||
|
|
||||||
case OCOMPLEX:
|
case OCOMPLEX:
|
||||||
// Use results from call expression as arguments for complex.
|
// Use results from call expression as arguments for complex.
|
||||||
if n.Left == nil && n.Right == nil {
|
if n.Left == nil && n.Right == nil {
|
||||||
|
|
@ -834,16 +815,21 @@ opswitch:
|
||||||
case OCONVIFACE:
|
case OCONVIFACE:
|
||||||
n.Left = walkexpr(n.Left, init)
|
n.Left = walkexpr(n.Left, init)
|
||||||
|
|
||||||
// Optimize convT2E or convT2I as a two-word copy when T is pointer-shaped.
|
fromType := n.Left.Type
|
||||||
if isdirectiface(n.Left.Type) {
|
toType := n.Type
|
||||||
var t *Node
|
|
||||||
if n.Type.IsEmptyInterface() {
|
// typeword generates the type word of the interface value.
|
||||||
t = typename(n.Left.Type)
|
typeword := func() *Node {
|
||||||
} else {
|
if toType.IsEmptyInterface() {
|
||||||
t = itabname(n.Left.Type, n.Type)
|
return typename(fromType)
|
||||||
}
|
}
|
||||||
l := nod(OEFACE, t, n.Left)
|
return itabname(fromType, toType)
|
||||||
l.Type = n.Type
|
}
|
||||||
|
|
||||||
|
// Optimize convT2E or convT2I as a two-word copy when T is pointer-shaped.
|
||||||
|
if isdirectiface(fromType) {
|
||||||
|
l := nod(OEFACE, typeword(), n.Left)
|
||||||
|
l.Type = toType
|
||||||
l.SetTypecheck(n.Typecheck())
|
l.SetTypecheck(n.Typecheck())
|
||||||
n = l
|
n = l
|
||||||
break
|
break
|
||||||
|
|
@ -863,11 +849,11 @@ opswitch:
|
||||||
// or creating one on the stack.
|
// or creating one on the stack.
|
||||||
var value *Node
|
var value *Node
|
||||||
switch {
|
switch {
|
||||||
case n.Left.Type.Size() == 0:
|
case fromType.Size() == 0:
|
||||||
// n.Left is zero-sized. Use zerobase.
|
// n.Left is zero-sized. Use zerobase.
|
||||||
cheapexpr(n.Left, init) // Evaluate n.Left for side-effects. See issue 19246.
|
cheapexpr(n.Left, init) // Evaluate n.Left for side-effects. See issue 19246.
|
||||||
value = zerobase
|
value = zerobase
|
||||||
case n.Left.Type.IsBoolean() || (n.Left.Type.Size() == 1 && n.Left.Type.IsInteger()):
|
case fromType.IsBoolean() || (fromType.Size() == 1 && fromType.IsInteger()):
|
||||||
// n.Left is a bool/byte. Use staticbytes[n.Left].
|
// n.Left is a bool/byte. Use staticbytes[n.Left].
|
||||||
n.Left = cheapexpr(n.Left, init)
|
n.Left = cheapexpr(n.Left, init)
|
||||||
value = nod(OINDEX, staticbytes, byteindex(n.Left))
|
value = nod(OINDEX, staticbytes, byteindex(n.Left))
|
||||||
|
|
@ -875,23 +861,17 @@ opswitch:
|
||||||
case n.Left.Class() == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly():
|
case n.Left.Class() == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly():
|
||||||
// n.Left is a readonly global; use it directly.
|
// n.Left is a readonly global; use it directly.
|
||||||
value = n.Left
|
value = n.Left
|
||||||
case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024:
|
case !fromType.IsInterface() && n.Esc == EscNone && fromType.Width <= 1024:
|
||||||
// n.Left does not escape. Use a stack temporary initialized to n.Left.
|
// n.Left does not escape. Use a stack temporary initialized to n.Left.
|
||||||
value = temp(n.Left.Type)
|
value = temp(fromType)
|
||||||
init.Append(typecheck(nod(OAS, value, n.Left), Etop))
|
init.Append(typecheck(nod(OAS, value, n.Left), Etop))
|
||||||
}
|
}
|
||||||
|
|
||||||
if value != nil {
|
if value != nil {
|
||||||
// Value is identical to n.Left.
|
// Value is identical to n.Left.
|
||||||
// Construct the interface directly: {type/itab, &value}.
|
// Construct the interface directly: {type/itab, &value}.
|
||||||
var t *Node
|
l := nod(OEFACE, typeword(), typecheck(nod(OADDR, value, nil), Erv))
|
||||||
if n.Type.IsEmptyInterface() {
|
l.Type = toType
|
||||||
t = typename(n.Left.Type)
|
|
||||||
} else {
|
|
||||||
t = itabname(n.Left.Type, n.Type)
|
|
||||||
}
|
|
||||||
l := nod(OEFACE, t, typecheck(nod(OADDR, value, nil), Erv))
|
|
||||||
l.Type = n.Type
|
|
||||||
l.SetTypecheck(n.Typecheck())
|
l.SetTypecheck(n.Typecheck())
|
||||||
n = l
|
n = l
|
||||||
break
|
break
|
||||||
|
|
@ -903,9 +883,9 @@ opswitch:
|
||||||
// tmp = tmp.type
|
// tmp = tmp.type
|
||||||
// }
|
// }
|
||||||
// e = iface{tmp, i.data}
|
// e = iface{tmp, i.data}
|
||||||
if n.Type.IsEmptyInterface() && n.Left.Type.IsInterface() && !n.Left.Type.IsEmptyInterface() {
|
if toType.IsEmptyInterface() && fromType.IsInterface() && !fromType.IsEmptyInterface() {
|
||||||
// Evaluate the input interface.
|
// Evaluate the input interface.
|
||||||
c := temp(n.Left.Type)
|
c := temp(fromType)
|
||||||
init.Append(nod(OAS, c, n.Left))
|
init.Append(nod(OAS, c, n.Left))
|
||||||
|
|
||||||
// Get the itab out of the interface.
|
// Get the itab out of the interface.
|
||||||
|
|
@ -919,26 +899,43 @@ opswitch:
|
||||||
|
|
||||||
// Build the result.
|
// Build the result.
|
||||||
e := nod(OEFACE, tmp, ifaceData(c, types.NewPtr(types.Types[TUINT8])))
|
e := nod(OEFACE, tmp, ifaceData(c, types.NewPtr(types.Types[TUINT8])))
|
||||||
e.Type = n.Type // assign type manually, typecheck doesn't understand OEFACE.
|
e.Type = toType // assign type manually, typecheck doesn't understand OEFACE.
|
||||||
e.SetTypecheck(1)
|
e.SetTypecheck(1)
|
||||||
n = e
|
n = e
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
var ll []*Node
|
fnname, needsaddr := convFuncName(fromType, toType)
|
||||||
if n.Type.IsEmptyInterface() {
|
|
||||||
if !n.Left.Type.IsInterface() {
|
if !needsaddr && !fromType.IsInterface() {
|
||||||
ll = append(ll, typename(n.Left.Type))
|
// Use a specialized conversion routine that only returns a data pointer.
|
||||||
}
|
// ptr = convT2X(val)
|
||||||
} else {
|
// e = iface{typ/tab, ptr}
|
||||||
if n.Left.Type.IsInterface() {
|
fn := syslook(fnname)
|
||||||
ll = append(ll, typename(n.Type))
|
dowidth(fromType)
|
||||||
} else {
|
fn = substArgTypes(fn, fromType)
|
||||||
ll = append(ll, itabname(n.Left.Type, n.Type))
|
dowidth(fn.Type)
|
||||||
}
|
call := nod(OCALL, fn, nil)
|
||||||
|
call.List.Set1(n.Left)
|
||||||
|
call = typecheck(call, Erv)
|
||||||
|
call = walkexpr(call, init)
|
||||||
|
call = safeexpr(call, init)
|
||||||
|
e := nod(OEFACE, typeword(), call)
|
||||||
|
e.Type = toType
|
||||||
|
e.SetTypecheck(1)
|
||||||
|
n = e
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
var tab *Node
|
||||||
|
if fromType.IsInterface() {
|
||||||
|
// convI2I
|
||||||
|
tab = typename(toType)
|
||||||
|
} else {
|
||||||
|
// convT2x
|
||||||
|
tab = typeword()
|
||||||
}
|
}
|
||||||
|
|
||||||
fnname, needsaddr := convFuncName(n.Left.Type, n.Type)
|
|
||||||
v := n.Left
|
v := n.Left
|
||||||
if needsaddr {
|
if needsaddr {
|
||||||
// Types of large or unknown size are passed by reference.
|
// Types of large or unknown size are passed by reference.
|
||||||
|
|
@ -952,14 +949,13 @@ opswitch:
|
||||||
}
|
}
|
||||||
v = nod(OADDR, v, nil)
|
v = nod(OADDR, v, nil)
|
||||||
}
|
}
|
||||||
ll = append(ll, v)
|
|
||||||
|
|
||||||
dowidth(n.Left.Type)
|
dowidth(fromType)
|
||||||
fn := syslook(fnname)
|
fn := syslook(fnname)
|
||||||
fn = substArgTypes(fn, n.Left.Type, n.Type)
|
fn = substArgTypes(fn, fromType, toType)
|
||||||
dowidth(fn.Type)
|
dowidth(fn.Type)
|
||||||
n = nod(OCALL, fn, nil)
|
n = nod(OCALL, fn, nil)
|
||||||
n.List.Set(ll)
|
n.List.Set2(tab, v)
|
||||||
n = typecheck(n, Erv)
|
n = typecheck(n, Erv)
|
||||||
n = walkexpr(n, init)
|
n = walkexpr(n, init)
|
||||||
|
|
||||||
|
|
@ -1343,14 +1339,17 @@ opswitch:
|
||||||
argtype = types.Types[TINT]
|
argtype = types.Types[TINT]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m := nod(OSLICEHEADER, nil, nil)
|
||||||
|
m.Type = t
|
||||||
|
|
||||||
fn := syslook(fnname)
|
fn := syslook(fnname)
|
||||||
n.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
|
m.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
|
||||||
n.Left.SetNonNil(true)
|
m.Left.SetNonNil(true)
|
||||||
n.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT]))
|
m.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT]))
|
||||||
n.Op = OSLICEHEADER
|
|
||||||
n.Type = t
|
m = typecheck(m, Erv)
|
||||||
n = typecheck(n, Erv)
|
m = walkexpr(m, init)
|
||||||
n = walkexpr(n, init)
|
n = m
|
||||||
}
|
}
|
||||||
|
|
||||||
case ORUNESTR:
|
case ORUNESTR:
|
||||||
|
|
|
||||||
|
|
@ -569,7 +569,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
ssa.OpPPC64ROTL, ssa.OpPPC64ROTLW,
|
ssa.OpPPC64ROTL, ssa.OpPPC64ROTLW,
|
||||||
ssa.OpPPC64MULHD, ssa.OpPPC64MULHW, ssa.OpPPC64MULHDU, ssa.OpPPC64MULHWU,
|
ssa.OpPPC64MULHD, ssa.OpPPC64MULHW, ssa.OpPPC64MULHDU, ssa.OpPPC64MULHWU,
|
||||||
ssa.OpPPC64FMUL, ssa.OpPPC64FMULS, ssa.OpPPC64FDIV, ssa.OpPPC64FDIVS, ssa.OpPPC64FCPSGN,
|
ssa.OpPPC64FMUL, ssa.OpPPC64FMULS, ssa.OpPPC64FDIV, ssa.OpPPC64FDIVS, ssa.OpPPC64FCPSGN,
|
||||||
ssa.OpPPC64AND, ssa.OpPPC64OR, ssa.OpPPC64ANDN, ssa.OpPPC64ORN, ssa.OpPPC64NOR, ssa.OpPPC64XOR, ssa.OpPPC64EQV:
|
ssa.OpPPC64AND, ssa.OpPPC64ANDCC, ssa.OpPPC64OR, ssa.OpPPC64ORCC, ssa.OpPPC64ANDN, ssa.OpPPC64ORN, ssa.OpPPC64NOR, ssa.OpPPC64XOR, ssa.OpPPC64XORCC, ssa.OpPPC64EQV:
|
||||||
r := v.Reg()
|
r := v.Reg()
|
||||||
r1 := v.Args[0].Reg()
|
r1 := v.Args[0].Reg()
|
||||||
r2 := v.Args[1].Reg()
|
r2 := v.Args[1].Reg()
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ type Logger interface {
|
||||||
// Logf logs a message from the compiler.
|
// Logf logs a message from the compiler.
|
||||||
Logf(string, ...interface{})
|
Logf(string, ...interface{})
|
||||||
|
|
||||||
// Log returns true if logging is not a no-op
|
// Log reports whether logging is not a no-op
|
||||||
// some logging calls account for more than a few heap allocations.
|
// some logging calls account for more than a few heap allocations.
|
||||||
Log() bool
|
Log() bool
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -790,7 +790,7 @@ func (e *pendingEntry) clear() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// canMerge returns true if the location description for new is the same as
|
// canMerge reports whether the location description for new is the same as
|
||||||
// pending.
|
// pending.
|
||||||
func canMerge(pending, new VarLoc) bool {
|
func canMerge(pending, new VarLoc) bool {
|
||||||
if pending.absent() && new.absent() {
|
if pending.absent() && new.absent() {
|
||||||
|
|
|
||||||
|
|
@ -621,7 +621,7 @@ func (f *Func) invalidateCFG() {
|
||||||
f.cachedLoopnest = nil
|
f.cachedLoopnest = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DebugHashMatch returns true if environment variable evname
|
// DebugHashMatch reports whether environment variable evname
|
||||||
// 1) is empty (this is a special more-quickly implemented case of 3)
|
// 1) is empty (this is a special more-quickly implemented case of 3)
|
||||||
// 2) is "y" or "Y"
|
// 2) is "y" or "Y"
|
||||||
// 3) is a suffix of the sha1 hash of name
|
// 3) is a suffix of the sha1 hash of name
|
||||||
|
|
|
||||||
|
|
@ -518,6 +518,13 @@
|
||||||
(LessEqual (InvertFlags x)) -> (GreaterEqual x)
|
(LessEqual (InvertFlags x)) -> (GreaterEqual x)
|
||||||
(GreaterEqual (InvertFlags x)) -> (LessEqual x)
|
(GreaterEqual (InvertFlags x)) -> (LessEqual x)
|
||||||
|
|
||||||
|
// Elide compares of bit tests // TODO need to make both CC and result of ANDCC available.
|
||||||
|
((EQ|NE|LT|LE|GT|GE) (CMPconst [0] (ANDconst [c] x)) yes no) -> ((EQ|NE|LT|LE|GT|GE) (ANDCCconst [c] x) yes no)
|
||||||
|
((EQ|NE|LT|LE|GT|GE) (CMPWconst [0] (ANDconst [c] x)) yes no) -> ((EQ|NE|LT|LE|GT|GE) (ANDCCconst [c] x) yes no)
|
||||||
|
((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> ((EQ|NE|LT|LE|GT|GE) (ANDCC x y) yes no)
|
||||||
|
((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(OR x y)) yes no) && z.Uses == 1 -> ((EQ|NE|LT|LE|GT|GE) (ORCC x y) yes no)
|
||||||
|
((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(XOR x y)) yes no) && z.Uses == 1 -> ((EQ|NE|LT|LE|GT|GE) (XORCC x y) yes no)
|
||||||
|
|
||||||
// Lowering loads
|
// Lowering loads
|
||||||
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
|
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
|
||||||
(Load <t> ptr mem) && is32BitInt(t) && isSigned(t) -> (MOVWload ptr mem)
|
(Load <t> ptr mem) && is32BitInt(t) && isSigned(t) -> (MOVWload ptr mem)
|
||||||
|
|
|
||||||
|
|
@ -243,10 +243,13 @@ func init() {
|
||||||
|
|
||||||
{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0&arg1
|
{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0&arg1
|
||||||
{name: "ANDN", argLength: 2, reg: gp21, asm: "ANDN"}, // arg0&^arg1
|
{name: "ANDN", argLength: 2, reg: gp21, asm: "ANDN"}, // arg0&^arg1
|
||||||
|
{name: "ANDCC", argLength: 2, reg: gp21, asm: "ANDCC", commutative: true, typ: "Flags"}, // arg0&arg1 sets CC
|
||||||
{name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0|arg1
|
{name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0|arg1
|
||||||
{name: "ORN", argLength: 2, reg: gp21, asm: "ORN"}, // arg0|^arg1
|
{name: "ORN", argLength: 2, reg: gp21, asm: "ORN"}, // arg0|^arg1
|
||||||
|
{name: "ORCC", argLength: 2, reg: gp21, asm: "ORCC", commutative: true, typ: "Flags"}, // arg0|arg1 sets CC
|
||||||
{name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true}, // ^(arg0|arg1)
|
{name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true}, // ^(arg0|arg1)
|
||||||
{name: "XOR", argLength: 2, reg: gp21, asm: "XOR", typ: "Int64", commutative: true}, // arg0^arg1
|
{name: "XOR", argLength: 2, reg: gp21, asm: "XOR", typ: "Int64", commutative: true}, // arg0^arg1
|
||||||
|
{name: "XORCC", argLength: 2, reg: gp21, asm: "XORCC", commutative: true, typ: "Flags"}, // arg0^arg1 sets CC
|
||||||
{name: "EQV", argLength: 2, reg: gp21, asm: "EQV", typ: "Int64", commutative: true}, // arg0^^arg1
|
{name: "EQV", argLength: 2, reg: gp21, asm: "EQV", typ: "Int64", commutative: true}, // arg0^^arg1
|
||||||
{name: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0 (integer)
|
{name: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0 (integer)
|
||||||
{name: "FNEG", argLength: 1, reg: fp11, asm: "FNEG"}, // -arg0 (floating point)
|
{name: "FNEG", argLength: 1, reg: fp11, asm: "FNEG"}, // -arg0 (floating point)
|
||||||
|
|
|
||||||
|
|
@ -1804,11 +1804,25 @@
|
||||||
// Later passes (deadstore, elim unread auto) will remove the A -> B move, if possible.
|
// Later passes (deadstore, elim unread auto) will remove the A -> B move, if possible.
|
||||||
// This happens most commonly when B is an autotmp inserted earlier
|
// This happens most commonly when B is an autotmp inserted earlier
|
||||||
// during compilation to ensure correctness.
|
// during compilation to ensure correctness.
|
||||||
(Move {t1} [s1] dst tmp1 midmem:(Move {t2} [s2] tmp2 src _))
|
// Take care that overlapping moves are preserved.
|
||||||
&& s1 == s2
|
// Restrict this optimization to the stack, to avoid duplicating loads from the heap;
|
||||||
|
// see CL 145208 for discussion.
|
||||||
|
(Move {t1} [s] dst tmp1 midmem:(Move {t2} [s] tmp2 src _))
|
||||||
&& t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq
|
&& t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq
|
||||||
&& isSamePtr(tmp1, tmp2)
|
&& isSamePtr(tmp1, tmp2)
|
||||||
-> (Move {t1} [s1] dst src midmem)
|
&& isStackPtr(src)
|
||||||
|
&& disjoint(src, s, tmp2, s)
|
||||||
|
&& (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))
|
||||||
|
-> (Move {t1} [s] dst src midmem)
|
||||||
|
|
||||||
|
// Same, but for large types that require VarDefs.
|
||||||
|
(Move {t1} [s] dst tmp1 midmem:(VarDef (Move {t2} [s] tmp2 src _)))
|
||||||
|
&& t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq
|
||||||
|
&& isSamePtr(tmp1, tmp2)
|
||||||
|
&& isStackPtr(src)
|
||||||
|
&& disjoint(src, s, tmp2, s)
|
||||||
|
&& (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))
|
||||||
|
-> (Move {t1} [s] dst src midmem)
|
||||||
|
|
||||||
// Elide self-moves. This only happens rarely (e.g test/fixedbugs/bug277.go).
|
// Elide self-moves. This only happens rarely (e.g test/fixedbugs/bug277.go).
|
||||||
// However, this rule is needed to prevent the previous rule from looping forever in such cases.
|
// However, this rule is needed to prevent the previous rule from looping forever in such cases.
|
||||||
|
|
|
||||||
|
|
@ -529,7 +529,7 @@ var genericOps = []opData{
|
||||||
{name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
|
{name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
|
||||||
{name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
|
{name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
|
||||||
{name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
|
{name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
|
||||||
{name: "AtomicCompareAndSwapRel32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Lock release, returns true if store happens and new memory.
|
{name: "AtomicCompareAndSwapRel32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Lock release, reports whether store happens and new memory.
|
||||||
{name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
|
{name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
|
||||||
{name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
|
{name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
// This program generates Go code that applies rewrite rules to a Value.
|
// This program generates Go code that applies rewrite rules to a Value.
|
||||||
// The generated code implements a function of type func (v *Value) bool
|
// The generated code implements a function of type func (v *Value) bool
|
||||||
// which returns true iff if did something.
|
// which reports whether if did something.
|
||||||
// Ideas stolen from Swift: http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-2000-2.html
|
// Ideas stolen from Swift: http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-2000-2.html
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
@ -386,7 +386,7 @@ func genRules(arch arch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// genMatch returns true if the match can fail.
|
// genMatch reports whether the match can fail.
|
||||||
func genMatch(w io.Writer, arch arch, match string, loc string) bool {
|
func genMatch(w io.Writer, arch arch, match string, loc string) bool {
|
||||||
return genMatch0(w, arch, match, "v", map[string]struct{}{}, true, loc)
|
return genMatch0(w, arch, match, "v", map[string]struct{}{}, true, loc)
|
||||||
}
|
}
|
||||||
|
|
@ -623,7 +623,7 @@ outer:
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBlock returns true if this op is a block opcode.
|
// isBlock reports whether this op is a block opcode.
|
||||||
func isBlock(name string, arch arch) bool {
|
func isBlock(name string, arch arch) bool {
|
||||||
for _, b := range genericBlocks {
|
for _, b := range genericBlocks {
|
||||||
if b.name == name {
|
if b.name == name {
|
||||||
|
|
@ -768,7 +768,7 @@ func typeName(typ string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unbalanced returns true if there aren't the same number of ( and ) in the string.
|
// unbalanced reports whether there aren't the same number of ( and ) in the string.
|
||||||
func unbalanced(s string) bool {
|
func unbalanced(s string) bool {
|
||||||
var left, right int
|
var left, right int
|
||||||
for _, c := range s {
|
for _, c := range s {
|
||||||
|
|
|
||||||
|
|
@ -1663,10 +1663,13 @@ const (
|
||||||
OpPPC64MTVSRD
|
OpPPC64MTVSRD
|
||||||
OpPPC64AND
|
OpPPC64AND
|
||||||
OpPPC64ANDN
|
OpPPC64ANDN
|
||||||
|
OpPPC64ANDCC
|
||||||
OpPPC64OR
|
OpPPC64OR
|
||||||
OpPPC64ORN
|
OpPPC64ORN
|
||||||
|
OpPPC64ORCC
|
||||||
OpPPC64NOR
|
OpPPC64NOR
|
||||||
OpPPC64XOR
|
OpPPC64XOR
|
||||||
|
OpPPC64XORCC
|
||||||
OpPPC64EQV
|
OpPPC64EQV
|
||||||
OpPPC64NEG
|
OpPPC64NEG
|
||||||
OpPPC64FNEG
|
OpPPC64FNEG
|
||||||
|
|
@ -22202,6 +22205,21 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ANDCC",
|
||||||
|
argLen: 2,
|
||||||
|
commutative: true,
|
||||||
|
asm: ppc64.AANDCC,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "OR",
|
name: "OR",
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
|
|
@ -22231,6 +22249,21 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ORCC",
|
||||||
|
argLen: 2,
|
||||||
|
commutative: true,
|
||||||
|
asm: ppc64.AORCC,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "NOR",
|
name: "NOR",
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
|
|
@ -22261,6 +22294,21 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "XORCC",
|
||||||
|
argLen: 2,
|
||||||
|
commutative: true,
|
||||||
|
asm: ppc64.AXORCC,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "EQV",
|
name: "EQV",
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
|
|
|
||||||
|
|
@ -781,7 +781,7 @@ func (po *poset) DotDump(fn string, title string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ordered returns true if n1<n2. It returns false either when it is
|
// Ordered reports whether n1<n2. It returns false either when it is
|
||||||
// certain that n1<n2 is false, or if there is not enough information
|
// certain that n1<n2 is false, or if there is not enough information
|
||||||
// to tell.
|
// to tell.
|
||||||
// Complexity is O(n).
|
// Complexity is O(n).
|
||||||
|
|
@ -799,7 +799,7 @@ func (po *poset) Ordered(n1, n2 *Value) bool {
|
||||||
return i1 != i2 && po.dominates(i1, i2, true)
|
return i1 != i2 && po.dominates(i1, i2, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ordered returns true if n1<=n2. It returns false either when it is
|
// Ordered reports whether n1<=n2. It returns false either when it is
|
||||||
// certain that n1<=n2 is false, or if there is not enough information
|
// certain that n1<=n2 is false, or if there is not enough information
|
||||||
// to tell.
|
// to tell.
|
||||||
// Complexity is O(n).
|
// Complexity is O(n).
|
||||||
|
|
@ -818,7 +818,7 @@ func (po *poset) OrderedOrEqual(n1, n2 *Value) bool {
|
||||||
(po.dominates(i2, i1, false) && !po.dominates(i2, i1, true))
|
(po.dominates(i2, i1, false) && !po.dominates(i2, i1, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal returns true if n1==n2. It returns false either when it is
|
// Equal reports whether n1==n2. It returns false either when it is
|
||||||
// certain that n1==n2 is false, or if there is not enough information
|
// certain that n1==n2 is false, or if there is not enough information
|
||||||
// to tell.
|
// to tell.
|
||||||
// Complexity is O(1).
|
// Complexity is O(1).
|
||||||
|
|
@ -832,7 +832,7 @@ func (po *poset) Equal(n1, n2 *Value) bool {
|
||||||
return f1 && f2 && i1 == i2
|
return f1 && f2 && i1 == i2
|
||||||
}
|
}
|
||||||
|
|
||||||
// NonEqual returns true if n1!=n2. It returns false either when it is
|
// NonEqual reports whether n1!=n2. It returns false either when it is
|
||||||
// certain that n1!=n2 is false, or if there is not enough information
|
// certain that n1!=n2 is false, or if there is not enough information
|
||||||
// to tell.
|
// to tell.
|
||||||
// Complexity is O(n) (because it internally calls Ordered to see if we
|
// Complexity is O(n) (because it internally calls Ordered to see if we
|
||||||
|
|
|
||||||
|
|
@ -485,7 +485,7 @@ func auxTo64F(i int64) float64 {
|
||||||
return math.Float64frombits(uint64(i))
|
return math.Float64frombits(uint64(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
// uaddOvf returns true if unsigned a+b would overflow.
|
// uaddOvf reports whether unsigned a+b would overflow.
|
||||||
func uaddOvf(a, b int64) bool {
|
func uaddOvf(a, b int64) bool {
|
||||||
return uint64(a)+uint64(b) < uint64(a)
|
return uint64(a)+uint64(b) < uint64(a)
|
||||||
}
|
}
|
||||||
|
|
@ -530,6 +530,13 @@ func isSamePtr(p1, p2 *Value) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isStackPtr(v *Value) bool {
|
||||||
|
for v.Op == OpOffPtr || v.Op == OpAddPtr {
|
||||||
|
v = v.Args[0]
|
||||||
|
}
|
||||||
|
return v.Op == OpSP || v.Op == OpLocalAddr
|
||||||
|
}
|
||||||
|
|
||||||
// disjoint reports whether the memory region specified by [p1:p1+n1)
|
// disjoint reports whether the memory region specified by [p1:p1+n1)
|
||||||
// does not overlap with [p2:p2+n2).
|
// does not overlap with [p2:p2+n2).
|
||||||
// A return value of false does not imply the regions overlap.
|
// A return value of false does not imply the regions overlap.
|
||||||
|
|
@ -542,7 +549,7 @@ func disjoint(p1 *Value, n1 int64, p2 *Value, n2 int64) bool {
|
||||||
}
|
}
|
||||||
baseAndOffset := func(ptr *Value) (base *Value, offset int64) {
|
baseAndOffset := func(ptr *Value) (base *Value, offset int64) {
|
||||||
base, offset = ptr, 0
|
base, offset = ptr, 0
|
||||||
if base.Op == OpOffPtr {
|
for base.Op == OpOffPtr {
|
||||||
offset += base.AuxInt
|
offset += base.AuxInt
|
||||||
base = base.Args[0]
|
base = base.Args[0]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30996,6 +30996,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
||||||
b.Aux = nil
|
b.Aux = nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (EQ (CMPconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (EQ (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64EQ
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (EQ (CMPWconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (EQ (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPWconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64EQ
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (EQ (CMPconst [0] z:(AND x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (EQ (ANDCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64AND {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64EQ
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (EQ (CMPconst [0] z:(OR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (EQ (ORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64OR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64EQ
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (EQ (CMPconst [0] z:(XOR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (EQ (XORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64XOR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64EQ
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
case BlockPPC64GE:
|
case BlockPPC64GE:
|
||||||
// match: (GE (FlagEQ) yes no)
|
// match: (GE (FlagEQ) yes no)
|
||||||
// cond:
|
// cond:
|
||||||
|
|
@ -31051,6 +31188,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
||||||
b.Aux = nil
|
b.Aux = nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (GE (CMPconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (GE (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64GE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (GE (CMPWconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (GE (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPWconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64GE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (GE (CMPconst [0] z:(AND x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (GE (ANDCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64AND {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64GE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (GE (CMPconst [0] z:(OR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (GE (ORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64OR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64GE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (GE (CMPconst [0] z:(XOR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (GE (XORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64XOR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64GE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
case BlockPPC64GT:
|
case BlockPPC64GT:
|
||||||
// match: (GT (FlagEQ) yes no)
|
// match: (GT (FlagEQ) yes no)
|
||||||
// cond:
|
// cond:
|
||||||
|
|
@ -31107,6 +31381,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
||||||
b.Aux = nil
|
b.Aux = nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (GT (CMPconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (GT (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64GT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (GT (CMPWconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (GT (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPWconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64GT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (GT (CMPconst [0] z:(AND x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (GT (ANDCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64AND {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64GT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (GT (CMPconst [0] z:(OR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (GT (ORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64OR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64GT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (GT (CMPconst [0] z:(XOR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (GT (XORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64XOR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64GT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
case BlockIf:
|
case BlockIf:
|
||||||
// match: (If (Equal cc) yes no)
|
// match: (If (Equal cc) yes no)
|
||||||
// cond:
|
// cond:
|
||||||
|
|
@ -31318,6 +31729,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
||||||
b.Aux = nil
|
b.Aux = nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (LE (CMPconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (LE (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64LE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LE (CMPWconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (LE (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPWconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64LE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LE (CMPconst [0] z:(AND x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (LE (ANDCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64AND {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64LE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LE (CMPconst [0] z:(OR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (LE (ORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64OR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64LE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LE (CMPconst [0] z:(XOR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (LE (XORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64XOR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64LE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
case BlockPPC64LT:
|
case BlockPPC64LT:
|
||||||
// match: (LT (FlagEQ) yes no)
|
// match: (LT (FlagEQ) yes no)
|
||||||
// cond:
|
// cond:
|
||||||
|
|
@ -31374,6 +31922,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
||||||
b.Aux = nil
|
b.Aux = nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (LT (CMPconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (LT (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64LT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LT (CMPWconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (LT (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPWconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64LT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LT (CMPconst [0] z:(AND x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (LT (ANDCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64AND {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64LT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LT (CMPconst [0] z:(OR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (LT (ORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64OR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64LT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LT (CMPconst [0] z:(XOR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (LT (XORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64XOR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64LT
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
case BlockPPC64NE:
|
case BlockPPC64NE:
|
||||||
// match: (NE (CMPWconst [0] (Equal cc)) yes no)
|
// match: (NE (CMPWconst [0] (Equal cc)) yes no)
|
||||||
// cond:
|
// cond:
|
||||||
|
|
@ -31689,6 +32374,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
||||||
b.Aux = nil
|
b.Aux = nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (NE (CMPconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (NE (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64NE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NE (CMPWconst [0] (ANDconst [c] x)) yes no)
|
||||||
|
// cond:
|
||||||
|
// result: (NE (ANDCCconst [c] x) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPWconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpPPC64ANDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := v_0.AuxInt
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.Kind = BlockPPC64NE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = c
|
||||||
|
v0.AddArg(x)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NE (CMPconst [0] z:(AND x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (NE (ANDCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64AND {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64NE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NE (CMPconst [0] z:(OR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (NE (ORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64OR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64NE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NE (CMPconst [0] z:(XOR x y)) yes no)
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (NE (XORCC x y) yes no)
|
||||||
|
for {
|
||||||
|
v := b.Control
|
||||||
|
if v.Op != OpPPC64CMPconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.AuxInt != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v.Args[0]
|
||||||
|
if z.Op != OpPPC64XOR {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
y := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.Kind = BlockPPC64NE
|
||||||
|
v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v0.AddArg(y)
|
||||||
|
b.SetControl(v0)
|
||||||
|
b.Aux = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17234,6 +17234,8 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||||
func rewriteValuegeneric_OpMove_20(v *Value) bool {
|
func rewriteValuegeneric_OpMove_20(v *Value) bool {
|
||||||
b := v.Block
|
b := v.Block
|
||||||
_ = b
|
_ = b
|
||||||
|
config := b.Func.Config
|
||||||
|
_ = config
|
||||||
// match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} (OffPtr <tt2> [o2] p2) d1 (Store {t3} (OffPtr <tt3> [o3] p3) d2 (Store {t4} (OffPtr <tt4> [o4] p4) d3 (Store {t5} (OffPtr <tt5> [o5] p5) d4 (Zero {t6} [n] p6 _)))))))
|
// match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} (OffPtr <tt2> [o2] p2) d1 (Store {t3} (OffPtr <tt3> [o3] p3) d2 (Store {t4} (OffPtr <tt4> [o4] p4) d3 (Store {t5} (OffPtr <tt5> [o5] p5) d4 (Zero {t6} [n] p6 _)))))))
|
||||||
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && isSamePtr(p5, p6) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && alignof(t5) <= alignof(t1) && alignof(t6) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && n >= o2 + sizeof(t2) && n >= o3 + sizeof(t3) && n >= o4 + sizeof(t4) && n >= o5 + sizeof(t5)
|
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && isSamePtr(p5, p6) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && alignof(t5) <= alignof(t1) && alignof(t6) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && n >= o2 + sizeof(t2) && n >= o3 + sizeof(t3) && n >= o4 + sizeof(t4) && n >= o5 + sizeof(t5)
|
||||||
// result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [o5] dst) d4 (Zero {t1} [n] dst mem)))))
|
// result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [o5] dst) d4 (Zero {t1} [n] dst mem)))))
|
||||||
|
|
@ -17355,11 +17357,11 @@ func rewriteValuegeneric_OpMove_20(v *Value) bool {
|
||||||
v.AddArg(v1)
|
v.AddArg(v1)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Move {t1} [s1] dst tmp1 midmem:(Move {t2} [s2] tmp2 src _))
|
// match: (Move {t1} [s] dst tmp1 midmem:(Move {t2} [s] tmp2 src _))
|
||||||
// cond: s1 == s2 && t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq && isSamePtr(tmp1, tmp2)
|
// cond: t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))
|
||||||
// result: (Move {t1} [s1] dst src midmem)
|
// result: (Move {t1} [s] dst src midmem)
|
||||||
for {
|
for {
|
||||||
s1 := v.AuxInt
|
s := v.AuxInt
|
||||||
t1 := v.Aux
|
t1 := v.Aux
|
||||||
_ = v.Args[2]
|
_ = v.Args[2]
|
||||||
dst := v.Args[0]
|
dst := v.Args[0]
|
||||||
|
|
@ -17368,16 +17370,53 @@ func rewriteValuegeneric_OpMove_20(v *Value) bool {
|
||||||
if midmem.Op != OpMove {
|
if midmem.Op != OpMove {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s2 := midmem.AuxInt
|
if midmem.AuxInt != s {
|
||||||
|
break
|
||||||
|
}
|
||||||
t2 := midmem.Aux
|
t2 := midmem.Aux
|
||||||
_ = midmem.Args[2]
|
_ = midmem.Args[2]
|
||||||
tmp2 := midmem.Args[0]
|
tmp2 := midmem.Args[0]
|
||||||
src := midmem.Args[1]
|
src := midmem.Args[1]
|
||||||
if !(s1 == s2 && t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq && isSamePtr(tmp1, tmp2)) {
|
if !(t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpMove)
|
v.reset(OpMove)
|
||||||
v.AuxInt = s1
|
v.AuxInt = s
|
||||||
|
v.Aux = t1
|
||||||
|
v.AddArg(dst)
|
||||||
|
v.AddArg(src)
|
||||||
|
v.AddArg(midmem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Move {t1} [s] dst tmp1 midmem:(VarDef (Move {t2} [s] tmp2 src _)))
|
||||||
|
// cond: t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))
|
||||||
|
// result: (Move {t1} [s] dst src midmem)
|
||||||
|
for {
|
||||||
|
s := v.AuxInt
|
||||||
|
t1 := v.Aux
|
||||||
|
_ = v.Args[2]
|
||||||
|
dst := v.Args[0]
|
||||||
|
tmp1 := v.Args[1]
|
||||||
|
midmem := v.Args[2]
|
||||||
|
if midmem.Op != OpVarDef {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
midmem_0 := midmem.Args[0]
|
||||||
|
if midmem_0.Op != OpMove {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if midmem_0.AuxInt != s {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
t2 := midmem_0.Aux
|
||||||
|
_ = midmem_0.Args[2]
|
||||||
|
tmp2 := midmem_0.Args[0]
|
||||||
|
src := midmem_0.Args[1]
|
||||||
|
if !(t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq && isSamePtr(tmp1, tmp2) && isStackPtr(src) && disjoint(src, s, tmp2, s) && (disjoint(src, s, dst, s) || isInlinableMemmove(dst, src, s, config))) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpMove)
|
||||||
|
v.AuxInt = s
|
||||||
v.Aux = t1
|
v.Aux = t1
|
||||||
v.AddArg(dst)
|
v.AddArg(dst)
|
||||||
v.AddArg(src)
|
v.AddArg(src)
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,13 @@
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
86: for i, a := range hist {
|
86: for i, a := range hist {
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
91: n += a
|
91: n += a
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
86: for i, a := range hist {
|
86: for i, a := range hist {
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
91: n += a
|
91: n += a
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
|
|
@ -70,11 +72,13 @@
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
86: for i, a := range hist {
|
86: for i, a := range hist {
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
91: n += a
|
91: n += a
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
86: for i, a := range hist {
|
86: for i, a := range hist {
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
91: n += a
|
91: n += a
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ t = 0
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
91: n += a
|
91: n += a
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
86: for i, a := range hist {
|
86: for i, a := range hist {
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
a = 3
|
a = 3
|
||||||
|
|
@ -131,6 +132,7 @@ t = 3
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
91: n += a
|
91: n += a
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
86: for i, a := range hist {
|
86: for i, a := range hist {
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
a = 0
|
a = 0
|
||||||
|
|
@ -144,6 +146,7 @@ t = 9
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
91: n += a
|
91: n += a
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
86: for i, a := range hist {
|
86: for i, a := range hist {
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
a = 1
|
a = 1
|
||||||
|
|
@ -152,6 +155,7 @@ t = 17
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
91: n += a
|
91: n += a
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
86: for i, a := range hist {
|
86: for i, a := range hist {
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
a = 0
|
a = 0
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ func trim(f *Func) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// emptyBlock returns true if the block does not contain actual
|
// emptyBlock reports whether the block does not contain actual
|
||||||
// instructions
|
// instructions
|
||||||
func emptyBlock(b *Block) bool {
|
func emptyBlock(b *Block) bool {
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
|
|
@ -105,7 +105,7 @@ func emptyBlock(b *Block) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// trimmableBlock returns true if the block can be trimmed from the CFG,
|
// trimmableBlock reports whether the block can be trimmed from the CFG,
|
||||||
// subject to the following criteria:
|
// subject to the following criteria:
|
||||||
// - it should not be the first block
|
// - it should not be the first block
|
||||||
// - it should be BlockPlain
|
// - it should be BlockPlain
|
||||||
|
|
|
||||||
|
|
@ -149,8 +149,11 @@ type Type struct {
|
||||||
Nod *Node // canonical OTYPE node
|
Nod *Node // canonical OTYPE node
|
||||||
Orig *Type // original type (type literal or predefined type)
|
Orig *Type // original type (type literal or predefined type)
|
||||||
|
|
||||||
SliceOf *Type
|
// Cache of composite types, with this type being the element type.
|
||||||
PtrBase *Type
|
Cache struct {
|
||||||
|
ptr *Type // *T, or nil
|
||||||
|
slice *Type // []T, or nil
|
||||||
|
}
|
||||||
|
|
||||||
Sym *Sym // symbol containing name, for named types
|
Sym *Sym // symbol containing name, for named types
|
||||||
Vargen int32 // unique name for OTYPE/ONAME
|
Vargen int32 // unique name for OTYPE/ONAME
|
||||||
|
|
@ -488,7 +491,7 @@ func NewArray(elem *Type, bound int64) *Type {
|
||||||
|
|
||||||
// NewSlice returns the slice Type with element type elem.
|
// NewSlice returns the slice Type with element type elem.
|
||||||
func NewSlice(elem *Type) *Type {
|
func NewSlice(elem *Type) *Type {
|
||||||
if t := elem.SliceOf; t != nil {
|
if t := elem.Cache.slice; t != nil {
|
||||||
if t.Elem() != elem {
|
if t.Elem() != elem {
|
||||||
Fatalf("elem mismatch")
|
Fatalf("elem mismatch")
|
||||||
}
|
}
|
||||||
|
|
@ -497,7 +500,7 @@ func NewSlice(elem *Type) *Type {
|
||||||
|
|
||||||
t := New(TSLICE)
|
t := New(TSLICE)
|
||||||
t.Extra = Slice{Elem: elem}
|
t.Extra = Slice{Elem: elem}
|
||||||
elem.SliceOf = t
|
elem.Cache.slice = t
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -551,7 +554,7 @@ func NewPtr(elem *Type) *Type {
|
||||||
Fatalf("NewPtr: pointer to elem Type is nil")
|
Fatalf("NewPtr: pointer to elem Type is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if t := elem.PtrBase; t != nil {
|
if t := elem.Cache.ptr; t != nil {
|
||||||
if t.Elem() != elem {
|
if t.Elem() != elem {
|
||||||
Fatalf("NewPtr: elem mismatch")
|
Fatalf("NewPtr: elem mismatch")
|
||||||
}
|
}
|
||||||
|
|
@ -563,7 +566,7 @@ func NewPtr(elem *Type) *Type {
|
||||||
t.Width = int64(Widthptr)
|
t.Width = int64(Widthptr)
|
||||||
t.Align = uint8(Widthptr)
|
t.Align = uint8(Widthptr)
|
||||||
if NewPtrCacheEnabled {
|
if NewPtrCacheEnabled {
|
||||||
elem.PtrBase = t
|
elem.Cache.ptr = t
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
@ -662,24 +665,19 @@ func SubstAny(t *Type, types *[]*Type) *Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
|
// Make a copy of all fields, including ones whose type does not change.
|
||||||
|
// This prevents aliasing across functions, which can lead to later
|
||||||
|
// fields getting their Offset incorrectly overwritten.
|
||||||
fields := t.FieldSlice()
|
fields := t.FieldSlice()
|
||||||
var nfs []*Field
|
nfs := make([]*Field, len(fields))
|
||||||
for i, f := range fields {
|
for i, f := range fields {
|
||||||
nft := SubstAny(f.Type, types)
|
nft := SubstAny(f.Type, types)
|
||||||
if nft == f.Type {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if nfs == nil {
|
|
||||||
nfs = append([]*Field(nil), fields...)
|
|
||||||
}
|
|
||||||
nfs[i] = f.Copy()
|
nfs[i] = f.Copy()
|
||||||
nfs[i].Type = nft
|
nfs[i].Type = nft
|
||||||
}
|
}
|
||||||
if nfs != nil {
|
|
||||||
t = t.copy()
|
t = t.copy()
|
||||||
t.SetFields(nfs)
|
t.SetFields(nfs)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
@ -1258,6 +1256,11 @@ func (t *Type) IsPtr() bool {
|
||||||
return t.Etype == TPTR
|
return t.Etype == TPTR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsPtrElem reports whether t is the element of a pointer (to t).
|
||||||
|
func (t *Type) IsPtrElem() bool {
|
||||||
|
return t.Cache.ptr != nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsUnsafePtr reports whether t is an unsafe pointer.
|
// IsUnsafePtr reports whether t is an unsafe pointer.
|
||||||
func (t *Type) IsUnsafePtr() bool {
|
func (t *Type) IsUnsafePtr() bool {
|
||||||
return t.Etype == TUNSAFEPTR
|
return t.Etype == TUNSAFEPTR
|
||||||
|
|
|
||||||
|
|
@ -478,7 +478,7 @@ func newPkgDot(pos token.Pos, pkg, name string) ast.Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
// renameTop renames all references to the top-level name old.
|
// renameTop renames all references to the top-level name old.
|
||||||
// It returns true if it makes any changes.
|
// It reports whether it makes any changes.
|
||||||
func renameTop(f *ast.File, old, new string) bool {
|
func renameTop(f *ast.File, old, new string) bool {
|
||||||
var fixed bool
|
var fixed bool
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -972,6 +972,8 @@
|
||||||
// and -dropreplace editing flags may be repeated, and the changes
|
// and -dropreplace editing flags may be repeated, and the changes
|
||||||
// are applied in the order given.
|
// are applied in the order given.
|
||||||
//
|
//
|
||||||
|
// The -go=version flag sets the expected Go language version.
|
||||||
|
//
|
||||||
// The -print flag prints the final go.mod in its text format instead of
|
// The -print flag prints the final go.mod in its text format instead of
|
||||||
// writing it back to go.mod.
|
// writing it back to go.mod.
|
||||||
//
|
//
|
||||||
|
|
@ -985,6 +987,7 @@
|
||||||
//
|
//
|
||||||
// type GoMod struct {
|
// type GoMod struct {
|
||||||
// Module Module
|
// Module Module
|
||||||
|
// Go string
|
||||||
// Require []Require
|
// Require []Require
|
||||||
// Exclude []Module
|
// Exclude []Module
|
||||||
// Replace []Replace
|
// Replace []Replace
|
||||||
|
|
@ -1604,17 +1607,20 @@
|
||||||
// verb followed by arguments. For example:
|
// verb followed by arguments. For example:
|
||||||
//
|
//
|
||||||
// module my/thing
|
// module my/thing
|
||||||
|
// go 1.12
|
||||||
// require other/thing v1.0.2
|
// require other/thing v1.0.2
|
||||||
// require new/thing v2.3.4
|
// require new/thing/v2 v2.3.4
|
||||||
// exclude old/thing v1.2.3
|
// exclude old/thing v1.2.3
|
||||||
// replace bad/thing v1.4.5 => good/thing v1.4.5
|
// replace bad/thing v1.4.5 => good/thing v1.4.5
|
||||||
//
|
//
|
||||||
// The verbs are module, to define the module path; require, to require
|
// The verbs are
|
||||||
// a particular module at a given version or later; exclude, to exclude
|
// module, to define the module path;
|
||||||
// a particular module version from use; and replace, to replace a module
|
// go, to set the expected language version;
|
||||||
// version with a different module version. Exclude and replace apply only
|
// require, to require a particular module at a given version or later;
|
||||||
// in the main module's go.mod and are ignored in dependencies.
|
// exclude, to exclude a particular module version from use; and
|
||||||
// See https://research.swtch.com/vgo-mvs for details.
|
// replace, to replace a module version with a different module version.
|
||||||
|
// Exclude and replace apply only in the main module's go.mod and are ignored
|
||||||
|
// in dependencies. See https://research.swtch.com/vgo-mvs for details.
|
||||||
//
|
//
|
||||||
// The leading verb can be factored out of adjacent lines to create a block,
|
// The leading verb can be factored out of adjacent lines to create a block,
|
||||||
// like in Go imports:
|
// like in Go imports:
|
||||||
|
|
|
||||||
2
src/cmd/go/internal/cache/hash.go
vendored
2
src/cmd/go/internal/cache/hash.go
vendored
|
|
@ -123,7 +123,7 @@ var hashFileCache struct {
|
||||||
m map[string][HashSize]byte
|
m map[string][HashSize]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashFile returns the hash of the named file.
|
// FileHash returns the hash of the named file.
|
||||||
// It caches repeated lookups for a given file,
|
// It caches repeated lookups for a given file,
|
||||||
// and the cache entry for a file can be initialized
|
// and the cache entry for a file can be initialized
|
||||||
// using SetFileHash.
|
// using SetFileHash.
|
||||||
|
|
|
||||||
|
|
@ -79,15 +79,15 @@ func AddKnownFlags(cmd string, defns []*Defn) {
|
||||||
|
|
||||||
// Parse sees if argument i is present in the definitions and if so,
|
// Parse sees if argument i is present in the definitions and if so,
|
||||||
// returns its definition, value, and whether it consumed an extra word.
|
// returns its definition, value, and whether it consumed an extra word.
|
||||||
// If the flag begins (cmd+".") it is ignored for the purpose of this function.
|
// If the flag begins (cmd.Name()+".") it is ignored for the purpose of this function.
|
||||||
func Parse(cmd string, defns []*Defn, args []string, i int) (f *Defn, value string, extra bool) {
|
func Parse(cmd string, usage func(), defns []*Defn, args []string, i int) (f *Defn, value string, extra bool) {
|
||||||
arg := args[i]
|
arg := args[i]
|
||||||
if strings.HasPrefix(arg, "--") { // reduce two minuses to one
|
if strings.HasPrefix(arg, "--") { // reduce two minuses to one
|
||||||
arg = arg[1:]
|
arg = arg[1:]
|
||||||
}
|
}
|
||||||
switch arg {
|
switch arg {
|
||||||
case "-?", "-h", "-help":
|
case "-?", "-h", "-help":
|
||||||
base.Usage()
|
usage()
|
||||||
}
|
}
|
||||||
if arg == "" || arg[0] != '-' {
|
if arg == "" || arg[0] != '-' {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@ The -require, -droprequire, -exclude, -dropexclude, -replace,
|
||||||
and -dropreplace editing flags may be repeated, and the changes
|
and -dropreplace editing flags may be repeated, and the changes
|
||||||
are applied in the order given.
|
are applied in the order given.
|
||||||
|
|
||||||
|
The -go=version flag sets the expected Go language version.
|
||||||
|
|
||||||
The -print flag prints the final go.mod in its text format instead of
|
The -print flag prints the final go.mod in its text format instead of
|
||||||
writing it back to go.mod.
|
writing it back to go.mod.
|
||||||
|
|
||||||
|
|
@ -75,6 +77,7 @@ writing it back to go.mod. The JSON output corresponds to these Go types:
|
||||||
|
|
||||||
type GoMod struct {
|
type GoMod struct {
|
||||||
Module Module
|
Module Module
|
||||||
|
Go string
|
||||||
Require []Require
|
Require []Require
|
||||||
Exclude []Module
|
Exclude []Module
|
||||||
Replace []Replace
|
Replace []Replace
|
||||||
|
|
@ -103,7 +106,7 @@ by invoking 'go mod edit' with -require, -exclude, and so on.
|
||||||
|
|
||||||
var (
|
var (
|
||||||
editFmt = cmdEdit.Flag.Bool("fmt", false, "")
|
editFmt = cmdEdit.Flag.Bool("fmt", false, "")
|
||||||
// editGo = cmdEdit.Flag.String("go", "", "")
|
editGo = cmdEdit.Flag.String("go", "", "")
|
||||||
editJSON = cmdEdit.Flag.Bool("json", false, "")
|
editJSON = cmdEdit.Flag.Bool("json", false, "")
|
||||||
editPrint = cmdEdit.Flag.Bool("print", false, "")
|
editPrint = cmdEdit.Flag.Bool("print", false, "")
|
||||||
editModule = cmdEdit.Flag.String("module", "", "")
|
editModule = cmdEdit.Flag.String("module", "", "")
|
||||||
|
|
@ -131,6 +134,7 @@ func init() {
|
||||||
func runEdit(cmd *base.Command, args []string) {
|
func runEdit(cmd *base.Command, args []string) {
|
||||||
anyFlags :=
|
anyFlags :=
|
||||||
*editModule != "" ||
|
*editModule != "" ||
|
||||||
|
*editGo != "" ||
|
||||||
*editJSON ||
|
*editJSON ||
|
||||||
*editPrint ||
|
*editPrint ||
|
||||||
*editFmt ||
|
*editFmt ||
|
||||||
|
|
@ -161,7 +165,11 @@ func runEdit(cmd *base.Command, args []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rsc): Implement -go= once we start advertising it.
|
if *editGo != "" {
|
||||||
|
if !modfile.GoVersionRE.MatchString(*editGo) {
|
||||||
|
base.Fatalf(`go mod: invalid -go option; expecting something like "-go 1.12"`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(gomod)
|
data, err := ioutil.ReadFile(gomod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -177,6 +185,12 @@ func runEdit(cmd *base.Command, args []string) {
|
||||||
modFile.AddModuleStmt(modload.CmdModModule)
|
modFile.AddModuleStmt(modload.CmdModModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *editGo != "" {
|
||||||
|
if err := modFile.AddGoStmt(*editGo); err != nil {
|
||||||
|
base.Fatalf("go: internal error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(edits) > 0 {
|
if len(edits) > 0 {
|
||||||
for _, edit := range edits {
|
for _, edit := range edits {
|
||||||
edit(modFile)
|
edit(modFile)
|
||||||
|
|
@ -344,6 +358,7 @@ func flagDropReplace(arg string) {
|
||||||
// fileJSON is the -json output data structure.
|
// fileJSON is the -json output data structure.
|
||||||
type fileJSON struct {
|
type fileJSON struct {
|
||||||
Module module.Version
|
Module module.Version
|
||||||
|
Go string `json:",omitempty"`
|
||||||
Require []requireJSON
|
Require []requireJSON
|
||||||
Exclude []module.Version
|
Exclude []module.Version
|
||||||
Replace []replaceJSON
|
Replace []replaceJSON
|
||||||
|
|
@ -364,6 +379,9 @@ type replaceJSON struct {
|
||||||
func editPrintJSON(modFile *modfile.File) {
|
func editPrintJSON(modFile *modfile.File) {
|
||||||
var f fileJSON
|
var f fileJSON
|
||||||
f.Module = modFile.Module.Mod
|
f.Module = modFile.Module.Mod
|
||||||
|
if modFile.Go != nil {
|
||||||
|
f.Go = modFile.Go.Version
|
||||||
|
}
|
||||||
for _, r := range modFile.Require {
|
for _, r := range modFile.Require {
|
||||||
f.Require = append(f.Require, requireJSON{Path: r.Mod.Path, Version: r.Mod.Version, Indirect: r.Indirect})
|
f.Require = append(f.Require, requireJSON{Path: r.Mod.Path, Version: r.Mod.Version, Indirect: r.Indirect})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var goVersionRE = regexp.MustCompile(`([1-9][0-9]*)\.(0|[1-9][0-9]*)`)
|
var GoVersionRE = regexp.MustCompile(`([1-9][0-9]*)\.(0|[1-9][0-9]*)`)
|
||||||
|
|
||||||
func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
|
func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
|
||||||
// If strict is false, this module is a dependency.
|
// If strict is false, this module is a dependency.
|
||||||
|
|
@ -181,7 +181,7 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
|
||||||
fmt.Fprintf(errs, "%s:%d: repeated go statement\n", f.Syntax.Name, line.Start.Line)
|
fmt.Fprintf(errs, "%s:%d: repeated go statement\n", f.Syntax.Name, line.Start.Line)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(args) != 1 || !goVersionRE.MatchString(args[0]) {
|
if len(args) != 1 || !GoVersionRE.MatchString(args[0]) {
|
||||||
fmt.Fprintf(errs, "%s:%d: usage: go 1.23\n", f.Syntax.Name, line.Start.Line)
|
fmt.Fprintf(errs, "%s:%d: usage: go 1.23\n", f.Syntax.Name, line.Start.Line)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -477,6 +477,22 @@ func (f *File) Cleanup() {
|
||||||
f.Syntax.Cleanup()
|
f.Syntax.Cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *File) AddGoStmt(version string) error {
|
||||||
|
if !GoVersionRE.MatchString(version) {
|
||||||
|
return fmt.Errorf("invalid language version string %q", version)
|
||||||
|
}
|
||||||
|
if f.Go == nil {
|
||||||
|
f.Go = &Go{
|
||||||
|
Version: version,
|
||||||
|
Syntax: f.Syntax.addLine(nil, "go", version),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f.Go.Version = version
|
||||||
|
f.Syntax.updateLine(f.Go.Syntax, "go", version)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (f *File) AddRequire(path, vers string) error {
|
func (f *File) AddRequire(path, vers string) error {
|
||||||
need := true
|
need := true
|
||||||
for _, r := range f.Require {
|
for _, r := range f.Require {
|
||||||
|
|
|
||||||
|
|
@ -393,17 +393,20 @@ no /* */ comments. Each line holds a single directive, made up of a
|
||||||
verb followed by arguments. For example:
|
verb followed by arguments. For example:
|
||||||
|
|
||||||
module my/thing
|
module my/thing
|
||||||
|
go 1.12
|
||||||
require other/thing v1.0.2
|
require other/thing v1.0.2
|
||||||
require new/thing v2.3.4
|
require new/thing/v2 v2.3.4
|
||||||
exclude old/thing v1.2.3
|
exclude old/thing v1.2.3
|
||||||
replace bad/thing v1.4.5 => good/thing v1.4.5
|
replace bad/thing v1.4.5 => good/thing v1.4.5
|
||||||
|
|
||||||
The verbs are module, to define the module path; require, to require
|
The verbs are
|
||||||
a particular module at a given version or later; exclude, to exclude
|
module, to define the module path;
|
||||||
a particular module version from use; and replace, to replace a module
|
go, to set the expected language version;
|
||||||
version with a different module version. Exclude and replace apply only
|
require, to require a particular module at a given version or later;
|
||||||
in the main module's go.mod and are ignored in dependencies.
|
exclude, to exclude a particular module version from use; and
|
||||||
See https://research.swtch.com/vgo-mvs for details.
|
replace, to replace a module version with a different module version.
|
||||||
|
Exclude and replace apply only in the main module's go.mod and are ignored
|
||||||
|
in dependencies. See https://research.swtch.com/vgo-mvs for details.
|
||||||
|
|
||||||
The leading verb can be factored out of adjacent lines to create a block,
|
The leading verb can be factored out of adjacent lines to create a block,
|
||||||
like in Go imports:
|
like in Go imports:
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"cmd/go/internal/search"
|
"cmd/go/internal/search"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/build"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
@ -335,6 +336,8 @@ func legacyModInit() {
|
||||||
modFile.AddModuleStmt(path)
|
modFile.AddModuleStmt(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addGoStmt()
|
||||||
|
|
||||||
for _, name := range altConfigs {
|
for _, name := range altConfigs {
|
||||||
cfg := filepath.Join(ModRoot, name)
|
cfg := filepath.Join(ModRoot, name)
|
||||||
data, err := ioutil.ReadFile(cfg)
|
data, err := ioutil.ReadFile(cfg)
|
||||||
|
|
@ -357,6 +360,25 @@ func legacyModInit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InitGoStmt adds a go statement, unless there already is one.
|
||||||
|
func InitGoStmt() {
|
||||||
|
if modFile.Go == nil {
|
||||||
|
addGoStmt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// addGoStmt adds a go statement referring to the current version.
|
||||||
|
func addGoStmt() {
|
||||||
|
tags := build.Default.ReleaseTags
|
||||||
|
version := tags[len(tags)-1]
|
||||||
|
if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) {
|
||||||
|
base.Fatalf("go: unrecognized default version %q", version)
|
||||||
|
}
|
||||||
|
if err := modFile.AddGoStmt(version[2:]); err != nil {
|
||||||
|
base.Fatalf("go: internal error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var altConfigs = []string{
|
var altConfigs = []string{
|
||||||
"Gopkg.lock",
|
"Gopkg.lock",
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,16 +124,6 @@ A cached test result is treated as executing in no time at all,
|
||||||
so a successful package test result will be cached and reused
|
so a successful package test result will be cached and reused
|
||||||
regardless of -timeout setting.
|
regardless of -timeout setting.
|
||||||
|
|
||||||
` + strings.TrimSpace(testFlag1) + ` See 'go help testflag' for details.
|
|
||||||
|
|
||||||
For more about build flags, see 'go help build'.
|
|
||||||
For more about specifying packages, see 'go help packages'.
|
|
||||||
|
|
||||||
See also: go build, go vet.
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
|
|
||||||
const testFlag1 = `
|
|
||||||
In addition to the build flags, the flags handled by 'go test' itself are:
|
In addition to the build flags, the flags handled by 'go test' itself are:
|
||||||
|
|
||||||
-args
|
-args
|
||||||
|
|
@ -164,15 +154,13 @@ In addition to the build flags, the flags handled by 'go test' itself are:
|
||||||
The test still runs (unless -c or -i is specified).
|
The test still runs (unless -c or -i is specified).
|
||||||
|
|
||||||
The test binary also accepts flags that control execution of the test; these
|
The test binary also accepts flags that control execution of the test; these
|
||||||
flags are also accessible by 'go test'.
|
flags are also accessible by 'go test'. See 'go help testflag' for details.
|
||||||
`
|
|
||||||
|
|
||||||
// Usage prints the usage message for 'go test -h' and exits.
|
For more about build flags, see 'go help build'.
|
||||||
func Usage() {
|
For more about specifying packages, see 'go help packages'.
|
||||||
os.Stderr.WriteString("usage: " + testUsage + "\n\n" +
|
|
||||||
strings.TrimSpace(testFlag1) + "\n\n\t" +
|
See also: go build, go vet.
|
||||||
strings.TrimSpace(testFlag2) + "\n")
|
`,
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var HelpTestflag = &base.Command{
|
var HelpTestflag = &base.Command{
|
||||||
|
|
@ -190,11 +178,6 @@ options of pprof control how the information is presented.
|
||||||
The following flags are recognized by the 'go test' command and
|
The following flags are recognized by the 'go test' command and
|
||||||
control the execution of any test:
|
control the execution of any test:
|
||||||
|
|
||||||
` + strings.TrimSpace(testFlag2) + `
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
|
|
||||||
const testFlag2 = `
|
|
||||||
-bench regexp
|
-bench regexp
|
||||||
Run only those benchmarks matching a regular expression.
|
Run only those benchmarks matching a regular expression.
|
||||||
By default, no benchmarks are run.
|
By default, no benchmarks are run.
|
||||||
|
|
@ -414,7 +397,8 @@ In the first example, the -x and the second -v are passed through to the
|
||||||
test binary unchanged and with no effect on the go command itself.
|
test binary unchanged and with no effect on the go command itself.
|
||||||
In the second example, the argument math is passed through to the test
|
In the second example, the argument math is passed through to the test
|
||||||
binary, instead of being interpreted as the package list.
|
binary, instead of being interpreted as the package list.
|
||||||
`
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
var HelpTestfunc = &base.Command{
|
var HelpTestfunc = &base.Command{
|
||||||
UsageLine: "testfunc",
|
UsageLine: "testfunc",
|
||||||
|
|
@ -532,7 +516,7 @@ var testVetFlags = []string{
|
||||||
func runTest(cmd *base.Command, args []string) {
|
func runTest(cmd *base.Command, args []string) {
|
||||||
modload.LoadTests = true
|
modload.LoadTests = true
|
||||||
|
|
||||||
pkgArgs, testArgs = testFlags(args)
|
pkgArgs, testArgs = testFlags(cmd.Usage, args)
|
||||||
|
|
||||||
work.FindExecCmd() // initialize cached result
|
work.FindExecCmd() // initialize cached result
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ func init() {
|
||||||
// to allow both
|
// to allow both
|
||||||
// go test fmt -custom-flag-for-fmt-test
|
// go test fmt -custom-flag-for-fmt-test
|
||||||
// go test -x math
|
// go test -x math
|
||||||
func testFlags(args []string) (packageNames, passToTest []string) {
|
func testFlags(usage func(), args []string) (packageNames, passToTest []string) {
|
||||||
args = str.StringList(cmdflag.FindGOFLAGS(testFlagDefn), args)
|
args = str.StringList(cmdflag.FindGOFLAGS(testFlagDefn), args)
|
||||||
inPkg := false
|
inPkg := false
|
||||||
var explicitArgs []string
|
var explicitArgs []string
|
||||||
|
|
@ -108,7 +108,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
|
||||||
inPkg = false
|
inPkg = false
|
||||||
}
|
}
|
||||||
|
|
||||||
f, value, extraWord := cmdflag.Parse(cmd, testFlagDefn, args, i)
|
f, value, extraWord := cmdflag.Parse(cmd, usage, testFlagDefn, args, i)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
// This is a flag we do not know; we must assume
|
// This is a flag we do not know; we must assume
|
||||||
// that any args we see after this might be flag
|
// that any args we see after this might be flag
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ See also: go fmt, go fix.
|
||||||
func runVet(cmd *base.Command, args []string) {
|
func runVet(cmd *base.Command, args []string) {
|
||||||
modload.LoadTests = true
|
modload.LoadTests = true
|
||||||
|
|
||||||
vetFlags, pkgArgs := vetFlags(args)
|
vetFlags, pkgArgs := vetFlags(cmd.Usage, args)
|
||||||
|
|
||||||
work.BuildInit()
|
work.BuildInit()
|
||||||
work.VetFlags = vetFlags
|
work.VetFlags = vetFlags
|
||||||
|
|
|
||||||
|
|
@ -23,24 +23,43 @@ import (
|
||||||
|
|
||||||
// go vet flag processing
|
// go vet flag processing
|
||||||
//
|
//
|
||||||
// We query the flags of the tool specified by GOVETTOOL (default:
|
// We query the flags of the tool specified by -vettool and accept any
|
||||||
// cmd/vet) and accept any of those flags plus any flag valid for 'go
|
// of those flags plus any flag valid for 'go build'. The tool must
|
||||||
// build'. The tool must support -flags, which prints a description of
|
// support -flags, which prints a description of its flags in JSON to
|
||||||
// its flags in JSON to stdout.
|
// stdout.
|
||||||
|
|
||||||
// GOVETTOOL specifies the vet command to run.
|
// vetTool specifies the vet command to run.
|
||||||
// This must be an environment variable because
|
// Any tool that supports the (still unpublished) vet
|
||||||
// we need it before flag processing, as we execute
|
// command-line protocol may be supplied; see
|
||||||
// $GOVETTOOL to discover the set of flags it supports.
|
// golang.org/x/tools/go/analysis/unitchecker for one
|
||||||
|
// implementation. It is also used by tests.
|
||||||
//
|
//
|
||||||
// Using an environment variable also makes it easy for users to opt in
|
// The default behavior (vetTool=="") runs 'go tool vet'.
|
||||||
// to (and later, opt out of) the new cmd/vet analysis driver during the
|
//
|
||||||
// transition. It is also used by tests.
|
var vetTool string // -vettool
|
||||||
var vetTool = os.Getenv("GOVETTOOL")
|
|
||||||
|
func init() {
|
||||||
|
// Extract -vettool by ad hoc flag processing:
|
||||||
|
// its value is needed even before we can declare
|
||||||
|
// the flags available during main flag processing.
|
||||||
|
for i, arg := range os.Args {
|
||||||
|
if arg == "-vettool" || arg == "--vettool" {
|
||||||
|
if i+1 >= len(os.Args) {
|
||||||
|
log.Fatalf("%s requires a filename", arg)
|
||||||
|
}
|
||||||
|
vetTool = os.Args[i+1]
|
||||||
|
break
|
||||||
|
} else if strings.HasPrefix(arg, "-vettool=") ||
|
||||||
|
strings.HasPrefix(arg, "--vettool=") {
|
||||||
|
vetTool = arg[strings.IndexByte(arg, '=')+1:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// vetFlags processes the command line, splitting it at the first non-flag
|
// vetFlags processes the command line, splitting it at the first non-flag
|
||||||
// into the list of flags and list of packages.
|
// into the list of flags and list of packages.
|
||||||
func vetFlags(args []string) (passToVet, packageNames []string) {
|
func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
|
||||||
// Query the vet command for its flags.
|
// Query the vet command for its flags.
|
||||||
tool := vetTool
|
tool := vetTool
|
||||||
if tool != "" {
|
if tool != "" {
|
||||||
|
|
@ -94,6 +113,9 @@ func vetFlags(args []string) (passToVet, packageNames []string) {
|
||||||
// Add build flags to vetFlagDefn.
|
// Add build flags to vetFlagDefn.
|
||||||
var cmd base.Command
|
var cmd base.Command
|
||||||
work.AddBuildFlags(&cmd)
|
work.AddBuildFlags(&cmd)
|
||||||
|
// This flag declaration is a placeholder:
|
||||||
|
// -vettool is actually parsed by the init function above.
|
||||||
|
cmd.Flag.StringVar(new(string), "vettool", "", "path to vet tool binary")
|
||||||
cmd.Flag.VisitAll(func(f *flag.Flag) {
|
cmd.Flag.VisitAll(func(f *flag.Flag) {
|
||||||
vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{
|
vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{
|
||||||
Name: f.Name,
|
Name: f.Name,
|
||||||
|
|
@ -108,7 +130,7 @@ func vetFlags(args []string) (passToVet, packageNames []string) {
|
||||||
return args[:i], args[i:]
|
return args[:i], args[i:]
|
||||||
}
|
}
|
||||||
|
|
||||||
f, value, extraWord := cmdflag.Parse("vet", vetFlagDefn, args, i)
|
f, value, extraWord := cmdflag.Parse("vet", usage, vetFlagDefn, args, i)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
|
fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
|
||||||
fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
|
fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,8 @@ func (b *Builder) toolID(name string) string {
|
||||||
path := base.Tool(name)
|
path := base.Tool(name)
|
||||||
desc := "go tool " + name
|
desc := "go tool " + name
|
||||||
|
|
||||||
// Special case: undocumented $GOVETTOOL overrides usual vet, for testing vet.
|
// Special case: undocumented -vettool overrides usual vet,
|
||||||
|
// for testing vet or supplying an alternative analysis tool.
|
||||||
if name == "vet" && VetTool != "" {
|
if name == "vet" && VetTool != "" {
|
||||||
path = VetTool
|
path = VetTool
|
||||||
desc = VetTool
|
desc = VetTool
|
||||||
|
|
|
||||||
|
|
@ -434,10 +434,6 @@ func (b *Builder) build(a *Action) (err error) {
|
||||||
return fmt.Errorf("missing or invalid binary-only package; expected file %q", a.Package.Target)
|
return fmt.Errorf("missing or invalid binary-only package; expected file %q", a.Package.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
|
|
||||||
return fmt.Errorf("module requires Go %s", p.Module.GoVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := b.Mkdir(a.Objdir); err != nil {
|
if err := b.Mkdir(a.Objdir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -638,12 +634,19 @@ func (b *Builder) build(a *Action) (err error) {
|
||||||
objpkg := objdir + "_pkg_.a"
|
objpkg := objdir + "_pkg_.a"
|
||||||
ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), len(sfiles) > 0, gofiles)
|
ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), len(sfiles) > 0, gofiles)
|
||||||
if len(out) > 0 {
|
if len(out) > 0 {
|
||||||
b.showOutput(a, a.Package.Dir, a.Package.Desc(), b.processOutput(out))
|
output := b.processOutput(out)
|
||||||
|
if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
|
||||||
|
output += "note: module requires Go " + p.Module.GoVersion
|
||||||
|
}
|
||||||
|
b.showOutput(a, a.Package.Dir, a.Package.Desc(), output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errPrintedOutput
|
return errPrintedOutput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
|
||||||
|
b.showOutput(a, a.Package.Dir, a.Package.Desc(), "note: module requires Go "+p.Module.GoVersion)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if ofile != objpkg {
|
if ofile != objpkg {
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,9 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a
|
||||||
pkgpath = "main"
|
pkgpath = "main"
|
||||||
}
|
}
|
||||||
gcargs := []string{"-p", pkgpath}
|
gcargs := []string{"-p", pkgpath}
|
||||||
|
if p.Module != nil && p.Module.GoVersion != "" && allowedVersion(p.Module.GoVersion) {
|
||||||
|
gcargs = append(gcargs, "-lang=go"+p.Module.GoVersion)
|
||||||
|
}
|
||||||
if p.Standard {
|
if p.Standard {
|
||||||
gcargs = append(gcargs, "-std")
|
gcargs = append(gcargs, "-std")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -235,17 +235,6 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mainUsage() {
|
func mainUsage() {
|
||||||
// special case "go test -h"
|
|
||||||
if len(os.Args) > 1 && os.Args[1] == "test" {
|
|
||||||
test.Usage()
|
|
||||||
}
|
|
||||||
// Since vet shares code with test in cmdflag, it doesn't show its
|
|
||||||
// command usage properly. For now, special case it too.
|
|
||||||
// TODO(mvdan): fix the cmdflag package instead; see
|
|
||||||
// golang.org/issue/26999
|
|
||||||
if len(os.Args) > 1 && os.Args[1] == "vet" {
|
|
||||||
vet.CmdVet.Usage()
|
|
||||||
}
|
|
||||||
help.PrintUsage(os.Stderr, base.Go)
|
help.PrintUsage(os.Stderr, base.Go)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/build"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -104,6 +105,7 @@ func (ts *testScript) setup() {
|
||||||
"GOROOT=" + testGOROOT,
|
"GOROOT=" + testGOROOT,
|
||||||
tempEnvName() + "=" + filepath.Join(ts.workdir, "tmp"),
|
tempEnvName() + "=" + filepath.Join(ts.workdir, "tmp"),
|
||||||
"devnull=" + os.DevNull,
|
"devnull=" + os.DevNull,
|
||||||
|
"goversion=" + goVersion(ts),
|
||||||
":=" + string(os.PathListSeparator),
|
":=" + string(os.PathListSeparator),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,6 +132,16 @@ func (ts *testScript) setup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// goVersion returns the current Go version.
|
||||||
|
func goVersion(ts *testScript) string {
|
||||||
|
tags := build.Default.ReleaseTags
|
||||||
|
version := tags[len(tags)-1]
|
||||||
|
if !regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`).MatchString(version) {
|
||||||
|
ts.fatalf("invalid go version %q", version)
|
||||||
|
}
|
||||||
|
return version[2:]
|
||||||
|
}
|
||||||
|
|
||||||
var execCache par.Cache
|
var execCache par.Cache
|
||||||
|
|
||||||
// run runs the test script.
|
// run runs the test script.
|
||||||
|
|
@ -331,6 +343,7 @@ var scriptCmds = map[string]func(*testScript, bool, []string){
|
||||||
"addcrlf": (*testScript).cmdAddcrlf,
|
"addcrlf": (*testScript).cmdAddcrlf,
|
||||||
"cd": (*testScript).cmdCd,
|
"cd": (*testScript).cmdCd,
|
||||||
"cmp": (*testScript).cmdCmp,
|
"cmp": (*testScript).cmdCmp,
|
||||||
|
"cmpenv": (*testScript).cmdCmpenv,
|
||||||
"cp": (*testScript).cmdCp,
|
"cp": (*testScript).cmdCp,
|
||||||
"env": (*testScript).cmdEnv,
|
"env": (*testScript).cmdEnv,
|
||||||
"exec": (*testScript).cmdExec,
|
"exec": (*testScript).cmdExec,
|
||||||
|
|
@ -396,7 +409,21 @@ func (ts *testScript) cmdCmp(neg bool, args []string) {
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
ts.fatalf("usage: cmp file1 file2")
|
ts.fatalf("usage: cmp file1 file2")
|
||||||
}
|
}
|
||||||
|
ts.doCmdCmp(args, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cmpenv compares two files with environment variable substitution.
|
||||||
|
func (ts *testScript) cmdCmpenv(neg bool, args []string) {
|
||||||
|
if neg {
|
||||||
|
ts.fatalf("unsupported: ! cmpenv")
|
||||||
|
}
|
||||||
|
if len(args) != 2 {
|
||||||
|
ts.fatalf("usage: cmpenv file1 file2")
|
||||||
|
}
|
||||||
|
ts.doCmdCmp(args, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *testScript) doCmdCmp(args []string, env bool) {
|
||||||
name1, name2 := args[0], args[1]
|
name1, name2 := args[0], args[1]
|
||||||
var text1, text2 string
|
var text1, text2 string
|
||||||
if name1 == "stdout" {
|
if name1 == "stdout" {
|
||||||
|
|
@ -413,6 +440,11 @@ func (ts *testScript) cmdCmp(neg bool, args []string) {
|
||||||
ts.check(err)
|
ts.check(err)
|
||||||
text2 = string(data)
|
text2 = string(data)
|
||||||
|
|
||||||
|
if env {
|
||||||
|
text1 = ts.expand(text1)
|
||||||
|
text2 = ts.expand(text2)
|
||||||
|
}
|
||||||
|
|
||||||
if text1 == text2 {
|
if text1 == text2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
src/cmd/go/testdata/script/README
vendored
5
src/cmd/go/testdata/script/README
vendored
|
|
@ -36,6 +36,7 @@ Scripts also have access to these other environment variables:
|
||||||
PATH=<actual PATH>
|
PATH=<actual PATH>
|
||||||
TMPDIR=$WORK/tmp
|
TMPDIR=$WORK/tmp
|
||||||
devnull=<value of os.DevNull>
|
devnull=<value of os.DevNull>
|
||||||
|
goversion=<current Go version; for example, 1.12>
|
||||||
|
|
||||||
The environment variable $exe (lowercase) is an empty string on most systems, ".exe" on Windows.
|
The environment variable $exe (lowercase) is an empty string on most systems, ".exe" on Windows.
|
||||||
|
|
||||||
|
|
@ -92,6 +93,10 @@ The commands are:
|
||||||
from the most recent exec or go command.
|
from the most recent exec or go command.
|
||||||
(If the files have differing content, the failure prints a diff.)
|
(If the files have differing content, the failure prints a diff.)
|
||||||
|
|
||||||
|
- cmpenv file1 file2
|
||||||
|
Like cmp, but environment variables are substituted in the file contents
|
||||||
|
before the comparison. For example, $GOOS is replaced by the target GOOS.
|
||||||
|
|
||||||
- cp src... dst
|
- cp src... dst
|
||||||
Copy the listed files to the target file or existing directory.
|
Copy the listed files to the target file or existing directory.
|
||||||
|
|
||||||
|
|
|
||||||
6
src/cmd/go/testdata/script/help.txt
vendored
6
src/cmd/go/testdata/script/help.txt
vendored
|
|
@ -35,6 +35,12 @@ stderr 'Run ''go help mod'' for usage.'
|
||||||
stderr 'usage: go vet'
|
stderr 'usage: go vet'
|
||||||
stderr 'Run ''go help vet'' for details'
|
stderr 'Run ''go help vet'' for details'
|
||||||
|
|
||||||
|
# Earlier versions of Go printed a large document here, instead of these two
|
||||||
|
# lines.
|
||||||
|
! go test -h
|
||||||
|
stderr 'usage: go test'
|
||||||
|
stderr 'Run ''go help test'' for details'
|
||||||
|
|
||||||
# go help get shows usage for get
|
# go help get shows usage for get
|
||||||
go help get
|
go help get
|
||||||
stdout 'usage: go get'
|
stdout 'usage: go get'
|
||||||
|
|
|
||||||
47
src/cmd/go/testdata/script/mod_edit.txt
vendored
47
src/cmd/go/testdata/script/mod_edit.txt
vendored
|
|
@ -10,37 +10,37 @@ stderr 'cannot determine module path'
|
||||||
|
|
||||||
go mod init x.x/y/z
|
go mod init x.x/y/z
|
||||||
stderr 'creating new go.mod: module x.x/y/z'
|
stderr 'creating new go.mod: module x.x/y/z'
|
||||||
cmp go.mod $WORK/go.mod.init
|
cmpenv go.mod $WORK/go.mod.init
|
||||||
|
|
||||||
! go mod init
|
! go mod init
|
||||||
cmp go.mod $WORK/go.mod.init
|
cmpenv go.mod $WORK/go.mod.init
|
||||||
|
|
||||||
# go mod edits
|
# go mod edits
|
||||||
go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z'
|
go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z'
|
||||||
cmp go.mod $WORK/go.mod.edit1
|
cmpenv go.mod $WORK/go.mod.edit1
|
||||||
go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0
|
go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0
|
||||||
cmp go.mod $WORK/go.mod.edit2
|
cmpenv go.mod $WORK/go.mod.edit2
|
||||||
|
|
||||||
# go mod edit -json
|
# go mod edit -json
|
||||||
go mod edit -json
|
go mod edit -json
|
||||||
cmp stdout $WORK/go.mod.json
|
cmpenv stdout $WORK/go.mod.json
|
||||||
|
|
||||||
# go mod edit -replace
|
# go mod edit -replace
|
||||||
go mod edit -replace=x.1@v1.3.0=y.1/v2@v2.3.5 -replace=x.1@v1.4.0=y.1/v2@v2.3.5
|
go mod edit -replace=x.1@v1.3.0=y.1/v2@v2.3.5 -replace=x.1@v1.4.0=y.1/v2@v2.3.5
|
||||||
cmp go.mod $WORK/go.mod.edit3
|
cmpenv go.mod $WORK/go.mod.edit3
|
||||||
go mod edit -replace=x.1=y.1/v2@v2.3.6
|
go mod edit -replace=x.1=y.1/v2@v2.3.6
|
||||||
cmp go.mod $WORK/go.mod.edit4
|
cmpenv go.mod $WORK/go.mod.edit4
|
||||||
go mod edit -dropreplace=x.1
|
go mod edit -dropreplace=x.1
|
||||||
cmp go.mod $WORK/go.mod.edit5
|
cmpenv go.mod $WORK/go.mod.edit5
|
||||||
|
|
||||||
# go mod edit -fmt
|
# go mod edit -fmt
|
||||||
cp $WORK/go.mod.badfmt go.mod
|
cp $WORK/go.mod.badfmt go.mod
|
||||||
go mod edit -fmt -print # -print should avoid writing file
|
go mod edit -fmt -print # -print should avoid writing file
|
||||||
cmp stdout $WORK/go.mod.edit4
|
cmpenv stdout $WORK/go.mod.edit6
|
||||||
cmp go.mod $WORK/go.mod.badfmt
|
cmp go.mod $WORK/go.mod.badfmt
|
||||||
go mod edit -fmt # without -print, should write file (and nothing to stdout)
|
go mod edit -fmt # without -print, should write file (and nothing to stdout)
|
||||||
! stdout .
|
! stdout .
|
||||||
cmp go.mod $WORK/go.mod.edit4
|
cmpenv go.mod $WORK/go.mod.edit6
|
||||||
|
|
||||||
-- x.go --
|
-- x.go --
|
||||||
package x
|
package x
|
||||||
|
|
@ -50,9 +50,13 @@ package w
|
||||||
|
|
||||||
-- $WORK/go.mod.init --
|
-- $WORK/go.mod.init --
|
||||||
module x.x/y/z
|
module x.x/y/z
|
||||||
|
|
||||||
|
go $goversion
|
||||||
-- $WORK/go.mod.edit1 --
|
-- $WORK/go.mod.edit1 --
|
||||||
module x.x/y/z
|
module x.x/y/z
|
||||||
|
|
||||||
|
go $goversion
|
||||||
|
|
||||||
require x.1 v1.0.0
|
require x.1 v1.0.0
|
||||||
|
|
||||||
exclude (
|
exclude (
|
||||||
|
|
@ -67,6 +71,8 @@ replace (
|
||||||
-- $WORK/go.mod.edit2 --
|
-- $WORK/go.mod.edit2 --
|
||||||
module x.x/y/z
|
module x.x/y/z
|
||||||
|
|
||||||
|
go $goversion
|
||||||
|
|
||||||
exclude x.1 v1.2.0
|
exclude x.1 v1.2.0
|
||||||
|
|
||||||
replace x.1 v1.4.0 => ../z
|
replace x.1 v1.4.0 => ../z
|
||||||
|
|
@ -77,6 +83,7 @@ require x.3 v1.99.0
|
||||||
"Module": {
|
"Module": {
|
||||||
"Path": "x.x/y/z"
|
"Path": "x.x/y/z"
|
||||||
},
|
},
|
||||||
|
"Go": "$goversion",
|
||||||
"Require": [
|
"Require": [
|
||||||
{
|
{
|
||||||
"Path": "x.3",
|
"Path": "x.3",
|
||||||
|
|
@ -104,6 +111,8 @@ require x.3 v1.99.0
|
||||||
-- $WORK/go.mod.edit3 --
|
-- $WORK/go.mod.edit3 --
|
||||||
module x.x/y/z
|
module x.x/y/z
|
||||||
|
|
||||||
|
go $goversion
|
||||||
|
|
||||||
exclude x.1 v1.2.0
|
exclude x.1 v1.2.0
|
||||||
|
|
||||||
replace (
|
replace (
|
||||||
|
|
@ -115,6 +124,8 @@ require x.3 v1.99.0
|
||||||
-- $WORK/go.mod.edit4 --
|
-- $WORK/go.mod.edit4 --
|
||||||
module x.x/y/z
|
module x.x/y/z
|
||||||
|
|
||||||
|
go $goversion
|
||||||
|
|
||||||
exclude x.1 v1.2.0
|
exclude x.1 v1.2.0
|
||||||
|
|
||||||
replace x.1 => y.1/v2 v2.3.6
|
replace x.1 => y.1/v2 v2.3.6
|
||||||
|
|
@ -123,12 +134,26 @@ require x.3 v1.99.0
|
||||||
-- $WORK/go.mod.edit5 --
|
-- $WORK/go.mod.edit5 --
|
||||||
module x.x/y/z
|
module x.x/y/z
|
||||||
|
|
||||||
|
go $goversion
|
||||||
|
|
||||||
exclude x.1 v1.2.0
|
exclude x.1 v1.2.0
|
||||||
|
|
||||||
require x.3 v1.99.0
|
require x.3 v1.99.0
|
||||||
-- $WORK/go.mod.badfmt --
|
-- $WORK/go.mod.edit6 --
|
||||||
module x.x/y/z
|
module x.x/y/z
|
||||||
|
|
||||||
|
go 1.10
|
||||||
|
|
||||||
|
exclude x.1 v1.2.0
|
||||||
|
|
||||||
|
replace x.1 => y.1/v2 v2.3.6
|
||||||
|
|
||||||
|
require x.3 v1.99.0
|
||||||
|
-- $WORK/go.mod.badfmt --
|
||||||
|
module x.x/y/z
|
||||||
|
|
||||||
|
go 1.10
|
||||||
|
|
||||||
exclude x.1 v1.2.0
|
exclude x.1 v1.2.0
|
||||||
|
|
||||||
replace x.1 => y.1/v2 v2.3.6
|
replace x.1 => y.1/v2 v2.3.6
|
||||||
|
|
|
||||||
16
src/cmd/go/testdata/script/mod_edit_go.txt
vendored
Normal file
16
src/cmd/go/testdata/script/mod_edit_go.txt
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Test support for go mod -edit to set language version.
|
||||||
|
|
||||||
|
env GO111MODULE=on
|
||||||
|
! go build
|
||||||
|
stderr 'type aliases only supported as of'
|
||||||
|
go mod edit -go=1.9
|
||||||
|
grep 'go 1.9' go.mod
|
||||||
|
go build
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module m
|
||||||
|
go 1.8
|
||||||
|
|
||||||
|
-- alias.go --
|
||||||
|
package alias
|
||||||
|
type T = int
|
||||||
16
src/cmd/go/testdata/script/mod_go_version.txt
vendored
16
src/cmd/go/testdata/script/mod_go_version.txt
vendored
|
|
@ -3,9 +3,10 @@
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
|
|
||||||
go list
|
go list
|
||||||
! go build
|
go build
|
||||||
stderr 'module requires Go 1.999'
|
|
||||||
go build sub.1
|
go build sub.1
|
||||||
|
go build subver.1
|
||||||
|
! stderr 'module requires'
|
||||||
! go build badsub.1
|
! go build badsub.1
|
||||||
stderr 'module requires Go 1.11111'
|
stderr 'module requires Go 1.11111'
|
||||||
|
|
||||||
|
|
@ -19,11 +20,13 @@ module m
|
||||||
go 1.999
|
go 1.999
|
||||||
require (
|
require (
|
||||||
sub.1 v1.0.0
|
sub.1 v1.0.0
|
||||||
|
subver.1 v1.0.0
|
||||||
badsub.1 v1.0.0
|
badsub.1 v1.0.0
|
||||||
versioned.1 v1.0.0
|
versioned.1 v1.0.0
|
||||||
)
|
)
|
||||||
replace (
|
replace (
|
||||||
sub.1 => ./sub
|
sub.1 => ./sub
|
||||||
|
subver.1 => ./subver
|
||||||
badsub.1 => ./badsub
|
badsub.1 => ./badsub
|
||||||
versioned.1 v1.0.0 => ./versioned1
|
versioned.1 v1.0.0 => ./versioned1
|
||||||
versioned.1 v1.1.0 => ./versioned2
|
versioned.1 v1.1.0 => ./versioned2
|
||||||
|
|
@ -39,12 +42,20 @@ go 1.11
|
||||||
-- sub/x.go --
|
-- sub/x.go --
|
||||||
package x
|
package x
|
||||||
|
|
||||||
|
-- subver/go.mod --
|
||||||
|
module m
|
||||||
|
go 1.11111
|
||||||
|
|
||||||
|
-- subver/x.go --
|
||||||
|
package x
|
||||||
|
|
||||||
-- badsub/go.mod --
|
-- badsub/go.mod --
|
||||||
module m
|
module m
|
||||||
go 1.11111
|
go 1.11111
|
||||||
|
|
||||||
-- badsub/x.go --
|
-- badsub/x.go --
|
||||||
package x
|
package x
|
||||||
|
invalid syntax
|
||||||
|
|
||||||
-- versioned1/go.mod --
|
-- versioned1/go.mod --
|
||||||
module versioned
|
module versioned
|
||||||
|
|
@ -59,3 +70,4 @@ go 1.99999
|
||||||
|
|
||||||
-- versioned2/x.go --
|
-- versioned2/x.go --
|
||||||
package x
|
package x
|
||||||
|
invalid syntax
|
||||||
|
|
|
||||||
2
src/cmd/go/testdata/script/mod_readonly.txt
vendored
2
src/cmd/go/testdata/script/mod_readonly.txt
vendored
|
|
@ -37,6 +37,8 @@ cmp go.mod go.mod.inconsistent
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module m
|
module m
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
-- x.go --
|
-- x.go --
|
||||||
package x
|
package x
|
||||||
import _ "rsc.io/quote"
|
import _ "rsc.io/quote"
|
||||||
|
|
|
||||||
9
src/cmd/go/testdata/script/mod_tidy.txt
vendored
9
src/cmd/go/testdata/script/mod_tidy.txt
vendored
|
|
@ -5,6 +5,9 @@ go mod tidy -v
|
||||||
stderr '^unused y.1'
|
stderr '^unused y.1'
|
||||||
! stderr '^unused [^y]'
|
! stderr '^unused [^y]'
|
||||||
|
|
||||||
|
# tidy should not touch existing go line
|
||||||
|
grep 'go 1.10' go.mod
|
||||||
|
|
||||||
go list -m all
|
go list -m all
|
||||||
! stdout '^y'
|
! stdout '^y'
|
||||||
stdout '^w.1 v1.2.0'
|
stdout '^w.1 v1.2.0'
|
||||||
|
|
@ -12,11 +15,17 @@ stdout '^z.1 v1.2.0'
|
||||||
|
|
||||||
# empty tidy should not crash
|
# empty tidy should not crash
|
||||||
cd triv
|
cd triv
|
||||||
|
! grep 'go ' go.mod
|
||||||
go mod tidy
|
go mod tidy
|
||||||
|
|
||||||
|
# tidy should add missing go line
|
||||||
|
grep 'go ' go.mod
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module m
|
module m
|
||||||
|
|
||||||
|
go 1.10
|
||||||
|
|
||||||
require (
|
require (
|
||||||
x.1 v1.0.0
|
x.1 v1.0.0
|
||||||
y.1 v1.0.0
|
y.1 v1.0.0
|
||||||
|
|
|
||||||
|
|
@ -967,7 +967,7 @@ Outer:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasChildren returns true if 'die' uses an abbrev that supports children.
|
// HasChildren reports whether 'die' uses an abbrev that supports children.
|
||||||
func HasChildren(die *DWDie) bool {
|
func HasChildren(die *DWDie) bool {
|
||||||
return abbrevs[die.Abbrev].children != 0
|
return abbrevs[die.Abbrev].children != 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -414,6 +414,8 @@ const (
|
||||||
C_BITCON // bitfield and logical immediate masks
|
C_BITCON // bitfield and logical immediate masks
|
||||||
C_ADDCON2 // 24-bit constant
|
C_ADDCON2 // 24-bit constant
|
||||||
C_LCON // 32-bit constant
|
C_LCON // 32-bit constant
|
||||||
|
C_MOVCON2 // a constant that can be loaded with one MOVZ/MOVN and one MOVK
|
||||||
|
C_MOVCON3 // a constant that can be loaded with one MOVZ/MOVN and two MOVKs
|
||||||
C_VCON // 64-bit constant
|
C_VCON // 64-bit constant
|
||||||
C_FCON // floating-point constant
|
C_FCON // floating-point constant
|
||||||
C_VCONADDR // 64-bit memory address
|
C_VCONADDR // 64-bit memory address
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ var cnames7 = []string{
|
||||||
"BITCON",
|
"BITCON",
|
||||||
"ADDCON2",
|
"ADDCON2",
|
||||||
"LCON",
|
"LCON",
|
||||||
|
"MOVCON2",
|
||||||
|
"MOVCON3",
|
||||||
"VCON",
|
"VCON",
|
||||||
"FCON",
|
"FCON",
|
||||||
"VCONADDR",
|
"VCONADDR",
|
||||||
|
|
|
||||||
|
|
@ -198,9 +198,15 @@ var optab = []Optab{
|
||||||
{ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
|
{ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
|
||||||
{AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, 0, 0},
|
{AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, 0, 0},
|
||||||
{AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, 0, 0},
|
{AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, 0, 0},
|
||||||
{AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 8, 0, LFROM, 0},
|
{AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0},
|
||||||
{AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 8, 0, LFROM, 0},
|
{AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 0},
|
||||||
{ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 8, 0, LFROM, 0},
|
{AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, 13, 16, 0, 0, 0},
|
||||||
|
{AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, 13, 16, 0, 0, 0},
|
||||||
|
{AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 20, 0, 0, 0},
|
||||||
|
{AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 20, 0, 0, 0},
|
||||||
|
{ACMP, C_MOVCON2, C_REG, C_NONE, C_NONE, 13, 12, 0, 0, 0},
|
||||||
|
{ACMP, C_MOVCON3, C_REG, C_NONE, C_NONE, 13, 16, 0, 0, 0},
|
||||||
|
{ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0},
|
||||||
{AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
{AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
||||||
{AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
{AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
||||||
{AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
{AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
||||||
|
|
@ -255,11 +261,21 @@ var optab = []Optab{
|
||||||
{AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
|
{AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
|
||||||
{AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
|
{AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
|
||||||
{ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0},
|
{ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0},
|
||||||
{AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
|
{AAND, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
|
||||||
{AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
|
{AAND, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
|
||||||
{AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
|
{AAND, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
|
||||||
{AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
|
{AAND, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
|
||||||
{ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 8, 0, LFROM, 0},
|
{AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
|
||||||
|
{AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
|
||||||
|
{AANDS, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
|
||||||
|
{AANDS, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
|
||||||
|
{AANDS, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
|
||||||
|
{AANDS, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
|
||||||
|
{AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
|
||||||
|
{AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
|
||||||
|
{ATST, C_MOVCON2, C_REG, C_NONE, C_NONE, 28, 12, 0, 0, 0},
|
||||||
|
{ATST, C_MOVCON3, C_REG, C_NONE, C_NONE, 28, 16, 0, 0, 0},
|
||||||
|
{ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 20, 0, 0, 0},
|
||||||
{AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
{AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
||||||
{AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
{AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
||||||
{AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
{AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
|
||||||
|
|
@ -278,8 +294,10 @@ var optab = []Optab{
|
||||||
{AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
|
{AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
|
||||||
{AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
|
{AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
|
||||||
{AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
|
{AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
|
||||||
{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
|
{AMOVW, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, 0, 0},
|
||||||
{AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
|
{AMOVD, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, 0, 0},
|
||||||
|
{AMOVD, C_MOVCON3, C_NONE, C_NONE, C_REG, 12, 12, 0, 0, 0},
|
||||||
|
{AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 16, 0, 0, 0},
|
||||||
|
|
||||||
{AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0},
|
{AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0},
|
||||||
{AMOVD, C_AACON, C_NONE, C_NONE, C_REG, 4, 4, REGFROM, 0, 0},
|
{AMOVD, C_AACON, C_NONE, C_NONE, C_REG, 4, 4, REGFROM, 0, 0},
|
||||||
|
|
@ -401,8 +419,8 @@ var optab = []Optab{
|
||||||
{AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
|
{AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
|
||||||
{AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
|
{AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
|
||||||
{AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
|
{AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
|
||||||
{AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
|
|
||||||
{AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
|
{AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
|
||||||
|
{AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
|
||||||
|
|
||||||
{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
|
{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
|
||||||
{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
|
{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
|
||||||
|
|
@ -411,15 +429,15 @@ var optab = []Optab{
|
||||||
|
|
||||||
/* scaled 12-bit unsigned displacement load */
|
/* scaled 12-bit unsigned displacement load */
|
||||||
{AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
{AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
{AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
{AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
{AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
|
|
||||||
{AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
|
{AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
|
||||||
{AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
|
{AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
|
||||||
|
|
@ -428,15 +446,15 @@ var optab = []Optab{
|
||||||
|
|
||||||
/* unscaled 9-bit signed displacement load */
|
/* unscaled 9-bit signed displacement load */
|
||||||
{AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
{AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
{AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
{AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
{AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
||||||
{AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
|
{AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
|
||||||
|
|
||||||
{AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
|
{AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
|
||||||
{AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
|
{AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
|
||||||
|
|
@ -1105,6 +1123,15 @@ func isSTXPop(op obj.As) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isANDop(op obj.As) bool {
|
||||||
|
switch op {
|
||||||
|
case AAND, AORR, AEOR, AANDS, ATST,
|
||||||
|
ABIC, AEON, AORN, ABICS:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func isANDWop(op obj.As) bool {
|
func isANDWop(op obj.As) bool {
|
||||||
switch op {
|
switch op {
|
||||||
case AANDW, AORRW, AEORW, AANDSW, ATSTW,
|
case AANDW, AORRW, AEORW, AANDSW, ATSTW,
|
||||||
|
|
@ -1114,6 +1141,14 @@ func isANDWop(op obj.As) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isADDop(op obj.As) bool {
|
||||||
|
switch op {
|
||||||
|
case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func isADDWop(op obj.As) bool {
|
func isADDWop(op obj.As) bool {
|
||||||
switch op {
|
switch op {
|
||||||
case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
|
case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
|
||||||
|
|
@ -1445,6 +1480,12 @@ func (c *ctxt7) con32class(a *obj.Addr) int {
|
||||||
if isbitcon(uint64(v)) {
|
if isbitcon(uint64(v)) {
|
||||||
return C_ABCON
|
return C_ABCON
|
||||||
}
|
}
|
||||||
|
if movcon(int64(v)) >= 0 {
|
||||||
|
return C_AMCON
|
||||||
|
}
|
||||||
|
if movcon(int64(^v)) >= 0 {
|
||||||
|
return C_AMCON
|
||||||
|
}
|
||||||
return C_ADDCON
|
return C_ADDCON
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1474,6 +1515,29 @@ func (c *ctxt7) con32class(a *obj.Addr) int {
|
||||||
return C_LCON
|
return C_LCON
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// con64class reclassifies the constant of C_VCON and C_LCON class.
|
||||||
|
func (c *ctxt7) con64class(a *obj.Addr) int {
|
||||||
|
zeroCount := 0
|
||||||
|
negCount := 0
|
||||||
|
for i := uint(0); i < 4; i++ {
|
||||||
|
immh := uint32(a.Offset >> (i * 16) & 0xffff)
|
||||||
|
if immh == 0 {
|
||||||
|
zeroCount++
|
||||||
|
} else if immh == 0xffff {
|
||||||
|
negCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if zeroCount >= 3 || negCount >= 3 {
|
||||||
|
return C_MOVCON
|
||||||
|
} else if zeroCount == 2 || negCount == 2 {
|
||||||
|
return C_MOVCON2
|
||||||
|
} else if zeroCount == 1 || negCount == 1 {
|
||||||
|
return C_MOVCON3
|
||||||
|
} else {
|
||||||
|
return C_VCON
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ctxt7) aclass(a *obj.Addr) int {
|
func (c *ctxt7) aclass(a *obj.Addr) int {
|
||||||
switch a.Type {
|
switch a.Type {
|
||||||
case obj.TYPE_NONE:
|
case obj.TYPE_NONE:
|
||||||
|
|
@ -1689,21 +1753,18 @@ func (c *ctxt7) oplook(p *obj.Prog) *Optab {
|
||||||
a1 = ra0 + 1
|
a1 = ra0 + 1
|
||||||
p.From.Class = int8(a1)
|
p.From.Class = int8(a1)
|
||||||
}
|
}
|
||||||
if isANDWop(p.As) {
|
if isANDWop(p.As) && a0 != C_BITCON {
|
||||||
switch p.As {
|
|
||||||
case AANDW, AORRW, AEORW, AANDSW, ATSTW:
|
|
||||||
// For 32-bit logical instruction with constant,
|
// For 32-bit logical instruction with constant,
|
||||||
// rewrite the high 32-bit to be a copy of the low
|
// the BITCON test is special in that it looks at
|
||||||
// 32-bit, so that the BITCON test can be shared
|
// the 64-bit which has the high 32-bit as a copy
|
||||||
// for both 32-bit and 64-bit.
|
// of the low 32-bit. We have handled that and
|
||||||
if a0 == C_BITCON {
|
// don't pass it to con32class.
|
||||||
break
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
a1 = c.con32class(&p.From) + 1
|
a1 = c.con32class(&p.From) + 1
|
||||||
p.From.Class = int8(a1)
|
p.From.Class = int8(a1)
|
||||||
}
|
}
|
||||||
|
if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) {
|
||||||
|
a1 = c.con64class(&p.From) + 1
|
||||||
|
p.From.Class = int8(a1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1800,6 +1861,9 @@ func cmp(a int, b int) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case C_MOVCON2:
|
||||||
|
return cmp(C_LCON, b)
|
||||||
|
|
||||||
case C_VCON:
|
case C_VCON:
|
||||||
return cmp(C_LCON, b)
|
return cmp(C_LCON, b)
|
||||||
|
|
||||||
|
|
@ -2718,6 +2782,7 @@ func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
|
var os [5]uint32
|
||||||
o1 := uint32(0)
|
o1 := uint32(0)
|
||||||
o2 := uint32(0)
|
o2 := uint32(0)
|
||||||
o3 := uint32(0)
|
o3 := uint32(0)
|
||||||
|
|
@ -2907,13 +2972,29 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 12: /* movT $vcon, reg */
|
case 12: /* movT $vcon, reg */
|
||||||
o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
|
num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
|
||||||
|
if num == 0 {
|
||||||
|
c.ctxt.Diag("invalid constant: %v", p)
|
||||||
|
}
|
||||||
|
o1 = os[0]
|
||||||
|
o2 = os[1]
|
||||||
|
o3 = os[2]
|
||||||
|
o4 = os[3]
|
||||||
|
|
||||||
case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
|
case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
|
||||||
o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
|
o := uint32(0)
|
||||||
|
num := uint8(0)
|
||||||
if o1 == 0 {
|
cls := oclass(&p.From)
|
||||||
break
|
if isADDWop(p.As) {
|
||||||
|
if (cls != C_LCON) && (cls != C_ADDCON2) {
|
||||||
|
c.ctxt.Diag("illegal combination: %v", p)
|
||||||
|
}
|
||||||
|
num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
|
||||||
|
} else {
|
||||||
|
num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
|
||||||
|
}
|
||||||
|
if num == 0 {
|
||||||
|
c.ctxt.Diag("invalid constant: %v", p)
|
||||||
}
|
}
|
||||||
rt := int(p.To.Reg)
|
rt := int(p.To.Reg)
|
||||||
if p.To.Type == obj.TYPE_NONE {
|
if p.To.Type == obj.TYPE_NONE {
|
||||||
|
|
@ -2924,16 +3005,23 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
r = rt
|
r = rt
|
||||||
}
|
}
|
||||||
if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
|
if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
|
||||||
o2 = c.opxrrr(p, p.As, false)
|
o = c.opxrrr(p, p.As, false)
|
||||||
o2 |= REGTMP & 31 << 16
|
o |= REGTMP & 31 << 16
|
||||||
o2 |= LSL0_64
|
o |= LSL0_64
|
||||||
} else {
|
} else {
|
||||||
o2 = c.oprrr(p, p.As)
|
o = c.oprrr(p, p.As)
|
||||||
o2 |= REGTMP & 31 << 16 /* shift is 0 */
|
o |= REGTMP & 31 << 16 /* shift is 0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
o2 |= uint32(r&31) << 5
|
o |= uint32(r&31) << 5
|
||||||
o2 |= uint32(rt & 31)
|
o |= uint32(rt & 31)
|
||||||
|
|
||||||
|
os[num] = o
|
||||||
|
o1 = os[0]
|
||||||
|
o2 = os[1]
|
||||||
|
o3 = os[2]
|
||||||
|
o4 = os[3]
|
||||||
|
o5 = os[4]
|
||||||
|
|
||||||
case 14: /* word */
|
case 14: /* word */
|
||||||
if c.aclass(&p.To) == C_ADDR {
|
if c.aclass(&p.To) == C_ADDR {
|
||||||
|
|
@ -3179,10 +3267,20 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
o1 |= (uint32(r&31) << 5) | uint32(rt&31)
|
o1 |= (uint32(r&31) << 5) | uint32(rt&31)
|
||||||
|
|
||||||
case 28: /* logop $vcon, [R], R (64 bit literal) */
|
case 28: /* logop $vcon, [R], R (64 bit literal) */
|
||||||
o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
|
o := uint32(0)
|
||||||
|
num := uint8(0)
|
||||||
|
cls := oclass(&p.From)
|
||||||
|
if isANDWop(p.As) {
|
||||||
|
if (cls != C_LCON) && (cls != C_ADDCON) {
|
||||||
|
c.ctxt.Diag("illegal combination: %v", p)
|
||||||
|
}
|
||||||
|
num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
|
||||||
|
} else {
|
||||||
|
num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
|
||||||
|
}
|
||||||
|
|
||||||
if o1 == 0 {
|
if num == 0 {
|
||||||
break
|
c.ctxt.Diag("invalid constant: %v", p)
|
||||||
}
|
}
|
||||||
rt := int(p.To.Reg)
|
rt := int(p.To.Reg)
|
||||||
if p.To.Type == obj.TYPE_NONE {
|
if p.To.Type == obj.TYPE_NONE {
|
||||||
|
|
@ -3192,10 +3290,17 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
r = rt
|
r = rt
|
||||||
}
|
}
|
||||||
o2 = c.oprrr(p, p.As)
|
o = c.oprrr(p, p.As)
|
||||||
o2 |= REGTMP & 31 << 16 /* shift is 0 */
|
o |= REGTMP & 31 << 16 /* shift is 0 */
|
||||||
o2 |= uint32(r&31) << 5
|
o |= uint32(r&31) << 5
|
||||||
o2 |= uint32(rt & 31)
|
o |= uint32(rt & 31)
|
||||||
|
|
||||||
|
os[num] = o
|
||||||
|
o1 = os[0]
|
||||||
|
o2 = os[1]
|
||||||
|
o3 = os[2]
|
||||||
|
o4 = os[3]
|
||||||
|
o5 = os[4]
|
||||||
|
|
||||||
case 29: /* op Rn, Rd */
|
case 29: /* op Rn, Rd */
|
||||||
fc := c.aclass(&p.From)
|
fc := c.aclass(&p.From)
|
||||||
|
|
@ -6326,10 +6431,155 @@ func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint3
|
||||||
}
|
}
|
||||||
o1 |= MOVCONST(d, s, rt)
|
o1 |= MOVCONST(d, s, rt)
|
||||||
}
|
}
|
||||||
|
|
||||||
return o1
|
return o1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
|
||||||
|
// put the instruction sequence in os and return the number of instructions.
|
||||||
|
func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
|
||||||
|
switch as {
|
||||||
|
case AMOVW:
|
||||||
|
d := uint32(a.Offset)
|
||||||
|
// use MOVZW and MOVKW to load a constant to rt
|
||||||
|
os[0] = c.opirr(p, AMOVZW)
|
||||||
|
os[0] |= MOVCONST(int64(d), 0, rt)
|
||||||
|
os[1] = c.opirr(p, AMOVKW)
|
||||||
|
os[1] |= MOVCONST(int64(d), 1, rt)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
case AMOVD:
|
||||||
|
d := a.Offset
|
||||||
|
dn := ^d
|
||||||
|
var immh [4]uint64
|
||||||
|
var i int
|
||||||
|
zeroCount := int(0)
|
||||||
|
negCount := int(0)
|
||||||
|
for i = 0; i < 4; i++ {
|
||||||
|
immh[i] = uint64((d >> uint(i*16)) & 0xffff)
|
||||||
|
if immh[i] == 0 {
|
||||||
|
zeroCount++
|
||||||
|
} else if immh[i] == 0xffff {
|
||||||
|
negCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if zeroCount == 4 || negCount == 4 {
|
||||||
|
c.ctxt.Diag("the immediate should be MOVCON: %v", p)
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case zeroCount == 3:
|
||||||
|
// one MOVZ
|
||||||
|
for i = 0; i < 4; i++ {
|
||||||
|
if immh[i] != 0 {
|
||||||
|
os[0] = c.opirr(p, AMOVZ)
|
||||||
|
os[0] |= MOVCONST(d, i, rt)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
|
||||||
|
case negCount == 3:
|
||||||
|
// one MOVN
|
||||||
|
for i = 0; i < 4; i++ {
|
||||||
|
if immh[i] != 0xffff {
|
||||||
|
os[0] = c.opirr(p, AMOVN)
|
||||||
|
os[0] |= MOVCONST(dn, i, rt)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
|
||||||
|
case zeroCount == 2:
|
||||||
|
// one MOVZ and one MOVK
|
||||||
|
for i = 0; i < 4; i++ {
|
||||||
|
if immh[i] != 0 {
|
||||||
|
os[0] = c.opirr(p, AMOVZ)
|
||||||
|
os[0] |= MOVCONST(d, i, rt)
|
||||||
|
i++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ; i < 4; i++ {
|
||||||
|
if immh[i] != 0 {
|
||||||
|
os[1] = c.opirr(p, AMOVK)
|
||||||
|
os[1] |= MOVCONST(d, i, rt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 2
|
||||||
|
|
||||||
|
case negCount == 2:
|
||||||
|
// one MOVN and one MOVK
|
||||||
|
for i = 0; i < 4; i++ {
|
||||||
|
if immh[i] != 0xffff {
|
||||||
|
os[0] = c.opirr(p, AMOVN)
|
||||||
|
os[0] |= MOVCONST(dn, i, rt)
|
||||||
|
i++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ; i < 4; i++ {
|
||||||
|
if immh[i] != 0xffff {
|
||||||
|
os[1] = c.opirr(p, AMOVK)
|
||||||
|
os[1] |= MOVCONST(d, i, rt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 2
|
||||||
|
|
||||||
|
case zeroCount == 1:
|
||||||
|
// one MOVZ and two MOVKs
|
||||||
|
for i = 0; i < 4; i++ {
|
||||||
|
if immh[i] != 0 {
|
||||||
|
os[0] = c.opirr(p, AMOVZ)
|
||||||
|
os[0] |= MOVCONST(d, i, rt)
|
||||||
|
i++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := 1; i < 4; i++ {
|
||||||
|
if immh[i] != 0 {
|
||||||
|
os[j] = c.opirr(p, AMOVK)
|
||||||
|
os[j] |= MOVCONST(d, i, rt)
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 3
|
||||||
|
|
||||||
|
case negCount == 1:
|
||||||
|
// one MOVN and two MOVKs
|
||||||
|
for i = 0; i < 4; i++ {
|
||||||
|
if immh[i] != 0xffff {
|
||||||
|
os[0] = c.opirr(p, AMOVN)
|
||||||
|
os[0] |= MOVCONST(dn, i, rt)
|
||||||
|
i++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := 1; i < 4; i++ {
|
||||||
|
if immh[i] != 0xffff {
|
||||||
|
os[j] = c.opirr(p, AMOVK)
|
||||||
|
os[j] |= MOVCONST(d, i, rt)
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 3
|
||||||
|
|
||||||
|
default:
|
||||||
|
// one MOVZ and 3 MOVKs
|
||||||
|
os[0] = c.opirr(p, AMOVZ)
|
||||||
|
os[0] |= MOVCONST(d, 0, rt)
|
||||||
|
for i = 1; i < 4; i++ {
|
||||||
|
os[i] = c.opirr(p, AMOVK)
|
||||||
|
os[i] |= MOVCONST(d, i, rt)
|
||||||
|
}
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
|
func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
|
||||||
var b uint32
|
var b uint32
|
||||||
o := c.opirr(p, a)
|
o := c.opirr(p, a)
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ such as str, stur, strb, sturb, strh, sturh stlr, stlrb. stlrh, st1.
|
||||||
Examples:
|
Examples:
|
||||||
MOVD R29, 384(R19) <=> str x29, [x19,#384]
|
MOVD R29, 384(R19) <=> str x29, [x19,#384]
|
||||||
MOVB.P R30, 30(R4) <=> strb w30, [x4],#30
|
MOVB.P R30, 30(R4) <=> strb w30, [x4],#30
|
||||||
STLRH R21, (R18) <=> stlrh w21, [x18]
|
STLRH R21, (R19) <=> stlrh w21, [x19]
|
||||||
|
|
||||||
(2) MADD, MADDW, MSUB, MSUBW, SMADDL, SMSUBL, UMADDL, UMSUBL <Rm>, <Ra>, <Rn>, <Rd>
|
(2) MADD, MADDW, MSUB, MSUBW, SMADDL, SMSUBL, UMADDL, UMSUBL <Rm>, <Ra>, <Rn>, <Rd>
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ such as str, stur, strb, sturb, strh, sturh stlr, stlrb. stlrh, st1.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
CCMN VS, R13, R22, $10 <=> ccmn x13, x22, #0xa, vs
|
CCMN VS, R13, R22, $10 <=> ccmn x13, x22, #0xa, vs
|
||||||
CCMPW HS, R18, R14, $11 <=> ccmp w18, w14, #0xb, cs
|
CCMPW HS, R19, R14, $11 <=> ccmp w19, w14, #0xb, cs
|
||||||
|
|
||||||
(9) CSEL, CSELW, CSNEG, CSNEGW, CSINC, CSINCW <cond>, <Rn>, <Rm>, <Rd> ;
|
(9) CSEL, CSELW, CSNEG, CSNEGW, CSINC, CSINCW <cond>, <Rn>, <Rm>, <Rd> ;
|
||||||
FCSELD, FCSELS <cond>, <Fn>, <Fm>, <Fd>
|
FCSELD, FCSELS <cond>, <Fn>, <Fm>, <Fd>
|
||||||
|
|
@ -144,12 +144,12 @@ FCSELD, FCSELS <cond>, <Fn>, <Fm>, <Fd>
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
STLXR ZR, (R15), R16 <=> stlxr w16, xzr, [x15]
|
STLXR ZR, (R15), R16 <=> stlxr w16, xzr, [x15]
|
||||||
STXRB R9, (R21), R18 <=> stxrb w18, w9, [x21]
|
STXRB R9, (R21), R19 <=> stxrb w19, w9, [x21]
|
||||||
|
|
||||||
(12) STLXP, STLXPW, STXP, STXPW (<Rf1>, <Rf2>), (<Rn|RSP>), <Rs>
|
(12) STLXP, STLXPW, STXP, STXPW (<Rf1>, <Rf2>), (<Rn|RSP>), <Rs>
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
STLXP (R17, R18), (R4), R5 <=> stlxp w5, x17, x18, [x4]
|
STLXP (R17, R19), (R4), R5 <=> stlxp w5, x17, x19, [x4]
|
||||||
STXPW (R30, R25), (R22), R13 <=> stxp w13, w30, w25, [x22]
|
STXPW (R30, R25), (R22), R13 <=> stxp w13, w30, w25, [x22]
|
||||||
|
|
||||||
2. Expressions for special arguments.
|
2. Expressions for special arguments.
|
||||||
|
|
@ -173,7 +173,7 @@ Extended registers are written as <Rm>{.<extend>{<<<amount>}}.
|
||||||
<extend> can be UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW or SXTX.
|
<extend> can be UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW or SXTX.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
ADDS R18.UXTB<<4, R9, R26 <=> adds x26, x9, w18, uxtb #4
|
ADDS R19.UXTB<<4, R9, R26 <=> adds x26, x9, w19, uxtb #4
|
||||||
ADDSW R14.SXTX, R14, R6 <=> adds w6, w14, w14, sxtx
|
ADDSW R14.SXTX, R14, R6 <=> adds w6, w14, w14, sxtx
|
||||||
|
|
||||||
Memory references: [<Xn|SP>{,#0}] is written as (Rn|RSP), a base register and an immediate
|
Memory references: [<Xn|SP>{,#0}] is written as (Rn|RSP), a base register and an immediate
|
||||||
|
|
|
||||||
|
|
@ -311,13 +311,10 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||||
// shared for both 32-bit and 64-bit. 32-bit ops
|
// shared for both 32-bit and 64-bit. 32-bit ops
|
||||||
// will zero the high 32-bit of the destination
|
// will zero the high 32-bit of the destination
|
||||||
// register anyway.
|
// register anyway.
|
||||||
switch p.As {
|
if isANDWop(p.As) && p.From.Type == obj.TYPE_CONST {
|
||||||
case AANDW, AORRW, AEORW, AANDSW, ATSTW:
|
|
||||||
if p.From.Type == obj.TYPE_CONST {
|
|
||||||
v := p.From.Offset & 0xffffffff
|
v := p.From.Offset & 0xffffffff
|
||||||
p.From.Offset = v | v<<32
|
p.From.Offset = v | v<<32
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if c.ctxt.Flag_dynlink {
|
if c.ctxt.Flag_dynlink {
|
||||||
c.rewriteToUseGot(p)
|
c.rewriteToUseGot(p)
|
||||||
|
|
|
||||||
|
|
@ -403,9 +403,9 @@ type FuncInfo struct {
|
||||||
dwarfAbsFnSym *LSym
|
dwarfAbsFnSym *LSym
|
||||||
dwarfIsStmtSym *LSym
|
dwarfIsStmtSym *LSym
|
||||||
|
|
||||||
GCArgs LSym
|
GCArgs *LSym
|
||||||
GCLocals LSym
|
GCLocals *LSym
|
||||||
GCRegs LSym
|
GCRegs *LSym
|
||||||
StackObjects *LSym
|
StackObjects *LSym
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,6 @@ type objWriter struct {
|
||||||
// Temporary buffer for zigzag int writing.
|
// Temporary buffer for zigzag int writing.
|
||||||
varintbuf [10]uint8
|
varintbuf [10]uint8
|
||||||
|
|
||||||
// Provide the index of a symbol reference by symbol name.
|
|
||||||
// One map for versioned symbols and one for unversioned symbols.
|
|
||||||
// Used for deduplicating the symbol reference list.
|
|
||||||
refIdx map[string]int
|
|
||||||
vrefIdx map[string]int
|
|
||||||
|
|
||||||
// Number of objects written of each type.
|
// Number of objects written of each type.
|
||||||
nRefs int
|
nRefs int
|
||||||
nData int
|
nData int
|
||||||
|
|
@ -81,8 +75,6 @@ func newObjWriter(ctxt *Link, b *bufio.Writer) *objWriter {
|
||||||
return &objWriter{
|
return &objWriter{
|
||||||
ctxt: ctxt,
|
ctxt: ctxt,
|
||||||
wr: b,
|
wr: b,
|
||||||
vrefIdx: make(map[string]int),
|
|
||||||
refIdx: make(map[string]int),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,17 +149,6 @@ func (w *objWriter) writeRef(s *LSym, isPath bool) {
|
||||||
if s == nil || s.RefIdx != 0 {
|
if s == nil || s.RefIdx != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var m map[string]int
|
|
||||||
if !s.Static() {
|
|
||||||
m = w.refIdx
|
|
||||||
} else {
|
|
||||||
m = w.vrefIdx
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx := m[s.Name]; idx != 0 {
|
|
||||||
s.RefIdx = idx
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.wr.WriteByte(symPrefix)
|
w.wr.WriteByte(symPrefix)
|
||||||
if isPath {
|
if isPath {
|
||||||
w.writeString(filepath.ToSlash(s.Name))
|
w.writeString(filepath.ToSlash(s.Name))
|
||||||
|
|
@ -178,7 +159,6 @@ func (w *objWriter) writeRef(s *LSym, isPath bool) {
|
||||||
w.writeBool(s.Static())
|
w.writeBool(s.Static())
|
||||||
w.nRefs++
|
w.nRefs++
|
||||||
s.RefIdx = w.nRefs
|
s.RefIdx = w.nRefs
|
||||||
m[s.Name] = w.nRefs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *objWriter) writeRefs(s *LSym) {
|
func (w *objWriter) writeRefs(s *LSym) {
|
||||||
|
|
|
||||||
|
|
@ -147,18 +147,6 @@ func (ctxt *Link) InitTextSym(s *LSym, flag int) {
|
||||||
isstmt.Type = objabi.SDWARFMISC
|
isstmt.Type = objabi.SDWARFMISC
|
||||||
isstmt.Set(AttrDuplicateOK, s.DuplicateOK())
|
isstmt.Set(AttrDuplicateOK, s.DuplicateOK())
|
||||||
ctxt.Data = append(ctxt.Data, isstmt)
|
ctxt.Data = append(ctxt.Data, isstmt)
|
||||||
|
|
||||||
// Set up the function's gcargs and gclocals.
|
|
||||||
// They will be filled in later if needed.
|
|
||||||
gcargs := &s.Func.GCArgs
|
|
||||||
gcargs.Set(AttrDuplicateOK, true)
|
|
||||||
gcargs.Type = objabi.SRODATA
|
|
||||||
gclocals := &s.Func.GCLocals
|
|
||||||
gclocals.Set(AttrDuplicateOK, true)
|
|
||||||
gclocals.Type = objabi.SRODATA
|
|
||||||
gcregs := &s.Func.GCRegs
|
|
||||||
gcregs.Set(AttrDuplicateOK, true)
|
|
||||||
gcregs.Type = objabi.SRODATA
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
|
func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,7 @@ const (
|
||||||
REG_RET1
|
REG_RET1
|
||||||
REG_RET2
|
REG_RET2
|
||||||
REG_RET3
|
REG_RET3
|
||||||
REG_RUN
|
REG_PAUSE
|
||||||
|
|
||||||
// locals
|
// locals
|
||||||
REG_R0
|
REG_R0
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ var Register = map[string]int16{
|
||||||
"RET1": REG_RET1,
|
"RET1": REG_RET1,
|
||||||
"RET2": REG_RET2,
|
"RET2": REG_RET2,
|
||||||
"RET3": REG_RET3,
|
"RET3": REG_RET3,
|
||||||
"RUN": REG_RUN,
|
"PAUSE": REG_PAUSE,
|
||||||
|
|
||||||
"R0": REG_R0,
|
"R0": REG_R0,
|
||||||
"R1": REG_R1,
|
"R1": REG_R1,
|
||||||
|
|
@ -777,7 +777,7 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
||||||
}
|
}
|
||||||
reg := p.From.Reg
|
reg := p.From.Reg
|
||||||
switch {
|
switch {
|
||||||
case reg >= REG_PC_F && reg <= REG_RUN:
|
case reg >= REG_PC_F && reg <= REG_PAUSE:
|
||||||
w.WriteByte(0x23) // get_global
|
w.WriteByte(0x23) // get_global
|
||||||
writeUleb128(w, uint64(reg-REG_PC_F))
|
writeUleb128(w, uint64(reg-REG_PC_F))
|
||||||
case reg >= REG_R0 && reg <= REG_R15:
|
case reg >= REG_R0 && reg <= REG_R15:
|
||||||
|
|
@ -797,7 +797,7 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
||||||
}
|
}
|
||||||
reg := p.To.Reg
|
reg := p.To.Reg
|
||||||
switch {
|
switch {
|
||||||
case reg >= REG_PC_F && reg <= REG_RUN:
|
case reg >= REG_PC_F && reg <= REG_PAUSE:
|
||||||
w.WriteByte(0x24) // set_global
|
w.WriteByte(0x24) // set_global
|
||||||
writeUleb128(w, uint64(reg-REG_PC_F))
|
writeUleb128(w, uint64(reg-REG_PC_F))
|
||||||
case reg >= REG_R0 && reg <= REG_F15:
|
case reg >= REG_R0 && reg <= REG_F15:
|
||||||
|
|
|
||||||
|
|
@ -4704,7 +4704,9 @@ func (ab *AsmBuf) doasm(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog) {
|
||||||
r = obj.Addrel(cursym)
|
r = obj.Addrel(cursym)
|
||||||
r.Off = int32(p.Pc + int64(ab.Len()))
|
r.Off = int32(p.Pc + int64(ab.Len()))
|
||||||
r.Sym = p.To.Sym
|
r.Sym = p.To.Sym
|
||||||
r.Type = objabi.R_PCREL
|
// Note: R_CALL instead of R_PCREL. R_CALL is more permissive in that
|
||||||
|
// it can point to a trampoline instead of the destination itself.
|
||||||
|
r.Type = objabi.R_CALL
|
||||||
r.Siz = 4
|
r.Siz = 4
|
||||||
ab.PutInt32(0)
|
ab.PutInt32(0)
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
|
||||||
// (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So
|
// (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So
|
||||||
// we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
|
// we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
|
||||||
// add + R_ADDRARM64.
|
// add + R_ADDRARM64.
|
||||||
if !(r.Sym.Version != 0 || r.Sym.Attr.VisibilityHidden() || r.Sym.Attr.Local()) && r.Sym.Type == sym.STEXT && ctxt.DynlinkingGo() {
|
if !(r.Sym.IsFileLocal() || r.Sym.Attr.VisibilityHidden() || r.Sym.Attr.Local()) && r.Sym.Type == sym.STEXT && ctxt.DynlinkingGo() {
|
||||||
if o2&0xffc00000 != 0xf9400000 {
|
if o2&0xffc00000 != 0xf9400000 {
|
||||||
ld.Errorf(s, "R_ARM64_GOTPCREL against unexpected instruction %x", o2)
|
ld.Errorf(s, "R_ARM64_GOTPCREL against unexpected instruction %x", o2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -342,6 +342,26 @@ func lookupOrDiag(ctxt *Link, n string) *sym.Symbol {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dwarfFuncSym looks up a DWARF metadata symbol for function symbol s.
|
||||||
|
// If the symbol does not exist, it creates it if create is true,
|
||||||
|
// or returns nil otherwise.
|
||||||
|
func dwarfFuncSym(ctxt *Link, s *sym.Symbol, meta string, create bool) *sym.Symbol {
|
||||||
|
// All function ABIs use symbol version 0 for the DWARF data.
|
||||||
|
//
|
||||||
|
// TODO(austin): It may be useful to have DWARF info for ABI
|
||||||
|
// wrappers, in which case we may want these versions to
|
||||||
|
// align. Better yet, replace these name lookups with a
|
||||||
|
// general way to attach metadata to a symbol.
|
||||||
|
ver := 0
|
||||||
|
if s.IsFileLocal() {
|
||||||
|
ver = int(s.Version)
|
||||||
|
}
|
||||||
|
if create {
|
||||||
|
return ctxt.Syms.Lookup(meta+s.Name, ver)
|
||||||
|
}
|
||||||
|
return ctxt.Syms.ROLookup(meta+s.Name, ver)
|
||||||
|
}
|
||||||
|
|
||||||
func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) *dwarf.DWDie {
|
func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) *dwarf.DWDie {
|
||||||
// Only emit typedefs for real names.
|
// Only emit typedefs for real names.
|
||||||
if strings.HasPrefix(name, "map[") {
|
if strings.HasPrefix(name, "map[") {
|
||||||
|
|
@ -843,7 +863,7 @@ func dwarfDefineGlobal(ctxt *Link, s *sym.Symbol, str string, v int64, gotype *s
|
||||||
}
|
}
|
||||||
dv := newdie(ctxt, ctxt.compUnitByPackage[lib].dwinfo, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
|
dv := newdie(ctxt, ctxt.compUnitByPackage[lib].dwinfo, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
|
||||||
newabslocexprattr(dv, v, s)
|
newabslocexprattr(dv, v, s)
|
||||||
if s.Version == 0 {
|
if !s.IsFileLocal() {
|
||||||
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
|
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
|
||||||
}
|
}
|
||||||
dt := defgotype(ctxt, gotype)
|
dt := defgotype(ctxt, gotype)
|
||||||
|
|
@ -1146,7 +1166,7 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
|
||||||
// indexes (created by numberfile) to CU-local indexes.
|
// indexes (created by numberfile) to CU-local indexes.
|
||||||
fileNums := make(map[int]int)
|
fileNums := make(map[int]int)
|
||||||
for _, s := range unit.lib.Textp { // textp has been dead-code-eliminated already.
|
for _, s := range unit.lib.Textp { // textp has been dead-code-eliminated already.
|
||||||
dsym := ctxt.Syms.Lookup(dwarf.InfoPrefix+s.Name, int(s.Version))
|
dsym := dwarfFuncSym(ctxt, s, dwarf.InfoPrefix, true)
|
||||||
for _, f := range s.FuncInfo.File {
|
for _, f := range s.FuncInfo.File {
|
||||||
if _, ok := fileNums[int(f.Value)]; ok {
|
if _, ok := fileNums[int(f.Value)]; ok {
|
||||||
continue
|
continue
|
||||||
|
|
@ -1756,12 +1776,12 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
||||||
// referenced abstract functions.
|
// referenced abstract functions.
|
||||||
// Collect all debug_range symbols in unit.rangeSyms
|
// Collect all debug_range symbols in unit.rangeSyms
|
||||||
for _, s := range lib.Textp { // textp has been dead-code-eliminated already.
|
for _, s := range lib.Textp { // textp has been dead-code-eliminated already.
|
||||||
dsym := ctxt.Syms.ROLookup(dwarf.InfoPrefix+s.Name, int(s.Version))
|
dsym := dwarfFuncSym(ctxt, s, dwarf.InfoPrefix, false)
|
||||||
dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
|
dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
|
||||||
dsym.Type = sym.SDWARFINFO
|
dsym.Type = sym.SDWARFINFO
|
||||||
unit.funcDIEs = append(unit.funcDIEs, dsym)
|
unit.funcDIEs = append(unit.funcDIEs, dsym)
|
||||||
|
|
||||||
rangeSym := ctxt.Syms.ROLookup(dwarf.RangePrefix+s.Name, int(s.Version))
|
rangeSym := dwarfFuncSym(ctxt, s, dwarf.RangePrefix, false)
|
||||||
if rangeSym != nil && rangeSym.Size > 0 {
|
if rangeSym != nil && rangeSym.Size > 0 {
|
||||||
rangeSym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
|
rangeSym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
|
||||||
rangeSym.Type = sym.SDWARFRANGE
|
rangeSym.Type = sym.SDWARFRANGE
|
||||||
|
|
|
||||||
|
|
@ -2130,7 +2130,7 @@ func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int6
|
||||||
if s.Attr.NotInSymbolTable() {
|
if s.Attr.NotInSymbolTable() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC." {
|
if (s.Name == "" || s.Name[0] == '.') && !s.IsFileLocal() && s.Name != ".rathole" && s.Name != ".TOC." {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
switch s.Type {
|
switch s.Type {
|
||||||
|
|
|
||||||
|
|
@ -704,7 +704,7 @@ func (f *peFile) writeSymbols(ctxt *Link) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class := IMAGE_SYM_CLASS_EXTERNAL
|
class := IMAGE_SYM_CLASS_EXTERNAL
|
||||||
if s.Version != 0 || s.Attr.VisibilityHidden() || s.Attr.Local() {
|
if s.IsFileLocal() || s.Attr.VisibilityHidden() || s.Attr.Local() {
|
||||||
class = IMAGE_SYM_CLASS_STATIC
|
class = IMAGE_SYM_CLASS_STATIC
|
||||||
}
|
}
|
||||||
f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class))
|
f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class))
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64, go
|
||||||
// maybe one day STB_WEAK.
|
// maybe one day STB_WEAK.
|
||||||
bind := STB_GLOBAL
|
bind := STB_GLOBAL
|
||||||
|
|
||||||
if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
|
if x.IsFileLocal() || x.Attr.VisibilityHidden() || x.Attr.Local() {
|
||||||
bind = STB_LOCAL
|
bind = STB_LOCAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,7 +224,7 @@ func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64
|
||||||
t := int(typ)
|
t := int(typ)
|
||||||
switch typ {
|
switch typ {
|
||||||
case TextSym, DataSym, BSSSym:
|
case TextSym, DataSym, BSSSym:
|
||||||
if x.Version != 0 {
|
if x.IsFileLocal() {
|
||||||
t += 'a' - 'A'
|
t += 'a' - 'A'
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ type AuxSymbol struct {
|
||||||
elftype elf.SymType
|
elftype elf.SymType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
SymVerStatic = 10 // Minimum version used by static (file-local) syms
|
||||||
|
)
|
||||||
|
|
||||||
func (s *Symbol) String() string {
|
func (s *Symbol) String() string {
|
||||||
if s.Version == 0 {
|
if s.Version == 0 {
|
||||||
return s.Name
|
return s.Name
|
||||||
|
|
@ -58,6 +62,10 @@ func (s *Symbol) String() string {
|
||||||
return fmt.Sprintf("%s<%d>", s.Name, s.Version)
|
return fmt.Sprintf("%s<%d>", s.Name, s.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Symbol) IsFileLocal() bool {
|
||||||
|
return s.Version >= SymVerStatic
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Symbol) ElfsymForReloc() int32 {
|
func (s *Symbol) ElfsymForReloc() int32 {
|
||||||
// If putelfsym created a local version of this symbol, use that in all
|
// If putelfsym created a local version of this symbol, use that in all
|
||||||
// relocations.
|
// relocations.
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,11 @@ type Symbols struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSymbols() *Symbols {
|
func NewSymbols() *Symbols {
|
||||||
|
hash := make([]map[string]*Symbol, SymVerStatic)
|
||||||
|
// Preallocate about 2mb for hash of non static symbols
|
||||||
|
hash[0] = make(map[string]*Symbol, 100000)
|
||||||
return &Symbols{
|
return &Symbols{
|
||||||
hash: []map[string]*Symbol{
|
hash: hash,
|
||||||
// preallocate about 2mb for hash of
|
|
||||||
// non static symbols
|
|
||||||
make(map[string]*Symbol, 100000),
|
|
||||||
},
|
|
||||||
Allsym: make([]*Symbol, 0, 100000),
|
Allsym: make([]*Symbol, 0, 100000),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue