mirror of https://github.com/golang/go.git
[dev.garbage] all: merge dev.cc (493ad916c3b1) into dev.garbage
TBR=austin CC=golang-codereviews https://golang.org/cl/179290043
This commit is contained in:
commit
b8540fc288
1
.hgtags
1
.hgtags
|
|
@ -136,3 +136,4 @@ f8b50ad4cac4d4c4ecf48324b4f512f65e82cc1c go1.3beta1
|
|||
f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 go1.3.3
|
||||
f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 release
|
||||
1fdfd7dfaedb1b7702141617e621ab7328a236a1 go1.4beta1
|
||||
bffdd0cae380ce1ccf3e98ed6b6cd53fece7ba72 go1.4rc1
|
||||
|
|
|
|||
2
AUTHORS
2
AUTHORS
|
|
@ -145,7 +145,7 @@ Egon Elbre <egonelbre@gmail.com>
|
|||
Ehren Kret <ehren.kret@gmail.com>
|
||||
Eivind Uggedal <eivind@uggedal.com>
|
||||
Elias Naur <elias.naur@gmail.com>
|
||||
Emil Hessman <c.emil.hessman@gmail.com>
|
||||
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
|
||||
Eoghan Sherry <ejsherry@gmail.com>
|
||||
Eric Clark <zerohp@gmail.com>
|
||||
Eric Milliken <emilliken@gmail.com>
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ Egon Elbre <egonelbre@gmail.com>
|
|||
Ehren Kret <ehren.kret@gmail.com>
|
||||
Eivind Uggedal <eivind@uggedal.com>
|
||||
Elias Naur <elias.naur@gmail.com>
|
||||
Emil Hessman <c.emil.hessman@gmail.com>
|
||||
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
|
||||
Eoghan Sherry <ejsherry@gmail.com>
|
||||
Eric Clark <zerohp@gmail.com>
|
||||
Eric Milliken <emilliken@gmail.com>
|
||||
|
|
@ -452,6 +452,7 @@ Nicholas Katsaros <nick@nickkatsaros.com>
|
|||
Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
|
||||
Nicholas Sullivan <nicholas.sullivan@gmail.com>
|
||||
Nicholas Waples <nwaples@gmail.com>
|
||||
Nick Cooper <nmvc@google.com>
|
||||
Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
|
||||
Nicolas Kaiser <nikai@nikai.net>
|
||||
Nicolas Owens <mischief@offblast.org>
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
<h2 id="introduction">Introduction to Go 1.4</h2>
|
||||
|
||||
<p>
|
||||
The latest Go release, version 1.4, arrives as scheduled six months after 1.3
|
||||
and contains only one tiny language change,
|
||||
a possibly breaking change to the compiler,
|
||||
a backwards-compatible simple form of <code>for</code>-<code>range</code> loop.
|
||||
The latest Go release, version 1.4, arrives as scheduled six months after 1.3.
|
||||
It contains only one tiny language change,
|
||||
in the form of a backwards-compatible simple variant of <code>for</code>-<code>range</code> loop,
|
||||
and a possibly breaking change to the compiler involving methods on pointers-to-pointers.
|
||||
The release focuses primarily on implementation work, improving the garbage collector
|
||||
and preparing the ground for a fully concurrent collector to be rolled out in the
|
||||
next few releases.
|
||||
|
|
@ -20,7 +20,7 @@ this release therefore eliminates the notorious "hot stack split" problem.
|
|||
There are some new tools available including support in the <code>go</code> command
|
||||
for build-time source code generation.
|
||||
The release also adds support for ARM processors on Android and Native Client (NaCl)
|
||||
and AMD64 on Plan 9.
|
||||
and for AMD64 on Plan 9.
|
||||
As always, Go 1.4 keeps the <a href="/doc/go1compat.html">promise
|
||||
of compatibility</a>,
|
||||
and almost everything
|
||||
|
|
@ -637,12 +637,29 @@ See the relevant package documentation for more information about each change.
|
|||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/archive/zip/"><code>archive/zip</code></a> package's
|
||||
<a href="/pkg/archive/zip/#Writer"><code>Writer</code></a> now supports a
|
||||
<a href="/pkg/archive/zip/#Writer.Flush"><code>Flush</code></a> method.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/compress/flate/"><code>compress/flate</code></a>,
|
||||
<a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>,
|
||||
and <a href="/pkg/compress/zlib/"><code>compress/zlib</code></a>
|
||||
packages now support a <code>Reset</code> method
|
||||
for the decompressors, allowing them to reuse buffers and improve performance.
|
||||
The <a href="/pkg/compress/gzip/"><code>compress/gzip</code></a> package also has a
|
||||
<a href="/pkg/compress/gzip/#Reader.Multistream"><code>Multistream</code></a> method to control support
|
||||
for multistream files.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/crypto/"><code>crypto</code></a> package now has a
|
||||
<a href="/pkg/crypto/#Signer"><code>Signer</code></a> interface, implemented by the
|
||||
<code>PrivateKey</code> types in
|
||||
<a href="/pkg/crypto/ecdsa"><code>crypto/ecdsa</code></a> and
|
||||
<a href="/pkg/crypto/rsa"><code>crypto/rsa</code></a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
|
@ -665,6 +682,16 @@ to help clients detect fallback attacks.
|
|||
those attacks.)
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/database/sql/"><code>database/sql</code></a> package can now list all registered
|
||||
<a href="/pkg/database/sql/#Drivers"><code>Drivers</code></a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/debug/dwarf/"><code>debug/dwarf</code></a> package now supports
|
||||
<a href="/pkg/debug/dwarf/#UnspecifiedType"><code>UnspecifiedType</code></a>s.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
In the <a href="/pkg/encoding/asn1/"><code>encoding/asn1</code></a> package,
|
||||
optional elements with a default value will now only be omitted if they have that value.
|
||||
|
|
@ -685,6 +712,11 @@ in some cases, especially involving arrays, it can be faster.
|
|||
There is no functional change.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> package's
|
||||
<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> can now report its input offset.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
In the <a href="/pkg/fmt/"><code>fmt</code></a> package,
|
||||
formatting of pointers to maps has changed to be consistent with that of pointers
|
||||
|
|
@ -693,6 +725,28 @@ For instance, <code>&map[string]int{"one":</code> <code>1}</code> now prints
|
|||
<code>&map[one:</code> <code>1]</code> rather than as a hexadecimal pointer value.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/image/"><code>image</code></a> package's
|
||||
<a href="/pkg/image/#Image"><code>Image</code></a>
|
||||
implementations like
|
||||
<a href="/pkg/image/#RGBA"><code>RGBA</code></a> and
|
||||
<a href="/pkg/image/#Gray"><code>Gray</code></a> have specialized
|
||||
<a href="/pkg/image/#RGBA.RGBAAt"><code>RGBAAt</code></a> and
|
||||
<a href="/pkg/image/#Gray.GrayAt"><code>GrayAt</code></a> methods alongside the general
|
||||
<a href="/pkg/image/#Image.At"><code>At</code></a> method.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/image/png/"><code>image/png</code></a> package now has an
|
||||
<a href="/pkg/image/png/#Encoder"><code>Encoder</code></a>
|
||||
type to control the compression level used for encoding.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/math/"><code>math</code></a> package now has a
|
||||
<a href="/pkg/math/#Nextafter32"><code>Nextafter32</code><a/> function.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <a href="/pkg/net/http/"><code>net/http</code></a> package's
|
||||
<a href="/pkg/net/http/#Request"><code>Request</code></a> type
|
||||
|
|
@ -721,6 +775,7 @@ The <a href="/pkg/os/"><code>os</code></a> package
|
|||
now implements symbolic links on the Windows operating system
|
||||
through the <a href="/pkg/os/#Symlink"><code>Symlink</code></a> function.
|
||||
Other operating systems already have this functionality.
|
||||
There is also a new <a href="/pkg/os/#Unsetenv"><code>Unsetenv</code></a> function.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of October 27, 2014",
|
||||
"Subtitle": "Version of November 11, 2014",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
|
@ -2521,30 +2521,40 @@ The following rules apply to selectors:
|
|||
<ol>
|
||||
<li>
|
||||
For a value <code>x</code> of type <code>T</code> or <code>*T</code>
|
||||
where <code>T</code> is not an interface type,
|
||||
where <code>T</code> is not a pointer or interface type,
|
||||
<code>x.f</code> denotes the field or method at the shallowest depth
|
||||
in <code>T</code> where there
|
||||
is such an <code>f</code>.
|
||||
If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a>
|
||||
with shallowest depth, the selector expression is illegal.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
For a variable <code>x</code> of type <code>I</code> where <code>I</code>
|
||||
For a value <code>x</code> of type <code>I</code> where <code>I</code>
|
||||
is an interface type, <code>x.f</code> denotes the actual method with name
|
||||
<code>f</code> of the value assigned to <code>x</code>.
|
||||
<code>f</code> of the dynamic value of <code>x</code>.
|
||||
If there is no method with name <code>f</code> in the
|
||||
<a href="#Method_sets">method set</a> of <code>I</code>, the selector
|
||||
expression is illegal.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
As an exception, if the type of <code>x</code> is a named pointer type
|
||||
and <code>(*x).f</code> is a valid selector expression denoting a field
|
||||
(but not a method), <code>x.f</code> is shorthand for <code>(*x).f</code>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
In all other cases, <code>x.f</code> is illegal.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
If <code>x</code> is of pointer type and has the value
|
||||
<code>nil</code> and <code>x.f</code> denotes a struct field,
|
||||
assigning to or evaluating <code>x.f</code>
|
||||
causes a <a href="#Run_time_panics">run-time panic</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
If <code>x</code> is of interface type and has the value
|
||||
<code>nil</code>, <a href="#Calls">calling</a> or
|
||||
|
|
@ -2553,18 +2563,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>.
|
|||
</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Selectors automatically <a href="#Address_operators">dereference</a>
|
||||
pointers to structs.
|
||||
If <code>x</code> is a pointer to a struct, <code>x.y</code>
|
||||
is shorthand for <code>(*x).y</code>; if the field <code>y</code>
|
||||
is also a pointer to a struct, <code>x.y.z</code> is shorthand
|
||||
for <code>(*(*x).y).z</code>, and so on.
|
||||
If <code>x</code> contains an anonymous field of type <code>*A</code>,
|
||||
where <code>A</code> is also a struct type,
|
||||
<code>x.f</code> is shorthand for <code>(*x.A).f</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, given the declarations:
|
||||
</p>
|
||||
|
|
@ -2574,13 +2572,13 @@ type T0 struct {
|
|||
x int
|
||||
}
|
||||
|
||||
func (recv *T0) M0()
|
||||
func (*T0) M0()
|
||||
|
||||
type T1 struct {
|
||||
y int
|
||||
}
|
||||
|
||||
func (recv T1) M1()
|
||||
func (T1) M1()
|
||||
|
||||
type T2 struct {
|
||||
z int
|
||||
|
|
@ -2588,9 +2586,13 @@ type T2 struct {
|
|||
*T0
|
||||
}
|
||||
|
||||
func (recv *T2) M2()
|
||||
func (*T2) M2()
|
||||
|
||||
var p *T2 // with p != nil and p.T0 != nil
|
||||
type Q *T2
|
||||
|
||||
var t T2 // with t.T0 != nil
|
||||
var p *T2 // with p != nil and (*p).T0 != nil
|
||||
var q Q = p
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
|
|
@ -2598,13 +2600,27 @@ one may write:
|
|||
</p>
|
||||
|
||||
<pre>
|
||||
p.z // (*p).z
|
||||
p.y // ((*p).T1).y
|
||||
p.x // (*(*p).T0).x
|
||||
t.z // t.z
|
||||
t.y // t.T1.y
|
||||
t.x // (*t.TO).x
|
||||
|
||||
p.M2() // (*p).M2()
|
||||
p.M1() // ((*p).T1).M1()
|
||||
p.M0() // ((*p).T0).M0()
|
||||
p.z // (*p).z
|
||||
p.y // (*p).T1.y
|
||||
p.x // (*(*p).T0).x
|
||||
|
||||
q.x // (*(*q).T0).x (*q).x is a valid field selector
|
||||
|
||||
p.M2() // p.M2() M2 expects *T2 receiver
|
||||
p.M1() // ((*p).T1).M1() M1 expects T1 receiver
|
||||
p.M0() // ((&(*p).T0)).M0() M0 expects *T0 receiver, see section on Calls
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
but the following is invalid:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
q.M0() // (*q).M0 is valid but not a field selector
|
||||
</pre>
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 215 KiB |
|
|
@ -47,7 +47,7 @@ proceeding. If your OS or architecture is not on the list, it's possible that
|
|||
<tr><td>FreeBSD 8 or later</td> <td>amd64, 386, arm</td> <td>Debian GNU/kFreeBSD not supported; FreeBSD/ARM needs FreeBSD 10 or later</td></tr>
|
||||
<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</td></tr>
|
||||
<tr><td>Mac OS X 10.6 or later</td> <td>amd64, 386</td> <td>use the gcc<sup>†</sup> that comes with Xcode<sup>‡</sup></td></tr>
|
||||
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cgywin or msys.</td></tr>
|
||||
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ struct Addr
|
|||
short type;
|
||||
uint8 index;
|
||||
int8 scale;
|
||||
int8 reg; // for 5l, 9l
|
||||
int8 reg; // for 5l, 9l; GPRs and FPRs both start at 0
|
||||
int8 name; // for 5l, 9l
|
||||
int8 class; // for 5l, 9l
|
||||
uint8 etype; // for 5g, 6g, 8g
|
||||
|
|
@ -94,6 +94,7 @@ struct Prog
|
|||
// operands
|
||||
Addr from;
|
||||
uchar reg; // arm, power64 only (e.g., ADD from, reg, to);
|
||||
// starts at 0 for both GPRs and FPRs;
|
||||
// also used for ADATA width on arm, power64
|
||||
Addr from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to)
|
||||
Addr to;
|
||||
|
|
@ -626,6 +627,11 @@ extern char* anames9[];
|
|||
extern char* cnames5[];
|
||||
extern char* cnames9[];
|
||||
|
||||
extern char* dnames5[];
|
||||
extern char* dnames6[];
|
||||
extern char* dnames8[];
|
||||
extern char* dnames9[];
|
||||
|
||||
extern LinkArch link386;
|
||||
extern LinkArch linkamd64;
|
||||
extern LinkArch linkamd64p32;
|
||||
|
|
@ -634,6 +640,7 @@ extern LinkArch linkpower64;
|
|||
extern LinkArch linkpower64le;
|
||||
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck type "E" uint
|
||||
#pragma varargck type "D" Addr*
|
||||
#pragma varargck type "lD" Addr*
|
||||
#pragma varargck type "P" Prog*
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ const (
|
|||
blogPath = "golang.org/x/blog"
|
||||
toolPath = "golang.org/x/tools"
|
||||
tourPath = "code.google.com/p/go-tour"
|
||||
defaultToolTag = "release-branch.go1.3"
|
||||
defaultTourTag = "release-branch.go1.3"
|
||||
defaultToolTag = "release-branch.go1.4"
|
||||
defaultTourTag = "release-branch.go1.4"
|
||||
)
|
||||
|
||||
// Import paths for tool commands.
|
||||
|
|
|
|||
|
|
@ -75,12 +75,18 @@ struct Reg
|
|||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
|
|
@ -93,6 +99,16 @@ struct Reg
|
|||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
|
|
@ -144,7 +160,7 @@ void prop(Reg*, Bits, Bits);
|
|||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpit(char *str, Flow *r0, int);
|
||||
|
|
@ -187,16 +203,16 @@ enum
|
|||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Register in middle; never written.
|
||||
// Register in middle (Prog.reg); only ever read.
|
||||
RegRead = 1<<12,
|
||||
CanRegRead = 1<<13,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<14,
|
||||
RightRead = 1<<15,
|
||||
RightWrite = 1<<16,
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ regopt(Prog *firstp)
|
|||
|
||||
/* the mod/div runtime routines smash R12 */
|
||||
if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU)
|
||||
r->set.b[z] |= RtoB(12);
|
||||
r->set.b[0] |= RtoB(12);
|
||||
}
|
||||
if(firstr == R)
|
||||
return;
|
||||
|
|
@ -454,9 +454,13 @@ brk:
|
|||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(debug['R']) {
|
||||
if(rgp->regno >= NREG)
|
||||
|
|
@ -477,9 +481,6 @@ brk:
|
|||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
|
|
@ -488,6 +489,15 @@ brk:
|
|||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
|
|
@ -1189,7 +1199,7 @@ paint1(Reg *r, int bn)
|
|||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
|
|
@ -1213,6 +1223,9 @@ paint2(Reg *r, int bn)
|
|||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
|
|
@ -1220,14 +1233,14 @@ paint2(Reg *r, int bn)
|
|||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
|
|
@ -1344,6 +1357,8 @@ RtoB(int r)
|
|||
int
|
||||
BtoR(uint32 b)
|
||||
{
|
||||
// TODO Allow R0 and R1, but be careful with a 0 return
|
||||
// TODO Allow R9. Only R10 is reserved now (just g, not m).
|
||||
b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
|
||||
if(b == 0)
|
||||
return 0;
|
||||
|
|
@ -1442,12 +1457,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
|||
print(" (only)");
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != nil) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -338,6 +338,8 @@ enum
|
|||
D_STATIC = (D_NONE+4),
|
||||
D_AUTO = (D_NONE+5),
|
||||
D_PARAM = (D_NONE+6),
|
||||
|
||||
D_LAST = (D_NONE+26),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -75,12 +75,18 @@ struct Reg
|
|||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
|
|
@ -93,6 +99,16 @@ struct Reg
|
|||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
|
|
@ -140,7 +156,7 @@ void prop(Reg*, Bits, Bits);
|
|||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
|
|
@ -165,8 +181,8 @@ typedef struct ProgInfo ProgInfo;
|
|||
struct ProgInfo
|
||||
{
|
||||
uint32 flags; // the bits below
|
||||
uint32 reguse; // required registers used by this instruction
|
||||
uint32 regset; // required registers set by this instruction
|
||||
uint32 reguse; // registers implicitly used by this instruction
|
||||
uint32 regset; // registers implicitly set by this instruction
|
||||
uint32 regindex; // registers used by addressing mode
|
||||
};
|
||||
|
||||
|
|
@ -187,12 +203,12 @@ enum
|
|||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<12,
|
||||
RightRead = 1<<13,
|
||||
RightWrite = 1<<14,
|
||||
|
|
|
|||
|
|
@ -389,9 +389,13 @@ brk:
|
|||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(rgp->regno != 0) {
|
||||
if(debug['R'] && debug['v']) {
|
||||
|
|
@ -406,9 +410,6 @@ brk:
|
|||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
|
|
@ -417,6 +418,15 @@ brk:
|
|||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
|
|
@ -1020,7 +1030,7 @@ paint1(Reg *r, int bn)
|
|||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
|
|
@ -1044,6 +1054,9 @@ paint2(Reg *r, int bn)
|
|||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
|
|
@ -1051,14 +1064,14 @@ paint2(Reg *r, int bn)
|
|||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
|
|
@ -1259,12 +1272,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
|||
print(" %.4ud", (int)r1->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != R) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -865,6 +865,8 @@ enum
|
|||
|
||||
D_INDIR, /* additive */
|
||||
|
||||
D_LAST,
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
|
|
|
|||
|
|
@ -75,12 +75,18 @@ struct Reg
|
|||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
|
|
@ -106,6 +112,16 @@ struct Reg
|
|||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
|
|
@ -158,7 +174,7 @@ void loopit(Reg*, int32);
|
|||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
|
|
@ -183,8 +199,8 @@ typedef struct ProgInfo ProgInfo;
|
|||
struct ProgInfo
|
||||
{
|
||||
uint32 flags; // the bits below
|
||||
uint32 reguse; // required registers used by this instruction
|
||||
uint32 regset; // required registers set by this instruction
|
||||
uint32 reguse; // registers implicitly used by this instruction
|
||||
uint32 regset; // registers implicitly set by this instruction
|
||||
uint32 regindex; // registers used by addressing mode
|
||||
};
|
||||
|
||||
|
|
@ -205,12 +221,12 @@ enum
|
|||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<12,
|
||||
RightRead = 1<<13,
|
||||
RightWrite = 1<<14,
|
||||
|
|
|
|||
|
|
@ -358,18 +358,19 @@ brk:
|
|||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %lld\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(rgp->regno != 0)
|
||||
paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
|
||||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
|
|
@ -378,6 +379,15 @@ brk:
|
|||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
|
|
@ -926,7 +936,7 @@ paint1(Reg *r, int bn)
|
|||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint64 bb;
|
||||
uint64 bb, rbz;
|
||||
|
||||
z = bn/64;
|
||||
bb = 1LL<<(bn%64);
|
||||
|
|
@ -945,7 +955,8 @@ paint1(Reg *r, int bn)
|
|||
r = r1;
|
||||
}
|
||||
|
||||
if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
|
||||
rbz = ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z]));
|
||||
if(LOAD(r) & rbz & bb) {
|
||||
change -= CLOAD * r->f.loop;
|
||||
}
|
||||
for(;;) {
|
||||
|
|
@ -996,7 +1007,7 @@ paint1(Reg *r, int bn)
|
|||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
|
|
@ -1020,6 +1031,9 @@ paint2(Reg *r, int bn)
|
|||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
|
|
@ -1027,14 +1041,14 @@ paint2(Reg *r, int bn)
|
|||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
|
|
@ -1053,7 +1067,7 @@ paint3(Reg *r, int bn, uint32 rb, int rn)
|
|||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint64 bb;
|
||||
uint64 bb, rbz;
|
||||
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
|
|
@ -1072,7 +1086,8 @@ paint3(Reg *r, int bn, uint32 rb, int rn)
|
|||
r = r1;
|
||||
}
|
||||
|
||||
if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
|
||||
rbz = ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z]));
|
||||
if(LOAD(r) & rbz & bb)
|
||||
addmove(r, bn, rn, 0);
|
||||
for(;;) {
|
||||
r->act.b[z] |= bb;
|
||||
|
|
@ -1227,12 +1242,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
|||
print(" %.4ud", (int)r1->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != nil) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -654,6 +654,8 @@ enum
|
|||
|
||||
D_CONST2 = D_INDIR+D_INDIR,
|
||||
|
||||
D_LAST,
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ struct
|
|||
"R27", LREG, 27,
|
||||
"R28", LREG, 28,
|
||||
"R29", LREG, 29,
|
||||
"R30", LREG, 30,
|
||||
"g", LREG, 30, // avoid unintentionally clobbering g using R30
|
||||
"R31", LREG, 31,
|
||||
|
||||
"F", LF, 0,
|
||||
|
|
@ -488,6 +488,7 @@ struct
|
|||
"SYSCALL", LNOP, ASYSCALL,
|
||||
"UNDEF", LNOP, AUNDEF,
|
||||
|
||||
"RET", LRETRN, ARETURN,
|
||||
"RETURN", LRETRN, ARETURN,
|
||||
"RFI", LRETRN, ARFI,
|
||||
"RFCI", LRETRN, ARFCI,
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
# Copyright 2012 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include ../../Make.dist
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
- effect of register expansion on 32-bit shifts and masks etc
|
||||
9c
|
||||
- multab
|
||||
- floating-point conversions
|
||||
- conversions of constants
|
||||
- nodtype for loads
|
||||
- sign-extension instruction (32-64) when in register?
|
||||
- double indexing
|
||||
- SLW (eg, in cat)
|
||||
- scheduling
|
||||
|
||||
9l
|
||||
- D_QCONST, DWORD
|
||||
- maskgen
|
||||
1147
src/cmd/9c/cgen.c
1147
src/cmd/9c/cgen.c
File diff suppressed because it is too large
Load Diff
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
|
||||
9c is a version of the Plan 9 C compiler. The original is documented at
|
||||
|
||||
http://plan9.bell-labs.com/magic/man2html/1/8c
|
||||
|
||||
Its target architecture is the Power64, referred to by these tools as
|
||||
power64 (big endian) or power64le (little endian).
|
||||
|
||||
*/
|
||||
package main
|
||||
350
src/cmd/9c/gc.h
350
src/cmd/9c/gc.h
|
|
@ -1,350 +0,0 @@
|
|||
// cmd/9c/gc.h from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <u.h>
|
||||
#include "../cc/cc.h"
|
||||
#include "../9l/9.out.h"
|
||||
|
||||
/*
|
||||
* 9c/powerpc64
|
||||
*/
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_IND 8
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_VLONG 8
|
||||
#define SZ_DOUBLE 8
|
||||
#define FNX 100
|
||||
|
||||
typedef struct Case Case;
|
||||
typedef struct C1 C1;
|
||||
typedef struct Multab Multab;
|
||||
typedef struct Hintab Hintab;
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
|
||||
#define A ((Adr*)0)
|
||||
|
||||
#define INDEXED 9
|
||||
#define P ((Prog*)0)
|
||||
|
||||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
vlong val;
|
||||
int32 label;
|
||||
char def;
|
||||
char isv;
|
||||
};
|
||||
#define C ((Case*)0)
|
||||
|
||||
struct C1
|
||||
{
|
||||
vlong val;
|
||||
int32 label;
|
||||
};
|
||||
|
||||
struct Multab
|
||||
{
|
||||
int32 val;
|
||||
char code[20];
|
||||
};
|
||||
|
||||
struct Hintab
|
||||
{
|
||||
ushort val;
|
||||
char hint[10];
|
||||
};
|
||||
|
||||
struct Reg
|
||||
{
|
||||
int32 pc;
|
||||
int32 rpo; /* reverse post ordering */
|
||||
|
||||
Bits set;
|
||||
Bits use1;
|
||||
Bits use2;
|
||||
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
int32 regu;
|
||||
int32 loop; /* could be shorter */
|
||||
|
||||
union
|
||||
{
|
||||
Reg* log5;
|
||||
int32 active;
|
||||
};
|
||||
Reg* p1;
|
||||
Reg* p2;
|
||||
Reg* p2link;
|
||||
Reg* s1;
|
||||
Reg* s2;
|
||||
Reg* link;
|
||||
Prog* prog;
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
|
||||
#define NRGN 600
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN int32 breakpc;
|
||||
EXTERN int32 nbreak;
|
||||
EXTERN Case* cases;
|
||||
EXTERN Node constnode;
|
||||
EXTERN Node fconstnode;
|
||||
EXTERN Node vconstnode;
|
||||
EXTERN int32 continpc;
|
||||
EXTERN int32 curarg;
|
||||
EXTERN int32 cursafe;
|
||||
EXTERN Prog* lastp;
|
||||
extern int hintabsize;
|
||||
EXTERN int32 maxargsafe;
|
||||
EXTERN Multab multab[20];
|
||||
EXTERN int mnstring;
|
||||
EXTERN Node* nodrat;
|
||||
EXTERN Node* nodret;
|
||||
EXTERN Node* nodsafe;
|
||||
EXTERN int32 nrathole;
|
||||
EXTERN int32 nstring;
|
||||
EXTERN Prog* p;
|
||||
EXTERN int32 pc;
|
||||
EXTERN Node regnode;
|
||||
EXTERN Node qregnode;
|
||||
EXTERN char string[NSNAME];
|
||||
EXTERN Sym* symrathole;
|
||||
EXTERN Node znode;
|
||||
EXTERN Prog zprog;
|
||||
EXTERN int reg[NREG+NREG];
|
||||
EXTERN int32 exregoffset;
|
||||
EXTERN int32 exfregoffset;
|
||||
EXTERN uchar typechlpv[NTYPE];
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
|
||||
|
||||
#define CLOAD 5
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
|
||||
EXTERN int32 regbits;
|
||||
EXTERN int32 exregbits;
|
||||
|
||||
EXTERN int change;
|
||||
EXTERN int suppress;
|
||||
|
||||
EXTERN Reg* firstr;
|
||||
EXTERN Reg* lastr;
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN Var var[NVAR];
|
||||
EXTERN int32* idom;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN int32 maxnr;
|
||||
|
||||
#define R0ISZERO (debug['0']==0)
|
||||
|
||||
extern char* anames[];
|
||||
extern Hintab hintab[];
|
||||
|
||||
/*
|
||||
* sgen.c
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gen(Node*);
|
||||
void usedset(Node*, int);
|
||||
void noretval(int);
|
||||
void xcom(Node*);
|
||||
int bcomplex(Node*, Node*);
|
||||
Prog* gtext(Sym*, int32);
|
||||
vlong argsize(int);
|
||||
|
||||
/*
|
||||
* cgen.c
|
||||
*/
|
||||
void cgen(Node*, Node*);
|
||||
void reglcgen(Node*, Node*, Node*);
|
||||
void lcgen(Node*, Node*);
|
||||
void bcgen(Node*, int);
|
||||
void boolgen(Node*, int, Node*);
|
||||
void sugen(Node*, Node*, int32);
|
||||
void layout(Node*, Node*, int, int, Node*);
|
||||
|
||||
/*
|
||||
* txt.c
|
||||
*/
|
||||
void ginit(void);
|
||||
void gclean(void);
|
||||
void nextpc(void);
|
||||
void gargs(Node*, Node*, Node*);
|
||||
void garg1(Node*, Node*, Node*, int, Node**);
|
||||
Node* nodconst(int32);
|
||||
Node* nod32const(vlong);
|
||||
Node* nodfconst(double);
|
||||
Node* nodgconst(vlong v, Type *t);
|
||||
void nodreg(Node*, Node*, int);
|
||||
void regret(Node*, Node*, Type*, int);
|
||||
void regalloc(Node*, Node*, Node*);
|
||||
void regfree(Node*);
|
||||
void regialloc(Node*, Node*, Node*);
|
||||
void regsalloc(Node*, Node*);
|
||||
void regaalloc1(Node*, Node*);
|
||||
void regaalloc(Node*, Node*);
|
||||
void regind(Node*, Node*);
|
||||
void gprep(Node*, Node*);
|
||||
void raddr(Node*, Prog*);
|
||||
void naddr(Node*, Addr*);
|
||||
void gmove(Node*, Node*);
|
||||
void gins(int a, Node*, Node*);
|
||||
void gopcode(int, Node*, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void gbranch(int);
|
||||
int immconst(Node*);
|
||||
void patch(Prog*, int32);
|
||||
int sconst(Node*);
|
||||
int sval(int32);
|
||||
int uconst(Node*);
|
||||
void gpseudo(int, Sym*, Node*);
|
||||
void gprefetch(Node*);
|
||||
void gpcdata(int, int);
|
||||
|
||||
/*
|
||||
* swt.c
|
||||
*/
|
||||
int swcmp(const void*, const void*);
|
||||
void doswit(Node*);
|
||||
void swit1(C1*, int, int32, Node*);
|
||||
void swit2(C1*, int, int32, Node*, Node*);
|
||||
void newcase(void);
|
||||
void bitload(Node*, Node*, Node*, Node*, Node*);
|
||||
void bitstore(Node*, Node*, Node*, Node*, Node*);
|
||||
int32 outstring(char*, int32);
|
||||
int mulcon(Node*, Node*);
|
||||
Multab* mulcon0(Node*, int32);
|
||||
int mulcon1(Node*, int32, Node*);
|
||||
void nullwarn(Node*, Node*);
|
||||
void sextern(Sym*, Node*, int32, int32);
|
||||
void gextern(Sym*, Node*, int32, int32);
|
||||
void outcode(void);
|
||||
|
||||
/*
|
||||
* list
|
||||
*/
|
||||
void listinit(void);
|
||||
int Pconv(Fmt*);
|
||||
int Aconv(Fmt*);
|
||||
int Dconv(Fmt*);
|
||||
int Sconv(Fmt*);
|
||||
int Nconv(Fmt*);
|
||||
int Bconv(Fmt*);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Addr*, int);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, int32);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
void paint3(Reg*, int, int32, int);
|
||||
void addreg(Addr*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(void);
|
||||
void excise(Reg*);
|
||||
Reg* uniqp(Reg*);
|
||||
Reg* uniqs(Reg*);
|
||||
int regtyp(Addr*);
|
||||
int regzer(Addr*);
|
||||
int anyvar(Addr*);
|
||||
int subprop(Reg*);
|
||||
int copyprop(Reg*);
|
||||
int copy1(Addr*, Addr*, Reg*, int);
|
||||
int copyu(Prog*, Addr*, Addr*);
|
||||
|
||||
int copyas(Addr*, Addr*);
|
||||
int copyau(Addr*, Addr*);
|
||||
int copyau1(Prog*, Addr*);
|
||||
int copysub(Addr*, Addr*, Addr*, int);
|
||||
int copysub1(Prog*, Addr*, Addr*, int);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
|
||||
/*
|
||||
* com64.c
|
||||
*/
|
||||
int com64(Node*);
|
||||
void com64init(void);
|
||||
void bool64(Node*);
|
||||
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck type "B" Bits
|
||||
#pragma varargck type "D" Addr*
|
||||
#pragma varargck type "N" Addr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "S" char*
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// cmd/9c/list.c from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#define EXTERN
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
listinit9();
|
||||
}
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
// cmd/9c/machcap.c from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
|
||||
if(n == Z)
|
||||
return 1; /* test */
|
||||
|
||||
switch(n->op) {
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
if(typechlv[n->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OAND:
|
||||
case OOR:
|
||||
case OSUB:
|
||||
case OXOR:
|
||||
case OASHL:
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
if(typechlv[n->left->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
return 1;
|
||||
|
||||
case OCOND:
|
||||
case OCOMMA:
|
||||
case OLIST:
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
case ONOT:
|
||||
return 1;
|
||||
|
||||
case OASADD:
|
||||
case OASSUB:
|
||||
case OASAND:
|
||||
case OASOR:
|
||||
case OASXOR:
|
||||
return 1;
|
||||
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASLSHR:
|
||||
return 1;
|
||||
|
||||
case OPOSTINC:
|
||||
case OPOSTDEC:
|
||||
case OPREINC:
|
||||
case OPREDEC:
|
||||
return 1;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OGT:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
return 1;
|
||||
case ONEG:
|
||||
case OCOM:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
638
src/cmd/9c/mul.c
638
src/cmd/9c/mul.c
|
|
@ -1,638 +0,0 @@
|
|||
// cmd/9c/mul.c from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
/*
|
||||
* code sequences for multiply by constant.
|
||||
* [a-l][0-3]
|
||||
* lsl $(A-'a'),r0,r1
|
||||
* [+][0-7]
|
||||
* add r0,r1,r2
|
||||
* [-][0-7]
|
||||
* sub r0,r1,r2
|
||||
*/
|
||||
|
||||
static int multabp;
|
||||
static int32 mulval;
|
||||
static char* mulcp;
|
||||
static int32 valmax;
|
||||
static int shmax;
|
||||
|
||||
static int docode(char *hp, char *cp, int r0, int r1);
|
||||
static int gen1(int len);
|
||||
static int gen2(int len, int32 r1);
|
||||
static int gen3(int len, int32 r0, int32 r1, int flag);
|
||||
enum
|
||||
{
|
||||
SR1 = 1<<0, /* r1 has been shifted */
|
||||
SR0 = 1<<1, /* r0 has been shifted */
|
||||
UR1 = 1<<2, /* r1 has not been used */
|
||||
UR0 = 1<<3, /* r0 has not been used */
|
||||
};
|
||||
|
||||
Multab*
|
||||
mulcon0(Node *n, int32 v)
|
||||
{
|
||||
int a1, a2, g;
|
||||
Multab *m, *m1;
|
||||
char hint[10];
|
||||
|
||||
if(v < 0)
|
||||
v = -v;
|
||||
|
||||
/*
|
||||
* look in cache
|
||||
*/
|
||||
m = multab;
|
||||
for(g=0; g<nelem(multab); g++) {
|
||||
if(m->val == v) {
|
||||
if(m->code[0] == 0)
|
||||
return 0;
|
||||
return m;
|
||||
}
|
||||
m++;
|
||||
}
|
||||
|
||||
/*
|
||||
* select a spot in cache to overwrite
|
||||
*/
|
||||
multabp++;
|
||||
if(multabp < 0 || multabp >= nelem(multab))
|
||||
multabp = 0;
|
||||
m = multab+multabp;
|
||||
m->val = v;
|
||||
mulval = v;
|
||||
|
||||
/*
|
||||
* look in execption hint table
|
||||
*/
|
||||
a1 = 0;
|
||||
a2 = hintabsize;
|
||||
for(;;) {
|
||||
if(a1 >= a2)
|
||||
goto no;
|
||||
g = (a2 + a1)/2;
|
||||
if(v < hintab[g].val) {
|
||||
a2 = g;
|
||||
continue;
|
||||
}
|
||||
if(v > hintab[g].val) {
|
||||
a1 = g+1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(docode(hintab[g].hint, m->code, 1, 0))
|
||||
return m;
|
||||
print("%L: multiply table failure %ld\n", n->lineno, v);
|
||||
m->code[0] = 0;
|
||||
return 0;
|
||||
|
||||
no:
|
||||
/*
|
||||
* try to search
|
||||
*/
|
||||
hint[0] = 0;
|
||||
for(g=1; g<=6; g++) {
|
||||
if(g >= 6 && v >= 65535)
|
||||
break;
|
||||
mulcp = hint+g;
|
||||
*mulcp = 0;
|
||||
if(gen1(g)) {
|
||||
if(docode(hint, m->code, 1, 0))
|
||||
return m;
|
||||
print("%L: multiply table failure (g=%d h=%s) %ld\n",
|
||||
n->lineno, g, hint, v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* try a recur followed by a shift
|
||||
*/
|
||||
g = 0;
|
||||
while(!(v & 1)) {
|
||||
g++;
|
||||
v >>= 1;
|
||||
}
|
||||
if(g) {
|
||||
m1 = mulcon0(n, v);
|
||||
if(m1) {
|
||||
strcpy(m->code, m1->code);
|
||||
sprint(strchr(m->code, 0), "%c0", g+'a');
|
||||
return m;
|
||||
}
|
||||
}
|
||||
m->code[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
docode(char *hp, char *cp, int r0, int r1)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
c = *hp++;
|
||||
*cp = c;
|
||||
cp += 2;
|
||||
switch(c) {
|
||||
default:
|
||||
c -= 'a';
|
||||
if(c < 1 || c >= 30)
|
||||
break;
|
||||
for(i=0; i<4; i++) {
|
||||
switch(i) {
|
||||
case 0:
|
||||
if(docode(hp, cp, r0<<c, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 1:
|
||||
if(docode(hp, cp, r1<<c, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 2:
|
||||
if(docode(hp, cp, r0, r0<<c))
|
||||
goto out;
|
||||
break;
|
||||
case 3:
|
||||
if(docode(hp, cp, r0, r1<<c))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
for(i=0; i<8; i++) {
|
||||
cp[-1] = i+'0';
|
||||
switch(i) {
|
||||
case 1:
|
||||
if(docode(hp, cp, r0+r1, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 5:
|
||||
if(docode(hp, cp, r0, r0+r1))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
for(i=0; i<8; i++) {
|
||||
cp[-1] = i+'0';
|
||||
switch(i) {
|
||||
case 1:
|
||||
if(docode(hp, cp, r0-r1, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 2:
|
||||
if(docode(hp, cp, r1-r0, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 5:
|
||||
if(docode(hp, cp, r0, r0-r1))
|
||||
goto out;
|
||||
break;
|
||||
case 6:
|
||||
if(docode(hp, cp, r0, r1-r0))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if(r0 == mulval)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out:
|
||||
cp[-1] = i+'0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gen1(int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(shmax=1; shmax<30; shmax++) {
|
||||
valmax = 1<<shmax;
|
||||
if(valmax >= mulval)
|
||||
break;
|
||||
}
|
||||
if(mulval == 1)
|
||||
return 1;
|
||||
|
||||
len--;
|
||||
for(i=1; i<=shmax; i++)
|
||||
if(gen2(len, 1<<i)) {
|
||||
*--mulcp = 'a'+i;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gen2(int len, int32 r1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(len <= 0) {
|
||||
if(r1 == mulval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
len--;
|
||||
if(len == 0)
|
||||
goto calcr0;
|
||||
|
||||
if(gen3(len, r1, r1+1, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, r1-1, r1, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, 1, r1+1, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, 1, r1-1, UR1)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
calcr0:
|
||||
if(mulval == r1+1) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(mulval == r1-1) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out:
|
||||
*--mulcp = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gen3(int len, int32 r0, int32 r1, int flag)
|
||||
{
|
||||
int i, f1, f2;
|
||||
int32 x;
|
||||
|
||||
if(r0 <= 0 ||
|
||||
r0 >= r1 ||
|
||||
r1 > valmax)
|
||||
return 0;
|
||||
|
||||
len--;
|
||||
if(len == 0)
|
||||
goto calcr0;
|
||||
|
||||
if(!(flag & UR1)) {
|
||||
f1 = UR1|SR1;
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r0<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r0, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & UR0)) {
|
||||
f1 = UR1|SR1;
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r1, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & SR1)) {
|
||||
f1 = UR1|SR1|(flag&UR0);
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r0, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & SR0)) {
|
||||
f1 = UR0|SR0|(flag&(SR1|UR1));
|
||||
|
||||
f2 = UR1|SR1;
|
||||
if(flag & UR1)
|
||||
f2 |= UR0;
|
||||
if(flag & SR1)
|
||||
f2 |= SR0;
|
||||
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r0<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(x > r1) {
|
||||
if(gen3(len, r1, x, f2)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
if(gen3(len, x, r1, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x = r1+r0;
|
||||
if(gen3(len, r0, x, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(gen3(len, r1, x, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
|
||||
x = r1-r0;
|
||||
if(gen3(len, x, r1, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(x > r0) {
|
||||
if(gen3(len, r0, x, UR1)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
if(gen3(len, x, r0, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
calcr0:
|
||||
f1 = flag & (UR0|UR1);
|
||||
if(f1 == UR1) {
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x >= mulval) {
|
||||
if(x == mulval) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mulval == r1+r0) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(mulval == r1-r0) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
*--mulcp = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* hint table has numbers that
|
||||
* the search algorithm fails on.
|
||||
* <1000:
|
||||
* all numbers
|
||||
* <5000:
|
||||
* ÷ by 5
|
||||
* <10000:
|
||||
* ÷ by 50
|
||||
* <65536:
|
||||
* ÷ by 250
|
||||
*/
|
||||
Hintab hintab[] =
|
||||
{
|
||||
683, "b++d+e+",
|
||||
687, "b+e++e-",
|
||||
691, "b++d+e+",
|
||||
731, "b++d+e+",
|
||||
811, "b++d+i+",
|
||||
821, "b++e+e+",
|
||||
843, "b+d++e+",
|
||||
851, "b+f-+e-",
|
||||
853, "b++e+e+",
|
||||
877, "c++++g-",
|
||||
933, "b+c++g-",
|
||||
981, "c-+e-d+",
|
||||
1375, "b+c+b+h-",
|
||||
1675, "d+b++h+",
|
||||
2425, "c++f-e+",
|
||||
2675, "c+d++f-",
|
||||
2750, "b+d-b+h-",
|
||||
2775, "c-+g-e-",
|
||||
3125, "b++e+g+",
|
||||
3275, "b+c+g+e+",
|
||||
3350, "c++++i+",
|
||||
3475, "c-+e-f-",
|
||||
3525, "c-+d+g-",
|
||||
3625, "c-+e-j+",
|
||||
3675, "b+d+d+e+",
|
||||
3725, "b+d-+h+",
|
||||
3925, "b+d+f-d-",
|
||||
4275, "b+g++e+",
|
||||
4325, "b+h-+d+",
|
||||
4425, "b+b+g-j-",
|
||||
4525, "b+d-d+f+",
|
||||
4675, "c++d-g+",
|
||||
4775, "b+d+b+g-",
|
||||
4825, "c+c-+i-",
|
||||
4850, "c++++i-",
|
||||
4925, "b++e-g-",
|
||||
4975, "c+f++e-",
|
||||
5500, "b+g-c+d+",
|
||||
6700, "d+b++i+",
|
||||
9700, "d++++j-",
|
||||
11000, "b+f-c-h-",
|
||||
11750, "b+d+g+j-",
|
||||
12500, "b+c+e-k+",
|
||||
13250, "b+d+e-f+",
|
||||
13750, "b+h-c-d+",
|
||||
14250, "b+g-c+e-",
|
||||
14500, "c+f+j-d-",
|
||||
14750, "d-g--f+",
|
||||
16750, "b+e-d-n+",
|
||||
17750, "c+h-b+e+",
|
||||
18250, "d+b+h-d+",
|
||||
18750, "b+g-++f+",
|
||||
19250, "b+e+b+h+",
|
||||
19750, "b++h--f-",
|
||||
20250, "b+e-l-c+",
|
||||
20750, "c++bi+e-",
|
||||
21250, "b+i+l+c+",
|
||||
22000, "b+e+d-g-",
|
||||
22250, "b+d-h+k-",
|
||||
22750, "b+d-e-g+",
|
||||
23250, "b+c+h+e-",
|
||||
23500, "b+g-c-g-",
|
||||
23750, "b+g-b+h-",
|
||||
24250, "c++g+m-",
|
||||
24750, "b+e+e+j-",
|
||||
25000, "b++dh+g+",
|
||||
25250, "b+e+d-g-",
|
||||
25750, "b+e+b+j+",
|
||||
26250, "b+h+c+e+",
|
||||
26500, "b+h+c+g+",
|
||||
26750, "b+d+e+g-",
|
||||
27250, "b+e+e+f+",
|
||||
27500, "c-i-c-d+",
|
||||
27750, "b+bd++j+",
|
||||
28250, "d-d-++i-",
|
||||
28500, "c+c-h-e-",
|
||||
29000, "b+g-d-f+",
|
||||
29500, "c+h+++e-",
|
||||
29750, "b+g+f-c+",
|
||||
30250, "b+f-g-c+",
|
||||
33500, "c-f-d-n+",
|
||||
33750, "b+d-b+j-",
|
||||
34250, "c+e+++i+",
|
||||
35250, "e+b+d+k+",
|
||||
35500, "c+e+d-g-",
|
||||
35750, "c+i-++e+",
|
||||
36250, "b+bh-d+e+",
|
||||
36500, "c+c-h-e-",
|
||||
36750, "d+e--i+",
|
||||
37250, "b+g+g+b+",
|
||||
37500, "b+h-b+f+",
|
||||
37750, "c+be++j-",
|
||||
38500, "b+e+b+i+",
|
||||
38750, "d+i-b+d+",
|
||||
39250, "b+g-l-+d+",
|
||||
39500, "b+g-c+g-",
|
||||
39750, "b+bh-c+f-",
|
||||
40250, "b+bf+d+g-",
|
||||
40500, "b+g-c+g+",
|
||||
40750, "c+b+i-e+",
|
||||
41250, "d++bf+h+",
|
||||
41500, "b+j+c+d-",
|
||||
41750, "c+f+b+h-",
|
||||
42500, "c+h++g+",
|
||||
42750, "b+g+d-f-",
|
||||
43250, "b+l-e+d-",
|
||||
43750, "c+bd+h+f-",
|
||||
44000, "b+f+g-d-",
|
||||
44250, "b+d-g--f+",
|
||||
44500, "c+e+c+h+",
|
||||
44750, "b+e+d-h-",
|
||||
45250, "b++g+j-g+",
|
||||
45500, "c+d+e-g+",
|
||||
45750, "b+d-h-e-",
|
||||
46250, "c+bd++j+",
|
||||
46500, "b+d-c-j-",
|
||||
46750, "e-e-b+g-",
|
||||
47000, "b+c+d-j-",
|
||||
47250, "b+e+e-g-",
|
||||
47500, "b+g-c-h-",
|
||||
47750, "b+f-c+h-",
|
||||
48250, "d--h+n-",
|
||||
48500, "b+c-g+m-",
|
||||
48750, "b+e+e-g+",
|
||||
49500, "c-f+e+j-",
|
||||
49750, "c+c+g++f-",
|
||||
50000, "b+e+e+k+",
|
||||
50250, "b++i++g+",
|
||||
50500, "c+g+f-i+",
|
||||
50750, "b+e+d+k-",
|
||||
51500, "b+i+c-f+",
|
||||
51750, "b+bd+g-e-",
|
||||
52250, "b+d+g-j+",
|
||||
52500, "c+c+f+g+",
|
||||
52750, "b+c+e+i+",
|
||||
53000, "b+i+c+g+",
|
||||
53500, "c+g+g-n+",
|
||||
53750, "b+j+d-c+",
|
||||
54250, "b+d-g-j-",
|
||||
54500, "c-f+e+f+",
|
||||
54750, "b+f-+c+g+",
|
||||
55000, "b+g-d-g-",
|
||||
55250, "b+e+e+g+",
|
||||
55500, "b+cd++j+",
|
||||
55750, "b+bh-d-f-",
|
||||
56250, "c+d-b+j-",
|
||||
56500, "c+d+c+i+",
|
||||
56750, "b+e+d++h-",
|
||||
57000, "b+d+g-f+",
|
||||
57250, "b+f-m+d-",
|
||||
57750, "b+i+c+e-",
|
||||
58000, "b+e+d+h+",
|
||||
58250, "c+b+g+g+",
|
||||
58750, "d-e-j--e+",
|
||||
59000, "d-i-+e+",
|
||||
59250, "e--h-m+",
|
||||
59500, "c+c-h+f-",
|
||||
59750, "b+bh-e+i-",
|
||||
60250, "b+bh-e-e-",
|
||||
60500, "c+c-g-g-",
|
||||
60750, "b+e-l-e-",
|
||||
61250, "b+g-g-c+",
|
||||
61750, "b+g-c+g+",
|
||||
62250, "f--+c-i-",
|
||||
62750, "e+f--+g+",
|
||||
64750, "b+f+d+p-",
|
||||
};
|
||||
int hintabsize = nelem(hintab);
|
||||
1076
src/cmd/9c/peep.c
1076
src/cmd/9c/peep.c
File diff suppressed because it is too large
Load Diff
1163
src/cmd/9c/reg.c
1163
src/cmd/9c/reg.c
File diff suppressed because it is too large
Load Diff
|
|
@ -1,291 +0,0 @@
|
|||
// cmd/9c/sgen.c from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
Prog*
|
||||
gtext(Sym *s, int32 stkoff)
|
||||
{
|
||||
vlong v;
|
||||
|
||||
v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
|
||||
if((textflag & NOSPLIT) && stkoff >= 128)
|
||||
yyerror("stack frame too large for NOSPLIT function");
|
||||
|
||||
gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
noretval(int n)
|
||||
{
|
||||
|
||||
if(n & 1) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = D_REG;
|
||||
p->to.reg = REGRET;
|
||||
}
|
||||
if(n & 2) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = D_FREG;
|
||||
p->to.reg = FREGRET;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate addressability as follows
|
||||
* CONST ==> 20 $value
|
||||
* NAME ==> 10 name
|
||||
* REGISTER ==> 11 register
|
||||
* INDREG ==> 12 *[(reg)+offset]
|
||||
* &10 ==> 2 $name
|
||||
* ADD(2, 20) ==> 2 $name+offset
|
||||
* ADD(3, 20) ==> 3 $(reg)+offset
|
||||
* &12 ==> 3 $(reg)+offset
|
||||
* *11 ==> 11 ??
|
||||
* *2 ==> 10 name
|
||||
* *3 ==> 12 *(reg)+offset
|
||||
* calculate complexity (number of registers)
|
||||
*/
|
||||
void
|
||||
xcom(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
int v;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
n->addable = 0;
|
||||
n->complex = 0;
|
||||
switch(n->op) {
|
||||
case OCONST:
|
||||
n->addable = 20;
|
||||
return;
|
||||
|
||||
case OREGISTER:
|
||||
n->addable = 11;
|
||||
return;
|
||||
|
||||
case OINDREG:
|
||||
n->addable = 12;
|
||||
return;
|
||||
|
||||
case ONAME:
|
||||
n->addable = 10;
|
||||
return;
|
||||
|
||||
case OADDR:
|
||||
xcom(l);
|
||||
if(l->addable == 10)
|
||||
n->addable = 2;
|
||||
if(l->addable == 12)
|
||||
n->addable = 3;
|
||||
break;
|
||||
|
||||
case OIND:
|
||||
xcom(l);
|
||||
if(l->addable == 11)
|
||||
n->addable = 12;
|
||||
if(l->addable == 3)
|
||||
n->addable = 12;
|
||||
if(l->addable == 2)
|
||||
n->addable = 10;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
if(l->addable == 20) {
|
||||
if(r->addable == 2)
|
||||
n->addable = 2;
|
||||
if(r->addable == 3)
|
||||
n->addable = 3;
|
||||
}
|
||||
if(r->addable == 20) {
|
||||
if(l->addable == 2)
|
||||
n->addable = 2;
|
||||
if(l->addable == 3)
|
||||
n->addable = 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
v = vlog(r);
|
||||
if(v >= 0) {
|
||||
n->op = OASASHL;
|
||||
r->vconst = v;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
v = vlog(r);
|
||||
if(v >= 0) {
|
||||
n->op = OASHL;
|
||||
r->vconst = v;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
v = vlog(l);
|
||||
if(v >= 0) {
|
||||
n->op = OASHL;
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
r = l;
|
||||
l = n->left;
|
||||
r->vconst = v;
|
||||
r->type = types[TINT];
|
||||
simplifyshift(n);
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
v = vlog(r);
|
||||
if(v >= 0) {
|
||||
n->op = OASLSHR;
|
||||
r->vconst = v;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
v = vlog(r);
|
||||
if(v >= 0) {
|
||||
n->op = OLSHR;
|
||||
r->vconst = v;
|
||||
r->type = types[TINT];
|
||||
simplifyshift(n);
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
v = vlog(r);
|
||||
if(v >= 0) {
|
||||
n->op = OASAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
v = vlog(r);
|
||||
if(v >= 0) {
|
||||
n->op = OAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
simplifyshift(n);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(l != Z)
|
||||
xcom(l);
|
||||
if(r != Z)
|
||||
xcom(r);
|
||||
break;
|
||||
}
|
||||
if(n->addable >= 10)
|
||||
return;
|
||||
if(l != Z)
|
||||
n->complex = l->complex;
|
||||
if(r != Z) {
|
||||
if(r->complex == n->complex)
|
||||
n->complex = r->complex+1;
|
||||
else
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
}
|
||||
if(n->complex == 0)
|
||||
n->complex++;
|
||||
|
||||
// if(com64(n))
|
||||
// return;
|
||||
|
||||
switch(n->op) {
|
||||
|
||||
case OFUNC:
|
||||
n->complex = FNX;
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OGT:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
/*
|
||||
* immediate operators, make const on right
|
||||
*/
|
||||
if(l->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
n->op = invrel[relindex(n->op)];
|
||||
}
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OXOR:
|
||||
case OAND:
|
||||
case OOR:
|
||||
/*
|
||||
* immediate operators, make const on right
|
||||
*/
|
||||
if(l->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
407
src/cmd/9c/swt.c
407
src/cmd/9c/swt.c
|
|
@ -1,407 +0,0 @@
|
|||
// cmd/9c/swt.c from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
swit1(C1 *q, int nc, int32 def, Node *n)
|
||||
{
|
||||
Node tn, nod;
|
||||
|
||||
regalloc(&nod, n, Z);
|
||||
/* always signed */
|
||||
if(typev[n->type->etype])
|
||||
nod.type = types[TVLONG];
|
||||
else
|
||||
nod.type = types[TLONG];
|
||||
cgen(n, &nod);
|
||||
regalloc(&tn, ®node, Z);
|
||||
swit2(q, nc, def, &nod, &tn);
|
||||
regfree(&tn);
|
||||
regfree(&nod);
|
||||
}
|
||||
|
||||
void
|
||||
swit2(C1 *q, int nc, int32 def, Node *n, Node *tn)
|
||||
{
|
||||
C1 *r;
|
||||
int i;
|
||||
Prog *sp;
|
||||
|
||||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(sval(q->val)) {
|
||||
gopcode(OEQ, n, Z, nodconst(q->val));
|
||||
} else {
|
||||
gopcode(OSUB, nodconst(q->val), n, tn);
|
||||
gopcode(OEQ, tn, Z, nodconst(0));
|
||||
}
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, def);
|
||||
return;
|
||||
}
|
||||
i = nc / 2;
|
||||
r = q+i;
|
||||
if(sval(r->val)) {
|
||||
gopcode(OGT, n, Z, nodconst(r->val));
|
||||
sp = p;
|
||||
} else {
|
||||
gopcode(OSUB, nodconst(r->val), n, tn);
|
||||
gopcode(OGT, tn, Z, nodconst(0));
|
||||
sp = p;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
p->as = ABEQ;
|
||||
patch(p, r->label);
|
||||
swit2(q, i, def, n, tn);
|
||||
|
||||
patch(sp, pc);
|
||||
swit2(r+1, nc-i-1, def, n, tn);
|
||||
}
|
||||
|
||||
void
|
||||
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int sh;
|
||||
int32 v;
|
||||
Node *l;
|
||||
|
||||
/*
|
||||
* n1 gets adjusted/masked value
|
||||
* n2 gets address of cell
|
||||
* n3 gets contents of cell
|
||||
*/
|
||||
l = b->left;
|
||||
if(n2 != Z) {
|
||||
regalloc(n1, l, nn);
|
||||
reglcgen(n2, l, Z);
|
||||
regalloc(n3, l, Z);
|
||||
gopcode(OAS, n2, Z, n3);
|
||||
gopcode(OAS, n3, Z, n1);
|
||||
} else {
|
||||
regalloc(n1, l, nn);
|
||||
cgen(l, n1);
|
||||
}
|
||||
if(b->type->shift == 0 && typeu[b->type->etype]) {
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, nodconst(v), Z, n1);
|
||||
} else {
|
||||
sh = 32 - b->type->shift - b->type->nbits;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, nodconst(sh), Z, n1);
|
||||
sh += b->type->shift;
|
||||
if(sh > 0)
|
||||
if(typeu[b->type->etype])
|
||||
gopcode(OLSHR, nodconst(sh), Z, n1);
|
||||
else
|
||||
gopcode(OASHR, nodconst(sh), Z, n1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int32 v;
|
||||
Node nod, *l;
|
||||
int sh;
|
||||
|
||||
/*
|
||||
* n1 has adjusted/masked value
|
||||
* n2 has address of cell
|
||||
* n3 has contents of cell
|
||||
*/
|
||||
l = b->left;
|
||||
regalloc(&nod, l, Z);
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, nodconst(v), Z, n1);
|
||||
gopcode(OAS, n1, Z, &nod);
|
||||
if(nn != Z)
|
||||
gopcode(OAS, n1, Z, nn);
|
||||
sh = b->type->shift;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, nodconst(sh), Z, &nod);
|
||||
v <<= sh;
|
||||
gopcode(OAND, nodconst(~v), Z, n3);
|
||||
gopcode(OOR, n3, Z, &nod);
|
||||
gopcode(OAS, &nod, Z, n2);
|
||||
|
||||
regfree(&nod);
|
||||
regfree(n1);
|
||||
regfree(n2);
|
||||
regfree(n3);
|
||||
}
|
||||
|
||||
int32
|
||||
outstring(char *s, int32 n)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
r = nstring;
|
||||
while(n) {
|
||||
string[mnstring] = *s++;
|
||||
mnstring++;
|
||||
nstring++;
|
||||
if(mnstring >= NSNAME) {
|
||||
gpseudo(ADATA, symstring, nodconst(0L));
|
||||
p->from.offset += nstring - NSNAME;
|
||||
p->reg = NSNAME;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.u.sval, string, NSNAME);
|
||||
mnstring = 0;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
mulcon(Node *n, Node *nn)
|
||||
{
|
||||
Node *l, *r, nod1, nod2;
|
||||
Multab *m;
|
||||
int32 v;
|
||||
int o;
|
||||
char code[sizeof(m->code)+2], *p;
|
||||
|
||||
if(typefd[n->type->etype])
|
||||
return 0;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l->op == OCONST) {
|
||||
l = r;
|
||||
r = n->left;
|
||||
}
|
||||
if(r->op != OCONST)
|
||||
return 0;
|
||||
v = convvtox(r->vconst, n->type->etype);
|
||||
if(v != r->vconst) {
|
||||
if(debug['M'])
|
||||
print("%L multiply conv: %lld\n", n->lineno, r->vconst);
|
||||
return 0;
|
||||
}
|
||||
m = mulcon0(n, v);
|
||||
if(!m) {
|
||||
if(debug['M'])
|
||||
print("%L multiply table: %lld\n", n->lineno, r->vconst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memmove(code, m->code, sizeof(m->code));
|
||||
code[sizeof(m->code)] = 0;
|
||||
|
||||
p = code;
|
||||
if(p[1] == 'i')
|
||||
p += 2;
|
||||
regalloc(&nod1, n, nn);
|
||||
cgen(l, &nod1);
|
||||
if(v < 0)
|
||||
gopcode(ONEG, &nod1, Z, &nod1);
|
||||
regalloc(&nod2, n, Z);
|
||||
|
||||
loop:
|
||||
switch(*p) {
|
||||
case 0:
|
||||
regfree(&nod2);
|
||||
gopcode(OAS, &nod1, Z, nn);
|
||||
regfree(&nod1);
|
||||
return 1;
|
||||
case '+':
|
||||
o = OADD;
|
||||
goto addsub;
|
||||
case '-':
|
||||
o = OSUB;
|
||||
addsub: /* number is r,n,l */
|
||||
v = p[1] - '0';
|
||||
r = &nod1;
|
||||
if(v&4)
|
||||
r = &nod2;
|
||||
n = &nod1;
|
||||
if(v&2)
|
||||
n = &nod2;
|
||||
l = &nod1;
|
||||
if(v&1)
|
||||
l = &nod2;
|
||||
gopcode(o, l, n, r);
|
||||
break;
|
||||
default: /* op is shiftcount, number is r,l */
|
||||
v = p[1] - '0';
|
||||
r = &nod1;
|
||||
if(v&2)
|
||||
r = &nod2;
|
||||
l = &nod1;
|
||||
if(v&1)
|
||||
l = &nod2;
|
||||
v = *p - 'a';
|
||||
if(v < 0 || v >= 32) {
|
||||
diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
|
||||
break;
|
||||
}
|
||||
gopcode(OASHL, nodconst(v), l, r);
|
||||
break;
|
||||
}
|
||||
p += 2;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
void
|
||||
sextern(Sym *s, Node *a, int32 o, int32 w)
|
||||
{
|
||||
int32 e, lw;
|
||||
|
||||
for(e=0; e<w; e+=NSNAME) {
|
||||
lw = NSNAME;
|
||||
if(w-e < lw)
|
||||
lw = w-e;
|
||||
gpseudo(ADATA, s, nodconst(0));
|
||||
p->from.offset += o+e;
|
||||
p->reg = lw;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.u.sval, a->cstring+e, lw);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gextern(Sym *s, Node *a, int32 o, int32 w)
|
||||
{
|
||||
gpseudo(ADATA, s, a);
|
||||
p->from.offset += o;
|
||||
p->reg = w;
|
||||
if(p->to.type == D_OREG)
|
||||
p->to.type = D_CONST;
|
||||
}
|
||||
|
||||
void
|
||||
outcode(void)
|
||||
{
|
||||
Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
|
||||
if(pragcgobuf.to > pragcgobuf.start) {
|
||||
Bprint(&outbuf, "\n");
|
||||
Bprint(&outbuf, "$$ // exports\n\n");
|
||||
Bprint(&outbuf, "$$ // local types\n\n");
|
||||
Bprint(&outbuf, "$$ // cgo\n");
|
||||
Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
|
||||
Bprint(&outbuf, "\n$$\n\n");
|
||||
}
|
||||
Bprint(&outbuf, "!\n");
|
||||
|
||||
writeobj(ctxt, &outbuf);
|
||||
lastp = nil;
|
||||
}
|
||||
|
||||
int32
|
||||
align(int32 i, Type *t, int op, int32 *maxalign)
|
||||
{
|
||||
int32 o;
|
||||
Type *v;
|
||||
int w, packw;
|
||||
|
||||
o = i;
|
||||
w = 1;
|
||||
packw = 0;
|
||||
switch(op) {
|
||||
default:
|
||||
diag(Z, "unknown align opcode %d", op);
|
||||
break;
|
||||
|
||||
case Asu2: /* padding at end of a struct */
|
||||
w = *maxalign;
|
||||
if(w < 1)
|
||||
w = 1;
|
||||
if(packflg)
|
||||
packw = packflg;
|
||||
break;
|
||||
|
||||
case Ael1: /* initial allign of struct element */
|
||||
for(v=t; v->etype==TARRAY; v=v->link)
|
||||
;
|
||||
if(v->etype == TSTRUCT || v->etype == TUNION)
|
||||
w = v->align;
|
||||
else
|
||||
w = ewidth[v->etype];
|
||||
if(w < 1 || w > SZ_VLONG)
|
||||
fatal(Z, "align");
|
||||
if(packflg)
|
||||
packw = packflg;
|
||||
break;
|
||||
|
||||
case Ael2: /* width of a struct element */
|
||||
o += t->width;
|
||||
break;
|
||||
|
||||
case Aarg0: /* initial passbyptr argument in arg list */
|
||||
if(typesu[t->etype]) {
|
||||
o = align(o, types[TIND], Aarg1, nil);
|
||||
o = align(o, types[TIND], Aarg2, nil);
|
||||
}
|
||||
break;
|
||||
|
||||
case Aarg1: /* initial align of parameter */
|
||||
w = ewidth[t->etype];
|
||||
if(w <= 0 || w >= SZ_VLONG) {
|
||||
w = SZ_VLONG;
|
||||
break;
|
||||
}
|
||||
w = 1;
|
||||
break;
|
||||
|
||||
case Aarg2: /* width of a parameter */
|
||||
o += t->width;
|
||||
w = t->width;
|
||||
if(w > SZ_VLONG)
|
||||
w = SZ_VLONG;
|
||||
break;
|
||||
|
||||
case Aaut3: /* total align of automatic */
|
||||
o = align(o, t, Ael1, nil);
|
||||
o = align(o, t, Ael2, nil);
|
||||
break;
|
||||
}
|
||||
if(packw != 0 && xround(o, w) != xround(o, packw))
|
||||
diag(Z, "#pragma pack changes offset of %T", t);
|
||||
o = xround(o, w);
|
||||
if(maxalign && *maxalign < w)
|
||||
*maxalign = w;
|
||||
if(debug['A'])
|
||||
print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int32
|
||||
maxround(int32 max, int32 v)
|
||||
{
|
||||
v = xround(v, SZ_VLONG);
|
||||
if(v > max)
|
||||
return v;
|
||||
return max;
|
||||
}
|
||||
1537
src/cmd/9c/txt.c
1537
src/cmd/9c/txt.c
File diff suppressed because it is too large
Load Diff
|
|
@ -134,11 +134,12 @@ proginfo(ProgInfo *info, Prog *p)
|
|||
}
|
||||
|
||||
if(p->as == ADUFFZERO) {
|
||||
info->reguse |= RtoB(0) | RtoB(2);
|
||||
info->regset |= RtoB(2);
|
||||
info->reguse |= (1<<D_R0) | RtoB(3);
|
||||
info->regset |= RtoB(3);
|
||||
}
|
||||
if(p->as == ADUFFCOPY) {
|
||||
info->reguse |= RtoB(0) | RtoB(2) | RtoB(3);
|
||||
info->regset |= RtoB(2) | RtoB(3);
|
||||
// TODO(austin) Revisit when duffcopy is implemented
|
||||
info->reguse |= RtoB(3) | RtoB(4) | RtoB(5);
|
||||
info->regset |= RtoB(3) | RtoB(4);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1322,7 +1322,6 @@ void
|
|||
dumpit(char *str, Flow *r0, int isreg)
|
||||
{
|
||||
Flow *r, *r1;
|
||||
int s1v, s2v;
|
||||
|
||||
print("\n%s\n", str);
|
||||
for(r = r0; r != nil; r = r->link) {
|
||||
|
|
@ -1334,10 +1333,8 @@ dumpit(char *str, Flow *r0, int isreg)
|
|||
print(" %.4ud", (int)r1->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
// If at least one successor is "interesting", print both
|
||||
s1v = (r->s1 != nil) && (r->s1->prog != r->prog->link);
|
||||
s2v = (r->s2 != nil) && (r->s2->prog != r->prog->link);
|
||||
if(s1v || s2v) {
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
|
|
|
|||
|
|
@ -497,6 +497,8 @@ enum
|
|||
D_DCONST,
|
||||
D_ADDR, // not used, use D_CONST with non-empty sym.
|
||||
|
||||
D_LAST,
|
||||
|
||||
/* reg names for 9g OREGISTER */
|
||||
D_R0 = 0, // type is D_REG
|
||||
D_F0 = D_R0+NREG, // type is D_FREG
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ In C, a function argument written as a fixed size array
|
|||
actually requires a pointer to the first element of the array.
|
||||
C compilers are aware of this calling convention and adjust
|
||||
the call accordingly, but Go cannot. In Go, you must pass
|
||||
the pointer to the first element explicitly: C.f(&x[0]).
|
||||
the pointer to the first element explicitly: C.f(&C.x[0]).
|
||||
|
||||
A few special functions convert between Go and C types
|
||||
by making copies of the data. In pseudo-Go definitions:
|
||||
|
|
|
|||
|
|
@ -615,8 +615,6 @@ static struct {
|
|||
{"anames9.c", mkanames},
|
||||
{"zdefaultcc.go", mkzdefaultcc},
|
||||
{"zsys_", mkzsys},
|
||||
{"zgoarch_", mkzgoarch},
|
||||
{"zgoos_", mkzgoos},
|
||||
{"zversion.go", mkzversion},
|
||||
{"zaexperiment.h", mkzexperiment},
|
||||
|
||||
|
|
@ -1419,12 +1417,13 @@ clean(void)
|
|||
xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
|
||||
}
|
||||
|
||||
// remove src/runtime/z* unconditionally
|
||||
// remove src/runtime/z* unconditionally,
|
||||
// except leave zgoos and zgoarch, now maintained with go generate.
|
||||
vreset(&dir);
|
||||
bpathf(&path, "%s/src/runtime", goroot);
|
||||
xreaddir(&dir, bstr(&path));
|
||||
for(j=0; j<dir.len; j++) {
|
||||
if(hasprefix(dir.p[j], "z"))
|
||||
if(hasprefix(dir.p[j], "z") && !hasprefix(dir.p[j], "zg"))
|
||||
xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,22 +63,36 @@ gcopnames(char *dir, char *file)
|
|||
vfree(&fields);
|
||||
}
|
||||
|
||||
static int
|
||||
xatoi(char *s, char **end)
|
||||
{
|
||||
int val = 0;
|
||||
for(; *s && *s >= '0' && *s <= '9'; ++s)
|
||||
val = val * 10 + (*s - '0');
|
||||
*end = s;
|
||||
return val;
|
||||
}
|
||||
|
||||
// mkanames reads [5689].out.h and writes anames[5689].c
|
||||
// The format is much the same as the Go opcodes above.
|
||||
// it also writes out cnames array for C_* constants.
|
||||
// It also writes out cnames array for C_* constants and the dnames
|
||||
// array for D_* constants.
|
||||
void
|
||||
mkanames(char *dir, char *file)
|
||||
{
|
||||
int i, j, ch;
|
||||
int i, j, ch, n, unknown;
|
||||
Buf in, b, out, out2;
|
||||
Vec lines;
|
||||
char *p;
|
||||
char *p, *p2;
|
||||
Vec dnames[128];
|
||||
|
||||
binit(&b);
|
||||
binit(&in);
|
||||
binit(&out);
|
||||
binit(&out2);
|
||||
vinit(&lines);
|
||||
for(i=0; i<nelem(dnames); i++)
|
||||
vinit(&dnames[i]);
|
||||
|
||||
ch = file[xstrlen(file)-3];
|
||||
bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
|
||||
|
|
@ -87,10 +101,12 @@ mkanames(char *dir, char *file)
|
|||
|
||||
// Include link.h so that the extern declaration there is
|
||||
// checked against the non-extern declaration we are generating.
|
||||
bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch));
|
||||
bwritestr(&out, bprintf(&b, "\n"));
|
||||
|
||||
bwritestr(&out, bprintf(&b, "char* anames%c[] = {\n", ch));
|
||||
|
|
@ -127,6 +143,69 @@ mkanames(char *dir, char *file)
|
|||
if(j>0)
|
||||
bwriteb(&out, &out2);
|
||||
|
||||
j=unknown=0;
|
||||
n=-1;
|
||||
for(i=0; i<lines.len; i++) {
|
||||
if(hasprefix(lines.p[i], "\tD_")) {
|
||||
p = xstrstr(lines.p[i], ",");
|
||||
if(p)
|
||||
*p = '\0';
|
||||
p = xstrstr(lines.p[i], "\n");
|
||||
if(p)
|
||||
*p = '\0';
|
||||
|
||||
// Parse explicit value, if any
|
||||
p = xstrstr(lines.p[i], "=");
|
||||
if(p) {
|
||||
// Skip space after '='
|
||||
p2 = p + 1;
|
||||
while(*p2 == ' ' || *p2 == '\t')
|
||||
p2++;
|
||||
n = xatoi(p2, &p2);
|
||||
// We can't do anything about
|
||||
// non-numeric values or anything that
|
||||
// follows
|
||||
while(*p2 == ' ' || *p2 == '\t')
|
||||
p2++;
|
||||
if(*p2 != 0) {
|
||||
unknown = 1;
|
||||
continue;
|
||||
}
|
||||
// Truncate space before '='
|
||||
while(*(p-1) == ' ' || *(p-1) == '\t')
|
||||
p--;
|
||||
*p = '\0';
|
||||
unknown = 0;
|
||||
} else {
|
||||
n++;
|
||||
}
|
||||
|
||||
if(unknown || n >= nelem(dnames))
|
||||
continue;
|
||||
|
||||
p = lines.p[i] + 3;
|
||||
if(xstrcmp(p, "LAST") == 0)
|
||||
continue;
|
||||
vadd(&dnames[n], p);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if(j>0){
|
||||
bwritestr(&out, bprintf(&b, "char* dnames%c[D_LAST] = {\n", ch));
|
||||
for(i=0; i<nelem(dnames); i++) {
|
||||
if(dnames[i].len == 0)
|
||||
continue;
|
||||
bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0]));
|
||||
for(j=0; j<dnames[i].len; j++) {
|
||||
if(j != 0)
|
||||
bwritestr(&out, "/");
|
||||
bwritestr(&out, dnames[i].p[j]);
|
||||
}
|
||||
bwritestr(&out, "\",\n");
|
||||
}
|
||||
bwritestr(&out, "};\n");
|
||||
}
|
||||
|
||||
writefile(&out, file, 0);
|
||||
|
||||
bfree(&b);
|
||||
|
|
@ -134,4 +213,6 @@ mkanames(char *dir, char *file)
|
|||
bfree(&out);
|
||||
bfree(&out2);
|
||||
vfree(&lines);
|
||||
for(i=0; i<nelem(dnames); i++)
|
||||
vfree(&dnames[i]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,66 +67,6 @@ mkzexperiment(char *dir, char *file)
|
|||
bfree(&exp);
|
||||
}
|
||||
|
||||
// mkzgoarch writes zgoarch_$GOARCH.go:
|
||||
//
|
||||
// package runtime
|
||||
// const theGoarch = <goarch>
|
||||
//
|
||||
void
|
||||
mkzgoarch(char *dir, char *file)
|
||||
{
|
||||
Buf b, out;
|
||||
|
||||
USED(dir);
|
||||
|
||||
binit(&b);
|
||||
binit(&out);
|
||||
|
||||
bwritestr(&out, bprintf(&b,
|
||||
"// auto generated by go tool dist\n"
|
||||
"\n"
|
||||
"package runtime\n"
|
||||
"\n"
|
||||
"const theGoarch = `%s`\n", goarch));
|
||||
|
||||
writefile(&out, file, 0);
|
||||
|
||||
bfree(&b);
|
||||
bfree(&out);
|
||||
}
|
||||
|
||||
// mkzgoos writes zgoos_$GOOS.go:
|
||||
//
|
||||
// package runtime
|
||||
// const theGoos = <goos>
|
||||
//
|
||||
void
|
||||
mkzgoos(char *dir, char *file)
|
||||
{
|
||||
Buf b, out;
|
||||
|
||||
USED(dir);
|
||||
|
||||
binit(&b);
|
||||
binit(&out);
|
||||
|
||||
bwritestr(&out, "// auto generated by go tool dist\n\n");
|
||||
|
||||
if(streq(goos, "linux")) {
|
||||
bwritestr(&out, "// +build !android\n\n");
|
||||
}
|
||||
|
||||
bwritestr(&out, bprintf(&b,
|
||||
"package runtime\n"
|
||||
"\n"
|
||||
"const theGoos = `%s`\n", goos));
|
||||
|
||||
writefile(&out, file, 0);
|
||||
|
||||
bfree(&b);
|
||||
bfree(&out);
|
||||
}
|
||||
|
||||
#define MAXWINCB 2000 /* maximum number of windows callbacks allowed */
|
||||
|
||||
// mkzsys writes zsys_$GOOS_$GOARCH.s,
|
||||
|
|
|
|||
|
|
@ -1776,7 +1776,6 @@ walkprint(Node *nn, NodeList **init)
|
|||
int notfirst, et, op;
|
||||
NodeList *calls;
|
||||
|
||||
on = nil;
|
||||
op = nn->op;
|
||||
all = nn->list;
|
||||
calls = nil;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ const toolWindowsExtension = ".exe"
|
|||
|
||||
func tool(toolName string) string {
|
||||
toolPath := filepath.Join(toolDir, toolName)
|
||||
if toolIsWindows && toolName != "pprof" {
|
||||
if toolIsWindows {
|
||||
toolPath += toolWindowsExtension
|
||||
}
|
||||
// Give a nice message if there is no tool with that name.
|
||||
|
|
@ -91,16 +91,6 @@ func runTool(cmd *Command, args []string) {
|
|||
if toolPath == "" {
|
||||
return
|
||||
}
|
||||
if toolIsWindows && toolName == "pprof" {
|
||||
args = append([]string{"perl", toolPath}, args[1:]...)
|
||||
var err error
|
||||
toolPath, err = exec.LookPath("perl")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
|
||||
setExitStatus(3)
|
||||
return
|
||||
}
|
||||
}
|
||||
if toolN {
|
||||
fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
|
||||
return
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
package objfile
|
||||
|
||||
import (
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
package main
|
||||
|
||||
import "debug/goobj"
|
||||
import "cmd/internal/goobj"
|
||||
|
||||
// dead removes unreachable code and data from the program.
|
||||
// It is basically a mark-sweep garbage collection: traverse all the
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
)
|
||||
|
||||
// A layoutSection describes a single section to add to the
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"encoding/binary"
|
||||
"os"
|
||||
"sort"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sort"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/build"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
package main
|
||||
|
||||
import "debug/goobj"
|
||||
import "cmd/internal/goobj"
|
||||
|
||||
func (p *Prog) runtime() {
|
||||
p.pclntab()
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"debug/goobj"
|
||||
"cmd/internal/goobj"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
|
@ -69,7 +69,7 @@ func (p *Prog) scanFile(pkgpath string, file string) {
|
|||
return
|
||||
}
|
||||
|
||||
// TODO(rsc): Change debug/goobj to record package name as gp.Name.
|
||||
// TODO(rsc): Change cmd/internal/goobj to record package name as gp.Name.
|
||||
// TODO(rsc): If pkgpath == "main", check that gp.Name == "main".
|
||||
|
||||
pkg.Package = gp
|
||||
|
|
|
|||
|
|
@ -358,9 +358,13 @@ func getFunctionSource(fun, file string, fns nodes, start, end int) (nodes, stri
|
|||
for {
|
||||
line, err := buf.ReadString('\n')
|
||||
if err != nil {
|
||||
if line == "" || err != io.EOF {
|
||||
if err != io.EOF {
|
||||
return nil, file, err
|
||||
}
|
||||
if line == "" {
|
||||
// end was at or past EOF; that's okay
|
||||
break
|
||||
}
|
||||
}
|
||||
if lineno >= start {
|
||||
flat, cum := sumNodes(lineNodes[lineno])
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ var certFiles = []string{
|
|||
"/etc/ssl/cert.pem", // OpenBSD
|
||||
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
|
||||
"/etc/pki/tls/cacert.pem", // OpenELEC
|
||||
"/etc/certs/ca-certificates.crt", // Solaris 11.2+
|
||||
}
|
||||
|
||||
// Possible directories with certificate files; stop after successfully
|
||||
|
|
|
|||
|
|
@ -34,11 +34,9 @@ import (
|
|||
|
||||
const testdata = "testdata"
|
||||
|
||||
var fsetErrs = token.NewFileSet()
|
||||
|
||||
// getFile assumes that each filename occurs at most once
|
||||
func getFile(filename string) (file *token.File) {
|
||||
fsetErrs.Iterate(func(f *token.File) bool {
|
||||
func getFile(fset *token.FileSet, filename string) (file *token.File) {
|
||||
fset.Iterate(func(f *token.File) bool {
|
||||
if f.Name() == filename {
|
||||
if file != nil {
|
||||
panic(filename + " used multiple times")
|
||||
|
|
@ -50,8 +48,8 @@ func getFile(filename string) (file *token.File) {
|
|||
return file
|
||||
}
|
||||
|
||||
func getPos(filename string, offset int) token.Pos {
|
||||
if f := getFile(filename); f != nil {
|
||||
func getPos(fset *token.FileSet, filename string, offset int) token.Pos {
|
||||
if f := getFile(fset, filename); f != nil {
|
||||
return f.Pos(offset)
|
||||
}
|
||||
return token.NoPos
|
||||
|
|
@ -68,14 +66,14 @@ var errRx = regexp.MustCompile(`^/\* *ERROR *(HERE)? *"([^"]*)" *\*/$`)
|
|||
// expectedErrors collects the regular expressions of ERROR comments found
|
||||
// in files and returns them as a map of error positions to error messages.
|
||||
//
|
||||
func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]string {
|
||||
func expectedErrors(t *testing.T, fset *token.FileSet, filename string, src []byte) map[token.Pos]string {
|
||||
errors := make(map[token.Pos]string)
|
||||
|
||||
var s scanner.Scanner
|
||||
// file was parsed already - do not add it again to the file
|
||||
// set otherwise the position information returned here will
|
||||
// not match the position information collected by the parser
|
||||
s.Init(getFile(filename), src, nil, scanner.ScanComments)
|
||||
s.Init(getFile(fset, filename), src, nil, scanner.ScanComments)
|
||||
var prev token.Pos // position of last non-comment, non-semicolon token
|
||||
var here token.Pos // position immediately after the token at position prev
|
||||
|
||||
|
|
@ -109,11 +107,11 @@ func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]str
|
|||
// compareErrors compares the map of expected error messages with the list
|
||||
// of found errors and reports discrepancies.
|
||||
//
|
||||
func compareErrors(t *testing.T, expected map[token.Pos]string, found scanner.ErrorList) {
|
||||
func compareErrors(t *testing.T, fset *token.FileSet, expected map[token.Pos]string, found scanner.ErrorList) {
|
||||
for _, error := range found {
|
||||
// error.Pos is a token.Position, but we want
|
||||
// a token.Pos so we can do a map lookup
|
||||
pos := getPos(error.Pos.Filename, error.Pos.Offset)
|
||||
pos := getPos(fset, error.Pos.Filename, error.Pos.Offset)
|
||||
if msg, found := expected[pos]; found {
|
||||
// we expect a message at pos; check if it matches
|
||||
rx, err := regexp.Compile(msg)
|
||||
|
|
@ -140,7 +138,7 @@ func compareErrors(t *testing.T, expected map[token.Pos]string, found scanner.Er
|
|||
if len(expected) > 0 {
|
||||
t.Errorf("%d errors not reported:", len(expected))
|
||||
for pos, msg := range expected {
|
||||
t.Errorf("%s: %s\n", fsetErrs.Position(pos), msg)
|
||||
t.Errorf("%s: %s\n", fset.Position(pos), msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -152,7 +150,8 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
|
|||
return
|
||||
}
|
||||
|
||||
_, err = ParseFile(fsetErrs, filename, src, DeclarationErrors|AllErrors)
|
||||
fset := token.NewFileSet()
|
||||
_, err = ParseFile(fset, filename, src, DeclarationErrors|AllErrors)
|
||||
found, ok := err.(scanner.ErrorList)
|
||||
if err != nil && !ok {
|
||||
t.Error(err)
|
||||
|
|
@ -162,10 +161,10 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
|
|||
|
||||
// we are expecting the following errors
|
||||
// (collect these after parsing a file so that it is found in the file set)
|
||||
expected := expectedErrors(t, filename, src)
|
||||
expected := expectedErrors(t, fset, filename, src)
|
||||
|
||||
// verify errors returned by the parser
|
||||
compareErrors(t, expected, found)
|
||||
compareErrors(t, fset, expected, found)
|
||||
}
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
var fset = token.NewFileSet()
|
||||
|
||||
var validFiles = []string{
|
||||
"parser.go",
|
||||
"parser_test.go",
|
||||
|
|
@ -25,7 +23,7 @@ var validFiles = []string{
|
|||
|
||||
func TestParse(t *testing.T) {
|
||||
for _, filename := range validFiles {
|
||||
_, err := ParseFile(fset, filename, nil, DeclarationErrors)
|
||||
_, err := ParseFile(token.NewFileSet(), filename, nil, DeclarationErrors)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseFile(%s): %v", filename, err)
|
||||
}
|
||||
|
|
@ -46,7 +44,7 @@ func dirFilter(f os.FileInfo) bool { return nameFilter(f.Name()) }
|
|||
|
||||
func TestParseDir(t *testing.T) {
|
||||
path := "."
|
||||
pkgs, err := ParseDir(fset, path, dirFilter, 0)
|
||||
pkgs, err := ParseDir(token.NewFileSet(), path, dirFilter, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseDir(%s): %v", path, err)
|
||||
}
|
||||
|
|
@ -131,7 +129,7 @@ func TestParseExpr(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestColonEqualsScope(t *testing.T) {
|
||||
f, err := ParseFile(fset, "", `package p; func f() { x, y, z := x, y, z }`, 0)
|
||||
f, err := ParseFile(token.NewFileSet(), "", `package p; func f() { x, y, z := x, y, z }`, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -153,7 +151,7 @@ func TestColonEqualsScope(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVarScope(t *testing.T) {
|
||||
f, err := ParseFile(fset, "", `package p; func f() { var x, y, z = x, y, z }`, 0)
|
||||
f, err := ParseFile(token.NewFileSet(), "", `package p; func f() { var x, y, z = x, y, z }`, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -183,7 +181,7 @@ var x int
|
|||
func f() { L: }
|
||||
`
|
||||
|
||||
f, err := ParseFile(fset, "", src, 0)
|
||||
f, err := ParseFile(token.NewFileSet(), "", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -221,7 +219,7 @@ func f() { L: }
|
|||
}
|
||||
|
||||
func TestUnresolved(t *testing.T) {
|
||||
f, err := ParseFile(fset, "", `
|
||||
f, err := ParseFile(token.NewFileSet(), "", `
|
||||
package p
|
||||
//
|
||||
func f1a(int)
|
||||
|
|
@ -316,7 +314,7 @@ var imports = map[string]bool{
|
|||
func TestImports(t *testing.T) {
|
||||
for path, isValid := range imports {
|
||||
src := fmt.Sprintf("package p; import %s", path)
|
||||
_, err := ParseFile(fset, "", src, 0)
|
||||
_, err := ParseFile(token.NewFileSet(), "", src, 0)
|
||||
switch {
|
||||
case err != nil && isValid:
|
||||
t.Errorf("ParseFile(%s): got %v; expected no error", src, err)
|
||||
|
|
@ -327,7 +325,7 @@ func TestImports(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCommentGroups(t *testing.T) {
|
||||
f, err := ParseFile(fset, "", `
|
||||
f, err := ParseFile(token.NewFileSet(), "", `
|
||||
package p /* 1a */ /* 1b */ /* 1c */ // 1d
|
||||
/* 2a
|
||||
*/
|
||||
|
|
@ -421,7 +419,7 @@ func checkFieldComments(t *testing.T, file *ast.File, fieldname, lead, line stri
|
|||
}
|
||||
|
||||
func TestLeadAndLineComments(t *testing.T) {
|
||||
f, err := ParseFile(fset, "", `
|
||||
f, err := ParseFile(token.NewFileSet(), "", `
|
||||
package p
|
||||
type T struct {
|
||||
/* F1 lead comment */
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ const Size = 4
|
|||
|
||||
// Predefined polynomials.
|
||||
const (
|
||||
// Far and away the most common CRC-32 polynomial.
|
||||
// Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, mpeg-2, ...
|
||||
// IEEE is by far and away the most common CRC-32 polynomial.
|
||||
// Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
|
||||
IEEE = 0xedb88320
|
||||
|
||||
// Castagnoli's polynomial, used in iSCSI.
|
||||
|
|
|
|||
|
|
@ -143,6 +143,9 @@ func (d *decoder) fill() error {
|
|||
// Fill in the rest of the buffer.
|
||||
n, err := d.r.Read(d.bytes.buf[d.bytes.j:])
|
||||
d.bytes.j += n
|
||||
if n > 0 {
|
||||
err = nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
|
|
@ -88,6 +89,51 @@ func decodeFile(filename string) (image.Image, error) {
|
|||
return Decode(f)
|
||||
}
|
||||
|
||||
type eofReader struct {
|
||||
data []byte // deliver from Read without EOF
|
||||
dataEOF []byte // then deliver from Read with EOF on last chunk
|
||||
lenAtEOF int
|
||||
}
|
||||
|
||||
func (r *eofReader) Read(b []byte) (n int, err error) {
|
||||
if len(r.data) > 0 {
|
||||
n = copy(b, r.data)
|
||||
r.data = r.data[n:]
|
||||
} else {
|
||||
n = copy(b, r.dataEOF)
|
||||
r.dataEOF = r.dataEOF[n:]
|
||||
if len(r.dataEOF) == 0 {
|
||||
err = io.EOF
|
||||
if r.lenAtEOF == -1 {
|
||||
r.lenAtEOF = n
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestDecodeEOF(t *testing.T) {
|
||||
// Check that if reader returns final data and EOF at same time, jpeg handles it.
|
||||
data, err := ioutil.ReadFile("../testdata/video-001.jpeg")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
n := len(data)
|
||||
for i := 0; i < n; {
|
||||
r := &eofReader{data[:n-i], data[n-i:], -1}
|
||||
_, err := Decode(r)
|
||||
if err != nil {
|
||||
t.Errorf("Decode with Read() = %d, EOF: %v", r.lenAtEOF, err)
|
||||
}
|
||||
if i == 0 {
|
||||
i = 1
|
||||
} else {
|
||||
i *= 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check checks that the two pix data are equal, within the given bounds.
|
||||
func check(bounds image.Rectangle, pix0, pix1 []byte, stride0, stride1 int) error {
|
||||
if stride0 <= 0 || stride0%8 != 0 {
|
||||
|
|
|
|||
|
|
@ -82,6 +82,19 @@ Pconv(Fmt *fp)
|
|||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
bigP = p;
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
char *s = str;
|
||||
s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, p->as);
|
||||
if(p->from.type != D_NONE)
|
||||
s += sprint(s, " from={%#D}", &p->from);
|
||||
if(p->reg)
|
||||
s += sprint(s, " reg=%d", p->reg);
|
||||
if(p->to.type != D_NONE)
|
||||
sprint(s, " to={%#D}", &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
switch(p->as) {
|
||||
case ADATA:
|
||||
sprint(str, "%.5lld (%L) %A %D/%d,%D",
|
||||
|
|
@ -126,6 +139,31 @@ Dconv(Fmt *fp)
|
|||
a = va_arg(fp->args, Addr*);
|
||||
i = a->type;
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
char *s = str;
|
||||
s += sprint(s, "type=");
|
||||
if(i == D_NONE) {
|
||||
sprint(s, "NONE");
|
||||
goto brk;
|
||||
}
|
||||
if(i >= D_INDIR) {
|
||||
i -= D_INDIR;
|
||||
s += sprint(s, "INDIR+");
|
||||
}
|
||||
if(i >= 0 && i < D_LAST && dnames6[i] != nil)
|
||||
s += sprint(s, "%s ", dnames6[i]);
|
||||
else
|
||||
s += sprint(s, "%d ", i);
|
||||
s += sprint(s, "offset=%lld etype=%E width=%lld", a->offset, a->etype, a->width);
|
||||
if(a->class != 0)
|
||||
s += sprint(s, " class=%s", cnames9[(int)a->class]);
|
||||
if(a->sym != nil)
|
||||
s += sprint(s, " sym=%s", a->sym->name);
|
||||
if(a->type == D_BRANCH && a->u.branch != nil)
|
||||
sprint(s, " branch=%.5lld", a->u.branch->pc);
|
||||
goto brk;
|
||||
}
|
||||
|
||||
if(fp->flags & FmtLong) {
|
||||
if(i == D_CONST)
|
||||
sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
|
||||
|
|
|
|||
|
|
@ -91,6 +91,21 @@ Pconv(Fmt *fp)
|
|||
p = va_arg(fp->args, Prog*);
|
||||
bigP = p;
|
||||
a = p->as;
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
s = str;
|
||||
s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, a);
|
||||
if(p->from.type != D_NONE)
|
||||
s += sprint(s, " from={%#D}", &p->from);
|
||||
if(p->reg)
|
||||
s += sprint(s, " reg=%d", p->reg);
|
||||
if(p->from3.type != D_NONE)
|
||||
s += sprint(s, " from3={%#D}", &p->from3);
|
||||
if(p->to.type != D_NONE)
|
||||
sprint(s, " to={%#D}", &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
if(a == ADATA || a == AINIT || a == ADYNT)
|
||||
sprint(str, "%.5lld (%L) %A %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
|
||||
else if(a == ATEXT) {
|
||||
|
|
@ -153,6 +168,32 @@ Dconv(Fmt *fp)
|
|||
|
||||
a = va_arg(fp->args, Addr*);
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
char *s = str;
|
||||
if(a->type == D_NONE) {
|
||||
sprint(s, "type=NONE");
|
||||
goto ret;
|
||||
}
|
||||
if(a->type >= 0 && a->type < D_LAST && dnames9[a->type] != nil)
|
||||
s += sprint(s, "type=%s ", dnames9[a->type]);
|
||||
else
|
||||
s += sprint(s, "type=%d ", a->type);
|
||||
if(a->name >= 0 && a->name < D_LAST && dnames9[(int)a->name] != nil)
|
||||
s += sprint(s, "name=%s ", dnames9[(int)a->name]);
|
||||
else
|
||||
s += sprint(s, "name=%d ", a->name);
|
||||
s += sprint(s, "offset=%lld etype=%E width=%lld", a->offset, a->etype, a->width);
|
||||
if(a->class != 0)
|
||||
s += sprint(s, " class=%s", cnames9[(int)a->class]);
|
||||
if(a->reg != NREG)
|
||||
s += sprint(s, " reg=%d", a->reg);
|
||||
if(a->sym != nil)
|
||||
s += sprint(s, " sym=%s", a->sym->name);
|
||||
if(a->type == D_BRANCH && a->u.branch != nil)
|
||||
sprint(s, " branch=%.5lld", a->u.branch->pc);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if(fp->flags & FmtLong) {
|
||||
if(a->type == D_CONST)
|
||||
sprint(str, "$%d-%d", (int32)a->offset, (int32)(a->offset>>32));
|
||||
|
|
|
|||
|
|
@ -22,8 +22,12 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// A Dir implements http.FileSystem using the native file
|
||||
// system restricted to a specific directory tree.
|
||||
// A Dir implements FileSystem using the native file system restricted to a
|
||||
// specific directory tree.
|
||||
//
|
||||
// While the FileSystem.Open method takes '/'-separated paths, a Dir's string
|
||||
// value is a filename on the native file system, not a URL, so it is separated
|
||||
// by filepath.Separator, which isn't necessarily '/'.
|
||||
//
|
||||
// An empty Dir is treated as ".".
|
||||
type Dir string
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ package url_test
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ExampleValues() {
|
||||
|
|
@ -39,3 +42,30 @@ func ExampleURL() {
|
|||
fmt.Println(u)
|
||||
// Output: https://google.com/search?q=golang
|
||||
}
|
||||
|
||||
func ExampleURL_opaque() {
|
||||
// Sending a literal '%' in an HTTP request's Path
|
||||
req := &http.Request{
|
||||
Method: "GET",
|
||||
Host: "example.com", // takes precendence over URL.Host
|
||||
URL: &url.URL{
|
||||
Host: "ignored",
|
||||
Scheme: "https",
|
||||
Opaque: "/%2f/",
|
||||
},
|
||||
Header: http.Header{
|
||||
"User-Agent": {"godoc-example/0.1"},
|
||||
},
|
||||
}
|
||||
out, err := httputil.DumpRequestOut(req, true)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(strings.Replace(string(out), "\r", "", -1))
|
||||
// Output:
|
||||
// GET /%2f/ HTTP/1.1
|
||||
// Host: example.com
|
||||
// User-Agent: godoc-example/0.1
|
||||
// Accept-Encoding: gzip
|
||||
//
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const (
|
|||
OpEmptyMatch // matches empty string
|
||||
OpLiteral // matches Runes sequence
|
||||
OpCharClass // matches Runes interpreted as range pair list
|
||||
OpAnyCharNotNL // matches any character
|
||||
OpAnyCharNotNL // matches any character except newline
|
||||
OpAnyChar // matches any character
|
||||
OpBeginLine // matches empty string at beginning of line
|
||||
OpEndLine // matches empty string at end of line
|
||||
|
|
|
|||
38
src/run.bash
38
src/run.bash
|
|
@ -64,18 +64,6 @@ echo
|
|||
echo '# sync -cpu=10'
|
||||
go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
|
||||
|
||||
# Race detector only supported on Linux, FreeBSD and OS X,
|
||||
# and only on amd64, and only when cgo is enabled.
|
||||
# DISABLED until we get garbage collection working.
|
||||
case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED-XXX-DISABLED" in
|
||||
linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
|
||||
echo
|
||||
echo '# Testing race detector.'
|
||||
go test -race -i runtime/race flag
|
||||
go test -race -run=Output runtime/race
|
||||
go test -race -short flag
|
||||
esac
|
||||
|
||||
xcd() {
|
||||
echo
|
||||
echo '#' $1
|
||||
|
|
@ -121,6 +109,7 @@ go run $GOROOT/test/run.go - . || exit 1
|
|||
[ "$CGO_ENABLED" != 1 ] ||
|
||||
(xcd ../misc/cgo/test
|
||||
# cgo tests inspect the traceback for runtime functions
|
||||
extlink=0
|
||||
export GOTRACEBACK=2
|
||||
go test -ldflags '-linkmode=auto' || exit 1
|
||||
# linkmode=internal fails on dragonfly since errno is a TLS relocation.
|
||||
|
|
@ -129,19 +118,24 @@ case "$GOHOSTOS-$GOARCH" in
|
|||
openbsd-386 | openbsd-amd64)
|
||||
# test linkmode=external, but __thread not supported, so skip testtls.
|
||||
go test -ldflags '-linkmode=external' || exit 1
|
||||
extlink=1
|
||||
;;
|
||||
darwin-386 | darwin-amd64)
|
||||
# linkmode=external fails on OS X 10.6 and earlier == Darwin
|
||||
# 10.8 and earlier.
|
||||
case $(uname -r) in
|
||||
[0-9].* | 10.*) ;;
|
||||
*) go test -ldflags '-linkmode=external' || exit 1;;
|
||||
*)
|
||||
go test -ldflags '-linkmode=external' || exit 1
|
||||
extlink=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
|
||||
go test -ldflags '-linkmode=external' || exit 1
|
||||
go test -ldflags '-linkmode=auto' ../testtls || exit 1
|
||||
go test -ldflags '-linkmode=external' ../testtls || exit 1
|
||||
extlink=1
|
||||
|
||||
case "$GOHOSTOS-$GOARCH" in
|
||||
netbsd-386 | netbsd-amd64) ;; # no static linking
|
||||
|
|
@ -165,6 +159,24 @@ android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | fr
|
|||
esac
|
||||
) || exit $?
|
||||
|
||||
# Race detector only supported on Linux, FreeBSD and OS X,
|
||||
# and only on amd64, and only when cgo is enabled.
|
||||
# Delayed until here so we know whether to try external linking.
|
||||
# DISABLED until we get garbage collection working.
|
||||
case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED-XXX-DISABLED" in
|
||||
linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
|
||||
echo
|
||||
echo '# Testing race detector.'
|
||||
go test -race -i runtime/race flag os/exec
|
||||
go test -race -run=Output runtime/race
|
||||
go test -race -short flag os/exec
|
||||
|
||||
# Test with external linking; see issue 9133.
|
||||
if [ "$extlink" = 1 ]; then
|
||||
go test -race -short -ldflags=-linkmode=external flag os/exec
|
||||
fi
|
||||
esac
|
||||
|
||||
# This tests cgo -cdefs. That mode is not supported,
|
||||
# so it's okay if it doesn't work on some systems.
|
||||
# In particular, it works badly with clang on OS X.
|
||||
|
|
|
|||
|
|
@ -134,9 +134,11 @@ if %FAIL%==1 goto fail
|
|||
set GOMAXPROCS=%OLDGOMAXPROCS%
|
||||
set OLDGOMAXPROCS=
|
||||
|
||||
echo # Checking API compatibility.
|
||||
go run "%GOROOT%\src\cmd\api\run.go"
|
||||
if errorlevel 1 goto fail
|
||||
:: echo # Checking API compatibility.
|
||||
:: go run "%GOROOT%\src\cmd\api\run.go"
|
||||
:: if errorlevel 1 goto fail
|
||||
:: echo.
|
||||
echo # SKIPPING API COMPATIBILITY UNTIL ALL SYSTEMS BUILD.
|
||||
echo.
|
||||
|
||||
echo ALL TESTS PASSED
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const (
|
|||
_BigEndian = 0
|
||||
_CacheLineSize = 64
|
||||
_RuntimeGogoBytes = 64
|
||||
_PhysPageSize = _NaCl*65536 + (1-_NaCl)*4096 // 4k normally; 64k on NaCl
|
||||
_PhysPageSize = goos_nacl*65536 + (1-goos_nacl)*4096 // 4k normally; 64k on NaCl
|
||||
_PCQuantum = 1
|
||||
_Int64Align = 4
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const (
|
|||
thechar = '6'
|
||||
_BigEndian = 0
|
||||
_CacheLineSize = 64
|
||||
_RuntimeGogoBytes = 64 + (_Plan9|_Solaris|_Windows)*16
|
||||
_RuntimeGogoBytes = 64 + (goos_plan9|goos_solaris|goos_windows)*16
|
||||
_PhysPageSize = 4096
|
||||
_PCQuantum = 1
|
||||
_Int64Align = 8
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2011 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 runtime
|
||||
|
||||
const (
|
||||
thechar = '6'
|
||||
_BigEndian = 0
|
||||
_CacheLineSize = 64
|
||||
_RuntimeGogoBytes = 64
|
||||
_PhysPageSize = 65536*goos_nacl + 4096*(1-goos_nacl)
|
||||
_PCQuantum = 1
|
||||
_Int64Align = 8
|
||||
)
|
||||
|
|
@ -9,7 +9,7 @@ const (
|
|||
_BigEndian = 0
|
||||
_CacheLineSize = 32
|
||||
_RuntimeGogoBytes = 60
|
||||
_PhysPageSize = 65536*_NaCl + 4096*(1-_NaCl)
|
||||
_PhysPageSize = 65536*goos_nacl + 4096*(1-goos_nacl)
|
||||
_PCQuantum = 4
|
||||
_Int64Align = 4
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2014 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 runtime
|
||||
|
||||
const (
|
||||
thechar = '9'
|
||||
_BigEndian = 1
|
||||
_CacheLineSize = 64
|
||||
_RuntimeGogoBytes = 64
|
||||
_PhysPageSize = 65536
|
||||
_PCQuantum = 4
|
||||
_Int64Align = 8
|
||||
)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2014 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 runtime
|
||||
|
||||
const (
|
||||
thechar = '9'
|
||||
_BigEndian = 0
|
||||
_CacheLineSize = 64
|
||||
_RuntimeGogoBytes = 64
|
||||
_PhysPageSize = 65536
|
||||
_PCQuantum = 4
|
||||
_Int64Align = 8
|
||||
)
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright 2011 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.
|
||||
|
||||
enum {
|
||||
thechar = '6',
|
||||
BigEndian = 0,
|
||||
CacheLineSize = 64,
|
||||
RuntimeGogoBytes = 64,
|
||||
#ifdef GOOS_nacl
|
||||
PhysPageSize = 65536,
|
||||
#else
|
||||
PhysPageSize = 4096,
|
||||
#endif
|
||||
PCQuantum = 1,
|
||||
Int64Align = 8
|
||||
};
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
enum {
|
||||
thechar = '9',
|
||||
BigEndian = 1,
|
||||
CacheLineSize = 64,
|
||||
RuntimeGogoBytes = 64,
|
||||
PhysPageSize = 65536,
|
||||
PCQuantum = 4,
|
||||
Int64Align = 8
|
||||
};
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
|
|||
// of the G stack. We need to distinguish the routine that
|
||||
// lives at the bottom of the G stack from the one that lives
|
||||
// at the top of the system stack because the one at the top of
|
||||
// the M stack terminates the stack walk (see topofstack()).
|
||||
// the system stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
|
||||
RET
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
// +build power64 power64le
|
||||
|
||||
#include "zasm_GOOS_GOARCH.h"
|
||||
#include "go_asm.h"
|
||||
#include "go_tls.h"
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
@ -144,58 +145,44 @@ TEXT runtime·mcall(SB), NOSPLIT, $-8-8
|
|||
BL (CTR)
|
||||
BR runtime·badmcall2(SB)
|
||||
|
||||
// switchtoM is a dummy routine that onM leaves at the bottom
|
||||
// systemstack_switch is a dummy routine that systemstack leaves at the bottom
|
||||
// of the G stack. We need to distinguish the routine that
|
||||
// lives at the bottom of the G stack from the one that lives
|
||||
// at the top of the M stack because the one at the top of
|
||||
// the M stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
|
||||
// at the top of the system stack because the one at the top of
|
||||
// the system stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
|
||||
UNDEF
|
||||
BL (LR) // make sure this function is not leaf
|
||||
RETURN
|
||||
|
||||
// func onM_signalok(fn func())
|
||||
TEXT runtime·onM_signalok(SB), NOSPLIT, $8-8
|
||||
MOVD g, R3 // R3 = g
|
||||
MOVD g_m(R3), R4 // R4 = g->m
|
||||
MOVD m_gsignal(R4), R4 // R4 = g->m->gsignal
|
||||
MOVD fn+0(FP), R11 // context for call below
|
||||
CMP R3, R4
|
||||
BEQ onsignal
|
||||
MOVD R11, 8(R1)
|
||||
BL runtime·onM(SB)
|
||||
RETURN
|
||||
|
||||
onsignal:
|
||||
MOVD 0(R11), R3 // code pointer
|
||||
MOVD R3, CTR
|
||||
BL (CTR)
|
||||
RETURN
|
||||
|
||||
// void onM(fn func())
|
||||
TEXT runtime·onM(SB), NOSPLIT, $0-8
|
||||
// func systemstack(fn func())
|
||||
TEXT runtime·systemstack(SB), NOSPLIT, $0-8
|
||||
MOVD fn+0(FP), R3 // R3 = fn
|
||||
MOVD R3, R11 // context
|
||||
MOVD g_m(g), R4 // R4 = m
|
||||
|
||||
MOVD m_gsignal(R4), R5 // R5 = gsignal
|
||||
CMP g, R5
|
||||
BEQ noswitch
|
||||
|
||||
MOVD m_g0(R4), R5 // R5 = g0
|
||||
CMP g, R5
|
||||
BEQ onm
|
||||
BEQ noswitch
|
||||
|
||||
MOVD m_curg(R4), R6
|
||||
CMP g, R6
|
||||
BEQ oncurg
|
||||
BEQ switch
|
||||
|
||||
// Not g0, not curg. Must be gsignal, but that's not allowed.
|
||||
// Bad: g is not gsignal, not g0, not curg. What is it?
|
||||
// Hide call from linker nosplit analysis.
|
||||
MOVD $runtime·badonm(SB), R3
|
||||
MOVD $runtime·badsystemstack(SB), R3
|
||||
MOVD R3, CTR
|
||||
BL (CTR)
|
||||
|
||||
oncurg:
|
||||
switch:
|
||||
// save our state in g->sched. Pretend to
|
||||
// be switchtoM if the G stack is scanned.
|
||||
MOVD $runtime·switchtoM(SB), R6
|
||||
// be systemstack_switch if the G stack is scanned.
|
||||
MOVD $runtime·systemstack_switch(SB), R6
|
||||
ADD $8, R6 // get past prologue
|
||||
MOVD R6, (g_sched+gobuf_pc)(g)
|
||||
MOVD R1, (g_sched+gobuf_sp)(g)
|
||||
|
|
@ -205,7 +192,7 @@ oncurg:
|
|||
// switch to g0
|
||||
MOVD R5, g
|
||||
MOVD (g_sched+gobuf_sp)(g), R3
|
||||
// make it look like mstart called onM on g0, to stop traceback
|
||||
// make it look like mstart called systemstack on g0, to stop traceback
|
||||
SUB $8, R3
|
||||
MOVD $runtime·mstart(SB), R4
|
||||
MOVD R4, 0(R3)
|
||||
|
|
@ -223,7 +210,7 @@ oncurg:
|
|||
MOVD R0, (g_sched+gobuf_sp)(g)
|
||||
RETURN
|
||||
|
||||
onm:
|
||||
noswitch:
|
||||
// already on m stack, just call directly
|
||||
MOVD 0(R11), R3 // code pointer
|
||||
MOVD R3, CTR
|
||||
|
|
@ -987,6 +974,10 @@ TEXT runtime·goexit(SB),NOSPLIT,$-8-0
|
|||
MOVD R0, R0 // NOP
|
||||
BL runtime·goexit1(SB) // does not return
|
||||
|
||||
TEXT runtime·getg(SB),NOSPLIT,$-8-8
|
||||
MOVD g, ret+0(FP)
|
||||
RETURN
|
||||
|
||||
TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
|
||||
RETURN
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build power64 power64le
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
//go:noescape
|
||||
func xadd(ptr *uint32, delta int32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xadd64(ptr *uint64, delta int64) uint64
|
||||
|
||||
//go:noescape
|
||||
func xchg(ptr *uint32, new uint32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xchg64(ptr *uint64, new uint64) uint64
|
||||
|
||||
// xchgp cannot have a go:noescape annotation, because
|
||||
// while ptr does not escape, new does. If new is marked as
|
||||
// not escaping, the compiler will make incorrect escape analysis
|
||||
// decisions about the value being xchg'ed.
|
||||
// Instead, make xchgp a wrapper around the actual atomic.
|
||||
// When calling the wrapper we mark ptr as noescape explicitly.
|
||||
|
||||
//go:nosplit
|
||||
func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
|
||||
return xchgp1(noescape(ptr), new)
|
||||
}
|
||||
|
||||
func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
func xchguintptr(ptr *uintptr, new uintptr) uintptr
|
||||
|
||||
//go:noescape
|
||||
func atomicload(ptr *uint32) uint32
|
||||
|
||||
//go:noescape
|
||||
func atomicload64(ptr *uint64) uint64
|
||||
|
||||
//go:noescape
|
||||
func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
func atomicor8(ptr *uint8, val uint8)
|
||||
|
||||
//go:noescape
|
||||
func cas64(ptr *uint64, old, new uint64) bool
|
||||
|
||||
//go:noescape
|
||||
func atomicstore(ptr *uint32, val uint32)
|
||||
|
||||
//go:noescape
|
||||
func atomicstore64(ptr *uint64, val uint64)
|
||||
|
||||
// atomicstorep cannot have a go:noescape annotation.
|
||||
// See comment above for xchgp.
|
||||
|
||||
//go:nosplit
|
||||
func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
|
||||
atomicstorep1(noescape(ptr), new)
|
||||
}
|
||||
|
||||
func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
|
||||
|
|
@ -630,6 +630,7 @@ func (q *waitq) dequeue() *sudog {
|
|||
return nil
|
||||
}
|
||||
q.first = sgp.next
|
||||
sgp.next = nil
|
||||
if q.last == sgp {
|
||||
q.last = nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ const (
|
|||
)
|
||||
|
||||
type sigaltstackt struct {
|
||||
ss_sp *byte
|
||||
ss_size uint32
|
||||
ss_sp uintptr
|
||||
ss_size uintptr
|
||||
ss_flags int32
|
||||
}
|
||||
|
||||
|
|
@ -101,8 +101,8 @@ type siginfo struct {
|
|||
}
|
||||
|
||||
type stackt struct {
|
||||
ss_sp *byte
|
||||
ss_size uint32
|
||||
ss_sp uintptr
|
||||
ss_size uintptr
|
||||
ss_flags int32
|
||||
}
|
||||
|
||||
|
|
@ -111,18 +111,30 @@ type timespec struct {
|
|||
tv_nsec int32
|
||||
}
|
||||
|
||||
func (ts *timespec) set_sec(x int32) {
|
||||
ts.tv_sec = int64(x)
|
||||
}
|
||||
|
||||
func (ts *timespec) set_nsec(x int32) {
|
||||
ts.tv_nsec = x
|
||||
}
|
||||
|
||||
type timeval struct {
|
||||
tv_sec int64
|
||||
tv_usec int32
|
||||
}
|
||||
|
||||
func (tv *timeval) set_usec(x int32) {
|
||||
tv.tv_usec = x
|
||||
}
|
||||
|
||||
type itimerval struct {
|
||||
it_interval timeval
|
||||
it_value timeval
|
||||
}
|
||||
|
||||
type mcontextt struct {
|
||||
__gregs [19]int32
|
||||
__gregs [19]uint32
|
||||
__fpregs [644]byte
|
||||
_mc_tlsbase int32
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ const (
|
|||
)
|
||||
|
||||
type sigaltstackt struct {
|
||||
ss_sp *byte
|
||||
ss_size uint64
|
||||
ss_sp uintptr
|
||||
ss_size uintptr
|
||||
ss_flags int32
|
||||
pad_cgo_0 [4]byte
|
||||
}
|
||||
|
|
@ -103,8 +103,8 @@ type siginfo struct {
|
|||
}
|
||||
|
||||
type stackt struct {
|
||||
ss_sp *byte
|
||||
ss_size uint64
|
||||
ss_sp uintptr
|
||||
ss_size uintptr
|
||||
ss_flags int32
|
||||
pad_cgo_0 [4]byte
|
||||
}
|
||||
|
|
@ -114,12 +114,24 @@ type timespec struct {
|
|||
tv_nsec int64
|
||||
}
|
||||
|
||||
func (ts *timespec) set_sec(x int32) {
|
||||
ts.tv_sec = int64(x)
|
||||
}
|
||||
|
||||
func (ts *timespec) set_nsec(x int32) {
|
||||
ts.tv_nsec = int64(x)
|
||||
}
|
||||
|
||||
type timeval struct {
|
||||
tv_sec int64
|
||||
tv_usec int32
|
||||
pad_cgo_0 [4]byte
|
||||
}
|
||||
|
||||
func (tv *timeval) set_usec(x int32) {
|
||||
tv.tv_usec = x
|
||||
}
|
||||
|
||||
type itimerval struct {
|
||||
it_interval timeval
|
||||
it_value timeval
|
||||
|
|
|
|||
|
|
@ -155,10 +155,11 @@ type sigactiont struct {
|
|||
}
|
||||
|
||||
type siginfo struct {
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
_sifields [116]byte
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
// below here is a union; si_addr is the only field we use
|
||||
si_addr uint32
|
||||
}
|
||||
|
||||
type sigaltstackt struct {
|
||||
|
|
|
|||
|
|
@ -117,11 +117,11 @@ type sigactiont struct {
|
|||
}
|
||||
|
||||
type siginfo struct {
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
pad_cgo_0 [4]byte
|
||||
_sifields [112]byte
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
// below here is a union; si_addr is the only field we use
|
||||
si_addr uint64
|
||||
}
|
||||
|
||||
type itimerval struct {
|
||||
|
|
|
|||
|
|
@ -147,10 +147,11 @@ type itimerval struct {
|
|||
}
|
||||
|
||||
type siginfo struct {
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
_sifields [4]uint8
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
// below here is a union; si_addr is the only field we use
|
||||
si_addr uint32
|
||||
}
|
||||
|
||||
type sigactiont struct {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
// created by cgo -cdefs and then converted to Go
|
||||
// cgo -cdefs defs_linux.go defs3_linux.go
|
||||
|
||||
package runtime
|
||||
|
||||
const (
|
||||
_EINTR = 0x4
|
||||
_EAGAIN = 0xb
|
||||
_ENOMEM = 0xc
|
||||
|
||||
_PROT_NONE = 0x0
|
||||
_PROT_READ = 0x1
|
||||
_PROT_WRITE = 0x2
|
||||
_PROT_EXEC = 0x4
|
||||
|
||||
_MAP_ANON = 0x20
|
||||
_MAP_PRIVATE = 0x2
|
||||
_MAP_FIXED = 0x10
|
||||
|
||||
_MADV_DONTNEED = 0x4
|
||||
|
||||
_SA_RESTART = 0x10000000
|
||||
_SA_ONSTACK = 0x8000000
|
||||
_SA_SIGINFO = 0x4
|
||||
|
||||
_SIGHUP = 0x1
|
||||
_SIGINT = 0x2
|
||||
_SIGQUIT = 0x3
|
||||
_SIGILL = 0x4
|
||||
_SIGTRAP = 0x5
|
||||
_SIGABRT = 0x6
|
||||
_SIGBUS = 0x7
|
||||
_SIGFPE = 0x8
|
||||
_SIGKILL = 0x9
|
||||
_SIGUSR1 = 0xa
|
||||
_SIGSEGV = 0xb
|
||||
_SIGUSR2 = 0xc
|
||||
_SIGPIPE = 0xd
|
||||
_SIGALRM = 0xe
|
||||
_SIGSTKFLT = 0x10
|
||||
_SIGCHLD = 0x11
|
||||
_SIGCONT = 0x12
|
||||
_SIGSTOP = 0x13
|
||||
_SIGTSTP = 0x14
|
||||
_SIGTTIN = 0x15
|
||||
_SIGTTOU = 0x16
|
||||
_SIGURG = 0x17
|
||||
_SIGXCPU = 0x18
|
||||
_SIGXFSZ = 0x19
|
||||
_SIGVTALRM = 0x1a
|
||||
_SIGPROF = 0x1b
|
||||
_SIGWINCH = 0x1c
|
||||
_SIGIO = 0x1d
|
||||
_SIGPWR = 0x1e
|
||||
_SIGSYS = 0x1f
|
||||
|
||||
_FPE_INTDIV = 0x1
|
||||
_FPE_INTOVF = 0x2
|
||||
_FPE_FLTDIV = 0x3
|
||||
_FPE_FLTOVF = 0x4
|
||||
_FPE_FLTUND = 0x5
|
||||
_FPE_FLTRES = 0x6
|
||||
_FPE_FLTINV = 0x7
|
||||
_FPE_FLTSUB = 0x8
|
||||
|
||||
_BUS_ADRALN = 0x1
|
||||
_BUS_ADRERR = 0x2
|
||||
_BUS_OBJERR = 0x3
|
||||
|
||||
_SEGV_MAPERR = 0x1
|
||||
_SEGV_ACCERR = 0x2
|
||||
|
||||
_ITIMER_REAL = 0x0
|
||||
_ITIMER_VIRTUAL = 0x1
|
||||
_ITIMER_PROF = 0x2
|
||||
|
||||
_EPOLLIN = 0x1
|
||||
_EPOLLOUT = 0x4
|
||||
_EPOLLERR = 0x8
|
||||
_EPOLLHUP = 0x10
|
||||
_EPOLLRDHUP = 0x2000
|
||||
_EPOLLET = 0x80000000
|
||||
_EPOLL_CLOEXEC = 0x80000
|
||||
_EPOLL_CTL_ADD = 0x1
|
||||
_EPOLL_CTL_DEL = 0x2
|
||||
_EPOLL_CTL_MOD = 0x3
|
||||
)
|
||||
|
||||
//struct Sigset {
|
||||
// uint64 sig[1];
|
||||
//};
|
||||
//typedef uint64 Sigset;
|
||||
|
||||
type timespec struct {
|
||||
tv_sec int64
|
||||
tv_nsec int64
|
||||
}
|
||||
|
||||
func (ts *timespec) set_sec(x int64) {
|
||||
ts.tv_sec = x
|
||||
}
|
||||
|
||||
func (ts *timespec) set_nsec(x int32) {
|
||||
ts.tv_nsec = int64(x)
|
||||
}
|
||||
|
||||
type timeval struct {
|
||||
tv_sec int64
|
||||
tv_usec int64
|
||||
}
|
||||
|
||||
func (tv *timeval) set_usec(x int32) {
|
||||
tv.tv_usec = int64(x)
|
||||
}
|
||||
|
||||
type sigactiont struct {
|
||||
sa_handler uintptr
|
||||
sa_flags uint64
|
||||
sa_restorer uintptr
|
||||
sa_mask uint64
|
||||
}
|
||||
|
||||
type siginfo struct {
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
// below here is a union; si_addr is the only field we use
|
||||
si_addr uint64
|
||||
}
|
||||
|
||||
type itimerval struct {
|
||||
it_interval timeval
|
||||
it_value timeval
|
||||
}
|
||||
|
||||
type epollevent struct {
|
||||
events uint32
|
||||
pad_cgo_0 [4]byte
|
||||
data [8]byte // unaligned uintptr
|
||||
}
|
||||
|
||||
// created by cgo -cdefs and then converted to Go
|
||||
// cgo -cdefs defs_linux.go defs3_linux.go
|
||||
|
||||
const (
|
||||
_O_RDONLY = 0x0
|
||||
_O_CLOEXEC = 0x80000
|
||||
_SA_RESTORER = 0
|
||||
)
|
||||
|
||||
type ptregs struct {
|
||||
gpr [32]uint64
|
||||
nip uint64
|
||||
msr uint64
|
||||
orig_gpr3 uint64
|
||||
ctr uint64
|
||||
link uint64
|
||||
xer uint64
|
||||
ccr uint64
|
||||
softe uint64
|
||||
trap uint64
|
||||
dar uint64
|
||||
dsisr uint64
|
||||
result uint64
|
||||
}
|
||||
|
||||
type vreg struct {
|
||||
u [4]uint32
|
||||
}
|
||||
|
||||
type sigaltstackt struct {
|
||||
ss_sp *byte
|
||||
ss_flags int32
|
||||
pad_cgo_0 [4]byte
|
||||
ss_size uintptr
|
||||
}
|
||||
|
||||
type sigcontext struct {
|
||||
_unused [4]uint64
|
||||
signal int32
|
||||
_pad0 int32
|
||||
handler uint64
|
||||
oldmask uint64
|
||||
regs *ptregs
|
||||
gp_regs [48]uint64
|
||||
fp_regs [33]float64
|
||||
v_regs *vreg
|
||||
vmx_reserve [101]int64
|
||||
}
|
||||
|
||||
type ucontext struct {
|
||||
uc_flags uint64
|
||||
uc_link *ucontext
|
||||
uc_stack sigaltstackt
|
||||
uc_sigmask uint64
|
||||
__unused [15]uint64
|
||||
uc_mcontext sigcontext
|
||||
}
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
// Created by cgo -cdefs - DO NOT EDIT
|
||||
// cgo -cdefs defs_linux.go defs3_linux.go
|
||||
|
||||
|
||||
enum {
|
||||
EINTR = 0x4,
|
||||
EAGAIN = 0xb,
|
||||
ENOMEM = 0xc,
|
||||
|
||||
PROT_NONE = 0x0,
|
||||
PROT_READ = 0x1,
|
||||
PROT_WRITE = 0x2,
|
||||
PROT_EXEC = 0x4,
|
||||
|
||||
MAP_ANON = 0x20,
|
||||
MAP_PRIVATE = 0x2,
|
||||
MAP_FIXED = 0x10,
|
||||
|
||||
MADV_DONTNEED = 0x4,
|
||||
|
||||
SA_RESTART = 0x10000000,
|
||||
SA_ONSTACK = 0x8000000,
|
||||
SA_SIGINFO = 0x4,
|
||||
|
||||
SIGHUP = 0x1,
|
||||
SIGINT = 0x2,
|
||||
SIGQUIT = 0x3,
|
||||
SIGILL = 0x4,
|
||||
SIGTRAP = 0x5,
|
||||
SIGABRT = 0x6,
|
||||
SIGBUS = 0x7,
|
||||
SIGFPE = 0x8,
|
||||
SIGKILL = 0x9,
|
||||
SIGUSR1 = 0xa,
|
||||
SIGSEGV = 0xb,
|
||||
SIGUSR2 = 0xc,
|
||||
SIGPIPE = 0xd,
|
||||
SIGALRM = 0xe,
|
||||
SIGSTKFLT = 0x10,
|
||||
SIGCHLD = 0x11,
|
||||
SIGCONT = 0x12,
|
||||
SIGSTOP = 0x13,
|
||||
SIGTSTP = 0x14,
|
||||
SIGTTIN = 0x15,
|
||||
SIGTTOU = 0x16,
|
||||
SIGURG = 0x17,
|
||||
SIGXCPU = 0x18,
|
||||
SIGXFSZ = 0x19,
|
||||
SIGVTALRM = 0x1a,
|
||||
SIGPROF = 0x1b,
|
||||
SIGWINCH = 0x1c,
|
||||
SIGIO = 0x1d,
|
||||
SIGPWR = 0x1e,
|
||||
SIGSYS = 0x1f,
|
||||
|
||||
FPE_INTDIV = 0x1,
|
||||
FPE_INTOVF = 0x2,
|
||||
FPE_FLTDIV = 0x3,
|
||||
FPE_FLTOVF = 0x4,
|
||||
FPE_FLTUND = 0x5,
|
||||
FPE_FLTRES = 0x6,
|
||||
FPE_FLTINV = 0x7,
|
||||
FPE_FLTSUB = 0x8,
|
||||
|
||||
BUS_ADRALN = 0x1,
|
||||
BUS_ADRERR = 0x2,
|
||||
BUS_OBJERR = 0x3,
|
||||
|
||||
SEGV_MAPERR = 0x1,
|
||||
SEGV_ACCERR = 0x2,
|
||||
|
||||
ITIMER_REAL = 0x0,
|
||||
ITIMER_VIRTUAL = 0x1,
|
||||
ITIMER_PROF = 0x2,
|
||||
|
||||
EPOLLIN = 0x1,
|
||||
EPOLLOUT = 0x4,
|
||||
EPOLLERR = 0x8,
|
||||
EPOLLHUP = 0x10,
|
||||
EPOLLRDHUP = 0x2000,
|
||||
EPOLLET = -0x80000000,
|
||||
EPOLL_CLOEXEC = 0x80000,
|
||||
EPOLL_CTL_ADD = 0x1,
|
||||
EPOLL_CTL_DEL = 0x2,
|
||||
EPOLL_CTL_MOD = 0x3,
|
||||
};
|
||||
|
||||
typedef struct Sigset Sigset;
|
||||
typedef struct Timespec Timespec;
|
||||
typedef struct Timeval Timeval;
|
||||
typedef struct SigactionT SigactionT;
|
||||
typedef struct Siginfo Siginfo;
|
||||
typedef struct Itimerval Itimerval;
|
||||
typedef struct EpollEvent EpollEvent;
|
||||
|
||||
#pragma pack on
|
||||
|
||||
//struct Sigset {
|
||||
// uint64 sig[1];
|
||||
//};
|
||||
//typedef uint64 Sigset;
|
||||
|
||||
struct Timespec {
|
||||
int64 tv_sec;
|
||||
int64 tv_nsec;
|
||||
};
|
||||
struct Timeval {
|
||||
int64 tv_sec;
|
||||
int64 tv_usec;
|
||||
};
|
||||
struct SigactionT {
|
||||
void *sa_handler;
|
||||
uint64 sa_flags;
|
||||
void *sa_restorer;
|
||||
uint64 sa_mask;
|
||||
};
|
||||
struct Siginfo {
|
||||
int32 si_signo;
|
||||
int32 si_errno;
|
||||
int32 si_code;
|
||||
byte Pad_cgo_0[4];
|
||||
byte _sifields[112];
|
||||
};
|
||||
struct Itimerval {
|
||||
Timeval it_interval;
|
||||
Timeval it_value;
|
||||
};
|
||||
struct EpollEvent {
|
||||
uint32 events;
|
||||
byte Pad_cgo_0[4];
|
||||
byte data[8]; // unaligned uintptr
|
||||
};
|
||||
|
||||
|
||||
#pragma pack off
|
||||
// Created by cgo -cdefs - DO NOT EDIT
|
||||
// cgo -cdefs defs_linux.go defs3_linux.go
|
||||
|
||||
|
||||
enum {
|
||||
O_RDONLY = 0x0,
|
||||
O_CLOEXEC = 0x80000,
|
||||
SA_RESTORER = 0,
|
||||
};
|
||||
|
||||
typedef struct Ptregs Ptregs;
|
||||
typedef struct Vreg Vreg;
|
||||
typedef struct SigaltstackT SigaltstackT;
|
||||
typedef struct Sigcontext Sigcontext;
|
||||
typedef struct Ucontext Ucontext;
|
||||
|
||||
#pragma pack on
|
||||
|
||||
struct Ptregs {
|
||||
uint64 gpr[32];
|
||||
uint64 nip;
|
||||
uint64 msr;
|
||||
uint64 orig_gpr3;
|
||||
uint64 ctr;
|
||||
uint64 link;
|
||||
uint64 xer;
|
||||
uint64 ccr;
|
||||
uint64 softe;
|
||||
uint64 trap;
|
||||
uint64 dar;
|
||||
uint64 dsisr;
|
||||
uint64 result;
|
||||
};
|
||||
typedef uint64 Gregset[48];
|
||||
typedef float64 FPregset[33];
|
||||
struct Vreg {
|
||||
uint32 u[4];
|
||||
};
|
||||
|
||||
struct SigaltstackT {
|
||||
byte *ss_sp;
|
||||
int32 ss_flags;
|
||||
byte Pad_cgo_0[4];
|
||||
uint64 ss_size;
|
||||
};
|
||||
|
||||
struct Sigcontext {
|
||||
uint64 _unused[4];
|
||||
int32 signal;
|
||||
int32 _pad0;
|
||||
uint64 handler;
|
||||
uint64 oldmask;
|
||||
Ptregs *regs;
|
||||
uint64 gp_regs[48];
|
||||
float64 fp_regs[33];
|
||||
Vreg *v_regs;
|
||||
int64 vmx_reserve[101];
|
||||
};
|
||||
struct Ucontext {
|
||||
uint64 uc_flags;
|
||||
Ucontext *uc_link;
|
||||
SigaltstackT uc_stack;
|
||||
uint64 uc_sigmask;
|
||||
uint64 __unused[15];
|
||||
Sigcontext uc_mcontext;
|
||||
};
|
||||
|
||||
|
||||
#pragma pack off
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
// created by cgo -cdefs and then converted to Go
|
||||
// cgo -cdefs defs_linux.go defs3_linux.go
|
||||
|
||||
package runtime
|
||||
|
||||
const (
|
||||
_EINTR = 0x4
|
||||
_EAGAIN = 0xb
|
||||
_ENOMEM = 0xc
|
||||
|
||||
_PROT_NONE = 0x0
|
||||
_PROT_READ = 0x1
|
||||
_PROT_WRITE = 0x2
|
||||
_PROT_EXEC = 0x4
|
||||
|
||||
_MAP_ANON = 0x20
|
||||
_MAP_PRIVATE = 0x2
|
||||
_MAP_FIXED = 0x10
|
||||
|
||||
_MADV_DONTNEED = 0x4
|
||||
|
||||
_SA_RESTART = 0x10000000
|
||||
_SA_ONSTACK = 0x8000000
|
||||
_SA_SIGINFO = 0x4
|
||||
|
||||
_SIGHUP = 0x1
|
||||
_SIGINT = 0x2
|
||||
_SIGQUIT = 0x3
|
||||
_SIGILL = 0x4
|
||||
_SIGTRAP = 0x5
|
||||
_SIGABRT = 0x6
|
||||
_SIGBUS = 0x7
|
||||
_SIGFPE = 0x8
|
||||
_SIGKILL = 0x9
|
||||
_SIGUSR1 = 0xa
|
||||
_SIGSEGV = 0xb
|
||||
_SIGUSR2 = 0xc
|
||||
_SIGPIPE = 0xd
|
||||
_SIGALRM = 0xe
|
||||
_SIGSTKFLT = 0x10
|
||||
_SIGCHLD = 0x11
|
||||
_SIGCONT = 0x12
|
||||
_SIGSTOP = 0x13
|
||||
_SIGTSTP = 0x14
|
||||
_SIGTTIN = 0x15
|
||||
_SIGTTOU = 0x16
|
||||
_SIGURG = 0x17
|
||||
_SIGXCPU = 0x18
|
||||
_SIGXFSZ = 0x19
|
||||
_SIGVTALRM = 0x1a
|
||||
_SIGPROF = 0x1b
|
||||
_SIGWINCH = 0x1c
|
||||
_SIGIO = 0x1d
|
||||
_SIGPWR = 0x1e
|
||||
_SIGSYS = 0x1f
|
||||
|
||||
_FPE_INTDIV = 0x1
|
||||
_FPE_INTOVF = 0x2
|
||||
_FPE_FLTDIV = 0x3
|
||||
_FPE_FLTOVF = 0x4
|
||||
_FPE_FLTUND = 0x5
|
||||
_FPE_FLTRES = 0x6
|
||||
_FPE_FLTINV = 0x7
|
||||
_FPE_FLTSUB = 0x8
|
||||
|
||||
_BUS_ADRALN = 0x1
|
||||
_BUS_ADRERR = 0x2
|
||||
_BUS_OBJERR = 0x3
|
||||
|
||||
_SEGV_MAPERR = 0x1
|
||||
_SEGV_ACCERR = 0x2
|
||||
|
||||
_ITIMER_REAL = 0x0
|
||||
_ITIMER_VIRTUAL = 0x1
|
||||
_ITIMER_PROF = 0x2
|
||||
|
||||
_EPOLLIN = 0x1
|
||||
_EPOLLOUT = 0x4
|
||||
_EPOLLERR = 0x8
|
||||
_EPOLLHUP = 0x10
|
||||
_EPOLLRDHUP = 0x2000
|
||||
_EPOLLET = 0x80000000
|
||||
_EPOLL_CLOEXEC = 0x80000
|
||||
_EPOLL_CTL_ADD = 0x1
|
||||
_EPOLL_CTL_DEL = 0x2
|
||||
_EPOLL_CTL_MOD = 0x3
|
||||
)
|
||||
|
||||
//struct Sigset {
|
||||
// uint64 sig[1];
|
||||
//};
|
||||
//typedef uint64 Sigset;
|
||||
|
||||
type timespec struct {
|
||||
tv_sec int64
|
||||
tv_nsec int64
|
||||
}
|
||||
|
||||
func (ts *timespec) set_sec(x int64) {
|
||||
ts.tv_sec = x
|
||||
}
|
||||
|
||||
func (ts *timespec) set_nsec(x int32) {
|
||||
ts.tv_nsec = int64(x)
|
||||
}
|
||||
|
||||
type timeval struct {
|
||||
tv_sec int64
|
||||
tv_usec int64
|
||||
}
|
||||
|
||||
func (tv *timeval) set_usec(x int32) {
|
||||
tv.tv_usec = int64(x)
|
||||
}
|
||||
|
||||
type sigactiont struct {
|
||||
sa_handler uintptr
|
||||
sa_flags uint64
|
||||
sa_restorer uintptr
|
||||
sa_mask uint64
|
||||
}
|
||||
|
||||
type siginfo struct {
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
// below here is a union; si_addr is the only field we use
|
||||
si_addr uint64
|
||||
}
|
||||
|
||||
type itimerval struct {
|
||||
it_interval timeval
|
||||
it_value timeval
|
||||
}
|
||||
|
||||
type epollevent struct {
|
||||
events uint32
|
||||
pad_cgo_0 [4]byte
|
||||
data [8]byte // unaligned uintptr
|
||||
}
|
||||
|
||||
// created by cgo -cdefs and then converted to Go
|
||||
// cgo -cdefs defs_linux.go defs3_linux.go
|
||||
|
||||
const (
|
||||
_O_RDONLY = 0x0
|
||||
_O_CLOEXEC = 0x80000
|
||||
_SA_RESTORER = 0
|
||||
)
|
||||
|
||||
type ptregs struct {
|
||||
gpr [32]uint64
|
||||
nip uint64
|
||||
msr uint64
|
||||
orig_gpr3 uint64
|
||||
ctr uint64
|
||||
link uint64
|
||||
xer uint64
|
||||
ccr uint64
|
||||
softe uint64
|
||||
trap uint64
|
||||
dar uint64
|
||||
dsisr uint64
|
||||
result uint64
|
||||
}
|
||||
|
||||
type vreg struct {
|
||||
u [4]uint32
|
||||
}
|
||||
|
||||
type sigaltstackt struct {
|
||||
ss_sp *byte
|
||||
ss_flags int32
|
||||
pad_cgo_0 [4]byte
|
||||
ss_size uintptr
|
||||
}
|
||||
|
||||
type sigcontext struct {
|
||||
_unused [4]uint64
|
||||
signal int32
|
||||
_pad0 int32
|
||||
handler uint64
|
||||
oldmask uint64
|
||||
regs *ptregs
|
||||
gp_regs [48]uint64
|
||||
fp_regs [33]float64
|
||||
v_regs *vreg
|
||||
vmx_reserve [101]int64
|
||||
}
|
||||
|
||||
type ucontext struct {
|
||||
uc_flags uint64
|
||||
uc_link *ucontext
|
||||
uc_stack sigaltstackt
|
||||
uc_sigmask uint64
|
||||
__unused [15]uint64
|
||||
uc_mcontext sigcontext
|
||||
}
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
// Created by cgo -cdefs - DO NOT EDIT
|
||||
// cgo -cdefs defs_linux.go defs3_linux.go
|
||||
|
||||
|
||||
enum {
|
||||
EINTR = 0x4,
|
||||
EAGAIN = 0xb,
|
||||
ENOMEM = 0xc,
|
||||
|
||||
PROT_NONE = 0x0,
|
||||
PROT_READ = 0x1,
|
||||
PROT_WRITE = 0x2,
|
||||
PROT_EXEC = 0x4,
|
||||
|
||||
MAP_ANON = 0x20,
|
||||
MAP_PRIVATE = 0x2,
|
||||
MAP_FIXED = 0x10,
|
||||
|
||||
MADV_DONTNEED = 0x4,
|
||||
|
||||
SA_RESTART = 0x10000000,
|
||||
SA_ONSTACK = 0x8000000,
|
||||
SA_SIGINFO = 0x4,
|
||||
|
||||
SIGHUP = 0x1,
|
||||
SIGINT = 0x2,
|
||||
SIGQUIT = 0x3,
|
||||
SIGILL = 0x4,
|
||||
SIGTRAP = 0x5,
|
||||
SIGABRT = 0x6,
|
||||
SIGBUS = 0x7,
|
||||
SIGFPE = 0x8,
|
||||
SIGKILL = 0x9,
|
||||
SIGUSR1 = 0xa,
|
||||
SIGSEGV = 0xb,
|
||||
SIGUSR2 = 0xc,
|
||||
SIGPIPE = 0xd,
|
||||
SIGALRM = 0xe,
|
||||
SIGSTKFLT = 0x10,
|
||||
SIGCHLD = 0x11,
|
||||
SIGCONT = 0x12,
|
||||
SIGSTOP = 0x13,
|
||||
SIGTSTP = 0x14,
|
||||
SIGTTIN = 0x15,
|
||||
SIGTTOU = 0x16,
|
||||
SIGURG = 0x17,
|
||||
SIGXCPU = 0x18,
|
||||
SIGXFSZ = 0x19,
|
||||
SIGVTALRM = 0x1a,
|
||||
SIGPROF = 0x1b,
|
||||
SIGWINCH = 0x1c,
|
||||
SIGIO = 0x1d,
|
||||
SIGPWR = 0x1e,
|
||||
SIGSYS = 0x1f,
|
||||
|
||||
FPE_INTDIV = 0x1,
|
||||
FPE_INTOVF = 0x2,
|
||||
FPE_FLTDIV = 0x3,
|
||||
FPE_FLTOVF = 0x4,
|
||||
FPE_FLTUND = 0x5,
|
||||
FPE_FLTRES = 0x6,
|
||||
FPE_FLTINV = 0x7,
|
||||
FPE_FLTSUB = 0x8,
|
||||
|
||||
BUS_ADRALN = 0x1,
|
||||
BUS_ADRERR = 0x2,
|
||||
BUS_OBJERR = 0x3,
|
||||
|
||||
SEGV_MAPERR = 0x1,
|
||||
SEGV_ACCERR = 0x2,
|
||||
|
||||
ITIMER_REAL = 0x0,
|
||||
ITIMER_VIRTUAL = 0x1,
|
||||
ITIMER_PROF = 0x2,
|
||||
|
||||
EPOLLIN = 0x1,
|
||||
EPOLLOUT = 0x4,
|
||||
EPOLLERR = 0x8,
|
||||
EPOLLHUP = 0x10,
|
||||
EPOLLRDHUP = 0x2000,
|
||||
EPOLLET = -0x80000000,
|
||||
EPOLL_CLOEXEC = 0x80000,
|
||||
EPOLL_CTL_ADD = 0x1,
|
||||
EPOLL_CTL_DEL = 0x2,
|
||||
EPOLL_CTL_MOD = 0x3,
|
||||
};
|
||||
|
||||
typedef struct Sigset Sigset;
|
||||
typedef struct Timespec Timespec;
|
||||
typedef struct Timeval Timeval;
|
||||
typedef struct SigactionT SigactionT;
|
||||
typedef struct Siginfo Siginfo;
|
||||
typedef struct Itimerval Itimerval;
|
||||
typedef struct EpollEvent EpollEvent;
|
||||
|
||||
#pragma pack on
|
||||
|
||||
//struct Sigset {
|
||||
// uint64 sig[1];
|
||||
//};
|
||||
//typedef uint64 Sigset;
|
||||
|
||||
struct Timespec {
|
||||
int64 tv_sec;
|
||||
int64 tv_nsec;
|
||||
};
|
||||
struct Timeval {
|
||||
int64 tv_sec;
|
||||
int64 tv_usec;
|
||||
};
|
||||
struct SigactionT {
|
||||
void *sa_handler;
|
||||
uint64 sa_flags;
|
||||
void *sa_restorer;
|
||||
uint64 sa_mask;
|
||||
};
|
||||
struct Siginfo {
|
||||
int32 si_signo;
|
||||
int32 si_errno;
|
||||
int32 si_code;
|
||||
byte Pad_cgo_0[4];
|
||||
byte _sifields[112];
|
||||
};
|
||||
struct Itimerval {
|
||||
Timeval it_interval;
|
||||
Timeval it_value;
|
||||
};
|
||||
struct EpollEvent {
|
||||
uint32 events;
|
||||
byte Pad_cgo_0[4];
|
||||
byte data[8]; // unaligned uintptr
|
||||
};
|
||||
|
||||
|
||||
#pragma pack off
|
||||
// Created by cgo -cdefs - DO NOT EDIT
|
||||
// cgo -cdefs defs_linux.go defs3_linux.go
|
||||
|
||||
|
||||
enum {
|
||||
O_RDONLY = 0x0,
|
||||
O_CLOEXEC = 0x80000,
|
||||
SA_RESTORER = 0,
|
||||
};
|
||||
|
||||
typedef struct Ptregs Ptregs;
|
||||
typedef struct Vreg Vreg;
|
||||
typedef struct SigaltstackT SigaltstackT;
|
||||
typedef struct Sigcontext Sigcontext;
|
||||
typedef struct Ucontext Ucontext;
|
||||
|
||||
#pragma pack on
|
||||
|
||||
struct Ptregs {
|
||||
uint64 gpr[32];
|
||||
uint64 nip;
|
||||
uint64 msr;
|
||||
uint64 orig_gpr3;
|
||||
uint64 ctr;
|
||||
uint64 link;
|
||||
uint64 xer;
|
||||
uint64 ccr;
|
||||
uint64 softe;
|
||||
uint64 trap;
|
||||
uint64 dar;
|
||||
uint64 dsisr;
|
||||
uint64 result;
|
||||
};
|
||||
typedef uint64 Gregset[48];
|
||||
typedef float64 FPregset[33];
|
||||
struct Vreg {
|
||||
uint32 u[4];
|
||||
};
|
||||
|
||||
struct SigaltstackT {
|
||||
byte *ss_sp;
|
||||
int32 ss_flags;
|
||||
byte Pad_cgo_0[4];
|
||||
uint64 ss_size;
|
||||
};
|
||||
|
||||
struct Sigcontext {
|
||||
uint64 _unused[4];
|
||||
int32 signal;
|
||||
int32 _pad0;
|
||||
uint64 handler;
|
||||
uint64 oldmask;
|
||||
Ptregs *regs;
|
||||
uint64 gp_regs[48];
|
||||
float64 fp_regs[33];
|
||||
Vreg *v_regs;
|
||||
int64 vmx_reserve[101];
|
||||
};
|
||||
struct Ucontext {
|
||||
uint64 uc_flags;
|
||||
Ucontext *uc_link;
|
||||
SigaltstackT uc_stack;
|
||||
uint64 uc_sigmask;
|
||||
uint64 __unused[15];
|
||||
Sigcontext uc_mcontext;
|
||||
};
|
||||
|
||||
|
||||
#pragma pack off
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package runtime
|
||||
|
||||
const _PAGESIZE = 0x1000
|
||||
|
||||
type ureg struct {
|
||||
di uint32 /* general registers */
|
||||
si uint32 /* ... */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package runtime
|
||||
|
||||
const _PAGESIZE = 0x1000
|
||||
|
||||
type ureg struct {
|
||||
ax uint64
|
||||
bx uint64
|
||||
|
|
|
|||
|
|
@ -54,3 +54,6 @@ func gogetenv(key string) string {
|
|||
sp.len = int(r)
|
||||
return s
|
||||
}
|
||||
|
||||
var _cgo_setenv unsafe.Pointer // pointer to C function
|
||||
var _cgo_unsetenv unsafe.Pointer // pointer to C function
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var gooses, goarches []string
|
||||
|
||||
func main() {
|
||||
data, err := ioutil.ReadFile("../go/build/syslist.go")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
const (
|
||||
goosPrefix = `const goosList = `
|
||||
goarchPrefix = `const goarchList = `
|
||||
)
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.HasPrefix(line, goosPrefix) {
|
||||
text, err := strconv.Unquote(strings.TrimPrefix(line, goosPrefix))
|
||||
if err != nil {
|
||||
log.Fatalf("parsing goosList %#q: %v", strings.TrimPrefix(line, goosPrefix), err)
|
||||
}
|
||||
gooses = strings.Fields(text)
|
||||
}
|
||||
if strings.HasPrefix(line, goarchPrefix) {
|
||||
text, err := strconv.Unquote(strings.TrimPrefix(line, goarchPrefix))
|
||||
if err != nil {
|
||||
log.Fatal("parsing goarchList: %v", err)
|
||||
}
|
||||
goarches = strings.Fields(text)
|
||||
}
|
||||
}
|
||||
|
||||
for _, target := range gooses {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
|
||||
if target == "linux" {
|
||||
fmt.Fprintf(&buf, "// +build !android\n\n") // must explicitly exclude android for linux
|
||||
}
|
||||
fmt.Fprintf(&buf, "package runtime\n\n")
|
||||
fmt.Fprintf(&buf, "const theGoos = `%s`\n\n", target)
|
||||
for _, goos := range gooses {
|
||||
value := 0
|
||||
if goos == target {
|
||||
value = 1
|
||||
}
|
||||
fmt.Fprintf(&buf, "const goos_%s = %d\n", goos, value)
|
||||
}
|
||||
err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, target := range goarches {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
|
||||
fmt.Fprintf(&buf, "package runtime\n\n")
|
||||
fmt.Fprintf(&buf, "const theGoarch = `%s`\n\n", target)
|
||||
for _, goarch := range goarches {
|
||||
value := 0
|
||||
if goarch == target {
|
||||
value = 1
|
||||
}
|
||||
fmt.Fprintf(&buf, "const goarch_%s = %d\n", goarch, value)
|
||||
}
|
||||
err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
// finalizers, etc.) to a file.
|
||||
|
||||
// The format of the dumped file is described at
|
||||
// http://code.google.com/p/go-wiki/wiki/heapdump14
|
||||
// http://golang.org/s/go14heapdump.
|
||||
|
||||
package runtime
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ import "unsafe"
|
|||
func lfstackpush(head *uint64, node *lfnode) {
|
||||
node.pushcnt++
|
||||
new := lfstackPack(node, node.pushcnt)
|
||||
if node1, _ := lfstackUnpack(new); node1 != node {
|
||||
println("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
|
||||
gothrow("lfstackpush")
|
||||
}
|
||||
for {
|
||||
old := atomicload64(head)
|
||||
node.next = old
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build 386 arm
|
||||
// +build 386 arm nacl
|
||||
|
||||
package runtime
|
||||
|
||||
|
|
|
|||
|
|
@ -9,18 +9,24 @@ package runtime
|
|||
|
||||
import "unsafe"
|
||||
|
||||
// On Power64, Linux limits the user address space to 43 bits.
|
||||
// (https://www.kernel.org/doc/ols/2001/ppc64.pdf)
|
||||
// In addition to the 21 bits taken from the top, we can take 3 from the
|
||||
// bottom, because node must be pointer-aligned, giving a total of 24 bits
|
||||
// On Power64, Linux limits the user address space to 46 bits (see
|
||||
// TASK_SIZE_USER64 in the Linux kernel). This has grown over time,
|
||||
// so here we allow 48 bit addresses.
|
||||
//
|
||||
// In addition to the 16 bits taken from the top, we can take 3 from the
|
||||
// bottom, because node must be pointer-aligned, giving a total of 19 bits
|
||||
// of count.
|
||||
const (
|
||||
addrBits = 48
|
||||
cntBits = 64 - addrBits + 3
|
||||
)
|
||||
|
||||
func lfstackPack(node *lfnode, cnt uintptr) uint64 {
|
||||
return uint64(uintptr(unsafe.Pointer(node)))<<21 | uint64(cnt&(1<<24-1))
|
||||
return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1))
|
||||
}
|
||||
|
||||
func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
|
||||
node = (*lfnode)(unsafe.Pointer(uintptr(val >> 24 << 3)))
|
||||
cnt = uintptr(val & (1<<24 - 1))
|
||||
node = (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3)))
|
||||
cnt = uintptr(val & (1<<cntBits - 1))
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -546,6 +546,8 @@ func GC() {
|
|||
|
||||
// linker-provided
|
||||
var noptrdata struct{}
|
||||
var enoptrdata struct{}
|
||||
var noptrbss struct{}
|
||||
var enoptrbss struct{}
|
||||
|
||||
// SetFinalizer sets the finalizer associated with x to f.
|
||||
|
|
@ -622,8 +624,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
|
|||
// func main() {
|
||||
// runtime.SetFinalizer(Foo, nil)
|
||||
// }
|
||||
// The segments are, in order: text, rodata, noptrdata, data, bss, noptrbss.
|
||||
if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
|
||||
// The relevant segments are: noptrdata, data, bss, noptrbss.
|
||||
// We cannot assume they are in any order or even contiguous,
|
||||
// due to external linking.
|
||||
if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) ||
|
||||
uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) ||
|
||||
uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) ||
|
||||
uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
|
||||
return
|
||||
}
|
||||
gothrow("runtime.SetFinalizer: pointer not in allocated block")
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ const (
|
|||
// See http://golang.org/issue/5402 and http://golang.org/issue/5236.
|
||||
// On other 64-bit platforms, we limit the arena to 128GB, or 37 bits.
|
||||
// On 32-bit, we don't bother limiting anything, so we use the full 32-bit address.
|
||||
_MHeapMap_TotalBits = (_64bit*_Windows)*35 + (_64bit*(1-_Windows))*37 + (1-_64bit)*32
|
||||
_MHeapMap_TotalBits = (_64bit*goos_windows)*35 + (_64bit*(1-goos_windows))*37 + (1-_64bit)*32
|
||||
_MHeapMap_Bits = _MHeapMap_TotalBits - _PageShift
|
||||
|
||||
_MaxMem = uintptr(1<<_MHeapMap_TotalBits - 1)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue