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>
|
||||
<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>R29</code> is the frame pointer.
|
||||
<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 Test26066(t *testing.T) { test26066(t) }
|
||||
func Test26213(t *testing.T) { test26213(t) }
|
||||
func Test27660(t *testing.T) { test27660(t) }
|
||||
|
||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(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
|
||||
pprof
|
||||
internal
|
||||
binutils
|
||||
testdata
|
||||
+
|
||||
driver
|
||||
testdata
|
||||
+
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@
|
|||
console.warn("exit code:", code);
|
||||
}
|
||||
};
|
||||
this._exitPromise = new Promise((resolve) => {
|
||||
this._resolveExitPromise = resolve;
|
||||
});
|
||||
this._pendingCallback = null;
|
||||
this._callbackTimeouts = new Map();
|
||||
this._nextCallbackTimeoutID = 1;
|
||||
|
||||
|
|
@ -194,6 +198,11 @@
|
|||
const timeOrigin = Date.now() - performance.now();
|
||||
this.importObject = {
|
||||
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)
|
||||
"runtime.wasmExit": (sp) => {
|
||||
const code = mem().getInt32(sp + 8, true);
|
||||
|
|
@ -229,7 +238,7 @@
|
|||
const id = this._nextCallbackTimeoutID;
|
||||
this._nextCallbackTimeoutID++;
|
||||
this._callbackTimeouts.set(id, setTimeout(
|
||||
() => { this._resolveCallbackPromise(); },
|
||||
() => { this._resume(); },
|
||||
getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
|
||||
));
|
||||
mem().setInt32(sp + 16, id, true);
|
||||
|
|
@ -254,7 +263,9 @@
|
|||
|
||||
// func valueGet(v ref, p string) ref
|
||||
"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)
|
||||
|
|
@ -278,7 +289,9 @@
|
|||
const v = loadValue(sp + 8);
|
||||
const m = Reflect.get(v, loadString(sp + 16));
|
||||
const args = loadSliceOfValues(sp + 32);
|
||||
storeValue(sp + 56, Reflect.apply(m, v, args));
|
||||
const result = Reflect.apply(m, v, args);
|
||||
sp = this._inst.exports.getsp(); // see comment above
|
||||
storeValue(sp + 56, result);
|
||||
mem().setUint8(sp + 64, 1);
|
||||
} catch (err) {
|
||||
storeValue(sp + 56, err);
|
||||
|
|
@ -291,7 +304,9 @@
|
|||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
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);
|
||||
} catch (err) {
|
||||
storeValue(sp + 40, err);
|
||||
|
|
@ -304,7 +319,9 @@
|
|||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
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);
|
||||
} catch (err) {
|
||||
storeValue(sp + 40, err);
|
||||
|
|
@ -355,7 +372,6 @@
|
|||
this,
|
||||
];
|
||||
this._refs = new Map();
|
||||
this._callbackShutdown = false;
|
||||
this.exited = false;
|
||||
|
||||
const mem = new DataView(this._inst.exports.mem.buffer)
|
||||
|
|
@ -390,42 +406,30 @@
|
|||
offset += 8;
|
||||
});
|
||||
|
||||
while (true) {
|
||||
const callbackPromise = new Promise((resolve) => {
|
||||
this._resolveCallbackPromise = () => {
|
||||
if (this.exited) {
|
||||
throw new Error("bad callback: Go program has already exited");
|
||||
}
|
||||
setTimeout(resolve, 0); // make sure it is asynchronous
|
||||
};
|
||||
});
|
||||
this._inst.exports.run(argc, argv);
|
||||
if (this.exited) {
|
||||
break;
|
||||
}
|
||||
await callbackPromise;
|
||||
this._inst.exports.run(argc, argv);
|
||||
if (this.exited) {
|
||||
this._resolveExitPromise();
|
||||
}
|
||||
await this._exitPromise;
|
||||
}
|
||||
|
||||
_resume() {
|
||||
if (this.exited) {
|
||||
throw new Error("bad callback: Go program has already exited");
|
||||
}
|
||||
this._inst.exports.resume();
|
||||
if (this.exited) {
|
||||
this._resolveExitPromise();
|
||||
}
|
||||
}
|
||||
|
||||
static _makeCallbackHelper(id, pendingCallbacks, go) {
|
||||
_makeCallbackHelper(id) {
|
||||
const go = this;
|
||||
return function () {
|
||||
pendingCallbacks.push({ id: id, args: arguments });
|
||||
go._resolveCallbackPromise();
|
||||
};
|
||||
}
|
||||
|
||||
static _makeEventCallbackHelper(preventDefault, stopPropagation, stopImmediatePropagation, fn) {
|
||||
return function (event) {
|
||||
if (preventDefault) {
|
||||
event.preventDefault();
|
||||
}
|
||||
if (stopPropagation) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
if (stopImmediatePropagation) {
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
fn(event);
|
||||
const cb = { id: id, this: this, args: arguments };
|
||||
go._pendingCallback = cb;
|
||||
go._resume();
|
||||
return cb.result;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -444,8 +448,8 @@
|
|||
process.on("exit", (code) => { // Node.js exits if no callback is pending
|
||||
if (code === 0 && !go.exited) {
|
||||
// deadlock, make Go print error and stack traces
|
||||
go._callbackShutdown = true;
|
||||
go._inst.exports.run();
|
||||
go._pendingCallback = { id: 0 };
|
||||
go._resume();
|
||||
}
|
||||
});
|
||||
return go.run(result.instance);
|
||||
|
|
|
|||
|
|
@ -550,7 +550,7 @@ func TestWriter(t *testing.T) {
|
|||
t.Errorf("%s: %d bytes written", context, len(written))
|
||||
}
|
||||
for l := 0; l < len(written); l++ {
|
||||
if written[i] != data[i] {
|
||||
if written[l] != data[l] {
|
||||
t.Errorf("wrong bytes written")
|
||||
t.Errorf("want=%q", data[0:len(written)])
|
||||
t.Errorf("have=%q", written)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ import (
|
|||
"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 {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
|
|
@ -24,6 +31,13 @@ func equalPortable(a, b []byte) bool {
|
|||
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),
|
||||
// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
|
||||
func explode(s []byte, n int) [][]byte {
|
||||
|
|
@ -83,6 +97,11 @@ func ContainsRune(b []byte, r rune) bool {
|
|||
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 {
|
||||
for i, b := range s {
|
||||
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 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
tab, err := f.PCLineTable()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -258,6 +258,9 @@ func archArm64() *Arch {
|
|||
for i := arm64.REG_R0; i <= arm64.REG_R31; 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++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -607,6 +607,7 @@ var arm64OperandTests = []operandTest{
|
|||
{"R0", "R0"},
|
||||
{"R10", "R10"},
|
||||
{"R11", "R11"},
|
||||
{"R18_PLATFORM", "R18"},
|
||||
{"$4503601774854144.0", "$(4503601774854144.0)"},
|
||||
{"$runtime·badsystemstack(SB)", "$runtime.badsystemstack(SB)"},
|
||||
{"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 ZR.SXTX<<1, R2, R3 // 43e43f8b
|
||||
ADDW R2.SXTW, R10, R12 // 4cc1220b
|
||||
ADD R18.UXTX, R14, R17 // d161328b
|
||||
ADDSW R18.UXTW, R14, R17 // d141322b
|
||||
ADD R19.UXTX, R14, R17 // d161338b
|
||||
ADDSW R19.UXTW, R14, R17 // d141332b
|
||||
ADDS R12.SXTX, R3, R1 // 61e02cab
|
||||
SUB R19.UXTH<<4, R2, R21 // 553033cb
|
||||
SUBW R1.UXTX<<1, R3, R2 // 6264214b
|
||||
|
|
@ -144,7 +144,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
||||
MOVD (R3)(R6), R5 // MOVD (R3)(R6*1), R5 // 656866f8
|
||||
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 (R3)(R7.SXTX<<3), R8 // 68f867f8
|
||||
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
|
||||
|
|
@ -154,7 +154,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
MOVHU (R1)(R2<<1), R5 // 25786278
|
||||
MOVB (R9)(R3.UXTW), R6 // 2649a338
|
||||
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
|
||||
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
|
||||
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
|
||||
|
|
@ -195,6 +195,11 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
CMPW $27745, R2 // 3b8c8d525f001b6b
|
||||
CMNW $0x3fffffc0, R2 // CMNW $1073741760, R2 // fb5f1a325f001b2b
|
||||
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
|
||||
// LTYPE1 imsr ',' spreg ','
|
||||
// {
|
||||
|
|
@ -222,6 +227,13 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
EOR $(1<<63), R1 // EOR $-9223372036854775808, R1 // 210041d2
|
||||
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
|
||||
ORR $0x22220000, R3, R4 // ORR $572653568, R3, R4 // 5b44a4d264001baa
|
||||
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
|
||||
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
|
||||
AND $0x7fffffff, R3 // AND $2147483647, R3 // 63784092
|
||||
ANDS $0x0ffffffff80000000, R2 // ANDS $-2147483648, R2 // 428061f2
|
||||
AND $0xfffff, R2 // AND $1048575, R2 // 424c4092
|
||||
ANDW $0xf00fffff, R1 // ANDW $4027580415, R1 // 215c0412
|
||||
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
|
||||
|
||||
AND $8, R0, RSP // 1f007d92
|
||||
|
|
@ -249,13 +270,20 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
EON $8, R0, RSP // 1ff87cd2
|
||||
|
||||
MOVD $0x3fffffffc000, R0 // MOVD $70368744161280, R0 // e07f72b2
|
||||
MOVW $1000000, R4 // 04488852e401a072
|
||||
MOVW $0xaaaa0000, R1 // MOVW $2863267840, R1 // 4155b552
|
||||
MOVW $0xaaaaffff, R1 // MOVW $2863333375, R1 // a1aaaa12
|
||||
MOVW $0xaaaa, R1 // MOVW $43690, R1 // 41559552
|
||||
MOVW $0xffffaaaa, R1 // MOVW $4294945450, R1 // a1aa8a12
|
||||
MOVW $0xffff0000, R1 // MOVW $4294901760, R1 // e1ffbf52
|
||||
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 $0xaaaa0000aaaa1111, R1 // MOVD $-6149102338357718767, R1 // 212282d24155b5f24155f5f2
|
||||
MOVD $0x1111ffff1111aaaa, R1 // MOVD $1230045644216969898, R1 // a1aa8a922122a2f22122e2f2
|
||||
MOVD $0, R1 // 010080d2
|
||||
MOVD $-1, R1 // 01008092
|
||||
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
|
||||
BFXIL $26, R8, $16, R20 // 14a55ab3
|
||||
BICW R7@>15, R5, R16 // b03ce70a
|
||||
BIC R12@>13, R12, R18 // 9235ec8a
|
||||
BIC R12@>13, R12, R19 // 9335ec8a
|
||||
BICSW R25->20, R3, R20 // 7450b96a
|
||||
BICS R19->12, R1, R23 // 3730b3ea
|
||||
BICS R19, R1, R23 // 370033ea
|
||||
|
|
@ -76,7 +76,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
CCMN LE, R30, R12, $6 // c6d34cba
|
||||
CCMPW VS, R29, $15, $7 // a76b4f7a
|
||||
CCMP LE, R7, $19, $3 // e3d853fa
|
||||
CCMPW HS, R18, R6, $0 // 4022467a
|
||||
CCMPW HS, R19, R6, $0 // 6022467a
|
||||
CCMP LT, R30, R6, $7 // c7b346fa
|
||||
CCMN MI, ZR, R1, $4 // e44341ba
|
||||
CSINCW HS, ZR, R27, R14 // ee279b1a
|
||||
|
|
@ -118,7 +118,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
CRC32H R3, R21, R27 // bb46c31a
|
||||
CRC32W R22, R30, R9 // c94bd61a
|
||||
CRC32X R20, R4, R15 // 8f4cd49a
|
||||
CRC32CB R18, R27, R22 // 7653d21a
|
||||
CRC32CB R19, R27, R22 // 7653d31a
|
||||
CRC32CH R21, R0, R20 // 1454d51a
|
||||
CRC32CW R9, R3, R21 // 7558c91a
|
||||
CRC32CX R11, R0, R24 // 185ccb9a
|
||||
|
|
@ -133,7 +133,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
CSINVW AL, R23, R21, R5 // e5e2955a
|
||||
CSINV LO, R2, R11, R14 // 4e308bda
|
||||
CSNEGW HS, R16, R29, R10 // 0a269d5a
|
||||
CSNEG NE, R21, R18, R11 // ab1692da
|
||||
CSNEG NE, R21, R19, R11 // ab1693da
|
||||
//TODO DC
|
||||
DCPS1 $11378 // 418ea5d4
|
||||
DCPS2 $10699 // 6239a5d4
|
||||
|
|
@ -185,23 +185,23 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
MOVBU.P 42(R2), R12 // 4ca44238
|
||||
MOVBU.W -27(R2), R14 // 4e5c5e38
|
||||
MOVBU 2916(R24), R3 // 03936d39
|
||||
MOVBU (R18)(R14<<0), R23 // 577a6e38
|
||||
MOVBU (R19)(R14<<0), R23 // 777a6e38
|
||||
MOVBU (R2)(R8.SXTX), R19 // 53e86838
|
||||
MOVBU (R27)(R23), R14 // MOVBU (R27)(R23*1), R14 // 6e6b7738
|
||||
MOVHU.P 107(R14), R13 // cdb54678
|
||||
MOVHU.W 192(R3), R2 // 620c4c78
|
||||
MOVHU 6844(R4), R18 // 92787579
|
||||
MOVHU 6844(R4), R19 // 93787579
|
||||
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
|
||||
//TODO MOVBW.W -57(R18), R13 // 4d7edc38
|
||||
//TODO MOVBW.W -57(R19), R13 // 6d7edc38
|
||||
MOVB.W -178(R16), R24 // 18ee9438
|
||||
//TODO MOVBW 430(R8), R22 // 16b9c639
|
||||
MOVB 997(R9), R23 // 37958f39
|
||||
//TODO MOVBW (R2<<1)(R21), R15 // af7ae238
|
||||
//TODO MOVBW (R26)(R0), R21 // 1568fa38
|
||||
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
|
||||
//TODO MOVHW.P 218(R22), R25 // d9a6cd78
|
||||
MOVH.P 179(R23), R5 // e5368b78
|
||||
|
|
@ -212,7 +212,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
//TODO MOVHW (R22)(R24.SXTX), R4 // c4eaf878
|
||||
MOVH (R26)(R30.UXTW<<1), ZR // 5f5bbe78
|
||||
MOVW.P -58(R16), R2 // 02669cb8
|
||||
MOVW.W -216(R18), R8 // 488e92b8
|
||||
MOVW.W -216(R19), R8 // 688e92b8
|
||||
MOVW 4764(R23), R10 // ea9e92b9
|
||||
MOVW (R8)(R3.UXTW), R17 // 1149a3b8
|
||||
//TODO LDTR -0x1e(R3), R4 // 64285eb8
|
||||
|
|
@ -297,7 +297,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
RET // c0035fd6
|
||||
REVW R8, R10 // 0a09c05a
|
||||
REV R1, R2 // 220cc0da
|
||||
REV16W R21, R18 // b206c05a
|
||||
REV16W R21, R19 // b306c05a
|
||||
REV16 R25, R4 // 2407c0da
|
||||
REV32 R27, R21 // 750bc0da
|
||||
EXTRW $27, R4, R25, R19 // 336f8413
|
||||
|
|
@ -308,7 +308,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
ROR R0, R23, R2 // e22ec09a
|
||||
SBCW R4, R8, R24 // 1801045a
|
||||
SBC R25, R10, R26 // 5a0119da
|
||||
SBCSW R27, R18, R18 // 52021b7a
|
||||
SBCSW R27, R19, R19 // 73021b7a
|
||||
SBCS R5, R9, R5 // 250105fa
|
||||
SBFIZW $9, R10, $18, R22 // 56451713
|
||||
SBFIZ $6, R11, $15, R20 // 74397a93
|
||||
|
|
@ -337,7 +337,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
//TODO STNPW 44(R1), R3, R10 // 2a8c0528
|
||||
//TODO STNP 0x108(R3), ZR, R7 // 67fc10a8
|
||||
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.W (R17, R11), 96(R8) // 112d86a9
|
||||
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
|
||||
MOVH R11, -80(R23) // eb021b78
|
||||
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
|
||||
MOVH R3, (R11)(R13<<1) // 63792d78
|
||||
//TODO STTR 55(R4), R29 // 9d7803b8
|
||||
//TODO STTR 124(R5), R25 // b9c807f8
|
||||
//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), (RSP), R10 // e10b2ac8
|
||||
STXPW (R1, R2), (R3), R10 // 61082a88
|
||||
STXPW (R1, R2), (RSP), R10 // e10b2a88
|
||||
STXRW R2, (R19), R18 // 627e1288
|
||||
STXRW R2, (R19), R20 // 627e1488
|
||||
STXR R15, (R21), R13 // af7e0dc8
|
||||
STXRB R7, (R9), R24 // 277d1808
|
||||
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 $(1923<<12), R4, R27 // SUB $7876608, R4, R27 // 9b0c5ed1
|
||||
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
|
||||
UBFX $33, R17, $25, R5 // 25e661d3
|
||||
UDIVW R8, R21, R15 // af0ac81a
|
||||
UDIV R2, R18, R21 // 550ac29a
|
||||
UDIV R2, R19, R21 // 750ac29a
|
||||
UMADDL R0, R20, R17, R17 // 3152a09b
|
||||
UMSUBL R22, R4, R3, R7 // 6790b69b
|
||||
UMNEGL R3, R18, R1 // 41fea39b
|
||||
UMNEGL R3, R19, R1 // 61fea39b
|
||||
UMULH R24, R20, R24 // 987ed89b
|
||||
UMULL R18, R22, R19 // d37eb29b
|
||||
UMULL R19, R22, R19 // d37eb39b
|
||||
UXTBW R2, R6 // 461c0053
|
||||
UXTHW R7, R20 // f43c0053
|
||||
VCNT V0.B8, V0.B8 // 0058200e
|
||||
|
|
@ -471,7 +471,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
//TODO FCVTAS F27, R7 // 6703241e
|
||||
//TODO FCVTAS F19, R26 // 7a02249e
|
||||
//TODO FCVTAS F4, R0 // 8000641e
|
||||
//TODO FCVTAS F3, R18 // 7200649e
|
||||
//TODO FCVTAS F3, R19 // 7300649e
|
||||
//TODO FCVTAU F18, F28 // 5cca217e
|
||||
//TODO VFCVTAU V30.S4, V27.S4 // dbcb216e
|
||||
//TODO FCVTAU F0, R2 // 0200251e
|
||||
|
|
@ -482,16 +482,16 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
//TODO VFCVTL2 V15.H8, V25.S4 // f979214e
|
||||
//TODO FCVTMS F21, F28 // bcba215e
|
||||
//TODO VFCVTMS V5.D2, V2.D2 // a2b8614e
|
||||
//TODO FCVTMS F31, R18 // f203301e
|
||||
//TODO FCVTMS F31, R19 // f303301e
|
||||
//TODO FCVTMS F23, R16 // f002309e
|
||||
//TODO FCVTMS F16, R22 // 1602701e
|
||||
//TODO FCVTMS F14, R19 // d301709e
|
||||
//TODO FCVTMU F14, F8 // c8b9217e
|
||||
//TODO VFCVTMU V7.D2, V1.D2 // e1b8616e
|
||||
//TODO FCVTMU F2, R0 // 4000311e
|
||||
//TODO FCVTMU F23, R18 // f202319e
|
||||
//TODO FCVTMU F23, R19 // f302319e
|
||||
//TODO FCVTMU F16, R17 // 1102711e
|
||||
//TODO FCVTMU F12, R18 // 9201719e
|
||||
//TODO FCVTMU F12, R19 // 9301719e
|
||||
//TODO VFCVTN V23.D2, V26.S2 // fa6a610e
|
||||
//TODO VFCVTN2 V2.D2, V31.S4 // 5f68614e
|
||||
//TODO FCVTNS F3, F27 // 7ba8215e
|
||||
|
|
@ -540,7 +540,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||
//TODO FCVTZU $14, F24, R20 // 14cb191e
|
||||
//TODO FCVTZU $6, F25, R17 // 31eb199e
|
||||
//TODO FCVTZU $5, F17, R10 // 2aee591e
|
||||
//TODO FCVTZU $6, F7, R18 // f2e8599e
|
||||
//TODO FCVTZU $6, F7, R19 // f3e8599e
|
||||
FCVTZUSW F2, R9 // 4900391e
|
||||
FCVTZUS F12, R29 // 9d01399e
|
||||
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 (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 (R18), V14.B[15] // 4e1e404d
|
||||
VLD1 (R19), V14.B[15] // 6e1e404d
|
||||
VLD1 (R29), V0.H[1] // a04b400d
|
||||
VLD1 (R27), V2.S[0] // 6283400d
|
||||
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 2(R1), V28.H[2] // 3c50df0d
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// We have a '#'; it must be followed by a known word (define, include, etc.).
|
||||
tok := in.Stack.Next()
|
||||
|
|
|
|||
|
|
@ -827,6 +827,10 @@ The directives are:
|
|||
possibly version in the dynamic library, and the optional "<library>"
|
||||
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.
|
||||
|
||||
Examples:
|
||||
|
|
|
|||
|
|
@ -246,7 +246,22 @@ func (p *Package) writeDefs() {
|
|||
|
||||
init := gccgoInit.String()
|
||||
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.Fprint(fc, init)
|
||||
fmt.Fprintln(fc, "}")
|
||||
|
|
|
|||
|
|
@ -587,6 +587,7 @@ var knownFormats = map[string]string{
|
|||
"*cmd/compile/internal/types.Sym %S": "",
|
||||
"*cmd/compile/internal/types.Sym %p": "",
|
||||
"*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 %-S": "",
|
||||
|
|
@ -598,6 +599,7 @@ var knownFormats = map[string]string{
|
|||
"*cmd/compile/internal/types.Type %v": "",
|
||||
"*cmd/internal/obj.Addr %v": "",
|
||||
"*cmd/internal/obj.LSym %v": "",
|
||||
"*math/big.Float %f": "",
|
||||
"*math/big.Int %#x": "",
|
||||
"*math/big.Int %s": "",
|
||||
"*math/big.Int %v": "",
|
||||
|
|
@ -658,6 +660,7 @@ var knownFormats = map[string]string{
|
|||
"cmd/compile/internal/ssa.rbrank %d": "",
|
||||
"cmd/compile/internal/ssa.regMask %d": "",
|
||||
"cmd/compile/internal/ssa.register %d": "",
|
||||
"cmd/compile/internal/syntax.Error %q": "",
|
||||
"cmd/compile/internal/syntax.Expr %#v": "",
|
||||
"cmd/compile/internal/syntax.Node %T": "",
|
||||
"cmd/compile/internal/syntax.Operator %s": "",
|
||||
|
|
@ -705,33 +708,34 @@ var knownFormats = map[string]string{
|
|||
"interface{} %v": "",
|
||||
"map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "",
|
||||
"map[cmd/compile/internal/ssa.ID]uint32 %v": "",
|
||||
"reflect.Type %s": "",
|
||||
"rune %#U": "",
|
||||
"rune %c": "",
|
||||
"string %-*s": "",
|
||||
"string %-16s": "",
|
||||
"string %-6s": "",
|
||||
"string %.*s": "",
|
||||
"string %q": "",
|
||||
"string %s": "",
|
||||
"string %v": "",
|
||||
"time.Duration %d": "",
|
||||
"time.Duration %v": "",
|
||||
"uint %04x": "",
|
||||
"uint %5d": "",
|
||||
"uint %d": "",
|
||||
"uint %x": "",
|
||||
"uint16 %d": "",
|
||||
"uint16 %v": "",
|
||||
"uint16 %x": "",
|
||||
"uint32 %#x": "",
|
||||
"uint32 %d": "",
|
||||
"uint32 %v": "",
|
||||
"uint32 %x": "",
|
||||
"uint64 %08x": "",
|
||||
"uint64 %d": "",
|
||||
"uint64 %x": "",
|
||||
"uint8 %d": "",
|
||||
"uint8 %x": "",
|
||||
"uintptr %d": "",
|
||||
"math/big.Accuracy %s": "",
|
||||
"reflect.Type %s": "",
|
||||
"rune %#U": "",
|
||||
"rune %c": "",
|
||||
"string %-*s": "",
|
||||
"string %-16s": "",
|
||||
"string %-6s": "",
|
||||
"string %.*s": "",
|
||||
"string %q": "",
|
||||
"string %s": "",
|
||||
"string %v": "",
|
||||
"time.Duration %d": "",
|
||||
"time.Duration %v": "",
|
||||
"uint %04x": "",
|
||||
"uint %5d": "",
|
||||
"uint %d": "",
|
||||
"uint %x": "",
|
||||
"uint16 %d": "",
|
||||
"uint16 %v": "",
|
||||
"uint16 %x": "",
|
||||
"uint32 %#x": "",
|
||||
"uint32 %d": "",
|
||||
"uint32 %v": "",
|
||||
"uint32 %x": "",
|
||||
"uint64 %08x": "",
|
||||
"uint64 %d": "",
|
||||
"uint64 %x": "",
|
||||
"uint8 %d": "",
|
||||
"uint8 %x": "",
|
||||
"uintptr %d": "",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,110 +51,105 @@ var runtimeDecls = [...]struct {
|
|||
{"decoderune", funcTag, 50},
|
||||
{"countrunes", funcTag, 51},
|
||||
{"convI2I", funcTag, 52},
|
||||
{"convT2E", funcTag, 53},
|
||||
{"convT2E16", funcTag, 52},
|
||||
{"convT2E32", funcTag, 52},
|
||||
{"convT2E64", funcTag, 52},
|
||||
{"convT2Estring", funcTag, 52},
|
||||
{"convT2Eslice", funcTag, 52},
|
||||
{"convT2Enoptr", funcTag, 53},
|
||||
{"convT2I", funcTag, 53},
|
||||
{"convT2I16", funcTag, 52},
|
||||
{"convT2I32", funcTag, 52},
|
||||
{"convT2I64", funcTag, 52},
|
||||
{"convT2Istring", funcTag, 52},
|
||||
{"convT2Islice", funcTag, 52},
|
||||
{"convT2Inoptr", funcTag, 53},
|
||||
{"convT16", funcTag, 54},
|
||||
{"convT32", funcTag, 54},
|
||||
{"convT64", funcTag, 54},
|
||||
{"convTstring", funcTag, 54},
|
||||
{"convTslice", funcTag, 54},
|
||||
{"convT2E", funcTag, 55},
|
||||
{"convT2Enoptr", funcTag, 55},
|
||||
{"convT2I", funcTag, 55},
|
||||
{"convT2Inoptr", funcTag, 55},
|
||||
{"assertE2I", funcTag, 52},
|
||||
{"assertE2I2", funcTag, 54},
|
||||
{"assertE2I2", funcTag, 56},
|
||||
{"assertI2I", funcTag, 52},
|
||||
{"assertI2I2", funcTag, 54},
|
||||
{"panicdottypeE", funcTag, 55},
|
||||
{"panicdottypeI", funcTag, 55},
|
||||
{"panicnildottype", funcTag, 56},
|
||||
{"ifaceeq", funcTag, 59},
|
||||
{"efaceeq", funcTag, 59},
|
||||
{"fastrand", funcTag, 61},
|
||||
{"makemap64", funcTag, 63},
|
||||
{"makemap", funcTag, 64},
|
||||
{"makemap_small", funcTag, 65},
|
||||
{"mapaccess1", funcTag, 66},
|
||||
{"mapaccess1_fast32", funcTag, 67},
|
||||
{"mapaccess1_fast64", funcTag, 67},
|
||||
{"mapaccess1_faststr", funcTag, 67},
|
||||
{"mapaccess1_fat", funcTag, 68},
|
||||
{"mapaccess2", funcTag, 69},
|
||||
{"mapaccess2_fast32", funcTag, 70},
|
||||
{"mapaccess2_fast64", funcTag, 70},
|
||||
{"mapaccess2_faststr", funcTag, 70},
|
||||
{"mapaccess2_fat", funcTag, 71},
|
||||
{"mapassign", funcTag, 66},
|
||||
{"mapassign_fast32", funcTag, 67},
|
||||
{"mapassign_fast32ptr", funcTag, 67},
|
||||
{"mapassign_fast64", funcTag, 67},
|
||||
{"mapassign_fast64ptr", funcTag, 67},
|
||||
{"mapassign_faststr", funcTag, 67},
|
||||
{"mapiterinit", funcTag, 72},
|
||||
{"mapdelete", funcTag, 72},
|
||||
{"mapdelete_fast32", funcTag, 73},
|
||||
{"mapdelete_fast64", funcTag, 73},
|
||||
{"mapdelete_faststr", funcTag, 73},
|
||||
{"mapiternext", funcTag, 74},
|
||||
{"mapclear", funcTag, 75},
|
||||
{"makechan64", funcTag, 77},
|
||||
{"makechan", funcTag, 78},
|
||||
{"chanrecv1", funcTag, 80},
|
||||
{"chanrecv2", funcTag, 81},
|
||||
{"chansend1", funcTag, 83},
|
||||
{"assertI2I2", funcTag, 56},
|
||||
{"panicdottypeE", funcTag, 57},
|
||||
{"panicdottypeI", funcTag, 57},
|
||||
{"panicnildottype", funcTag, 58},
|
||||
{"ifaceeq", funcTag, 60},
|
||||
{"efaceeq", funcTag, 60},
|
||||
{"fastrand", funcTag, 62},
|
||||
{"makemap64", funcTag, 64},
|
||||
{"makemap", funcTag, 65},
|
||||
{"makemap_small", funcTag, 66},
|
||||
{"mapaccess1", funcTag, 67},
|
||||
{"mapaccess1_fast32", funcTag, 68},
|
||||
{"mapaccess1_fast64", funcTag, 68},
|
||||
{"mapaccess1_faststr", funcTag, 68},
|
||||
{"mapaccess1_fat", funcTag, 69},
|
||||
{"mapaccess2", funcTag, 70},
|
||||
{"mapaccess2_fast32", funcTag, 71},
|
||||
{"mapaccess2_fast64", funcTag, 71},
|
||||
{"mapaccess2_faststr", funcTag, 71},
|
||||
{"mapaccess2_fat", funcTag, 72},
|
||||
{"mapassign", funcTag, 67},
|
||||
{"mapassign_fast32", funcTag, 68},
|
||||
{"mapassign_fast32ptr", funcTag, 68},
|
||||
{"mapassign_fast64", funcTag, 68},
|
||||
{"mapassign_fast64ptr", funcTag, 68},
|
||||
{"mapassign_faststr", funcTag, 68},
|
||||
{"mapiterinit", funcTag, 73},
|
||||
{"mapdelete", funcTag, 73},
|
||||
{"mapdelete_fast32", funcTag, 74},
|
||||
{"mapdelete_fast64", funcTag, 74},
|
||||
{"mapdelete_faststr", funcTag, 74},
|
||||
{"mapiternext", funcTag, 75},
|
||||
{"mapclear", funcTag, 76},
|
||||
{"makechan64", funcTag, 78},
|
||||
{"makechan", funcTag, 79},
|
||||
{"chanrecv1", funcTag, 81},
|
||||
{"chanrecv2", funcTag, 82},
|
||||
{"chansend1", funcTag, 84},
|
||||
{"closechan", funcTag, 23},
|
||||
{"writeBarrier", varTag, 85},
|
||||
{"typedmemmove", funcTag, 86},
|
||||
{"typedmemclr", funcTag, 87},
|
||||
{"typedslicecopy", funcTag, 88},
|
||||
{"selectnbsend", funcTag, 89},
|
||||
{"selectnbrecv", funcTag, 90},
|
||||
{"selectnbrecv2", funcTag, 92},
|
||||
{"selectsetpc", funcTag, 56},
|
||||
{"selectgo", funcTag, 93},
|
||||
{"writeBarrier", varTag, 86},
|
||||
{"typedmemmove", funcTag, 87},
|
||||
{"typedmemclr", funcTag, 88},
|
||||
{"typedslicecopy", funcTag, 89},
|
||||
{"selectnbsend", funcTag, 90},
|
||||
{"selectnbrecv", funcTag, 91},
|
||||
{"selectnbrecv2", funcTag, 93},
|
||||
{"selectsetpc", funcTag, 58},
|
||||
{"selectgo", funcTag, 94},
|
||||
{"block", funcTag, 5},
|
||||
{"makeslice", funcTag, 94},
|
||||
{"makeslice64", funcTag, 95},
|
||||
{"growslice", funcTag, 97},
|
||||
{"memmove", funcTag, 98},
|
||||
{"memclrNoHeapPointers", funcTag, 99},
|
||||
{"memclrHasPointers", funcTag, 99},
|
||||
{"memequal", funcTag, 100},
|
||||
{"memequal8", funcTag, 101},
|
||||
{"memequal16", funcTag, 101},
|
||||
{"memequal32", funcTag, 101},
|
||||
{"memequal64", funcTag, 101},
|
||||
{"memequal128", funcTag, 101},
|
||||
{"int64div", funcTag, 102},
|
||||
{"uint64div", funcTag, 103},
|
||||
{"int64mod", funcTag, 102},
|
||||
{"uint64mod", funcTag, 103},
|
||||
{"float64toint64", funcTag, 104},
|
||||
{"float64touint64", funcTag, 105},
|
||||
{"float64touint32", funcTag, 106},
|
||||
{"int64tofloat64", funcTag, 107},
|
||||
{"uint64tofloat64", funcTag, 108},
|
||||
{"uint32tofloat64", funcTag, 109},
|
||||
{"complex128div", funcTag, 110},
|
||||
{"racefuncenter", funcTag, 111},
|
||||
{"makeslice", funcTag, 95},
|
||||
{"makeslice64", funcTag, 96},
|
||||
{"growslice", funcTag, 98},
|
||||
{"memmove", funcTag, 99},
|
||||
{"memclrNoHeapPointers", funcTag, 100},
|
||||
{"memclrHasPointers", funcTag, 100},
|
||||
{"memequal", funcTag, 101},
|
||||
{"memequal8", funcTag, 102},
|
||||
{"memequal16", funcTag, 102},
|
||||
{"memequal32", funcTag, 102},
|
||||
{"memequal64", funcTag, 102},
|
||||
{"memequal128", funcTag, 102},
|
||||
{"int64div", funcTag, 103},
|
||||
{"uint64div", funcTag, 104},
|
||||
{"int64mod", funcTag, 103},
|
||||
{"uint64mod", funcTag, 104},
|
||||
{"float64toint64", funcTag, 105},
|
||||
{"float64touint64", funcTag, 106},
|
||||
{"float64touint32", funcTag, 107},
|
||||
{"int64tofloat64", funcTag, 108},
|
||||
{"uint64tofloat64", funcTag, 109},
|
||||
{"uint32tofloat64", funcTag, 110},
|
||||
{"complex128div", funcTag, 111},
|
||||
{"racefuncenter", funcTag, 112},
|
||||
{"racefuncenterfp", funcTag, 5},
|
||||
{"racefuncexit", funcTag, 5},
|
||||
{"raceread", funcTag, 111},
|
||||
{"racewrite", funcTag, 111},
|
||||
{"racereadrange", funcTag, 112},
|
||||
{"racewriterange", funcTag, 112},
|
||||
{"msanread", funcTag, 112},
|
||||
{"msanwrite", funcTag, 112},
|
||||
{"raceread", funcTag, 112},
|
||||
{"racewrite", funcTag, 112},
|
||||
{"racereadrange", funcTag, 113},
|
||||
{"racewriterange", funcTag, 113},
|
||||
{"msanread", funcTag, 113},
|
||||
{"msanwrite", funcTag, 113},
|
||||
{"support_popcnt", varTag, 11},
|
||||
{"support_sse41", varTag, 11},
|
||||
}
|
||||
|
||||
func runtimeTypes() []*types.Type {
|
||||
var typs [113]*types.Type
|
||||
var typs [114]*types.Type
|
||||
typs[0] = types.Bytetype
|
||||
typs[1] = types.NewPtr(typs[0])
|
||||
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[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[53] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
|
||||
typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])})
|
||||
typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
|
||||
typs[56] = functype(nil, []*Node{anonfield(typs[1])}, nil)
|
||||
typs[57] = types.NewPtr(typs[47])
|
||||
typs[58] = types.Types[TUNSAFEPTR]
|
||||
typs[59] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[58]), anonfield(typs[58])}, []*Node{anonfield(typs[11])})
|
||||
typs[60] = types.Types[TUINT32]
|
||||
typs[61] = functype(nil, nil, []*Node{anonfield(typs[60])})
|
||||
typs[62] = types.NewMap(typs[2], typs[2])
|
||||
typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[62])})
|
||||
typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[3])}, []*Node{anonfield(typs[62])})
|
||||
typs[65] = functype(nil, nil, []*Node{anonfield(typs[62])})
|
||||
typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
|
||||
typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, []*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[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
|
||||
typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, []*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[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, nil)
|
||||
typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, nil)
|
||||
typs[74] = functype(nil, []*Node{anonfield(typs[3])}, nil)
|
||||
typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62])}, nil)
|
||||
typs[76] = types.NewChan(typs[2], types.Cboth)
|
||||
typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[76])})
|
||||
typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[76])})
|
||||
typs[79] = types.NewChan(typs[2], types.Crecv)
|
||||
typs[80] = functype(nil, []*Node{anonfield(typs[79]), anonfield(typs[3])}, nil)
|
||||
typs[81] = functype(nil, []*Node{anonfield(typs[79]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||
typs[82] = types.NewChan(typs[2], types.Csend)
|
||||
typs[83] = functype(nil, []*Node{anonfield(typs[82]), anonfield(typs[3])}, nil)
|
||||
typs[84] = types.NewArray(typs[0], 3)
|
||||
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[86] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
|
||||
typs[87] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
|
||||
typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
|
||||
typs[89] = functype(nil, []*Node{anonfield(typs[82]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||
typs[90] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
|
||||
typs[91] = types.NewPtr(typs[11])
|
||||
typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
|
||||
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
|
||||
typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[58])})
|
||||
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[58])})
|
||||
typs[96] = types.NewSlice(typs[2])
|
||||
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[96]), anonfield(typs[32])}, []*Node{anonfield(typs[96])})
|
||||
typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
|
||||
typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil)
|
||||
typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])})
|
||||
typs[101] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||
typs[102] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
|
||||
typs[103] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
|
||||
typs[104] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])})
|
||||
typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
|
||||
typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[60])})
|
||||
typs[107] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
|
||||
typs[108] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
|
||||
typs[109] = functype(nil, []*Node{anonfield(typs[60])}, []*Node{anonfield(typs[13])})
|
||||
typs[110] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
|
||||
typs[111] = functype(nil, []*Node{anonfield(typs[47])}, nil)
|
||||
typs[112] = functype(nil, []*Node{anonfield(typs[47]), anonfield(typs[47])}, nil)
|
||||
typs[53] = types.Types[TUNSAFEPTR]
|
||||
typs[54] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[53])})
|
||||
typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
|
||||
typs[56] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])})
|
||||
typs[57] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
|
||||
typs[58] = functype(nil, []*Node{anonfield(typs[1])}, nil)
|
||||
typs[59] = types.NewPtr(typs[47])
|
||||
typs[60] = functype(nil, []*Node{anonfield(typs[59]), anonfield(typs[53]), anonfield(typs[53])}, []*Node{anonfield(typs[11])})
|
||||
typs[61] = types.Types[TUINT32]
|
||||
typs[62] = functype(nil, nil, []*Node{anonfield(typs[61])})
|
||||
typs[63] = types.NewMap(typs[2], typs[2])
|
||||
typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[63])})
|
||||
typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[3])}, []*Node{anonfield(typs[63])})
|
||||
typs[66] = functype(nil, nil, []*Node{anonfield(typs[63])})
|
||||
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[63]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
|
||||
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[63]), anonfield(typs[3])}, []*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[63]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
|
||||
typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), 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[3])}, nil)
|
||||
typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63])}, nil)
|
||||
typs[77] = types.NewChan(typs[2], types.Cboth)
|
||||
typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[77])})
|
||||
typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[77])})
|
||||
typs[80] = types.NewChan(typs[2], types.Crecv)
|
||||
typs[81] = functype(nil, []*Node{anonfield(typs[80]), anonfield(typs[3])}, nil)
|
||||
typs[82] = functype(nil, []*Node{anonfield(typs[80]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||
typs[83] = types.NewChan(typs[2], types.Csend)
|
||||
typs[84] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, nil)
|
||||
typs[85] = types.NewArray(typs[0], 3)
|
||||
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]), anonfield(typs[3])}, nil)
|
||||
typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
|
||||
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[83]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||
typs[91] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[80])}, []*Node{anonfield(typs[11])})
|
||||
typs[92] = types.NewPtr(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[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
|
||||
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[53])})
|
||||
typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[53])})
|
||||
typs[97] = types.NewSlice(typs[2])
|
||||
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[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
|
||||
typs[100] = functype(nil, []*Node{anonfield(typs[53]), anonfield(typs[47])}, nil)
|
||||
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[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
|
||||
typs[103] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*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[15])})
|
||||
typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
|
||||
typs[107] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[61])})
|
||||
typs[108] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
|
||||
typs[109] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
|
||||
typs[110] = functype(nil, []*Node{anonfield(typs[61])}, []*Node{anonfield(typs[13])})
|
||||
typs[111] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
|
||||
typs[112] = functype(nil, []*Node{anonfield(typs[47])}, nil)
|
||||
typs[113] = functype(nil, []*Node{anonfield(typs[47]), anonfield(typs[47])}, nil)
|
||||
return typs[:]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,23 +61,23 @@ func slicestringcopy(to any, fr any) int
|
|||
func decoderune(string, int) (retv rune, retk int)
|
||||
func countrunes(string) int
|
||||
|
||||
// interface conversions
|
||||
// Non-empty-interface to non-empty-interface conversion.
|
||||
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 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)
|
||||
|
||||
// Type to non-empty-interface conversion.
|
||||
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)
|
||||
|
||||
// interface type assertions x.(T)
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ func transformclosure(xfunc *Node) {
|
|||
lineno = lno
|
||||
}
|
||||
|
||||
// hasemptycvars returns true iff closure clo has an
|
||||
// hasemptycvars reports whether closure clo has an
|
||||
// empty list of captured vars.
|
||||
func hasemptycvars(clo *Node) bool {
|
||||
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]
|
||||
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]
|
||||
|
||||
|
|
|
|||
|
|
@ -1114,6 +1114,7 @@ var opprec = []int{
|
|||
OSLICEARR: 8,
|
||||
OSLICE3: 8,
|
||||
OSLICE3ARR: 8,
|
||||
OSLICEHEADER: 8,
|
||||
ODOTINTER: 8,
|
||||
ODOTMETH: 8,
|
||||
ODOTPTR: 8,
|
||||
|
|
@ -1393,6 +1394,12 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
|||
}
|
||||
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:
|
||||
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 (
|
||||
isforw [NTYPE]bool
|
||||
isInt [NTYPE]bool
|
||||
isFloat [NTYPE]bool
|
||||
isComplex [NTYPE]bool
|
||||
|
|
|
|||
|
|
@ -185,24 +185,6 @@ func (pp *Progs) settext(fn *Node) {
|
|||
ptxt.From.Type = obj.TYPE_MEM
|
||||
ptxt.From.Name = obj.NAME_EXTERN
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -909,7 +909,7 @@ func (w *exportWriter) mpfloat(f *big.Float, typ *types.Type) {
|
|||
|
||||
manti, acc := mant.Int(nil)
|
||||
if acc != big.Exact {
|
||||
Fatalf("exporter: internal error")
|
||||
Fatalf("mantissa scaling failed for %f (%s)", f, acc)
|
||||
}
|
||||
w.mpint(manti, typ)
|
||||
if manti.Sign() != 0 {
|
||||
|
|
|
|||
|
|
@ -38,9 +38,10 @@ import (
|
|||
const (
|
||||
inlineMaxBudget = 80
|
||||
inlineExtraAppendCost = 0
|
||||
inlineExtraCallCost = inlineMaxBudget // default is do not inline, -l=4 enables by using 1 instead.
|
||||
inlineExtraPanicCost = 1 // do not penalize inlining panics.
|
||||
inlineExtraThrowCost = inlineMaxBudget // with current (2018-05/1.11) code, inlining runtime.throw does not help.
|
||||
// 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.
|
||||
inlineExtraThrowCost = inlineMaxBudget // with current (2018-05/1.11) code, inlining runtime.throw does not help.
|
||||
|
||||
inlineBigFunctionNodes = 5000 // Functions with this many nodes are considered "big".
|
||||
inlineBigFunctionMaxCost = 20 // Max cost of inlinee when inlining into a "big" function.
|
||||
|
|
@ -141,6 +142,13 @@ func caninl(fn *Node) {
|
|||
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
|
||||
// granularity, so inlining yeswritebarrierrec functions can
|
||||
// confuse it (#22342). As a workaround, disallow inlining
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ func TestIntendedInlining(t *testing.T) {
|
|||
"isDirectIface",
|
||||
"itabHashFunc",
|
||||
"noescape",
|
||||
"pcvalueCacheKey",
|
||||
"readUnaligned32",
|
||||
"readUnaligned64",
|
||||
"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) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(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:
|
||||
p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`})
|
||||
return
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package gc
|
|||
import (
|
||||
"cmd/compile/internal/syntax"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
@ -49,10 +50,12 @@ func TestPragmaFields(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPragcgo(t *testing.T) {
|
||||
var tests = []struct {
|
||||
type testStruct struct {
|
||||
in string
|
||||
want []string
|
||||
}{
|
||||
}
|
||||
|
||||
var tests = []testStruct{
|
||||
{`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'`}},
|
||||
|
|
@ -61,8 +64,6 @@ func TestPragcgo(t *testing.T) {
|
|||
{`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 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_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`}},
|
||||
}
|
||||
|
||||
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 nopos syntax.Pos
|
||||
for _, tt := range tests {
|
||||
p.pragcgobuf = nil
|
||||
p.pragcgo(nopos, tt.in)
|
||||
|
||||
got := p.pragcgobuf
|
||||
want := [][]string{tt.want}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, got, want)
|
||||
continue
|
||||
p.err = make(chan syntax.Error)
|
||||
gotch := make(chan [][]string)
|
||||
go func() {
|
||||
p.pragcgobuf = nil
|
||||
p.pragcgo(nopos, tt.in)
|
||||
if p.pragcgobuf != nil {
|
||||
gotch <- 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}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("pragcgo(%q) = %q; want %q", tt.in, got, want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,6 +229,9 @@ func Main(archInit func(*Arch)) {
|
|||
flag.BoolVar(&flag_race, "race", false, "enable race detector")
|
||||
}
|
||||
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.BoolVar(&Debug_vlog, "v", false, "increase debug verbosity")
|
||||
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.
|
||||
// This will gather all the information about types
|
||||
// and methods but doesn't depend on any of it.
|
||||
//
|
||||
// We also defer type alias declarations until phase 2
|
||||
// to avoid cycles like #18640.
|
||||
// TODO(gri) Remove this again once we have a fix for #25838.
|
||||
defercheckwidth()
|
||||
|
||||
// Don't use range--typecheck can add closures to xtop.
|
||||
timings.Start("fe", "typecheck", "top1")
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
n := xtop[i]
|
||||
if op := n.Op; op != ODCL && op != OAS && op != OAS2 {
|
||||
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
|
||||
xtop[i] = typecheck(n, Etop)
|
||||
}
|
||||
}
|
||||
|
|
@ -506,7 +513,7 @@ func Main(archInit func(*Arch)) {
|
|||
timings.Start("fe", "typecheck", "top2")
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
n := xtop[i]
|
||||
if op := n.Op; op == ODCL || op == OAS || op == OAS2 {
|
||||
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
|
||||
xtop[i] = typecheck(n, Etop)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,22 +273,18 @@ func dumpglobls() {
|
|||
}
|
||||
|
||||
// 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,
|
||||
// storing only a single copy of the data,
|
||||
// failure to remove these duplicates adds a few percent to object file size.
|
||||
//
|
||||
// This is done during the sequential phase after compilation, since
|
||||
// global symbols can't be declared during parallel compilation.
|
||||
func addGCLocals() {
|
||||
seen := make(map[string]bool)
|
||||
for _, s := range Ctxt.Text {
|
||||
if s.Func == nil {
|
||||
continue
|
||||
}
|
||||
for _, gcsym := range []*obj.LSym{&s.Func.GCArgs, &s.Func.GCLocals, &s.Func.GCRegs} {
|
||||
if seen[gcsym.Name] {
|
||||
continue
|
||||
for _, gcsym := range []*obj.LSym{s.Func.GCArgs, s.Func.GCLocals, s.Func.GCRegs} {
|
||||
if gcsym != nil && !gcsym.OnList() {
|
||||
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 {
|
||||
ggloblsym(x, int32(len(x.P)), obj.RODATA|obj.LOCAL)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ package gc
|
|||
|
||||
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 {
|
||||
if i >= Op(len(_Op_index)-1) {
|
||||
|
|
|
|||
|
|
@ -1019,7 +1019,7 @@ func (lv *Liveness) epilogue() {
|
|||
live := lv.livevars[index]
|
||||
if v.Op.IsCall() && live.regs != 0 {
|
||||
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++
|
||||
}
|
||||
|
|
@ -1038,7 +1038,7 @@ func (lv *Liveness) epilogue() {
|
|||
// input parameters.
|
||||
for j, n := range lv.vars {
|
||||
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.
|
||||
|
|
@ -1047,7 +1047,7 @@ func (lv *Liveness) epilogue() {
|
|||
// so it doesn't appear live at entry.
|
||||
if regs := lv.regMaps[0]; regs != 0 {
|
||||
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
|
||||
// length of the bitmaps. All bitmaps are assumed to be of equal length. The
|
||||
// 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.
|
||||
// First, find the largest Xoffset node we care about.
|
||||
// (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.
|
||||
maxLocals := lv.stkptrsize
|
||||
|
||||
// Temporary symbols for encoding bitmaps.
|
||||
var argsSymTmp, liveSymTmp, regsSymTmp obj.LSym
|
||||
|
||||
args := bvalloc(int32(maxArgs / int64(Widthptr)))
|
||||
aoff := duint32(argssym, 0, uint32(len(lv.stackMaps))) // number of bitmaps
|
||||
aoff = duint32(argssym, aoff, uint32(args.n)) // number of bits in each bitmap
|
||||
aoff := duint32(&argsSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
|
||||
aoff = duint32(&argsSymTmp, aoff, uint32(args.n)) // number of bits in each bitmap
|
||||
|
||||
locals := bvalloc(int32(maxLocals / int64(Widthptr)))
|
||||
loff := duint32(livesym, 0, uint32(len(lv.stackMaps))) // number of bitmaps
|
||||
loff = duint32(livesym, loff, uint32(locals.n)) // number of bits in each bitmap
|
||||
loff := duint32(&liveSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
|
||||
loff = duint32(&liveSymTmp, loff, uint32(locals.n)) // number of bits in each bitmap
|
||||
|
||||
for _, live := range lv.stackMaps {
|
||||
args.Clear()
|
||||
|
|
@ -1503,13 +1506,13 @@ func (lv *Liveness) emit(argssym, livesym, regssym *obj.LSym) {
|
|||
|
||||
lv.pointerMap(live, lv.vars, args, locals)
|
||||
|
||||
aoff = dbvec(argssym, aoff, args)
|
||||
loff = dbvec(livesym, loff, locals)
|
||||
aoff = dbvec(&argsSymTmp, aoff, args)
|
||||
loff = dbvec(&liveSymTmp, loff, locals)
|
||||
}
|
||||
|
||||
regs := bvalloc(lv.usedRegs())
|
||||
roff := duint32(regssym, 0, uint32(len(lv.regMaps))) // number of bitmaps
|
||||
roff = duint32(regssym, roff, uint32(regs.n)) // number of bits in each bitmap
|
||||
roff := duint32(®sSymTmp, 0, uint32(len(lv.regMaps))) // number of bitmaps
|
||||
roff = duint32(®sSymTmp, roff, uint32(regs.n)) // number of bits in each bitmap
|
||||
if regs.n > 32 {
|
||||
// Our uint32 conversion below won't work.
|
||||
Fatalf("GP registers overflow uint32")
|
||||
|
|
@ -1519,25 +1522,29 @@ func (lv *Liveness) emit(argssym, livesym, regssym *obj.LSym) {
|
|||
for _, live := range lv.regMaps {
|
||||
regs.Clear()
|
||||
regs.b[0] = uint32(live)
|
||||
roff = dbvec(regssym, roff, regs)
|
||||
roff = dbvec(®sSymTmp, roff, regs)
|
||||
}
|
||||
}
|
||||
|
||||
// Give these LSyms content-addressable names,
|
||||
// so that they can be de-duplicated.
|
||||
// This provides significant binary size savings.
|
||||
// It is safe to rename these LSyms because
|
||||
// they are tracked separately from ctxt.hash.
|
||||
argssym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(argssym.P))
|
||||
livesym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(livesym.P))
|
||||
regssym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(regssym.P))
|
||||
//
|
||||
// These symbols will be added to Ctxt.Data by addGCLocals
|
||||
// after parallel compilation is done.
|
||||
makeSym := func(tmpSym *obj.LSym) *obj.LSym {
|
||||
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
|
||||
// pointer variables in the function and emits a runtime data
|
||||
// structure read by the garbage collector.
|
||||
// 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.
|
||||
vars, idx := getvariables(e.curfn)
|
||||
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
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -812,7 +812,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
|
|||
|
||||
sptrWeak := true
|
||||
var sptr *obj.LSym
|
||||
if !t.IsPtr() || t.PtrBase != nil {
|
||||
if !t.IsPtr() || t.IsPtrElem() {
|
||||
tptr := types.NewPtr(t)
|
||||
if t.Sym != nil || methods(tptr) != nil {
|
||||
sptrWeak = false
|
||||
|
|
@ -1137,7 +1137,7 @@ func dtypesym(t *types.Type) *obj.LSym {
|
|||
return lsym
|
||||
}
|
||||
// TODO(mdempsky): Investigate whether this can happen.
|
||||
if isforw[tbase.Etype] {
|
||||
if tbase.Etype == TFORW {
|
||||
return lsym
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5051,7 +5051,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||
|
||||
e := f.Frontend().(*ssafn)
|
||||
|
||||
s.livenessMap = liveness(e, f)
|
||||
s.livenessMap = liveness(e, f, pp)
|
||||
emitStackObjects(e, pp)
|
||||
|
||||
// Remember where each block starts.
|
||||
|
|
|
|||
|
|
@ -929,7 +929,7 @@ type nodeQueue struct {
|
|||
head, tail int
|
||||
}
|
||||
|
||||
// empty returns true if q contains no Nodes.
|
||||
// empty reports whether q contains no Nodes.
|
||||
func (q *nodeQueue) empty() bool {
|
||||
return q.head == q.tail
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,50 @@ import (
|
|||
"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 (
|
||||
Etop = 1 << iota // evaluated at statement level
|
||||
Erv // evaluated in value context
|
||||
|
|
@ -31,11 +75,16 @@ const (
|
|||
var typecheckdefstack []*Node
|
||||
|
||||
// resolve ONONAME to definition, if any.
|
||||
func resolve(n *Node) *Node {
|
||||
func resolve(n *Node) (res *Node) {
|
||||
if n == nil || n.Op != ONONAME {
|
||||
return n
|
||||
}
|
||||
|
||||
// only trace if there's work to do
|
||||
if enableTrace && trace {
|
||||
defer tracePrint("resolve", n)(&res)
|
||||
}
|
||||
|
||||
if n.Sym.Pkg != localpkg {
|
||||
if inimport {
|
||||
Fatalf("recursive inimport")
|
||||
|
|
@ -150,7 +199,7 @@ var typecheck_tcstack []*Node
|
|||
// typecheck type checks node n.
|
||||
// The result of typecheck MUST be assigned back to n, e.g.
|
||||
// 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
|
||||
if !typecheckok {
|
||||
Fatalf("early typecheck")
|
||||
|
|
@ -160,6 +209,11 @@ func typecheck(n *Node, top int) *Node {
|
|||
return nil
|
||||
}
|
||||
|
||||
// only trace if there's work to do
|
||||
if enableTrace && trace {
|
||||
defer tracePrint("typecheck", n)(&res)
|
||||
}
|
||||
|
||||
lno := setlineno(n)
|
||||
|
||||
// Skip over parens.
|
||||
|
|
@ -201,8 +255,16 @@ func typecheck(n *Node, top int) *Node {
|
|||
// since it would expand indefinitely when aliases
|
||||
// are substituted.
|
||||
cycle := cycleFor(n)
|
||||
for _, n := range cycle {
|
||||
if n.Name != nil && !n.Name.Param.Alias {
|
||||
for _, n1 := range cycle {
|
||||
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
|
||||
return n
|
||||
}
|
||||
|
|
@ -294,7 +356,11 @@ func indexlit(n *Node) *Node {
|
|||
|
||||
// The result of typecheck1 MUST be assigned back to n, e.g.
|
||||
// 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 {
|
||||
case OLITERAL, ONAME, ONONAME, OTYPE:
|
||||
if n.Sym == nil {
|
||||
|
|
@ -1094,11 +1160,15 @@ func typecheck1(n *Node, top int) *Node {
|
|||
ok |= Erv
|
||||
|
||||
t := n.Type
|
||||
if t == nil {
|
||||
Fatalf("no type specified for OSLICEHEADER")
|
||||
}
|
||||
|
||||
if !t.IsSlice() {
|
||||
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")
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
// 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
|
||||
|
||||
// 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.
|
||||
// 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
|
||||
defer func() {
|
||||
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,
|
||||
// fill in the var's type.
|
||||
func typecheckas(n *Node) {
|
||||
if enableTrace && trace {
|
||||
defer tracePrint("typecheckas", n)(nil)
|
||||
}
|
||||
|
||||
// delicate little dance.
|
||||
// the definition of n may refer to this assignment
|
||||
// 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) {
|
||||
if enableTrace && trace {
|
||||
defer tracePrint("typecheckas2", n)(nil)
|
||||
}
|
||||
|
||||
ls := n.List.Slice()
|
||||
for i1, n1 := range ls {
|
||||
// delicate little dance.
|
||||
|
|
@ -3521,6 +3607,10 @@ out:
|
|||
|
||||
// type check function definition
|
||||
func typecheckfunc(n *Node) {
|
||||
if enableTrace && trace {
|
||||
defer tracePrint("typecheckfunc", n)(nil)
|
||||
}
|
||||
|
||||
for _, ln := range n.Func.Dcl {
|
||||
if ln.Op == ONAME && (ln.Class() == PPARAM || ln.Class() == PPARAMOUT) {
|
||||
ln.Name.Decldepth = 1
|
||||
|
|
@ -3593,8 +3683,7 @@ func copytype(n *Node, t *types.Type) {
|
|||
embedlineno := n.Type.ForwardType().Embedlineno
|
||||
l := n.Type.ForwardType().Copyto
|
||||
|
||||
ptrBase := n.Type.PtrBase
|
||||
sliceOf := n.Type.SliceOf
|
||||
cache := n.Type.Cache
|
||||
|
||||
// TODO(mdempsky): Fix Type rekinding.
|
||||
*n.Type = *t
|
||||
|
|
@ -3615,8 +3704,7 @@ func copytype(n *Node, t *types.Type) {
|
|||
|
||||
t.Nod = asTypesNode(n)
|
||||
t.SetDeferwidth(false)
|
||||
t.PtrBase = ptrBase
|
||||
t.SliceOf = sliceOf
|
||||
t.Cache = cache
|
||||
|
||||
// Propagate go:notinheap pragma from the Name to the Type.
|
||||
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) {
|
||||
if enableTrace && trace {
|
||||
defer tracePrint("typecheckdeftype", n)(nil)
|
||||
}
|
||||
|
||||
n.Type.Sym = n.Sym
|
||||
n.SetTypecheck(1)
|
||||
n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
|
||||
|
|
@ -3654,6 +3746,10 @@ func typecheckdeftype(n *Node) {
|
|||
}
|
||||
|
||||
func typecheckdef(n *Node) {
|
||||
if enableTrace && trace {
|
||||
defer tracePrint("typecheckdef", n)(nil)
|
||||
}
|
||||
|
||||
lno := setlineno(n)
|
||||
|
||||
if n.Op == ONONAME {
|
||||
|
|
@ -3992,6 +4088,12 @@ func deadcode(fn *Node) {
|
|||
}
|
||||
|
||||
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() {
|
||||
// Cut is set to true when all nodes after i'th position
|
||||
// should be removed.
|
||||
|
|
@ -4014,10 +4116,14 @@ func deadcodeslice(nn Nodes) {
|
|||
// If "then" or "else" branch ends with panic or return statement,
|
||||
// it is safe to remove all statements after this node.
|
||||
// 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 {
|
||||
switch body[(len(body) - 1)].Op {
|
||||
case ORETURN, ORETJMP, OPANIC:
|
||||
cut = true
|
||||
if i > lastLabel {
|
||||
cut = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,8 +200,6 @@ func typeinit() {
|
|||
isComplex[TCOMPLEX64] = true
|
||||
isComplex[TCOMPLEX128] = true
|
||||
|
||||
isforw[TFORW] = true
|
||||
|
||||
// initialize okfor
|
||||
for et := types.EType(0); et < NTYPE; et++ {
|
||||
if isInt[et] || et == TIDEAL {
|
||||
|
|
|
|||
|
|
@ -384,41 +384,31 @@ func convFuncName(from, to *types.Type) (fnname string, needsaddr bool) {
|
|||
tkind := to.Tie()
|
||||
switch from.Tie() {
|
||||
case 'I':
|
||||
switch tkind {
|
||||
case 'I':
|
||||
if tkind == 'I' {
|
||||
return "convI2I", false
|
||||
}
|
||||
case 'T':
|
||||
switch {
|
||||
case from.Size() == 2 && from.Align == 2:
|
||||
return "convT16", false
|
||||
case from.Size() == 4 && from.Align == 4 && !types.Haspointers(from):
|
||||
return "convT32", false
|
||||
case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !types.Haspointers(from):
|
||||
return "convT64", false
|
||||
case from.IsString():
|
||||
return "convTstring", false
|
||||
case from.IsSlice():
|
||||
return "convTslice", false
|
||||
}
|
||||
|
||||
switch tkind {
|
||||
case 'E':
|
||||
switch {
|
||||
case from.Size() == 2 && from.Align == 2:
|
||||
return "convT2E16", false
|
||||
case from.Size() == 4 && from.Align == 4 && !types.Haspointers(from):
|
||||
return "convT2E32", false
|
||||
case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !types.Haspointers(from):
|
||||
return "convT2E64", false
|
||||
case from.IsString():
|
||||
return "convT2Estring", false
|
||||
case from.IsSlice():
|
||||
return "convT2Eslice", false
|
||||
case !types.Haspointers(from):
|
||||
if !types.Haspointers(from) {
|
||||
return "convT2Enoptr", true
|
||||
}
|
||||
return "convT2E", true
|
||||
case 'I':
|
||||
switch {
|
||||
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):
|
||||
if !types.Haspointers(from) {
|
||||
return "convT2Inoptr", true
|
||||
}
|
||||
return "convT2I", true
|
||||
|
|
@ -496,7 +486,7 @@ opswitch:
|
|||
OIND, OSPTR, OITAB, OIDATA, OADDR:
|
||||
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.Right = walkexpr(n.Right, init)
|
||||
|
||||
|
|
@ -548,15 +538,6 @@ opswitch:
|
|||
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:
|
||||
// Use results from call expression as arguments for complex.
|
||||
if n.Left == nil && n.Right == nil {
|
||||
|
|
@ -834,16 +815,21 @@ opswitch:
|
|||
case OCONVIFACE:
|
||||
n.Left = walkexpr(n.Left, init)
|
||||
|
||||
// Optimize convT2E or convT2I as a two-word copy when T is pointer-shaped.
|
||||
if isdirectiface(n.Left.Type) {
|
||||
var t *Node
|
||||
if n.Type.IsEmptyInterface() {
|
||||
t = typename(n.Left.Type)
|
||||
} else {
|
||||
t = itabname(n.Left.Type, n.Type)
|
||||
fromType := n.Left.Type
|
||||
toType := n.Type
|
||||
|
||||
// typeword generates the type word of the interface value.
|
||||
typeword := func() *Node {
|
||||
if toType.IsEmptyInterface() {
|
||||
return typename(fromType)
|
||||
}
|
||||
l := nod(OEFACE, t, n.Left)
|
||||
l.Type = n.Type
|
||||
return itabname(fromType, toType)
|
||||
}
|
||||
|
||||
// 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())
|
||||
n = l
|
||||
break
|
||||
|
|
@ -863,11 +849,11 @@ opswitch:
|
|||
// or creating one on the stack.
|
||||
var value *Node
|
||||
switch {
|
||||
case n.Left.Type.Size() == 0:
|
||||
case fromType.Size() == 0:
|
||||
// n.Left is zero-sized. Use zerobase.
|
||||
cheapexpr(n.Left, init) // Evaluate n.Left for side-effects. See issue 19246.
|
||||
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 = cheapexpr(n.Left, init)
|
||||
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():
|
||||
// n.Left is a readonly global; use it directly.
|
||||
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.
|
||||
value = temp(n.Left.Type)
|
||||
value = temp(fromType)
|
||||
init.Append(typecheck(nod(OAS, value, n.Left), Etop))
|
||||
}
|
||||
|
||||
if value != nil {
|
||||
// Value is identical to n.Left.
|
||||
// Construct the interface directly: {type/itab, &value}.
|
||||
var t *Node
|
||||
if n.Type.IsEmptyInterface() {
|
||||
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 := nod(OEFACE, typeword(), typecheck(nod(OADDR, value, nil), Erv))
|
||||
l.Type = toType
|
||||
l.SetTypecheck(n.Typecheck())
|
||||
n = l
|
||||
break
|
||||
|
|
@ -903,9 +883,9 @@ opswitch:
|
|||
// tmp = tmp.type
|
||||
// }
|
||||
// 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.
|
||||
c := temp(n.Left.Type)
|
||||
c := temp(fromType)
|
||||
init.Append(nod(OAS, c, n.Left))
|
||||
|
||||
// Get the itab out of the interface.
|
||||
|
|
@ -919,26 +899,43 @@ opswitch:
|
|||
|
||||
// Build the result.
|
||||
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)
|
||||
n = e
|
||||
break
|
||||
}
|
||||
|
||||
var ll []*Node
|
||||
if n.Type.IsEmptyInterface() {
|
||||
if !n.Left.Type.IsInterface() {
|
||||
ll = append(ll, typename(n.Left.Type))
|
||||
}
|
||||
} else {
|
||||
if n.Left.Type.IsInterface() {
|
||||
ll = append(ll, typename(n.Type))
|
||||
} else {
|
||||
ll = append(ll, itabname(n.Left.Type, n.Type))
|
||||
}
|
||||
fnname, needsaddr := convFuncName(fromType, toType)
|
||||
|
||||
if !needsaddr && !fromType.IsInterface() {
|
||||
// Use a specialized conversion routine that only returns a data pointer.
|
||||
// ptr = convT2X(val)
|
||||
// e = iface{typ/tab, ptr}
|
||||
fn := syslook(fnname)
|
||||
dowidth(fromType)
|
||||
fn = substArgTypes(fn, fromType)
|
||||
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
|
||||
if needsaddr {
|
||||
// Types of large or unknown size are passed by reference.
|
||||
|
|
@ -952,14 +949,13 @@ opswitch:
|
|||
}
|
||||
v = nod(OADDR, v, nil)
|
||||
}
|
||||
ll = append(ll, v)
|
||||
|
||||
dowidth(n.Left.Type)
|
||||
dowidth(fromType)
|
||||
fn := syslook(fnname)
|
||||
fn = substArgTypes(fn, n.Left.Type, n.Type)
|
||||
fn = substArgTypes(fn, fromType, toType)
|
||||
dowidth(fn.Type)
|
||||
n = nod(OCALL, fn, nil)
|
||||
n.List.Set(ll)
|
||||
n.List.Set2(tab, v)
|
||||
n = typecheck(n, Erv)
|
||||
n = walkexpr(n, init)
|
||||
|
||||
|
|
@ -1343,14 +1339,17 @@ opswitch:
|
|||
argtype = types.Types[TINT]
|
||||
}
|
||||
|
||||
m := nod(OSLICEHEADER, nil, nil)
|
||||
m.Type = t
|
||||
|
||||
fn := syslook(fnname)
|
||||
n.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
|
||||
n.Left.SetNonNil(true)
|
||||
n.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT]))
|
||||
n.Op = OSLICEHEADER
|
||||
n.Type = t
|
||||
n = typecheck(n, Erv)
|
||||
n = walkexpr(n, init)
|
||||
m.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
|
||||
m.Left.SetNonNil(true)
|
||||
m.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT]))
|
||||
|
||||
m = typecheck(m, Erv)
|
||||
m = walkexpr(m, init)
|
||||
n = m
|
||||
}
|
||||
|
||||
case ORUNESTR:
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
ssa.OpPPC64ROTL, ssa.OpPPC64ROTLW,
|
||||
ssa.OpPPC64MULHD, ssa.OpPPC64MULHW, ssa.OpPPC64MULHDU, ssa.OpPPC64MULHWU,
|
||||
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()
|
||||
r1 := v.Args[0].Reg()
|
||||
r2 := v.Args[1].Reg()
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ type Logger interface {
|
|||
// Logf logs a message from the compiler.
|
||||
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.
|
||||
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.
|
||||
func canMerge(pending, new VarLoc) bool {
|
||||
if pending.absent() && new.absent() {
|
||||
|
|
|
|||
|
|
@ -621,7 +621,7 @@ func (f *Func) invalidateCFG() {
|
|||
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)
|
||||
// 2) is "y" or "Y"
|
||||
// 3) is a suffix of the sha1 hash of name
|
||||
|
|
|
|||
|
|
@ -518,6 +518,13 @@
|
|||
(LessEqual (InvertFlags x)) -> (GreaterEqual 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
|
||||
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
|
||||
(Load <t> ptr mem) && is32BitInt(t) && isSigned(t) -> (MOVWload ptr mem)
|
||||
|
|
|
|||
|
|
@ -241,24 +241,27 @@ func init() {
|
|||
{name: "MFVSRD", argLength: 1, reg: fpgp, asm: "MFVSRD", typ: "Int64"}, // move 64 bits of F register into G register
|
||||
{name: "MTVSRD", argLength: 1, reg: gpfp, asm: "MTVSRD", typ: "Float64"}, // move 64 bits of G register into F register
|
||||
|
||||
{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0&arg1
|
||||
{name: "ANDN", argLength: 2, reg: gp21, asm: "ANDN"}, // 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: "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: "EQV", argLength: 2, reg: gp21, asm: "EQV", typ: "Int64", commutative: true}, // arg0^^arg1
|
||||
{name: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0 (integer)
|
||||
{name: "FNEG", argLength: 1, reg: fp11, asm: "FNEG"}, // -arg0 (floating point)
|
||||
{name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"}, // sqrt(arg0) (floating point)
|
||||
{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"}, // sqrt(arg0) (floating point, single precision)
|
||||
{name: "FFLOOR", argLength: 1, reg: fp11, asm: "FRIM"}, // floor(arg0), float64
|
||||
{name: "FCEIL", argLength: 1, reg: fp11, asm: "FRIP"}, // ceil(arg0), float64
|
||||
{name: "FTRUNC", argLength: 1, reg: fp11, asm: "FRIZ"}, // trunc(arg0), float64
|
||||
{name: "FROUND", argLength: 1, reg: fp11, asm: "FRIN"}, // round(arg0), float64
|
||||
{name: "FABS", argLength: 1, reg: fp11, asm: "FABS"}, // abs(arg0), float64
|
||||
{name: "FNABS", argLength: 1, reg: fp11, asm: "FNABS"}, // -abs(arg0), float64
|
||||
{name: "FCPSGN", argLength: 2, reg: fp21, asm: "FCPSGN"}, // copysign arg0 -> arg1, float64
|
||||
{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // 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: "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: "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: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0 (integer)
|
||||
{name: "FNEG", argLength: 1, reg: fp11, asm: "FNEG"}, // -arg0 (floating point)
|
||||
{name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"}, // sqrt(arg0) (floating point)
|
||||
{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"}, // sqrt(arg0) (floating point, single precision)
|
||||
{name: "FFLOOR", argLength: 1, reg: fp11, asm: "FRIM"}, // floor(arg0), float64
|
||||
{name: "FCEIL", argLength: 1, reg: fp11, asm: "FRIP"}, // ceil(arg0), float64
|
||||
{name: "FTRUNC", argLength: 1, reg: fp11, asm: "FRIZ"}, // trunc(arg0), float64
|
||||
{name: "FROUND", argLength: 1, reg: fp11, asm: "FRIN"}, // round(arg0), float64
|
||||
{name: "FABS", argLength: 1, reg: fp11, asm: "FABS"}, // abs(arg0), float64
|
||||
{name: "FNABS", argLength: 1, reg: fp11, asm: "FNABS"}, // -abs(arg0), float64
|
||||
{name: "FCPSGN", argLength: 2, reg: fp21, asm: "FCPSGN"}, // copysign arg0 -> arg1, float64
|
||||
|
||||
{name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64"}, // arg0|aux
|
||||
{name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64"}, // arg0^aux
|
||||
|
|
|
|||
|
|
@ -1804,11 +1804,25 @@
|
|||
// 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
|
||||
// during compilation to ensure correctness.
|
||||
(Move {t1} [s1] dst tmp1 midmem:(Move {t2} [s2] tmp2 src _))
|
||||
&& s1 == s2
|
||||
// Take care that overlapping moves are preserved.
|
||||
// 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
|
||||
&& 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).
|
||||
// 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: "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: "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: "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.
|
||||
// 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
|
||||
|
||||
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 {
|
||||
return genMatch0(w, arch, match, "v", map[string]struct{}{}, true, loc)
|
||||
}
|
||||
|
|
@ -623,7 +623,7 @@ outer:
|
|||
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 {
|
||||
for _, b := range genericBlocks {
|
||||
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 {
|
||||
var left, right int
|
||||
for _, c := range s {
|
||||
|
|
|
|||
|
|
@ -1663,10 +1663,13 @@ const (
|
|||
OpPPC64MTVSRD
|
||||
OpPPC64AND
|
||||
OpPPC64ANDN
|
||||
OpPPC64ANDCC
|
||||
OpPPC64OR
|
||||
OpPPC64ORN
|
||||
OpPPC64ORCC
|
||||
OpPPC64NOR
|
||||
OpPPC64XOR
|
||||
OpPPC64XORCC
|
||||
OpPPC64EQV
|
||||
OpPPC64NEG
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
argLen: 2,
|
||||
|
|
|
|||
|
|
@ -781,7 +781,7 @@ func (po *poset) DotDump(fn string, title string) error {
|
|||
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
|
||||
// to tell.
|
||||
// Complexity is O(n).
|
||||
|
|
@ -799,7 +799,7 @@ func (po *poset) Ordered(n1, n2 *Value) bool {
|
|||
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
|
||||
// to tell.
|
||||
// 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))
|
||||
}
|
||||
|
||||
// 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
|
||||
// to tell.
|
||||
// Complexity is O(1).
|
||||
|
|
@ -832,7 +832,7 @@ func (po *poset) Equal(n1, n2 *Value) bool {
|
|||
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
|
||||
// to tell.
|
||||
// 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))
|
||||
}
|
||||
|
||||
// uaddOvf returns true if unsigned a+b would overflow.
|
||||
// uaddOvf reports whether unsigned a+b would overflow.
|
||||
func uaddOvf(a, b int64) bool {
|
||||
return uint64(a)+uint64(b) < uint64(a)
|
||||
}
|
||||
|
|
@ -530,6 +530,13 @@ func isSamePtr(p1, p2 *Value) bool {
|
|||
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)
|
||||
// does not overlap with [p2:p2+n2).
|
||||
// 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) {
|
||||
base, offset = ptr, 0
|
||||
if base.Op == OpOffPtr {
|
||||
for base.Op == OpOffPtr {
|
||||
offset += base.AuxInt
|
||||
base = base.Args[0]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30996,6 +30996,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
|||
b.Aux = nil
|
||||
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:
|
||||
// match: (GE (FlagEQ) yes no)
|
||||
// cond:
|
||||
|
|
@ -31051,6 +31188,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
|||
b.Aux = nil
|
||||
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:
|
||||
// match: (GT (FlagEQ) yes no)
|
||||
// cond:
|
||||
|
|
@ -31107,6 +31381,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
|||
b.Aux = nil
|
||||
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:
|
||||
// match: (If (Equal cc) yes no)
|
||||
// cond:
|
||||
|
|
@ -31318,6 +31729,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
|||
b.Aux = nil
|
||||
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:
|
||||
// match: (LT (FlagEQ) yes no)
|
||||
// cond:
|
||||
|
|
@ -31374,6 +31922,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
|||
b.Aux = nil
|
||||
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:
|
||||
// match: (NE (CMPWconst [0] (Equal cc)) yes no)
|
||||
// cond:
|
||||
|
|
@ -31689,6 +32374,143 @@ func rewriteBlockPPC64(b *Block) bool {
|
|||
b.Aux = nil
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17234,6 +17234,8 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
|||
func rewriteValuegeneric_OpMove_20(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = 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 _)))))))
|
||||
// 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)))))
|
||||
|
|
@ -17355,11 +17357,11 @@ func rewriteValuegeneric_OpMove_20(v *Value) bool {
|
|||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
// match: (Move {t1} [s1] dst tmp1 midmem:(Move {t2} [s2] tmp2 src _))
|
||||
// cond: s1 == s2 && t1.(*types.Type).Compare(t2.(*types.Type)) == types.CMPeq && isSamePtr(tmp1, tmp2)
|
||||
// result: (Move {t1} [s1] dst src midmem)
|
||||
// match: (Move {t1} [s] dst tmp1 midmem:(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 {
|
||||
s1 := v.AuxInt
|
||||
s := v.AuxInt
|
||||
t1 := v.Aux
|
||||
_ = v.Args[2]
|
||||
dst := v.Args[0]
|
||||
|
|
@ -17368,16 +17370,53 @@ func rewriteValuegeneric_OpMove_20(v *Value) bool {
|
|||
if midmem.Op != OpMove {
|
||||
break
|
||||
}
|
||||
s2 := midmem.AuxInt
|
||||
if midmem.AuxInt != s {
|
||||
break
|
||||
}
|
||||
t2 := midmem.Aux
|
||||
_ = midmem.Args[2]
|
||||
tmp2 := midmem.Args[0]
|
||||
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
|
||||
}
|
||||
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.AddArg(dst)
|
||||
v.AddArg(src)
|
||||
|
|
|
|||
|
|
@ -58,11 +58,13 @@
|
|||
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||
86: for i, a := range hist {
|
||||
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
|
||||
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 {
|
||||
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
|
||||
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)
|
||||
|
|
@ -70,11 +72,13 @@
|
|||
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||
86: for i, a := range hist {
|
||||
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
|
||||
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 {
|
||||
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
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
91: n += 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 {
|
||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||
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)
|
||||
91: n += 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 {
|
||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||
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)
|
||||
91: n += 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 {
|
||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||
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)
|
||||
91: n += 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 {
|
||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||
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
|
||||
func emptyBlock(b *Block) bool {
|
||||
for _, v := range b.Values {
|
||||
|
|
@ -105,7 +105,7 @@ func emptyBlock(b *Block) bool {
|
|||
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:
|
||||
// - it should not be the first block
|
||||
// - it should be BlockPlain
|
||||
|
|
|
|||
|
|
@ -149,8 +149,11 @@ type Type struct {
|
|||
Nod *Node // canonical OTYPE node
|
||||
Orig *Type // original type (type literal or predefined type)
|
||||
|
||||
SliceOf *Type
|
||||
PtrBase *Type
|
||||
// Cache of composite types, with this type being the element type.
|
||||
Cache struct {
|
||||
ptr *Type // *T, or nil
|
||||
slice *Type // []T, or nil
|
||||
}
|
||||
|
||||
Sym *Sym // symbol containing name, for named types
|
||||
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.
|
||||
func NewSlice(elem *Type) *Type {
|
||||
if t := elem.SliceOf; t != nil {
|
||||
if t := elem.Cache.slice; t != nil {
|
||||
if t.Elem() != elem {
|
||||
Fatalf("elem mismatch")
|
||||
}
|
||||
|
|
@ -497,7 +500,7 @@ func NewSlice(elem *Type) *Type {
|
|||
|
||||
t := New(TSLICE)
|
||||
t.Extra = Slice{Elem: elem}
|
||||
elem.SliceOf = t
|
||||
elem.Cache.slice = t
|
||||
return t
|
||||
}
|
||||
|
||||
|
|
@ -551,7 +554,7 @@ func NewPtr(elem *Type) *Type {
|
|||
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 {
|
||||
Fatalf("NewPtr: elem mismatch")
|
||||
}
|
||||
|
|
@ -563,7 +566,7 @@ func NewPtr(elem *Type) *Type {
|
|||
t.Width = int64(Widthptr)
|
||||
t.Align = uint8(Widthptr)
|
||||
if NewPtrCacheEnabled {
|
||||
elem.PtrBase = t
|
||||
elem.Cache.ptr = t
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
|
@ -662,23 +665,18 @@ func SubstAny(t *Type, types *[]*Type) *Type {
|
|||
}
|
||||
|
||||
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()
|
||||
var nfs []*Field
|
||||
nfs := make([]*Field, len(fields))
|
||||
for i, f := range fields {
|
||||
nft := SubstAny(f.Type, types)
|
||||
if nft == f.Type {
|
||||
continue
|
||||
}
|
||||
if nfs == nil {
|
||||
nfs = append([]*Field(nil), fields...)
|
||||
}
|
||||
nfs[i] = f.Copy()
|
||||
nfs[i].Type = nft
|
||||
}
|
||||
if nfs != nil {
|
||||
t = t.copy()
|
||||
t.SetFields(nfs)
|
||||
}
|
||||
t = t.copy()
|
||||
t.SetFields(nfs)
|
||||
}
|
||||
|
||||
return t
|
||||
|
|
@ -1258,6 +1256,11 @@ func (t *Type) IsPtr() bool {
|
|||
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.
|
||||
func (t *Type) IsUnsafePtr() bool {
|
||||
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.
|
||||
// It returns true if it makes any changes.
|
||||
// It reports whether it makes any changes.
|
||||
func renameTop(f *ast.File, old, new string) bool {
|
||||
var fixed bool
|
||||
|
||||
|
|
|
|||
|
|
@ -972,6 +972,8 @@
|
|||
// and -dropreplace editing flags may be repeated, and the changes
|
||||
// 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
|
||||
// writing it back to go.mod.
|
||||
//
|
||||
|
|
@ -984,7 +986,8 @@
|
|||
// }
|
||||
//
|
||||
// type GoMod struct {
|
||||
// Module Module
|
||||
// Module Module
|
||||
// Go string
|
||||
// Require []Require
|
||||
// Exclude []Module
|
||||
// Replace []Replace
|
||||
|
|
@ -1604,17 +1607,20 @@
|
|||
// verb followed by arguments. For example:
|
||||
//
|
||||
// module my/thing
|
||||
// go 1.12
|
||||
// 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
|
||||
// replace bad/thing v1.4.5 => good/thing v1.4.5
|
||||
//
|
||||
// The verbs are module, to define the module path; require, to require
|
||||
// a particular module at a given version or later; exclude, to exclude
|
||||
// a particular module version from use; and 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 verbs are
|
||||
// module, to define the module path;
|
||||
// go, to set the expected language version;
|
||||
// require, to require a particular module at a given version or later;
|
||||
// exclude, to exclude a particular module version from use; and
|
||||
// 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,
|
||||
// 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
|
||||
}
|
||||
|
||||
// HashFile returns the hash of the named file.
|
||||
// FileHash returns the hash of the named file.
|
||||
// It caches repeated lookups for a given file,
|
||||
// and the cache entry for a file can be initialized
|
||||
// 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,
|
||||
// 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.
|
||||
func Parse(cmd string, defns []*Defn, args []string, i int) (f *Defn, value string, extra bool) {
|
||||
// If the flag begins (cmd.Name()+".") it is ignored for the purpose of this function.
|
||||
func Parse(cmd string, usage func(), defns []*Defn, args []string, i int) (f *Defn, value string, extra bool) {
|
||||
arg := args[i]
|
||||
if strings.HasPrefix(arg, "--") { // reduce two minuses to one
|
||||
arg = arg[1:]
|
||||
}
|
||||
switch arg {
|
||||
case "-?", "-h", "-help":
|
||||
base.Usage()
|
||||
usage()
|
||||
}
|
||||
if arg == "" || arg[0] != '-' {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ The -require, -droprequire, -exclude, -dropexclude, -replace,
|
|||
and -dropreplace editing flags may be repeated, and the changes
|
||||
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
|
||||
writing it back to go.mod.
|
||||
|
||||
|
|
@ -74,7 +76,8 @@ writing it back to go.mod. The JSON output corresponds to these Go types:
|
|||
}
|
||||
|
||||
type GoMod struct {
|
||||
Module Module
|
||||
Module Module
|
||||
Go string
|
||||
Require []Require
|
||||
Exclude []Module
|
||||
Replace []Replace
|
||||
|
|
@ -102,8 +105,8 @@ by invoking 'go mod edit' with -require, -exclude, and so on.
|
|||
}
|
||||
|
||||
var (
|
||||
editFmt = cmdEdit.Flag.Bool("fmt", false, "")
|
||||
// editGo = cmdEdit.Flag.String("go", "", "")
|
||||
editFmt = cmdEdit.Flag.Bool("fmt", false, "")
|
||||
editGo = cmdEdit.Flag.String("go", "", "")
|
||||
editJSON = cmdEdit.Flag.Bool("json", false, "")
|
||||
editPrint = cmdEdit.Flag.Bool("print", false, "")
|
||||
editModule = cmdEdit.Flag.String("module", "", "")
|
||||
|
|
@ -131,6 +134,7 @@ func init() {
|
|||
func runEdit(cmd *base.Command, args []string) {
|
||||
anyFlags :=
|
||||
*editModule != "" ||
|
||||
*editGo != "" ||
|
||||
*editJSON ||
|
||||
*editPrint ||
|
||||
*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)
|
||||
if err != nil {
|
||||
|
|
@ -177,6 +185,12 @@ func runEdit(cmd *base.Command, args []string) {
|
|||
modFile.AddModuleStmt(modload.CmdModModule)
|
||||
}
|
||||
|
||||
if *editGo != "" {
|
||||
if err := modFile.AddGoStmt(*editGo); err != nil {
|
||||
base.Fatalf("go: internal error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(edits) > 0 {
|
||||
for _, edit := range edits {
|
||||
edit(modFile)
|
||||
|
|
@ -344,6 +358,7 @@ func flagDropReplace(arg string) {
|
|||
// fileJSON is the -json output data structure.
|
||||
type fileJSON struct {
|
||||
Module module.Version
|
||||
Go string `json:",omitempty"`
|
||||
Require []requireJSON
|
||||
Exclude []module.Version
|
||||
Replace []replaceJSON
|
||||
|
|
@ -364,6 +379,9 @@ type replaceJSON struct {
|
|||
func editPrintJSON(modFile *modfile.File) {
|
||||
var f fileJSON
|
||||
f.Module = modFile.Module.Mod
|
||||
if modFile.Go != nil {
|
||||
f.Go = modFile.Go.Version
|
||||
}
|
||||
for _, r := range modFile.Require {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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)
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
|
@ -477,6 +477,22 @@ func (f *File) 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 {
|
||||
need := true
|
||||
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:
|
||||
|
||||
module my/thing
|
||||
go 1.12
|
||||
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
|
||||
replace bad/thing v1.4.5 => good/thing v1.4.5
|
||||
|
||||
The verbs are module, to define the module path; require, to require
|
||||
a particular module at a given version or later; exclude, to exclude
|
||||
a particular module version from use; and 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 verbs are
|
||||
module, to define the module path;
|
||||
go, to set the expected language version;
|
||||
require, to require a particular module at a given version or later;
|
||||
exclude, to exclude a particular module version from use; and
|
||||
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,
|
||||
like in Go imports:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import (
|
|||
"cmd/go/internal/search"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
|
@ -335,6 +336,8 @@ func legacyModInit() {
|
|||
modFile.AddModuleStmt(path)
|
||||
}
|
||||
|
||||
addGoStmt()
|
||||
|
||||
for _, name := range altConfigs {
|
||||
cfg := filepath.Join(ModRoot, name)
|
||||
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{
|
||||
"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
|
||||
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:
|
||||
|
||||
-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 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.
|
||||
func Usage() {
|
||||
os.Stderr.WriteString("usage: " + testUsage + "\n\n" +
|
||||
strings.TrimSpace(testFlag1) + "\n\n\t" +
|
||||
strings.TrimSpace(testFlag2) + "\n")
|
||||
os.Exit(2)
|
||||
For more about build flags, see 'go help build'.
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
|
||||
See also: go build, go vet.
|
||||
`,
|
||||
}
|
||||
|
||||
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
|
||||
control the execution of any test:
|
||||
|
||||
` + strings.TrimSpace(testFlag2) + `
|
||||
`,
|
||||
}
|
||||
|
||||
const testFlag2 = `
|
||||
-bench regexp
|
||||
Run only those benchmarks matching a regular expression.
|
||||
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.
|
||||
In the second example, the argument math is passed through to the test
|
||||
binary, instead of being interpreted as the package list.
|
||||
`
|
||||
`,
|
||||
}
|
||||
|
||||
var HelpTestfunc = &base.Command{
|
||||
UsageLine: "testfunc",
|
||||
|
|
@ -532,7 +516,7 @@ var testVetFlags = []string{
|
|||
func runTest(cmd *base.Command, args []string) {
|
||||
modload.LoadTests = true
|
||||
|
||||
pkgArgs, testArgs = testFlags(args)
|
||||
pkgArgs, testArgs = testFlags(cmd.Usage, args)
|
||||
|
||||
work.FindExecCmd() // initialize cached result
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ func init() {
|
|||
// to allow both
|
||||
// go test fmt -custom-flag-for-fmt-test
|
||||
// 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)
|
||||
inPkg := false
|
||||
var explicitArgs []string
|
||||
|
|
@ -108,7 +108,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
|
|||
inPkg = false
|
||||
}
|
||||
|
||||
f, value, extraWord := cmdflag.Parse(cmd, testFlagDefn, args, i)
|
||||
f, value, extraWord := cmdflag.Parse(cmd, usage, testFlagDefn, args, i)
|
||||
if f == nil {
|
||||
// This is a flag we do not know; we must assume
|
||||
// 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) {
|
||||
modload.LoadTests = true
|
||||
|
||||
vetFlags, pkgArgs := vetFlags(args)
|
||||
vetFlags, pkgArgs := vetFlags(cmd.Usage, args)
|
||||
|
||||
work.BuildInit()
|
||||
work.VetFlags = vetFlags
|
||||
|
|
|
|||
|
|
@ -23,24 +23,43 @@ import (
|
|||
|
||||
// go vet flag processing
|
||||
//
|
||||
// We query the flags of the tool specified by GOVETTOOL (default:
|
||||
// cmd/vet) and accept any of those flags plus any flag valid for 'go
|
||||
// build'. The tool must support -flags, which prints a description of
|
||||
// its flags in JSON to stdout.
|
||||
// We query the flags of the tool specified by -vettool and accept any
|
||||
// of those flags plus any flag valid for 'go build'. The tool must
|
||||
// support -flags, which prints a description of its flags in JSON to
|
||||
// stdout.
|
||||
|
||||
// GOVETTOOL specifies the vet command to run.
|
||||
// This must be an environment variable because
|
||||
// we need it before flag processing, as we execute
|
||||
// $GOVETTOOL to discover the set of flags it supports.
|
||||
// vetTool specifies the vet command to run.
|
||||
// Any tool that supports the (still unpublished) vet
|
||||
// command-line protocol may be supplied; see
|
||||
// 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
|
||||
// to (and later, opt out of) the new cmd/vet analysis driver during the
|
||||
// transition. It is also used by tests.
|
||||
var vetTool = os.Getenv("GOVETTOOL")
|
||||
// The default behavior (vetTool=="") runs 'go tool vet'.
|
||||
//
|
||||
var vetTool string // -vettool
|
||||
|
||||
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
|
||||
// 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.
|
||||
tool := vetTool
|
||||
if tool != "" {
|
||||
|
|
@ -94,6 +113,9 @@ func vetFlags(args []string) (passToVet, packageNames []string) {
|
|||
// Add build flags to vetFlagDefn.
|
||||
var cmd base.Command
|
||||
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) {
|
||||
vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{
|
||||
Name: f.Name,
|
||||
|
|
@ -108,7 +130,7 @@ func vetFlags(args []string) (passToVet, packageNames []string) {
|
|||
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 {
|
||||
fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
|
||||
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)
|
||||
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 != "" {
|
||||
path = 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)
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
|
@ -638,12 +634,19 @@ func (b *Builder) build(a *Action) (err error) {
|
|||
objpkg := objdir + "_pkg_.a"
|
||||
ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), len(sfiles) > 0, gofiles)
|
||||
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 {
|
||||
return errPrintedOutput
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
if ofile != objpkg {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a
|
|||
pkgpath = "main"
|
||||
}
|
||||
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 {
|
||||
gcargs = append(gcargs, "-std")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,17 +235,6 @@ func init() {
|
|||
}
|
||||
|
||||
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)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
|
@ -104,6 +105,7 @@ func (ts *testScript) setup() {
|
|||
"GOROOT=" + testGOROOT,
|
||||
tempEnvName() + "=" + filepath.Join(ts.workdir, "tmp"),
|
||||
"devnull=" + os.DevNull,
|
||||
"goversion=" + goVersion(ts),
|
||||
":=" + 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
|
||||
|
||||
// run runs the test script.
|
||||
|
|
@ -331,6 +343,7 @@ var scriptCmds = map[string]func(*testScript, bool, []string){
|
|||
"addcrlf": (*testScript).cmdAddcrlf,
|
||||
"cd": (*testScript).cmdCd,
|
||||
"cmp": (*testScript).cmdCmp,
|
||||
"cmpenv": (*testScript).cmdCmpenv,
|
||||
"cp": (*testScript).cmdCp,
|
||||
"env": (*testScript).cmdEnv,
|
||||
"exec": (*testScript).cmdExec,
|
||||
|
|
@ -396,7 +409,21 @@ func (ts *testScript) cmdCmp(neg bool, args []string) {
|
|||
if len(args) != 2 {
|
||||
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]
|
||||
var text1, text2 string
|
||||
if name1 == "stdout" {
|
||||
|
|
@ -413,6 +440,11 @@ func (ts *testScript) cmdCmp(neg bool, args []string) {
|
|||
ts.check(err)
|
||||
text2 = string(data)
|
||||
|
||||
if env {
|
||||
text1 = ts.expand(text1)
|
||||
text2 = ts.expand(text2)
|
||||
}
|
||||
|
||||
if text1 == text2 {
|
||||
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>
|
||||
TMPDIR=$WORK/tmp
|
||||
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.
|
||||
|
||||
|
|
@ -92,6 +93,10 @@ The commands are:
|
|||
from the most recent exec or go command.
|
||||
(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
|
||||
Copy the listed files to the target file or existing directory.
|
||||
|
||||
|
|
|
|||
8
src/cmd/go/testdata/script/help.txt
vendored
8
src/cmd/go/testdata/script/help.txt
vendored
|
|
@ -35,7 +35,13 @@ stderr 'Run ''go help mod'' for usage.'
|
|||
stderr 'usage: go vet'
|
||||
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
|
||||
stdout 'usage: go get'
|
||||
stdout 'get when using GOPATH'
|
||||
stdout 'get when using GOPATH'
|
||||
|
|
|
|||
45
src/cmd/go/testdata/script/mod_edit.txt
vendored
45
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
|
||||
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
|
||||
cmp go.mod $WORK/go.mod.init
|
||||
cmpenv go.mod $WORK/go.mod.init
|
||||
|
||||
# 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'
|
||||
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
|
||||
cmp go.mod $WORK/go.mod.edit2
|
||||
cmpenv go.mod $WORK/go.mod.edit2
|
||||
|
||||
# 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=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
|
||||
cmp go.mod $WORK/go.mod.edit4
|
||||
cmpenv go.mod $WORK/go.mod.edit4
|
||||
go mod edit -dropreplace=x.1
|
||||
cmp go.mod $WORK/go.mod.edit5
|
||||
cmpenv go.mod $WORK/go.mod.edit5
|
||||
|
||||
# go mod edit -fmt
|
||||
cp $WORK/go.mod.badfmt go.mod
|
||||
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
|
||||
go mod edit -fmt # without -print, should write file (and nothing to stdout)
|
||||
! stdout .
|
||||
cmp go.mod $WORK/go.mod.edit4
|
||||
cmpenv go.mod $WORK/go.mod.edit6
|
||||
|
||||
-- x.go --
|
||||
package x
|
||||
|
|
@ -50,9 +50,13 @@ package w
|
|||
|
||||
-- $WORK/go.mod.init --
|
||||
module x.x/y/z
|
||||
|
||||
go $goversion
|
||||
-- $WORK/go.mod.edit1 --
|
||||
module x.x/y/z
|
||||
|
||||
go $goversion
|
||||
|
||||
require x.1 v1.0.0
|
||||
|
||||
exclude (
|
||||
|
|
@ -67,6 +71,8 @@ replace (
|
|||
-- $WORK/go.mod.edit2 --
|
||||
module x.x/y/z
|
||||
|
||||
go $goversion
|
||||
|
||||
exclude x.1 v1.2.0
|
||||
|
||||
replace x.1 v1.4.0 => ../z
|
||||
|
|
@ -77,6 +83,7 @@ require x.3 v1.99.0
|
|||
"Module": {
|
||||
"Path": "x.x/y/z"
|
||||
},
|
||||
"Go": "$goversion",
|
||||
"Require": [
|
||||
{
|
||||
"Path": "x.3",
|
||||
|
|
@ -104,6 +111,8 @@ require x.3 v1.99.0
|
|||
-- $WORK/go.mod.edit3 --
|
||||
module x.x/y/z
|
||||
|
||||
go $goversion
|
||||
|
||||
exclude x.1 v1.2.0
|
||||
|
||||
replace (
|
||||
|
|
@ -115,6 +124,8 @@ require x.3 v1.99.0
|
|||
-- $WORK/go.mod.edit4 --
|
||||
module x.x/y/z
|
||||
|
||||
go $goversion
|
||||
|
||||
exclude x.1 v1.2.0
|
||||
|
||||
replace x.1 => y.1/v2 v2.3.6
|
||||
|
|
@ -123,12 +134,26 @@ require x.3 v1.99.0
|
|||
-- $WORK/go.mod.edit5 --
|
||||
module x.x/y/z
|
||||
|
||||
go $goversion
|
||||
|
||||
exclude x.1 v1.2.0
|
||||
|
||||
require x.3 v1.99.0
|
||||
-- $WORK/go.mod.edit6 --
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
go list
|
||||
! go build
|
||||
stderr 'module requires Go 1.999'
|
||||
go build
|
||||
go build sub.1
|
||||
go build subver.1
|
||||
! stderr 'module requires'
|
||||
! go build badsub.1
|
||||
stderr 'module requires Go 1.11111'
|
||||
|
||||
|
|
@ -19,11 +20,13 @@ module m
|
|||
go 1.999
|
||||
require (
|
||||
sub.1 v1.0.0
|
||||
subver.1 v1.0.0
|
||||
badsub.1 v1.0.0
|
||||
versioned.1 v1.0.0
|
||||
)
|
||||
replace (
|
||||
sub.1 => ./sub
|
||||
subver.1 => ./subver
|
||||
badsub.1 => ./badsub
|
||||
versioned.1 v1.0.0 => ./versioned1
|
||||
versioned.1 v1.1.0 => ./versioned2
|
||||
|
|
@ -39,12 +42,20 @@ go 1.11
|
|||
-- sub/x.go --
|
||||
package x
|
||||
|
||||
-- subver/go.mod --
|
||||
module m
|
||||
go 1.11111
|
||||
|
||||
-- subver/x.go --
|
||||
package x
|
||||
|
||||
-- badsub/go.mod --
|
||||
module m
|
||||
go 1.11111
|
||||
|
||||
-- badsub/x.go --
|
||||
package x
|
||||
invalid syntax
|
||||
|
||||
-- versioned1/go.mod --
|
||||
module versioned
|
||||
|
|
@ -59,3 +70,4 @@ go 1.99999
|
|||
|
||||
-- versioned2/x.go --
|
||||
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 --
|
||||
module m
|
||||
|
||||
go 1.20
|
||||
|
||||
-- x.go --
|
||||
package x
|
||||
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]'
|
||||
|
||||
# tidy should not touch existing go line
|
||||
grep 'go 1.10' go.mod
|
||||
|
||||
go list -m all
|
||||
! stdout '^y'
|
||||
stdout '^w.1 v1.2.0'
|
||||
|
|
@ -12,11 +15,17 @@ stdout '^z.1 v1.2.0'
|
|||
|
||||
# empty tidy should not crash
|
||||
cd triv
|
||||
! grep 'go ' go.mod
|
||||
go mod tidy
|
||||
|
||||
# tidy should add missing go line
|
||||
grep 'go ' go.mod
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
go 1.10
|
||||
|
||||
require (
|
||||
x.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 {
|
||||
return abbrevs[die.Abbrev].children != 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,6 +414,8 @@ const (
|
|||
C_BITCON // bitfield and logical immediate masks
|
||||
C_ADDCON2 // 24-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_FCON // floating-point constant
|
||||
C_VCONADDR // 64-bit memory address
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ var cnames7 = []string{
|
|||
"BITCON",
|
||||
"ADDCON2",
|
||||
"LCON",
|
||||
"MOVCON2",
|
||||
"MOVCON3",
|
||||
"VCON",
|
||||
"FCON",
|
||||
"VCONADDR",
|
||||
|
|
|
|||
|
|
@ -198,9 +198,15 @@ var optab = []Optab{
|
|||
{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_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_VCON, C_NONE, C_NONE, C_RSP, 13, 8, 0, LFROM, 0},
|
||||
{ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 8, 0, LFROM, 0},
|
||||
{AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0},
|
||||
{AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 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_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_NONE, C_NONE, C_REG, 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_VCON, C_NONE, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
|
||||
{AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
|
||||
{AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
|
||||
{ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 8, 0, LFROM, 0},
|
||||
{AAND, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
|
||||
{AAND, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
|
||||
{AAND, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
|
||||
{AAND, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 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_NONE, 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},
|
||||
{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},
|
||||
{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
|
||||
{AMOVD, C_VCON, 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_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},
|
||||
{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},
|
||||
{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},
|
||||
{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_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_NSOREG, 20, 4, 0, 0, 0},
|
||||
|
|
@ -411,15 +429,15 @@ var optab = []Optab{
|
|||
|
||||
/* scaled 12-bit unsigned displacement load */
|
||||
{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_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_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_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_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_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 */
|
||||
{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_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_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_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_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_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
|
||||
|
|
@ -1105,6 +1123,15 @@ func isSTXPop(op obj.As) bool {
|
|||
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 {
|
||||
switch op {
|
||||
case AANDW, AORRW, AEORW, AANDSW, ATSTW,
|
||||
|
|
@ -1114,6 +1141,14 @@ func isANDWop(op obj.As) bool {
|
|||
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 {
|
||||
switch op {
|
||||
case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
|
||||
|
|
@ -1445,6 +1480,12 @@ func (c *ctxt7) con32class(a *obj.Addr) int {
|
|||
if isbitcon(uint64(v)) {
|
||||
return C_ABCON
|
||||
}
|
||||
if movcon(int64(v)) >= 0 {
|
||||
return C_AMCON
|
||||
}
|
||||
if movcon(int64(^v)) >= 0 {
|
||||
return C_AMCON
|
||||
}
|
||||
return C_ADDCON
|
||||
}
|
||||
|
||||
|
|
@ -1474,6 +1515,29 @@ func (c *ctxt7) con32class(a *obj.Addr) int {
|
|||
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 {
|
||||
switch a.Type {
|
||||
case obj.TYPE_NONE:
|
||||
|
|
@ -1689,21 +1753,18 @@ func (c *ctxt7) oplook(p *obj.Prog) *Optab {
|
|||
a1 = ra0 + 1
|
||||
p.From.Class = int8(a1)
|
||||
}
|
||||
if isANDWop(p.As) {
|
||||
switch p.As {
|
||||
case AANDW, AORRW, AEORW, AANDSW, ATSTW:
|
||||
// For 32-bit logical instruction with constant,
|
||||
// rewrite the high 32-bit to be a copy of the low
|
||||
// 32-bit, so that the BITCON test can be shared
|
||||
// for both 32-bit and 64-bit.
|
||||
if a0 == C_BITCON {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
a1 = c.con32class(&p.From) + 1
|
||||
p.From.Class = int8(a1)
|
||||
}
|
||||
if isANDWop(p.As) && a0 != C_BITCON {
|
||||
// For 32-bit logical instruction with constant,
|
||||
// the BITCON test is special in that it looks at
|
||||
// the 64-bit which has the high 32-bit as a copy
|
||||
// of the low 32-bit. We have handled that and
|
||||
// don't pass it to con32class.
|
||||
a1 = c.con32class(&p.From) + 1
|
||||
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
|
||||
}
|
||||
|
||||
case C_MOVCON2:
|
||||
return cmp(C_LCON, b)
|
||||
|
||||
case C_VCON:
|
||||
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) {
|
||||
var os [5]uint32
|
||||
o1 := uint32(0)
|
||||
o2 := 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 */
|
||||
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 */
|
||||
o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
|
||||
|
||||
if o1 == 0 {
|
||||
break
|
||||
o := uint32(0)
|
||||
num := uint8(0)
|
||||
cls := oclass(&p.From)
|
||||
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)
|
||||
if p.To.Type == obj.TYPE_NONE {
|
||||
|
|
@ -2924,16 +3005,23 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||
r = rt
|
||||
}
|
||||
if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
|
||||
o2 = c.opxrrr(p, p.As, false)
|
||||
o2 |= REGTMP & 31 << 16
|
||||
o2 |= LSL0_64
|
||||
o = c.opxrrr(p, p.As, false)
|
||||
o |= REGTMP & 31 << 16
|
||||
o |= LSL0_64
|
||||
} else {
|
||||
o2 = c.oprrr(p, p.As)
|
||||
o2 |= REGTMP & 31 << 16 /* shift is 0 */
|
||||
o = c.oprrr(p, p.As)
|
||||
o |= REGTMP & 31 << 16 /* shift is 0 */
|
||||
}
|
||||
|
||||
o2 |= uint32(r&31) << 5
|
||||
o2 |= uint32(rt & 31)
|
||||
o |= uint32(r&31) << 5
|
||||
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 */
|
||||
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)
|
||||
|
||||
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 {
|
||||
break
|
||||
if num == 0 {
|
||||
c.ctxt.Diag("invalid constant: %v", p)
|
||||
}
|
||||
rt := int(p.To.Reg)
|
||||
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 {
|
||||
r = rt
|
||||
}
|
||||
o2 = c.oprrr(p, p.As)
|
||||
o2 |= REGTMP & 31 << 16 /* shift is 0 */
|
||||
o2 |= uint32(r&31) << 5
|
||||
o2 |= uint32(rt & 31)
|
||||
o = c.oprrr(p, p.As)
|
||||
o |= REGTMP & 31 << 16 /* shift is 0 */
|
||||
o |= uint32(r&31) << 5
|
||||
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 */
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
var b uint32
|
||||
o := c.opirr(p, a)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ such as str, stur, strb, sturb, strh, sturh stlr, stlrb. stlrh, st1.
|
|||
Examples:
|
||||
MOVD R29, 384(R19) <=> str x29, [x19,#384]
|
||||
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>
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ such as str, stur, strb, sturb, strh, sturh stlr, stlrb. stlrh, st1.
|
|||
|
||||
Examples:
|
||||
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> ;
|
||||
FCSELD, FCSELS <cond>, <Fn>, <Fm>, <Fd>
|
||||
|
|
@ -144,12 +144,12 @@ FCSELD, FCSELS <cond>, <Fn>, <Fm>, <Fd>
|
|||
|
||||
Examples:
|
||||
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>
|
||||
|
||||
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]
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
Memory references: [<Xn|SP>{,#0}] is written as (Rn|RSP), a base register and an immediate
|
||||
|
|
|
|||
|
|
@ -311,12 +311,9 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
|||
// shared for both 32-bit and 64-bit. 32-bit ops
|
||||
// will zero the high 32-bit of the destination
|
||||
// register anyway.
|
||||
switch p.As {
|
||||
case AANDW, AORRW, AEORW, AANDSW, ATSTW:
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
v := p.From.Offset & 0xffffffff
|
||||
p.From.Offset = v | v<<32
|
||||
}
|
||||
if isANDWop(p.As) && p.From.Type == obj.TYPE_CONST {
|
||||
v := p.From.Offset & 0xffffffff
|
||||
p.From.Offset = v | v<<32
|
||||
}
|
||||
|
||||
if c.ctxt.Flag_dynlink {
|
||||
|
|
|
|||
|
|
@ -403,9 +403,9 @@ type FuncInfo struct {
|
|||
dwarfAbsFnSym *LSym
|
||||
dwarfIsStmtSym *LSym
|
||||
|
||||
GCArgs LSym
|
||||
GCLocals LSym
|
||||
GCRegs LSym
|
||||
GCArgs *LSym
|
||||
GCLocals *LSym
|
||||
GCRegs *LSym
|
||||
StackObjects *LSym
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,12 +25,6 @@ type objWriter struct {
|
|||
// Temporary buffer for zigzag int writing.
|
||||
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.
|
||||
nRefs int
|
||||
nData int
|
||||
|
|
@ -79,10 +73,8 @@ func (w *objWriter) writeLengths() {
|
|||
|
||||
func newObjWriter(ctxt *Link, b *bufio.Writer) *objWriter {
|
||||
return &objWriter{
|
||||
ctxt: ctxt,
|
||||
wr: b,
|
||||
vrefIdx: make(map[string]int),
|
||||
refIdx: make(map[string]int),
|
||||
ctxt: ctxt,
|
||||
wr: b,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,17 +149,6 @@ func (w *objWriter) writeRef(s *LSym, isPath bool) {
|
|||
if s == nil || s.RefIdx != 0 {
|
||||
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)
|
||||
if isPath {
|
||||
w.writeString(filepath.ToSlash(s.Name))
|
||||
|
|
@ -178,7 +159,6 @@ func (w *objWriter) writeRef(s *LSym, isPath bool) {
|
|||
w.writeBool(s.Static())
|
||||
w.nRefs++
|
||||
s.RefIdx = w.nRefs
|
||||
m[s.Name] = w.nRefs
|
||||
}
|
||||
|
||||
func (w *objWriter) writeRefs(s *LSym) {
|
||||
|
|
|
|||
|
|
@ -147,18 +147,6 @@ func (ctxt *Link) InitTextSym(s *LSym, flag int) {
|
|||
isstmt.Type = objabi.SDWARFMISC
|
||||
isstmt.Set(AttrDuplicateOK, s.DuplicateOK())
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ const (
|
|||
REG_RET1
|
||||
REG_RET2
|
||||
REG_RET3
|
||||
REG_RUN
|
||||
REG_PAUSE
|
||||
|
||||
// locals
|
||||
REG_R0
|
||||
|
|
|
|||
|
|
@ -16,16 +16,16 @@ import (
|
|||
)
|
||||
|
||||
var Register = map[string]int16{
|
||||
"PC_F": REG_PC_F,
|
||||
"PC_B": REG_PC_B,
|
||||
"SP": REG_SP,
|
||||
"CTXT": REG_CTXT,
|
||||
"g": REG_g,
|
||||
"RET0": REG_RET0,
|
||||
"RET1": REG_RET1,
|
||||
"RET2": REG_RET2,
|
||||
"RET3": REG_RET3,
|
||||
"RUN": REG_RUN,
|
||||
"PC_F": REG_PC_F,
|
||||
"PC_B": REG_PC_B,
|
||||
"SP": REG_SP,
|
||||
"CTXT": REG_CTXT,
|
||||
"g": REG_g,
|
||||
"RET0": REG_RET0,
|
||||
"RET1": REG_RET1,
|
||||
"RET2": REG_RET2,
|
||||
"RET3": REG_RET3,
|
||||
"PAUSE": REG_PAUSE,
|
||||
|
||||
"R0": REG_R0,
|
||||
"R1": REG_R1,
|
||||
|
|
@ -777,7 +777,7 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
|||
}
|
||||
reg := p.From.Reg
|
||||
switch {
|
||||
case reg >= REG_PC_F && reg <= REG_RUN:
|
||||
case reg >= REG_PC_F && reg <= REG_PAUSE:
|
||||
w.WriteByte(0x23) // get_global
|
||||
writeUleb128(w, uint64(reg-REG_PC_F))
|
||||
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
|
||||
switch {
|
||||
case reg >= REG_PC_F && reg <= REG_RUN:
|
||||
case reg >= REG_PC_F && reg <= REG_PAUSE:
|
||||
w.WriteByte(0x24) // set_global
|
||||
writeUleb128(w, uint64(reg-REG_PC_F))
|
||||
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.Off = int32(p.Pc + int64(ab.Len()))
|
||||
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
|
||||
ab.PutInt32(0)
|
||||
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
|
||||
// we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
|
||||
// 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 {
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// Only emit typedefs for real names.
|
||||
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))
|
||||
newabslocexprattr(dv, v, s)
|
||||
if s.Version == 0 {
|
||||
if !s.IsFileLocal() {
|
||||
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
|
||||
}
|
||||
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.
|
||||
fileNums := make(map[int]int)
|
||||
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 {
|
||||
if _, ok := fileNums[int(f.Value)]; ok {
|
||||
continue
|
||||
|
|
@ -1756,12 +1776,12 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
|||
// referenced abstract functions.
|
||||
// Collect all debug_range symbols in unit.rangeSyms
|
||||
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.Type = sym.SDWARFINFO
|
||||
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 {
|
||||
rangeSym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
|
||||
rangeSym.Type = sym.SDWARFRANGE
|
||||
|
|
|
|||
|
|
@ -2130,7 +2130,7 @@ func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int6
|
|||
if s.Attr.NotInSymbolTable() {
|
||||
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
|
||||
}
|
||||
switch s.Type {
|
||||
|
|
|
|||
|
|
@ -704,7 +704,7 @@ func (f *peFile) writeSymbols(ctxt *Link) {
|
|||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
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.
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64
|
|||
t := int(typ)
|
||||
switch typ {
|
||||
case TextSym, DataSym, BSSSym:
|
||||
if x.Version != 0 {
|
||||
if x.IsFileLocal() {
|
||||
t += 'a' - 'A'
|
||||
}
|
||||
fallthrough
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ type AuxSymbol struct {
|
|||
elftype elf.SymType
|
||||
}
|
||||
|
||||
const (
|
||||
SymVerStatic = 10 // Minimum version used by static (file-local) syms
|
||||
)
|
||||
|
||||
func (s *Symbol) String() string {
|
||||
if s.Version == 0 {
|
||||
return s.Name
|
||||
|
|
@ -58,6 +62,10 @@ func (s *Symbol) String() string {
|
|||
return fmt.Sprintf("%s<%d>", s.Name, s.Version)
|
||||
}
|
||||
|
||||
func (s *Symbol) IsFileLocal() bool {
|
||||
return s.Version >= SymVerStatic
|
||||
}
|
||||
|
||||
func (s *Symbol) ElfsymForReloc() int32 {
|
||||
// If putelfsym created a local version of this symbol, use that in all
|
||||
// relocations.
|
||||
|
|
|
|||
|
|
@ -40,12 +40,11 @@ type Symbols struct {
|
|||
}
|
||||
|
||||
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{
|
||||
hash: []map[string]*Symbol{
|
||||
// preallocate about 2mb for hash of
|
||||
// non static symbols
|
||||
make(map[string]*Symbol, 100000),
|
||||
},
|
||||
hash: hash,
|
||||
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