Commit b8540fc2 authored by Russ Cox's avatar Russ Cox

[dev.garbage] all: merge dev.cc (493ad916c3b1) into dev.garbage

TBR=austin
CC=golang-codereviews
https://golang.org/cl/179290043
parents 273507aa a236804c
...@@ -136,3 +136,4 @@ f8b50ad4cac4d4c4ecf48324b4f512f65e82cc1c go1.3beta1 ...@@ -136,3 +136,4 @@ f8b50ad4cac4d4c4ecf48324b4f512f65e82cc1c go1.3beta1
f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 go1.3.3 f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 go1.3.3
f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 release f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 release
1fdfd7dfaedb1b7702141617e621ab7328a236a1 go1.4beta1 1fdfd7dfaedb1b7702141617e621ab7328a236a1 go1.4beta1
bffdd0cae380ce1ccf3e98ed6b6cd53fece7ba72 go1.4rc1
...@@ -145,7 +145,7 @@ Egon Elbre <egonelbre@gmail.com> ...@@ -145,7 +145,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com> Ehren Kret <ehren.kret@gmail.com>
Eivind Uggedal <eivind@uggedal.com> Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.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> Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com> Eric Clark <zerohp@gmail.com>
Eric Milliken <emilliken@gmail.com> Eric Milliken <emilliken@gmail.com>
......
...@@ -214,7 +214,7 @@ Egon Elbre <egonelbre@gmail.com> ...@@ -214,7 +214,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com> Ehren Kret <ehren.kret@gmail.com>
Eivind Uggedal <eivind@uggedal.com> Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.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> Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com> Eric Clark <zerohp@gmail.com>
Eric Milliken <emilliken@gmail.com> Eric Milliken <emilliken@gmail.com>
...@@ -452,6 +452,7 @@ Nicholas Katsaros <nick@nickkatsaros.com> ...@@ -452,6 +452,7 @@ Nicholas Katsaros <nick@nickkatsaros.com>
Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com> Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
Nicholas Sullivan <nicholas.sullivan@gmail.com> Nicholas Sullivan <nicholas.sullivan@gmail.com>
Nicholas Waples <nwaples@gmail.com> Nicholas Waples <nwaples@gmail.com>
Nick Cooper <nmvc@google.com>
Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com> Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
Nicolas Kaiser <nikai@nikai.net> Nicolas Kaiser <nikai@nikai.net>
Nicolas Owens <mischief@offblast.org> Nicolas Owens <mischief@offblast.org>
......
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
<h2 id="introduction">Introduction to Go 1.4</h2> <h2 id="introduction">Introduction to Go 1.4</h2>
<p> <p>
The latest Go release, version 1.4, arrives as scheduled six months after 1.3 The latest Go release, version 1.4, arrives as scheduled six months after 1.3.
and contains only one tiny language change, It contains only one tiny language change,
a possibly breaking change to the compiler, in the form of a backwards-compatible simple variant of <code>for</code>-<code>range</code> loop,
a backwards-compatible simple form 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 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 and preparing the ground for a fully concurrent collector to be rolled out in the
next few releases. next few releases.
...@@ -20,7 +20,7 @@ this release therefore eliminates the notorious "hot stack split" problem. ...@@ -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 There are some new tools available including support in the <code>go</code> command
for build-time source code generation. for build-time source code generation.
The release also adds support for ARM processors on Android and Native Client (NaCl) 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 As always, Go 1.4 keeps the <a href="/doc/go1compat.html">promise
of compatibility</a>, of compatibility</a>,
and almost everything and almost everything
...@@ -637,12 +637,29 @@ See the relevant package documentation for more information about each change. ...@@ -637,12 +637,29 @@ See the relevant package documentation for more information about each change.
<ul> <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> <li>
The <a href="/pkg/compress/flate/"><code>compress/flate</code></a>, The <a href="/pkg/compress/flate/"><code>compress/flate</code></a>,
<a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>, <a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>,
and <a href="/pkg/compress/zlib/"><code>compress/zlib</code></a> and <a href="/pkg/compress/zlib/"><code>compress/zlib</code></a>
packages now support a <code>Reset</code> method packages now support a <code>Reset</code> method
for the decompressors, allowing them to reuse buffers and improve performance. 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>
<li> <li>
...@@ -665,6 +682,16 @@ to help clients detect fallback attacks. ...@@ -665,6 +682,16 @@ to help clients detect fallback attacks.
those attacks.) those attacks.)
</li> </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> <li>
In the <a href="/pkg/encoding/asn1/"><code>encoding/asn1</code></a> package, 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. 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. ...@@ -685,6 +712,11 @@ in some cases, especially involving arrays, it can be faster.
There is no functional change. There is no functional change.
</li> </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> <li>
In the <a href="/pkg/fmt/"><code>fmt</code></a> package, 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 formatting of pointers to maps has changed to be consistent with that of pointers
...@@ -693,6 +725,28 @@ For instance, <code>&amp;map[string]int{"one":</code> <code>1}</code> now prints ...@@ -693,6 +725,28 @@ For instance, <code>&amp;map[string]int{"one":</code> <code>1}</code> now prints
<code>&amp;map[one:</code> <code>1]</code> rather than as a hexadecimal pointer value. <code>&amp;map[one:</code> <code>1]</code> rather than as a hexadecimal pointer value.
</li> </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> <li>
The <a href="/pkg/net/http/"><code>net/http</code></a> package's The <a href="/pkg/net/http/"><code>net/http</code></a> package's
<a href="/pkg/net/http/#Request"><code>Request</code></a> type <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 ...@@ -721,6 +775,7 @@ The <a href="/pkg/os/"><code>os</code></a> package
now implements symbolic links on the Windows operating system now implements symbolic links on the Windows operating system
through the <a href="/pkg/os/#Symlink"><code>Symlink</code></a> function. through the <a href="/pkg/os/#Symlink"><code>Symlink</code></a> function.
Other operating systems already have this functionality. Other operating systems already have this functionality.
There is also a new <a href="/pkg/os/#Unsetenv"><code>Unsetenv</code></a> function.
</li> </li>
<li> <li>
......
<!--{ <!--{
"Title": "The Go Programming Language Specification", "Title": "The Go Programming Language Specification",
"Subtitle": "Version of October 27, 2014", "Subtitle": "Version of November 11, 2014",
"Path": "/ref/spec" "Path": "/ref/spec"
}--> }-->
...@@ -2521,30 +2521,40 @@ The following rules apply to selectors: ...@@ -2521,30 +2521,40 @@ The following rules apply to selectors:
<ol> <ol>
<li> <li>
For a value <code>x</code> of type <code>T</code> or <code>*T</code> 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 <code>x.f</code> denotes the field or method at the shallowest depth
in <code>T</code> where there in <code>T</code> where there
is such an <code>f</code>. is such an <code>f</code>.
If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a> If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a>
with shallowest depth, the selector expression is illegal. with shallowest depth, the selector expression is illegal.
</li> </li>
<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 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 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 <a href="#Method_sets">method set</a> of <code>I</code>, the selector
expression is illegal. expression is illegal.
</li> </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> <li>
In all other cases, <code>x.f</code> is illegal. In all other cases, <code>x.f</code> is illegal.
</li> </li>
<li> <li>
If <code>x</code> is of pointer type and has the value If <code>x</code> is of pointer type and has the value
<code>nil</code> and <code>x.f</code> denotes a struct field, <code>nil</code> and <code>x.f</code> denotes a struct field,
assigning to or evaluating <code>x.f</code> assigning to or evaluating <code>x.f</code>
causes a <a href="#Run_time_panics">run-time panic</a>. causes a <a href="#Run_time_panics">run-time panic</a>.
</li> </li>
<li> <li>
If <code>x</code> is of interface type and has the value If <code>x</code> is of interface type and has the value
<code>nil</code>, <a href="#Calls">calling</a> or <code>nil</code>, <a href="#Calls">calling</a> or
...@@ -2553,18 +2563,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>. ...@@ -2553,18 +2563,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>.
</li> </li>
</ol> </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> <p>
For example, given the declarations: For example, given the declarations:
</p> </p>
...@@ -2574,13 +2572,13 @@ type T0 struct { ...@@ -2574,13 +2572,13 @@ type T0 struct {
x int x int
} }
func (recv *T0) M0() func (*T0) M0()
type T1 struct { type T1 struct {
y int y int
} }
func (recv T1) M1() func (T1) M1()
type T2 struct { type T2 struct {
z int z int
...@@ -2588,9 +2586,13 @@ type T2 struct { ...@@ -2588,9 +2586,13 @@ type T2 struct {
*T0 *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> </pre>
<p> <p>
...@@ -2598,13 +2600,27 @@ one may write: ...@@ -2598,13 +2600,27 @@ one may write:
</p> </p>
<pre> <pre>
t.z // t.z
t.y // t.T1.y
t.x // (*t.TO).x
p.z // (*p).z p.z // (*p).z
p.y // ((*p).T1).y p.y // (*p).T1.y
p.x // (*(*p).T0).x p.x // (*(*p).T0).x
p.M2() // (*p).M2() q.x // (*(*q).T0).x (*q).x is a valid field selector
p.M1() // ((*p).T1).M1()
p.M0() // ((*p).T0).M0() 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> </pre>
......
...@@ -47,7 +47,7 @@ proceeding. If your OS or architecture is not on the list, it's possible that ...@@ -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>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>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>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr> <tr><td>Mac OS X 10.6 or later</td> <td>amd64, 386</td> <td>use the gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</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>&#8224;</sup>. No need for cygwin or msys.</td></tr>
</table> </table>
<p> <p>
......
...@@ -62,7 +62,7 @@ struct Addr ...@@ -62,7 +62,7 @@ struct Addr
short type; short type;
uint8 index; uint8 index;
int8 scale; 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 name; // for 5l, 9l
int8 class; // for 5l, 9l int8 class; // for 5l, 9l
uint8 etype; // for 5g, 6g, 8g uint8 etype; // for 5g, 6g, 8g
...@@ -94,6 +94,7 @@ struct Prog ...@@ -94,6 +94,7 @@ struct Prog
// operands // operands
Addr from; Addr from;
uchar reg; // arm, power64 only (e.g., ADD from, reg, to); 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 // also used for ADATA width on arm, power64
Addr from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to) Addr from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to)
Addr to; Addr to;
...@@ -626,6 +627,11 @@ extern char* anames9[]; ...@@ -626,6 +627,11 @@ extern char* anames9[];
extern char* cnames5[]; extern char* cnames5[];
extern char* cnames9[]; extern char* cnames9[];
extern char* dnames5[];
extern char* dnames6[];
extern char* dnames8[];
extern char* dnames9[];
extern LinkArch link386; extern LinkArch link386;
extern LinkArch linkamd64; extern LinkArch linkamd64;
extern LinkArch linkamd64p32; extern LinkArch linkamd64p32;
...@@ -634,6 +640,7 @@ extern LinkArch linkpower64; ...@@ -634,6 +640,7 @@ extern LinkArch linkpower64;
extern LinkArch linkpower64le; extern LinkArch linkpower64le;
#pragma varargck type "A" int #pragma varargck type "A" int
#pragma varargck type "E" uint
#pragma varargck type "D" Addr* #pragma varargck type "D" Addr*
#pragma varargck type "lD" Addr* #pragma varargck type "lD" Addr*
#pragma varargck type "P" Prog* #pragma varargck type "P" Prog*
......
...@@ -56,8 +56,8 @@ const ( ...@@ -56,8 +56,8 @@ const (
blogPath = "golang.org/x/blog" blogPath = "golang.org/x/blog"
toolPath = "golang.org/x/tools" toolPath = "golang.org/x/tools"
tourPath = "code.google.com/p/go-tour" tourPath = "code.google.com/p/go-tour"
defaultToolTag = "release-branch.go1.3" defaultToolTag = "release-branch.go1.4"
defaultTourTag = "release-branch.go1.3" defaultTourTag = "release-branch.go1.4"
) )
// Import paths for tool commands. // Import paths for tool commands.
......
...@@ -75,12 +75,18 @@ struct Reg ...@@ -75,12 +75,18 @@ struct Reg
{ {
Flow f; Flow f;
Bits set; // variables written by this instruction. Bits set; // regopt variables written by this instruction.
Bits use1; // variables read by prog->from. Bits use1; // regopt variables read by prog->from.
Bits use2; // variables read by prog->to. 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 refbehind;
Bits refahead; Bits refahead;
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
Bits calbehind; Bits calbehind;
Bits calahead; Bits calahead;
Bits regdiff; Bits regdiff;
...@@ -93,6 +99,16 @@ struct Reg ...@@ -93,6 +99,16 @@ struct Reg
#define NRGN 600 #define NRGN 600
/*c2go enum { 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 struct Rgn
{ {
Reg* enter; Reg* enter;
...@@ -144,7 +160,7 @@ void prop(Reg*, Bits, Bits); ...@@ -144,7 +160,7 @@ void prop(Reg*, Bits, Bits);
void synch(Reg*, Bits); void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*); uint32 allreg(uint32, Rgn*);
void paint1(Reg*, int); void paint1(Reg*, int);
uint32 paint2(Reg*, int); uint32 paint2(Reg*, int, int);
void paint3(Reg*, int, uint32, int); void paint3(Reg*, int, uint32, int);
void addreg(Adr*, int); void addreg(Adr*, int);
void dumpit(char *str, Flow *r0, int); void dumpit(char *str, Flow *r0, int);
...@@ -187,16 +203,16 @@ enum ...@@ -187,16 +203,16 @@ enum
SizeF = 1<<7, // float aka float32 SizeF = 1<<7, // float aka float32
SizeD = 1<<8, // double aka float64 SizeD = 1<<8, // double aka float64
// Left side: address taken, read, write. // Left side (Prog.from): address taken, read, write.
LeftAddr = 1<<9, LeftAddr = 1<<9,
LeftRead = 1<<10, LeftRead = 1<<10,
LeftWrite = 1<<11, LeftWrite = 1<<11,
// Register in middle; never written. // Register in middle (Prog.reg); only ever read.
RegRead = 1<<12, RegRead = 1<<12,
CanRegRead = 1<<13, CanRegRead = 1<<13,
// Right side: address taken, read, write. // Right side (Prog.to): address taken, read, write.
RightAddr = 1<<14, RightAddr = 1<<14,
RightRead = 1<<15, RightRead = 1<<15,
RightWrite = 1<<16, RightWrite = 1<<16,
......
...@@ -230,7 +230,7 @@ regopt(Prog *firstp) ...@@ -230,7 +230,7 @@ regopt(Prog *firstp)
/* the mod/div runtime routines smash R12 */ /* the mod/div runtime routines smash R12 */
if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU) 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) if(firstr == R)
return; return;
...@@ -454,9 +454,13 @@ brk: ...@@ -454,9 +454,13 @@ brk:
* replace code (paint3) * replace code (paint3)
*/ */
rgp = region; rgp = region;
if(debug['R'] && debug['v'])
print("\nregisterizing\n");
for(i=0; i<nregion; i++) { 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); bit = blsh(rgp->varno);
vreg = paint2(rgp->enter, rgp->varno); vreg = paint2(rgp->enter, rgp->varno, 0);
vreg = allreg(vreg, rgp); vreg = allreg(vreg, rgp);
if(debug['R']) { if(debug['R']) {
if(rgp->regno >= NREG) if(rgp->regno >= NREG)
...@@ -477,9 +481,6 @@ brk: ...@@ -477,9 +481,6 @@ brk:
rgp++; rgp++;
} }
if(debug['R'] && debug['v'])
dumpit("pass6", &firstr->f, 1);
/* /*
* free aux structures. peep allocates new ones. * free aux structures. peep allocates new ones.
*/ */
...@@ -488,6 +489,15 @@ brk: ...@@ -488,6 +489,15 @@ brk:
flowend(g); flowend(g);
firstr = R; 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 * pass 7
* peep-hole on basic block * peep-hole on basic block
...@@ -1189,7 +1199,7 @@ paint1(Reg *r, int bn) ...@@ -1189,7 +1199,7 @@ paint1(Reg *r, int bn)
} }
uint32 uint32
paint2(Reg *r, int bn) paint2(Reg *r, int bn, int depth)
{ {
Reg *r1; Reg *r1;
int z; int z;
...@@ -1213,6 +1223,9 @@ paint2(Reg *r, int bn) ...@@ -1213,6 +1223,9 @@ paint2(Reg *r, int bn)
r = r1; r = r1;
} }
for(;;) { for(;;) {
if(debug['R'] && debug['v'])
print(" paint2 %d %P\n", depth, r->f.prog);
r->act.b[z] &= ~bb; r->act.b[z] &= ~bb;
vreg |= r->regu; vreg |= r->regu;
...@@ -1220,14 +1233,14 @@ paint2(Reg *r, int bn) ...@@ -1220,14 +1233,14 @@ paint2(Reg *r, int bn)
if(r->refbehind.b[z] & bb) if(r->refbehind.b[z] & bb)
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
if(r1->refahead.b[z] & bb) if(r1->refahead.b[z] & bb)
vreg |= paint2(r1, bn); vreg |= paint2(r1, bn, depth+1);
if(!(r->refahead.b[z] & bb)) if(!(r->refahead.b[z] & bb))
break; break;
r1 = (Reg*)r->f.s2; r1 = (Reg*)r->f.s2;
if(r1 != R) if(r1 != R)
if(r1->refbehind.b[z] & bb) if(r1->refbehind.b[z] & bb)
vreg |= paint2(r1, bn); vreg |= paint2(r1, bn, depth+1);
r = (Reg*)r->f.s1; r = (Reg*)r->f.s1;
if(r == R) if(r == R)
break; break;
...@@ -1344,6 +1357,8 @@ RtoB(int r) ...@@ -1344,6 +1357,8 @@ RtoB(int r)
int int
BtoR(uint32 b) 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 b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
if(b == 0) if(b == 0)
return 0; return 0;
...@@ -1442,12 +1457,14 @@ dumpit(char *str, Flow *r0, int isreg) ...@@ -1442,12 +1457,14 @@ dumpit(char *str, Flow *r0, int isreg)
print(" (only)"); print(" (only)");
print("\n"); print("\n");
} }
// r1 = r->s1; // Print successors if it's not just the next one
// if(r1 != nil) { if(r->s1 != r->link || r->s2 != nil) {
// print(" succ:"); print(" succ:");
// for(; r1 != R; r1 = r1->s1) if(r->s1 != nil)
// print(" %.4ud", (int)r1->prog->pc); print(" %.4ud", (int)r->s1->prog->pc);
// print("\n"); if(r->s2 != nil)
// } print(" %.4ud", (int)r->s2->prog->pc);
print("\n");
}
} }
} }
...@@ -338,6 +338,8 @@ enum ...@@ -338,6 +338,8 @@ enum
D_STATIC = (D_NONE+4), D_STATIC = (D_NONE+4),
D_AUTO = (D_NONE+5), D_AUTO = (D_NONE+5),
D_PARAM = (D_NONE+6), D_PARAM = (D_NONE+6),
D_LAST = (D_NONE+26),
}; };
/* /*
......
...@@ -75,12 +75,18 @@ struct Reg ...@@ -75,12 +75,18 @@ struct Reg
{ {
Flow f; Flow f;
Bits set; // variables written by this instruction. Bits set; // regopt variables written by this instruction.
Bits use1; // variables read by prog->from. Bits use1; // regopt variables read by prog->from.
Bits use2; // variables read by prog->to. 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 refbehind;
Bits refahead; Bits refahead;
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
Bits calbehind; Bits calbehind;
Bits calahead; Bits calahead;
Bits regdiff; Bits regdiff;
...@@ -93,6 +99,16 @@ struct Reg ...@@ -93,6 +99,16 @@ struct Reg
#define NRGN 600 #define NRGN 600
/*c2go enum { 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 struct Rgn
{ {
Reg* enter; Reg* enter;
...@@ -140,7 +156,7 @@ void prop(Reg*, Bits, Bits); ...@@ -140,7 +156,7 @@ void prop(Reg*, Bits, Bits);
void synch(Reg*, Bits); void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*); uint32 allreg(uint32, Rgn*);
void paint1(Reg*, int); void paint1(Reg*, int);
uint32 paint2(Reg*, int); uint32 paint2(Reg*, int, int);
void paint3(Reg*, int, uint32, int); void paint3(Reg*, int, uint32, int);
void addreg(Adr*, int); void addreg(Adr*, int);
void dumpone(Flow*, int); void dumpone(Flow*, int);
...@@ -165,8 +181,8 @@ typedef struct ProgInfo ProgInfo; ...@@ -165,8 +181,8 @@ typedef struct ProgInfo ProgInfo;
struct ProgInfo struct ProgInfo
{ {
uint32 flags; // the bits below uint32 flags; // the bits below
uint32 reguse; // required registers used by this instruction uint32 reguse; // registers implicitly used by this instruction
uint32 regset; // required registers set by this instruction uint32 regset; // registers implicitly set by this instruction
uint32 regindex; // registers used by addressing mode uint32 regindex; // registers used by addressing mode
}; };
...@@ -187,12 +203,12 @@ enum ...@@ -187,12 +203,12 @@ enum
SizeF = 1<<7, // float aka float32 SizeF = 1<<7, // float aka float32
SizeD = 1<<8, // double aka float64 SizeD = 1<<8, // double aka float64
// Left side: address taken, read, write. // Left side (Prog.from): address taken, read, write.
LeftAddr = 1<<9, LeftAddr = 1<<9,
LeftRead = 1<<10, LeftRead = 1<<10,
LeftWrite = 1<<11, LeftWrite = 1<<11,
// Right side: address taken, read, write. // Right side (Prog.to): address taken, read, write.
RightAddr = 1<<12, RightAddr = 1<<12,
RightRead = 1<<13, RightRead = 1<<13,
RightWrite = 1<<14, RightWrite = 1<<14,
......
...@@ -389,9 +389,13 @@ brk: ...@@ -389,9 +389,13 @@ brk:
* replace code (paint3) * replace code (paint3)
*/ */
rgp = region; rgp = region;
if(debug['R'] && debug['v'])
print("\nregisterizing\n");
for(i=0; i<nregion; i++) { 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); bit = blsh(rgp->varno);
vreg = paint2(rgp->enter, rgp->varno); vreg = paint2(rgp->enter, rgp->varno, 0);
vreg = allreg(vreg, rgp); vreg = allreg(vreg, rgp);
if(rgp->regno != 0) { if(rgp->regno != 0) {
if(debug['R'] && debug['v']) { if(debug['R'] && debug['v']) {
...@@ -406,9 +410,6 @@ brk: ...@@ -406,9 +410,6 @@ brk:
rgp++; rgp++;
} }
if(debug['R'] && debug['v'])
dumpit("pass6", &firstr->f, 1);
/* /*
* free aux structures. peep allocates new ones. * free aux structures. peep allocates new ones.
*/ */
...@@ -417,6 +418,15 @@ brk: ...@@ -417,6 +418,15 @@ brk:
flowend(g); flowend(g);
firstr = R; 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 * pass 7
* peep-hole on basic block * peep-hole on basic block
...@@ -1020,7 +1030,7 @@ paint1(Reg *r, int bn) ...@@ -1020,7 +1030,7 @@ paint1(Reg *r, int bn)
} }
uint32 uint32
paint2(Reg *r, int bn) paint2(Reg *r, int bn, int depth)
{ {
Reg *r1; Reg *r1;
int z; int z;
...@@ -1044,6 +1054,9 @@ paint2(Reg *r, int bn) ...@@ -1044,6 +1054,9 @@ paint2(Reg *r, int bn)
r = r1; r = r1;
} }
for(;;) { for(;;) {
if(debug['R'] && debug['v'])
print(" paint2 %d %P\n", depth, r->f.prog);
r->act.b[z] &= ~bb; r->act.b[z] &= ~bb;
vreg |= r->regu; vreg |= r->regu;
...@@ -1051,14 +1064,14 @@ paint2(Reg *r, int bn) ...@@ -1051,14 +1064,14 @@ paint2(Reg *r, int bn)
if(r->refbehind.b[z] & bb) if(r->refbehind.b[z] & bb)
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
if(r1->refahead.b[z] & bb) if(r1->refahead.b[z] & bb)
vreg |= paint2(r1, bn); vreg |= paint2(r1, bn, depth+1);
if(!(r->refahead.b[z] & bb)) if(!(r->refahead.b[z] & bb))
break; break;
r1 = (Reg*)r->f.s2; r1 = (Reg*)r->f.s2;
if(r1 != R) if(r1 != R)
if(r1->refbehind.b[z] & bb) if(r1->refbehind.b[z] & bb)
vreg |= paint2(r1, bn); vreg |= paint2(r1, bn, depth+1);
r = (Reg*)r->f.s1; r = (Reg*)r->f.s1;
if(r == R) if(r == R)
break; break;
...@@ -1259,12 +1272,14 @@ dumpit(char *str, Flow *r0, int isreg) ...@@ -1259,12 +1272,14 @@ dumpit(char *str, Flow *r0, int isreg)
print(" %.4ud", (int)r1->prog->pc); print(" %.4ud", (int)r1->prog->pc);
print("\n"); print("\n");
} }
// r1 = r->s1; // Print successors if it's not just the next one
// if(r1 != R) { if(r->s1 != r->link || r->s2 != nil) {
// print(" succ:"); print(" succ:");
// for(; r1 != R; r1 = r1->s1) if(r->s1 != nil)
// print(" %.4ud", (int)r1->prog->pc); print(" %.4ud", (int)r->s1->prog->pc);
// print("\n"); if(r->s2 != nil)
// } print(" %.4ud", (int)r->s2->prog->pc);
print("\n");
}
} }
} }
...@@ -865,6 +865,8 @@ enum ...@@ -865,6 +865,8 @@ enum
D_INDIR, /* additive */ D_INDIR, /* additive */
D_LAST,
T_TYPE = 1<<0, T_TYPE = 1<<0,
T_INDEX = 1<<1, T_INDEX = 1<<1,
T_OFFSET = 1<<2, T_OFFSET = 1<<2,
......
...@@ -75,12 +75,18 @@ struct Reg ...@@ -75,12 +75,18 @@ struct Reg
{ {
Flow f; Flow f;
Bits set; // variables written by this instruction. Bits set; // regopt variables written by this instruction.
Bits use1; // variables read by prog->from. Bits use1; // regopt variables read by prog->from.
Bits use2; // variables read by prog->to. 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 refbehind;
Bits refahead; Bits refahead;
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
Bits calbehind; Bits calbehind;
Bits calahead; Bits calahead;
Bits regdiff; Bits regdiff;
...@@ -106,6 +112,16 @@ struct Reg ...@@ -106,6 +112,16 @@ struct Reg
#define NRGN 600 #define NRGN 600
/*c2go enum { 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 struct Rgn
{ {
Reg* enter; Reg* enter;
...@@ -158,7 +174,7 @@ void loopit(Reg*, int32); ...@@ -158,7 +174,7 @@ void loopit(Reg*, int32);
void synch(Reg*, Bits); void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*); uint32 allreg(uint32, Rgn*);
void paint1(Reg*, int); void paint1(Reg*, int);
uint32 paint2(Reg*, int); uint32 paint2(Reg*, int, int);
void paint3(Reg*, int, uint32, int); void paint3(Reg*, int, uint32, int);
void addreg(Adr*, int); void addreg(Adr*, int);
void dumpone(Flow*, int); void dumpone(Flow*, int);
...@@ -183,8 +199,8 @@ typedef struct ProgInfo ProgInfo; ...@@ -183,8 +199,8 @@ typedef struct ProgInfo ProgInfo;
struct ProgInfo struct ProgInfo
{ {
uint32 flags; // the bits below uint32 flags; // the bits below
uint32 reguse; // required registers used by this instruction uint32 reguse; // registers implicitly used by this instruction
uint32 regset; // required registers set by this instruction uint32 regset; // registers implicitly set by this instruction
uint32 regindex; // registers used by addressing mode uint32 regindex; // registers used by addressing mode
}; };
...@@ -205,12 +221,12 @@ enum ...@@ -205,12 +221,12 @@ enum
SizeF = 1<<7, // float aka float32 SizeF = 1<<7, // float aka float32
SizeD = 1<<8, // double aka float64 SizeD = 1<<8, // double aka float64
// Left side: address taken, read, write. // Left side (Prog.from): address taken, read, write.
LeftAddr = 1<<9, LeftAddr = 1<<9,
LeftRead = 1<<10, LeftRead = 1<<10,
LeftWrite = 1<<11, LeftWrite = 1<<11,
// Right side: address taken, read, write. // Right side (Prog.to): address taken, read, write.
RightAddr = 1<<12, RightAddr = 1<<12,
RightRead = 1<<13, RightRead = 1<<13,
RightWrite = 1<<14, RightWrite = 1<<14,
......
...@@ -358,18 +358,19 @@ brk: ...@@ -358,18 +358,19 @@ brk:
* replace code (paint3) * replace code (paint3)
*/ */
rgp = region; rgp = region;
if(debug['R'] && debug['v'])
print("\nregisterizing\n");
for(i=0; i<nregion; i++) { 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); bit = blsh(rgp->varno);
vreg = paint2(rgp->enter, rgp->varno); vreg = paint2(rgp->enter, rgp->varno, 0);
vreg = allreg(vreg, rgp); vreg = allreg(vreg, rgp);
if(rgp->regno != 0) if(rgp->regno != 0)
paint3(rgp->enter, rgp->varno, vreg, rgp->regno); paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
rgp++; rgp++;
} }
if(debug['R'] && debug['v'])
dumpit("pass6", &firstr->f, 1);
/* /*
* free aux structures. peep allocates new ones. * free aux structures. peep allocates new ones.
*/ */
...@@ -378,6 +379,15 @@ brk: ...@@ -378,6 +379,15 @@ brk:
flowend(g); flowend(g);
firstr = R; 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 * pass 7
* peep-hole on basic block * peep-hole on basic block
...@@ -926,7 +936,7 @@ paint1(Reg *r, int bn) ...@@ -926,7 +936,7 @@ paint1(Reg *r, int bn)
Reg *r1; Reg *r1;
Prog *p; Prog *p;
int z; int z;
uint64 bb; uint64 bb, rbz;
z = bn/64; z = bn/64;
bb = 1LL<<(bn%64); bb = 1LL<<(bn%64);
...@@ -945,7 +955,8 @@ paint1(Reg *r, int bn) ...@@ -945,7 +955,8 @@ paint1(Reg *r, int bn)
r = r1; 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; change -= CLOAD * r->f.loop;
} }
for(;;) { for(;;) {
...@@ -996,7 +1007,7 @@ paint1(Reg *r, int bn) ...@@ -996,7 +1007,7 @@ paint1(Reg *r, int bn)
} }
uint32 uint32
paint2(Reg *r, int bn) paint2(Reg *r, int bn, int depth)
{ {
Reg *r1; Reg *r1;
int z; int z;
...@@ -1020,6 +1031,9 @@ paint2(Reg *r, int bn) ...@@ -1020,6 +1031,9 @@ paint2(Reg *r, int bn)
r = r1; r = r1;
} }
for(;;) { for(;;) {
if(debug['R'] && debug['v'])
print(" paint2 %d %P\n", depth, r->f.prog);
r->act.b[z] &= ~bb; r->act.b[z] &= ~bb;
vreg |= r->regu; vreg |= r->regu;
...@@ -1027,14 +1041,14 @@ paint2(Reg *r, int bn) ...@@ -1027,14 +1041,14 @@ paint2(Reg *r, int bn)
if(r->refbehind.b[z] & bb) if(r->refbehind.b[z] & bb)
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
if(r1->refahead.b[z] & bb) if(r1->refahead.b[z] & bb)
vreg |= paint2(r1, bn); vreg |= paint2(r1, bn, depth+1);
if(!(r->refahead.b[z] & bb)) if(!(r->refahead.b[z] & bb))
break; break;
r1 = (Reg*)r->f.s2; r1 = (Reg*)r->f.s2;
if(r1 != R) if(r1 != R)
if(r1->refbehind.b[z] & bb) if(r1->refbehind.b[z] & bb)
vreg |= paint2(r1, bn); vreg |= paint2(r1, bn, depth+1);
r = (Reg*)r->f.s1; r = (Reg*)r->f.s1;
if(r == R) if(r == R)
break; break;
...@@ -1053,7 +1067,7 @@ paint3(Reg *r, int bn, uint32 rb, int rn) ...@@ -1053,7 +1067,7 @@ paint3(Reg *r, int bn, uint32 rb, int rn)
Reg *r1; Reg *r1;
Prog *p; Prog *p;
int z; int z;
uint64 bb; uint64 bb, rbz;
z = bn/64; z = bn/64;
bb = 1LL << (bn%64); bb = 1LL << (bn%64);
...@@ -1072,7 +1086,8 @@ paint3(Reg *r, int bn, uint32 rb, int rn) ...@@ -1072,7 +1086,8 @@ paint3(Reg *r, int bn, uint32 rb, int rn)
r = r1; 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); addmove(r, bn, rn, 0);
for(;;) { for(;;) {
r->act.b[z] |= bb; r->act.b[z] |= bb;
...@@ -1227,12 +1242,14 @@ dumpit(char *str, Flow *r0, int isreg) ...@@ -1227,12 +1242,14 @@ dumpit(char *str, Flow *r0, int isreg)
print(" %.4ud", (int)r1->prog->pc); print(" %.4ud", (int)r1->prog->pc);
print("\n"); print("\n");
} }
// r1 = r->s1; // Print successors if it's not just the next one
// if(r1 != nil) { if(r->s1 != r->link || r->s2 != nil) {
// print(" succ:"); print(" succ:");
// for(; r1 != R; r1 = r1->s1) if(r->s1 != nil)
// print(" %.4ud", (int)r1->prog->pc); print(" %.4ud", (int)r->s1->prog->pc);
// print("\n"); if(r->s2 != nil)
// } print(" %.4ud", (int)r->s2->prog->pc);
print("\n");
}
} }
} }
...@@ -654,6 +654,8 @@ enum ...@@ -654,6 +654,8 @@ enum
D_CONST2 = D_INDIR+D_INDIR, D_CONST2 = D_INDIR+D_INDIR,
D_LAST,
T_TYPE = 1<<0, T_TYPE = 1<<0,
T_INDEX = 1<<1, T_INDEX = 1<<1,
T_OFFSET = 1<<2, T_OFFSET = 1<<2,
......
...@@ -250,7 +250,7 @@ struct ...@@ -250,7 +250,7 @@ struct
"R27", LREG, 27, "R27", LREG, 27,
"R28", LREG, 28, "R28", LREG, 28,
"R29", LREG, 29, "R29", LREG, 29,
"R30", LREG, 30, "g", LREG, 30, // avoid unintentionally clobbering g using R30
"R31", LREG, 31, "R31", LREG, 31,
"F", LF, 0, "F", LF, 0,
...@@ -488,6 +488,7 @@ struct ...@@ -488,6 +488,7 @@ struct
"SYSCALL", LNOP, ASYSCALL, "SYSCALL", LNOP, ASYSCALL,
"UNDEF", LNOP, AUNDEF, "UNDEF", LNOP, AUNDEF,
"RET", LRETRN, ARETURN,
"RETURN", LRETRN, ARETURN, "RETURN", LRETRN, ARETURN,
"RFI", LRETRN, ARFI, "RFI", LRETRN, ARFI,
"RFCI", LRETRN, ARFCI, "RFCI", LRETRN, ARFCI,
......
# 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
- 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
This diff is collapsed.
// 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
// 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*
// 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();
}
// 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;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// 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;
}
}
// 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, &regnode, 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;
}
This diff is collapsed.
...@@ -134,11 +134,12 @@ proginfo(ProgInfo *info, Prog *p) ...@@ -134,11 +134,12 @@ proginfo(ProgInfo *info, Prog *p)
} }
if(p->as == ADUFFZERO) { if(p->as == ADUFFZERO) {
info->reguse |= RtoB(0) | RtoB(2); info->reguse |= (1<<D_R0) | RtoB(3);
info->regset |= RtoB(2); info->regset |= RtoB(3);
} }
if(p->as == ADUFFCOPY) { if(p->as == ADUFFCOPY) {
info->reguse |= RtoB(0) | RtoB(2) | RtoB(3); // TODO(austin) Revisit when duffcopy is implemented
info->regset |= RtoB(2) | RtoB(3); info->reguse |= RtoB(3) | RtoB(4) | RtoB(5);
info->regset |= RtoB(3) | RtoB(4);
} }
} }
This diff is collapsed.
...@@ -497,6 +497,8 @@ enum ...@@ -497,6 +497,8 @@ enum
D_DCONST, D_DCONST,
D_ADDR, // not used, use D_CONST with non-empty sym. D_ADDR, // not used, use D_CONST with non-empty sym.
D_LAST,
/* reg names for 9g OREGISTER */ /* reg names for 9g OREGISTER */
D_R0 = 0, // type is D_REG D_R0 = 0, // type is D_REG
D_F0 = D_R0+NREG, // type is D_FREG D_F0 = D_R0+NREG, // type is D_FREG
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment