[dev.power64] build: merge default into dev.power64

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/160200044
This commit is contained in:
Austin Clements 2014-10-22 11:21:16 -04:00
commit 3208250185
846 changed files with 25440 additions and 21103 deletions

View File

@ -131,4 +131,5 @@ f8b50ad4cac4d4c4ecf48324b4f512f65e82cc1c go1.3beta1
9d5451df4e53acc58a848005b7ec3a24c4b6050c go1.3rc1
3f66a43d5180052e2e1e38d979d1aa5ad05b21f9 go1.3rc2
9895f9e36435468d503eaa74ee217f28d5e28dd4 go1.3
9895f9e36435468d503eaa74ee217f28d5e28dd4 release
073fc578434bf3e1e22749b559d273c8da728ebb go1.3.1
073fc578434bf3e1e22749b559d273c8da728ebb release

View File

@ -16,6 +16,7 @@ Adrien Bustany <adrien-xx-google@bustany.org>
Akshat Kumar <seed@mail.nanosouffle.net>
Alan Shreve <alan@inconshreveable.com>
Albert Strasheim <fullung@gmail.com>
Alberto Donizetti <alb.donizetti@gmail.com>
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
Aleksandar Dezelin <dezelin@gmail.com>
Alex A Skinner <alex@lx.lc>
@ -35,6 +36,7 @@ Amrut Joshi <amrut.joshi@gmail.com>
Andrei Vieru <euvieru@gmail.com>
Andrew Balholm <andybalholm@gmail.com>
Andrew Bonventre <andybons@chromium.org>
Andrew Bursavich <abursavich@gmail.com>
Andrew Harding <andrew@spacemonkey.com>
Andrew Lutomirski <andy@luto.us>
Andrew Pritchard <awpritchard@gmail.com>
@ -118,6 +120,7 @@ David du Colombier <0intro@gmail.com>
David Forsythe <dforsythe@gmail.com>
David G. Andersen <dave.andersen@gmail.com>
David Jakob Fritz <david.jakob.fritz@gmail.com>
David Leon Gil <coruus@gmail.com>
David Thomas <davidthomas426@gmail.com>
David Titarenco <david.titarenco@gmail.com>
Dean Prichard <dean.prichard@gmail.com>
@ -152,6 +155,7 @@ Evan Shaw <chickencha@gmail.com>
Ewan Chou <coocood@gmail.com>
Fabrizio Milo <mistobaan@gmail.com>
Fan Hongjian <fan.howard@gmail.com>
Fatih Arslan <fatih@arslan.io>
Fazlul Shahriar <fshahriar@gmail.com>
Felix Geisendörfer <haimuiba@gmail.com>
Firmansyah Adiputra <frm.adiputra@gmail.com>
@ -178,6 +182,7 @@ Gustavo Niemeyer <gustavo@niemeyer.net>
Gwenael Treguier <gwenn.kahz@gmail.com>
Harley Laue <losinggeneration@gmail.com>
Hector Chu <hectorchu@gmail.com>
Henning Schmiedehausen <henning@schmiedehausen.org>
Henrik Edwards <henrik.edwards@gmail.com>
Herbert Georg Fischer <herbert.fischer@gmail.com>
Hong Ruiqi <hongruiqi@gmail.com>
@ -213,6 +218,8 @@ Jimmy Zelinskie <jimmyzelinskie@gmail.com>
Jingcheng Zhang <diogin@gmail.com>
Joakim Sernbrant <serbaut@gmail.com>
Joe Poirier <jdpoirier@gmail.com>
Joe Shaw <joe@joeshaw.org>
Joel Stemmer <stemmertech@gmail.com>
John Asmuth <jasmuth@gmail.com>
John C Barstow <jbowtie@amathaine.com>
John Graham-Cumming <jgc@jgc.org> <jgrahamc@gmail.com>
@ -257,6 +264,7 @@ Luke Curley <qpingu@gmail.com>
Manuel Mendez <mmendez534@gmail.com>
Marc Weistroff <marc@weistroff.net>
Marco Hennings <marco.hennings@freiheit.com>
Mark Theunissen <mark.theunissen@gmail.com>
Marko Juhani Silokunnas <marko.silokunnas@gmail.com>
Marko Tiikkaja <marko@joh.to>
Markover Inc. DBA Poptip
@ -399,6 +407,7 @@ Taj Khattra <taj.khattra@gmail.com>
Tarmigan Casebolt <tarmigan@gmail.com>
Taru Karttunen <taruti@taruti.net>
Tetsuo Kiso <tetsuokiso9@gmail.com>
Thiago Fransosi Farina <thiago.farina@gmail.com>
Thomas Alan Copeland <talan.copeland@gmail.com>
Thomas Kappler <tkappler@gmail.com>
Timo Savola <timo.savola@gmail.com>

View File

@ -42,6 +42,7 @@ Akshat Kumar <seed@mail.nanosouffle.net>
Alan Donovan <adonovan@google.com>
Alan Shreve <alan@inconshreveable.com>
Albert Strasheim <fullung@gmail.com>
Alberto Donizetti <alb.donizetti@gmail.com>
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
Aleksandar Dezelin <dezelin@gmail.com>
Alex A Skinner <alex@lx.lc>
@ -66,6 +67,7 @@ Andreas Jellinghaus <andreas@ionisiert.de> <anj@google.com>
Andrei Vieru <euvieru@gmail.com>
Andrew Balholm <andybalholm@gmail.com>
Andrew Bonventre <andybons@chromium.org>
Andrew Bursavich <abursavich@gmail.com>
Andrew Gerrand <adg@golang.org>
Andrew Harding <andrew@spacemonkey.com>
Andrew Lutomirski <andy@luto.us>
@ -180,6 +182,7 @@ David du Colombier <0intro@gmail.com>
David Forsythe <dforsythe@gmail.com>
David G. Andersen <dave.andersen@gmail.com>
David Jakob Fritz <david.jakob.fritz@gmail.com>
David Leon Gil <coruus@gmail.com>
David McLeish <davemc@google.com>
David Presotto <presotto@gmail.com>
David Symonds <dsymonds@golang.org>
@ -221,6 +224,7 @@ Evan Shaw <chickencha@gmail.com>
Ewan Chou <coocood@gmail.com>
Fabrizio Milo <mistobaan@gmail.com>
Fan Hongjian <fan.howard@gmail.com>
Fatih Arslan <fatih@arslan.io>
Fazlul Shahriar <fshahriar@gmail.com>
Felix Geisendörfer <haimuiba@gmail.com>
Firmansyah Adiputra <frm.adiputra@gmail.com>
@ -253,6 +257,7 @@ Gwenael Treguier <gwenn.kahz@gmail.com>
Han-Wen Nienhuys <hanwen@google.com>
Harley Laue <losinggeneration@gmail.com>
Hector Chu <hectorchu@gmail.com>
Henning Schmiedehausen <henning@schmiedehausen.org>
Henrik Edwards <henrik.edwards@gmail.com>
Herbert Georg Fischer <herbert.fischer@gmail.com>
Hong Ruiqi <hongruiqi@gmail.com>
@ -300,7 +305,9 @@ Jimmy Zelinskie <jimmyzelinskie@gmail.com>
Jingcheng Zhang <diogin@gmail.com>
Joakim Sernbrant <serbaut@gmail.com>
Joe Poirier <jdpoirier@gmail.com>
Joe Shaw <joe@joeshaw.org>
Joel Sing <jsing@google.com>
Joel Stemmer <stemmertech@gmail.com>
Johan Euphrosine <proppy@google.com>
John Asmuth <jasmuth@gmail.com>
John Beisley <huin@google.com>
@ -368,6 +375,7 @@ Manuel Mendez <mmendez534@gmail.com>
Marc Weistroff <marc@weistroff.net>
Marcel van Lohuizen <mpvl@golang.org>
Marco Hennings <marco.hennings@freiheit.com>
Mark Theunissen <mark.theunissen@gmail.com>
Mark Zavislak <zavislak@google.com>
Marko Juhani Silokunnas <marko.silokunnas@gmail.com>
Marko Mikulicic <mkm@google.com>
@ -455,6 +463,7 @@ Paul Borman <borman@google.com>
Paul Chang <paulchang@google.com>
Paul Hammond <paul@paulhammond.org>
Paul Lalonde <paul.a.lalonde@gmail.com>
Paul Nasrat <pnasrat@google.com>
Paul Sbarra <Sbarra.Paul@gmail.com>
Paul van Brouwershaven <paul@vanbrouwershaven.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
@ -486,6 +495,7 @@ Richard Crowley <r@rcrowley.org>
Richard Eric Gavaletz <gavaletz@gmail.com>
Richard Musiol <mail@richard-musiol.de> <neelance@gmail.com>
Rick Arnold <rickarnoldjr@gmail.com>
Rick Hudson <rlh@golang.org>
Risto Jaakko Saarelma <rsaarelm@gmail.com>
Rob Pike <r@golang.org>
Robert Daniel Kortschak <dan.kortschak@adelaide.edu.au>
@ -547,6 +557,7 @@ Taj Khattra <taj.khattra@gmail.com>
Tarmigan Casebolt <tarmigan@gmail.com>
Taru Karttunen <taruti@taruti.net>
Tetsuo Kiso <tetsuokiso9@gmail.com>
Thiago Fransosi Farina <thiago.farina@gmail.com> <tfarina@chromium.org>
Thomas Alan Copeland <talan.copeland@gmail.com>
Thomas Habets <habets@google.com>
Thomas Kappler <tkappler@gmail.com>

View File

@ -327,3 +327,4 @@ pkg syscall (netbsd-arm), const SizeofIfData = 132
pkg syscall (netbsd-arm), type IfMsghdr struct, Pad_cgo_1 [4]uint8
pkg syscall (netbsd-arm-cgo), const SizeofIfData = 132
pkg syscall (netbsd-arm-cgo), type IfMsghdr struct, Pad_cgo_1 [4]uint8
pkg unicode, const Version = "6.3.0"

View File

@ -115,3 +115,27 @@ pkg debug/goobj, type Var struct, Kind int
pkg debug/goobj, type Var struct, Name string
pkg debug/goobj, type Var struct, Offset int
pkg debug/goobj, type Var struct, Type SymID
pkg unicode, const Version = "7.0.0"
pkg unicode, var Bassa_Vah *RangeTable
pkg unicode, var Caucasian_Albanian *RangeTable
pkg unicode, var Duployan *RangeTable
pkg unicode, var Elbasan *RangeTable
pkg unicode, var Grantha *RangeTable
pkg unicode, var Khojki *RangeTable
pkg unicode, var Khudawadi *RangeTable
pkg unicode, var Linear_A *RangeTable
pkg unicode, var Mahajani *RangeTable
pkg unicode, var Manichaean *RangeTable
pkg unicode, var Mende_Kikakui *RangeTable
pkg unicode, var Modi *RangeTable
pkg unicode, var Mro *RangeTable
pkg unicode, var Nabataean *RangeTable
pkg unicode, var Old_North_Arabian *RangeTable
pkg unicode, var Old_Permic *RangeTable
pkg unicode, var Pahawh_Hmong *RangeTable
pkg unicode, var Palmyrene *RangeTable
pkg unicode, var Pau_Cin_Hau *RangeTable
pkg unicode, var Psalter_Pahlavi *RangeTable
pkg unicode, var Siddham *RangeTable
pkg unicode, var Tirhuta *RangeTable
pkg unicode, var Warang_Citi *RangeTable

View File

@ -253,7 +253,7 @@ There may be one or two arguments to the directives.
If there are two, the first is a bit mask of flags,
which can be written as numeric expressions, added or or-ed together,
or can be set symbolically for easier absorption by a human.
Their values, defined in the file <code>src/cmd/ld/textflag.h</code>, are:
Their values, defined in the standard <code>#include</code> file <code>textflag.h</code>, are:
</p>
<ul>

View File

@ -65,7 +65,7 @@ details.
<td><a href="//godoc.org/code.google.com/p/go.tools/cmd/cover/">cover</a></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>Cover is a program for creating and analyzing the coverage profiles
generated by <code>"go test -coverprofile"</code>.
generated by <code>"go test -coverprofile"</code>.</td>
</tr>
<tr>

View File

@ -20,6 +20,13 @@ Go 1.3 is a major release of Go.
Read the <a href="/doc/go1.3">Go 1.3 Release Notes</a> for more information.
</p>
<h3 id="go1.3.minor">Minor revisions</h3>
<p>
go1.3.1 (released 2014/08/13) includes bug fixes to the compiler and the <code>runtime</code>, <code>net</code>, and <code>crypto/rsa</code> packages.
See the <a href="//code.google.com/p/go/source/list?name=release-branch.go1.3&r=073fc578434bf3e1e22749b559d273c8da728ebb">change history</a> for details.
</p>
<h2 id="go1.2">go1.2 (released 2013/12/01)</h2>
<p>

View File

@ -521,6 +521,15 @@ field to specify an end-to-end timeout on requests made using the
client.
</li>
<li>
The <a href="/pkg/net/http/"><code>net/http</code></a> package's
<a href="/pkg/net/http/#Request.ParseMultipartForm"><code>Request.ParseMultipartForm</code></a>
method will now return an error if the body's <code>Content-Type</code>
is not <code>mutipart/form-data</code>.
Prior to Go 1.3 it would silently fail and return <code>nil</code>.
Code that relies on the previous behavior should be updated.
</li>
<li> In the <a href="/pkg/net/"><code>net</code></a> package,
the <a href="/pkg/net/#Dialer"><code>Dialer</code></a> struct now
has a <code>KeepAlive</code> option to specify a keep-alive period for the connection.

View File

@ -7,12 +7,27 @@ Please keep the list sorted (as in sort.Strings of the lines).
spec: permit for range x (CL 104680043)
cmd/6l, liblink: use pc-relative addressing for all memory references, so that linking Go binaries at high addresses works (CL 125140043). This cuts the maximum size of a Go binary's text+data+bss from 4GB to 2GB.
cmd/go: import comments (CL 124940043)
cmd/go: implement "internal" (CL 120600043)
cmd/go: implement "generate" (CL 125580044)
asm: make textflag.h available outside of cmd/ld (CL 128050043)
crypto/tls: add support for ALPN (RFC 7301) (CL 108710046)
crypto/tls: support programmatic selection of server certificates (CL 107400043)
encoding/gob: remove unsafe (CL 102680045)
misc: deleted editor support; refer to https://code.google.com/p/go-wiki/wiki/IDEsAndTextEditorPlugins instead (CL 105470043)
net/http: add Request.BasicAuth method (CL 76540043)
net/http: add Transport.DialTLS hook (CL 137940043)
net/http/httputil: add ReverseProxy.ErrorLog (CL 132750043)
os: implement symlink support for windows (CL 86160044)
runtime: implement monotonic clocks on windows (CL 108700045)
runtime/race: freebsd is supported (CL 107270043)
syscall: Setuid, Setgid are disabled on linux platforms. On linux those syscalls operate on the calling thread, not the whole process. This does not match the semantics of other platforms, nor the expectations of the caller, so the operations have been disabled until issue 1435 is resolved (CL 106170043)
syscal: now frozen (CL 129820043)
testing: add Coverage (CL 98150043)
text/scanner: add IsIdentRune field of Scanner. (CL 108030044)
time: use the micro symbol (µ (U+00B5)) to print microsecond duration (CL 105030046)
encoding/asn1: optional elements with a default value will now only be omitted if they have that value (CL 86960045).
go.sys subrepo created: http://golang.org/s/go1.4-syscall

View File

@ -152,6 +152,21 @@ will be tagged as appropriate to identify versions that are compatible
with the Go 1 point releases.
</p>
<h2 id="operating_systems">Operating systems</h2>
<p>
It is impossible to guarantee long-term compatibility with operating
system interfaces, which are changed by outside parties.
The <a href="/pkg/syscall/"><code>syscall</code></a> package
is therefore outside the purview of the guarantees made here.
As of Go version 1.4, the <code>syscall</code> package is frozen.
Any evolution of the system call interface must be supported elsewhere,
such as in the
<a href="http://godoc.org/code.google.com/p/go.sys">go.sys</a> subrepository.
For details and background, see
<a href="https://golang.org/s/go1.4-syscall">this document</a>.
</p>
<h2 id="tools">Tools</h2>
<p>

View File

@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of August 5, 2014",
"Subtitle": "Version of August 28, 2014",
"Path": "/ref/spec"
}-->
@ -479,7 +479,7 @@ Interpreted string literals are character sequences between double
quotes <code>&quot;&quot;</code>. The text between the quotes,
which may not contain newlines, forms the
value of the literal, with backslash escapes interpreted as they
are in rune literals (except that <code>\'</code> is illegal and
are in <a href="#Rune_literals">rune literals</a> (except that <code>\'</code> is illegal and
<code>\"</code> is legal), with the same restrictions.
The three-digit octal (<code>\</code><i>nnn</i>)
and two-digit hexadecimal (<code>\x</code><i>nn</i>) escapes represent individual
@ -1034,7 +1034,7 @@ The value of an uninitialized pointer is <code>nil</code>.
<pre class="ebnf">
PointerType = "*" BaseType .
BaseType = Type .
BaseType = Type .
</pre>
<pre>
@ -2118,9 +2118,9 @@ operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
</p>
<pre class="ebnf">
Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit .
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit .
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
OperandName = identifier | QualifiedIdent.
</pre>
@ -2537,6 +2537,233 @@ p.M0() // ((*p).T0).M0()
</pre>
<h3 id="Method_expressions">Method expressions</h3>
<p>
If <code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
<code>T.M</code> is a function that is callable as a regular function
with the same arguments as <code>M</code> prefixed by an additional
argument that is the receiver of the method.
</p>
<pre class="ebnf">
MethodExpr = ReceiverType "." MethodName .
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
</pre>
<p>
Consider a struct type <code>T</code> with two methods,
<code>Mv</code>, whose receiver is of type <code>T</code>, and
<code>Mp</code>, whose receiver is of type <code>*T</code>.
</p>
<pre>
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
</pre>
<p>
The expression
</p>
<pre>
T.Mv
</pre>
<p>
yields a function equivalent to <code>Mv</code> but
with an explicit receiver as its first argument; it has signature
</p>
<pre>
func(tv T, a int) int
</pre>
<p>
That function may be called normally with an explicit receiver, so
these five invocations are equivalent:
</p>
<pre>
t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
</pre>
<p>
Similarly, the expression
</p>
<pre>
(*T).Mp
</pre>
<p>
yields a function value representing <code>Mp</code> with signature
</p>
<pre>
func(tp *T, f float32) float32
</pre>
<p>
For a method with a value receiver, one can derive a function
with an explicit pointer receiver, so
</p>
<pre>
(*T).Mv
</pre>
<p>
yields a function value representing <code>Mv</code> with signature
</p>
<pre>
func(tv *T, a int) int
</pre>
<p>
Such a function indirects through the receiver to create a value
to pass as the receiver to the underlying method;
the method does not overwrite the value whose address is passed in
the function call.
</p>
<p>
The final case, a value-receiver function for a pointer-receiver method,
is illegal because pointer-receiver methods are not in the method set
of the value type.
</p>
<p>
Function values derived from methods are called with function call syntax;
the receiver is provided as the first argument to the call.
That is, given <code>f := T.Mv</code>, <code>f</code> is invoked
as <code>f(t, 7)</code> not <code>t.f(7)</code>.
To construct a function that binds the receiver, use a
<a href="#Function_literals">function literal</a> or
<a href="#Method_values">method value</a>.
</p>
<p>
It is legal to derive a function value from a method of an interface type.
The resulting function takes an explicit receiver of that interface type.
</p>
<h3 id="Method_values">Method values</h3>
<p>
If the expression <code>x</code> has static type <code>T</code> and
<code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
<code>x.M</code> is called a <i>method value</i>.
The method value <code>x.M</code> is a function value that is callable
with the same arguments as a method call of <code>x.M</code>.
The expression <code>x</code> is evaluated and saved during the evaluation of the
method value; the saved copy is then used as the receiver in any calls,
which may be executed later.
</p>
<p>
The type <code>T</code> may be an interface or non-interface type.
</p>
<p>
As in the discussion of <a href="#Method_expressions">method expressions</a> above,
consider a struct type <code>T</code> with two methods,
<code>Mv</code>, whose receiver is of type <code>T</code>, and
<code>Mp</code>, whose receiver is of type <code>*T</code>.
</p>
<pre>
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
var pt *T
func makeT() T
</pre>
<p>
The expression
</p>
<pre>
t.Mv
</pre>
<p>
yields a function value of type
</p>
<pre>
func(int) int
</pre>
<p>
These two invocations are equivalent:
</p>
<pre>
t.Mv(7)
f := t.Mv; f(7)
</pre>
<p>
Similarly, the expression
</p>
<pre>
pt.Mp
</pre>
<p>
yields a function value of type
</p>
<pre>
func(float32) float32
</pre>
<p>
As with <a href="#Selectors">selectors</a>, a reference to a non-interface method with a value receiver
using a pointer will automatically dereference that pointer: <code>pt.Mv</code> is equivalent to <code>(*pt).Mv</code>.
</p>
<p>
As with <a href="#Calls">method calls</a>, a reference to a non-interface method with a pointer receiver
using an addressable value will automatically take the address of that value: <code>t.Mp</code> is equivalent to <code>(&amp;t).Mp</code>.
</p>
<pre>
f := t.Mv; f(7) // like t.Mv(7)
f := pt.Mp; f(7) // like pt.Mp(7)
f := pt.Mv; f(7) // like (*pt).Mv(7)
f := t.Mp; f(7) // like (&amp;t).Mp(7)
f := makeT().Mp // invalid: result of makeT() is not addressable
</pre>
<p>
Although the examples above use non-interface types, it is also legal to create a method value
from a value of interface type.
</p>
<pre>
var i interface { M(int) } = myVal
f := i.M; f(7) // like i.M(7)
</pre>
<h3 id="Index_expressions">Index expressions</h3>
<p>
@ -3371,7 +3598,7 @@ or an array indexing operation of an addressable array.
As an exception to the addressability requirement, <code>x</code> may also be a
(possibly parenthesized)
<a href="#Composite_literals">composite literal</a>.
If the evaluation of <code>x</code> would cause a <a href="#Run_time_panics">run-time panic</a>,
If the evaluation of <code>x</code> would cause a <a href="#Run_time_panics">run-time panic</a>,
then the evaluation of <code>&amp;x</code> does too.
</p>
@ -3436,232 +3663,6 @@ channel is closed and empty.
</p>
<h3 id="Method_expressions">Method expressions</h3>
<p>
If <code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
<code>T.M</code> is a function that is callable as a regular function
with the same arguments as <code>M</code> prefixed by an additional
argument that is the receiver of the method.
</p>
<pre class="ebnf">
MethodExpr = ReceiverType "." MethodName .
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
</pre>
<p>
Consider a struct type <code>T</code> with two methods,
<code>Mv</code>, whose receiver is of type <code>T</code>, and
<code>Mp</code>, whose receiver is of type <code>*T</code>.
</p>
<pre>
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
</pre>
<p>
The expression
</p>
<pre>
T.Mv
</pre>
<p>
yields a function equivalent to <code>Mv</code> but
with an explicit receiver as its first argument; it has signature
</p>
<pre>
func(tv T, a int) int
</pre>
<p>
That function may be called normally with an explicit receiver, so
these five invocations are equivalent:
</p>
<pre>
t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
</pre>
<p>
Similarly, the expression
</p>
<pre>
(*T).Mp
</pre>
<p>
yields a function value representing <code>Mp</code> with signature
</p>
<pre>
func(tp *T, f float32) float32
</pre>
<p>
For a method with a value receiver, one can derive a function
with an explicit pointer receiver, so
</p>
<pre>
(*T).Mv
</pre>
<p>
yields a function value representing <code>Mv</code> with signature
</p>
<pre>
func(tv *T, a int) int
</pre>
<p>
Such a function indirects through the receiver to create a value
to pass as the receiver to the underlying method;
the method does not overwrite the value whose address is passed in
the function call.
</p>
<p>
The final case, a value-receiver function for a pointer-receiver method,
is illegal because pointer-receiver methods are not in the method set
of the value type.
</p>
<p>
Function values derived from methods are called with function call syntax;
the receiver is provided as the first argument to the call.
That is, given <code>f := T.Mv</code>, <code>f</code> is invoked
as <code>f(t, 7)</code> not <code>t.f(7)</code>.
To construct a function that binds the receiver, use a
<a href="#Function_literals">function literal</a> or
<a href="#Method_values">method value</a>.
</p>
<p>
It is legal to derive a function value from a method of an interface type.
The resulting function takes an explicit receiver of that interface type.
</p>
<h3 id="Method_values">Method values</h3>
<p>
If the expression <code>x</code> has static type <code>T</code> and
<code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
<code>x.M</code> is called a <i>method value</i>.
The method value <code>x.M</code> is a function value that is callable
with the same arguments as a method call of <code>x.M</code>.
The expression <code>x</code> is evaluated and saved during the evaluation of the
method value; the saved copy is then used as the receiver in any calls,
which may be executed later.
</p>
<p>
The type <code>T</code> may be an interface or non-interface type.
</p>
<p>
As in the discussion of <a href="#Method_expressions">method expressions</a> above,
consider a struct type <code>T</code> with two methods,
<code>Mv</code>, whose receiver is of type <code>T</code>, and
<code>Mp</code>, whose receiver is of type <code>*T</code>.
</p>
<pre>
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
var pt *T
func makeT() T
</pre>
<p>
The expression
</p>
<pre>
t.Mv
</pre>
<p>
yields a function value of type
</p>
<pre>
func(int) int
</pre>
<p>
These two invocations are equivalent:
</p>
<pre>
t.Mv(7)
f := t.Mv; f(7)
</pre>
<p>
Similarly, the expression
</p>
<pre>
pt.Mp
</pre>
<p>
yields a function value of type
</p>
<pre>
func(float32) float32
</pre>
<p>
As with <a href="#Selectors">selectors</a>, a reference to a non-interface method with a value receiver
using a pointer will automatically dereference that pointer: <code>pt.Mv</code> is equivalent to <code>(*pt).Mv</code>.
</p>
<p>
As with <a href="#Calls">method calls</a>, a reference to a non-interface method with a pointer receiver
using an addressable value will automatically take the address of that value: <code>t.Mp</code> is equivalent to <code>(&amp;t).Mp</code>.
</p>
<pre>
f := t.Mv; f(7) // like t.Mv(7)
f := pt.Mp; f(7) // like pt.Mp(7)
f := pt.Mv; f(7) // like (*pt).Mv(7)
f := t.Mp; f(7) // like (&amp;t).Mp(7)
f := makeT().Mp // invalid: result of makeT() is not addressable
</pre>
<p>
Although the examples above use non-interface types, it is also legal to create a method value
from a value of interface type.
</p>
<pre>
var i interface { M(int) } = myVal
f := i.M; f(7) // like i.M(7)
</pre>
<h3 id="Conversions">Conversions</h3>
<p>
@ -4051,7 +4052,7 @@ n := map[int]int{a: f()} // n may be {2: 3} or {3: 3}: evaluation order bet
<p>
At package level, initialization dependencies override the left-to-right rule
for individual initialization expressions, but not for operands within each
expression:
expression:
</p>
<pre>
@ -5941,7 +5942,7 @@ variable or function.
<li>
A reference to a method <code>m</code> is a
<a href="#Method_values">method value</a> or
<a href="#Method_expressions">method expression</a> of the form
<a href="#Method_expressions">method expression</a> of the form
<code>t.m</code>, where the (static) type of <code>t</code> is
not an interface type, and the method <code>m</code> is in the
<a href="#Method_sets">method set</a> of <code>t</code>.
@ -5950,7 +5951,7 @@ It is immaterial whether the resulting function value
</li>
<li>
A variable, function, or method <code>x</code> depends on a variable
A variable, function, or method <code>x</code> depends on a variable
<code>y</code> if <code>x</code>'s initialization expression or body
(for functions and methods) contains a reference to <code>y</code>
or to a function or method that depends on <code>y</code>.
@ -6002,7 +6003,7 @@ func init() { … }
</pre>
<p>
Multiple such functions may be defined, even within a single
Multiple such functions may be defined, even within a single
source file. The <code>init</code> identifier is not
<a href="#Declarations_and_scope">declared</a> and thus
<code>init</code> functions cannot be referred to from anywhere

View File

@ -127,6 +127,7 @@ struct LSym
short type;
short version;
uchar dupok;
uchar cfunc;
uchar external;
uchar nosplit;
uchar reachable;

View File

@ -1 +1,2 @@
defaultcc: golang-codereviews@googlegroups.com
contributors: http://go.googlecode.com/hg/CONTRIBUTORS

View File

@ -3603,11 +3603,17 @@ class MercurialVCS(VersionControlSystem):
if use_hg_shell:
base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], silent_ok=True)
else:
base_content = str(self.repo[base_rev][oldrelpath].data())
try:
base_content = str(self.repo[base_rev][oldrelpath].data())
except Exception:
pass
is_binary = "\0" in base_content # Mercurial's heuristic
if status != "R":
new_content = open(relpath, "rb").read()
is_binary = is_binary or "\0" in new_content
try:
new_content = open(relpath, "rb").read()
is_binary = is_binary or "\0" in new_content
except Exception:
pass
if is_binary and base_content and use_hg_shell:
# Fetch again without converting newlines
base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],

View File

@ -0,0 +1,14 @@
// 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 main
/*
void foo() {}
*/
import "C"
func main() {
C.foo = C.foo // ERROR HERE
}

View File

@ -0,0 +1,17 @@
// 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 main
// Issue 8442. Cgo output unhelpful error messages for
// invalid C preambles.
/*
void issue8442foo(UNDEF*); // ERROR HERE
*/
import "C"
func main() {
C.issue8442foo(nil)
}

View File

@ -27,6 +27,8 @@ check() {
check err1.go
check err2.go
check err3.go
check issue7757.go
check issue8442.go
rm -rf errs _obj
exit 0

View File

@ -10,20 +10,6 @@
typedef char bool;
bool runtime·lockedOSThread(void);
static void
FLUSH(void*)
{
}
void
·LockedOSThread(bool b)
{
b = runtime·lockedOSThread();
FLUSH(&b);
}
// This is what a cgo-compiled stub declaration looks like.
void
·Issue7695(struct{void *y[8*sizeof(void*)];}p)

View File

@ -0,0 +1,16 @@
// 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.
// Assembly to get into package runtime without using exported symbols.
// +build amd64 amd64p32 arm 386
#include "textflag.h"
#ifdef GOARCH_arm
#define JMP B
#endif
TEXT ·LockedOSThread(SB),NOSPLIT,$0-0
JMP runtime·lockedOSThread(SB)

View File

@ -0,0 +1,77 @@
// 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 cgotest
// Test that we have no more than one build ID. In the past we used
// to generate a separate build ID for each package using cgo, and the
// linker concatenated them all. We don't want that--we only want
// one.
import (
"bytes"
"debug/elf"
"os"
"testing"
)
func testBuildID(t *testing.T) {
f, err := elf.Open("/proc/self/exe")
if err != nil {
if os.IsNotExist(err) {
t.Skip("no /proc/self/exe")
}
t.Fatalf("opening /proc/self/exe: ", err)
}
defer f.Close()
c := 0
for i, s := range f.Sections {
if s.Type != elf.SHT_NOTE {
continue
}
d, err := s.Data()
if err != nil {
t.Logf("reading data of note section %d: %v", i, err)
continue
}
for len(d) > 0 {
// ELF standards differ as to the sizes in
// note sections. Both the GNU linker and
// gold always generate 32-bit sizes, so that
// is what we assume here.
if len(d) < 12 {
t.Logf("note section %d too short (%d < 12)", i, len(d))
continue
}
namesz := f.ByteOrder.Uint32(d)
descsz := f.ByteOrder.Uint32(d[4:])
typ := f.ByteOrder.Uint32(d[8:])
an := (namesz + 3) &^ 3
ad := (descsz + 3) &^ 3
if int(12+an+ad) > len(d) {
t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz)
continue
}
// 3 == NT_GNU_BUILD_ID
if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
c++
}
d = d[12+an+ad:]
}
}
if c > 1 {
t.Errorf("found %d build ID notes", c)
}
}

View File

@ -13,12 +13,13 @@ void callPanic(void);
import "C"
import (
"./backdoor"
"path"
"runtime"
"strings"
"testing"
"unsafe"
"./backdoor"
)
// nestedCall calls into C, back into Go, and finally to f.
@ -152,11 +153,13 @@ func testCallbackCallers(t *testing.T) {
n := 0
name := []string{
"test.goCallback",
"runtime.call16",
"runtime.cgocallbackg1",
"runtime.cgocallbackg",
"runtime.cgocallback_gofunc",
"runtime.asmcgocall",
"runtime.cgocall",
"asmcgocall",
"runtime.asmcgocall_errno",
"runtime.cgocall_errno",
"test._Cfunc_callback",
"test.nestedCall",
"test.testCallbackCallers",
@ -181,8 +184,12 @@ func testCallbackCallers(t *testing.T) {
if strings.HasPrefix(fname, "_") {
fname = path.Base(f.Name()[1:])
}
if fname != name[i] {
t.Errorf("expected function name %s, got %s", name[i], fname)
namei := ""
if i < len(name) {
namei = name[i]
}
if fname != namei {
t.Errorf("stk[%d] = %q, want %q", i, fname, namei)
}
}
}

View File

@ -6,5 +6,6 @@ package cgotest
import "testing"
func TestSetgid(t *testing.T) { testSetgid(t) }
func Test6997(t *testing.T) { test6997(t) }
func TestSetgid(t *testing.T) { testSetgid(t) }
func Test6997(t *testing.T) { test6997(t) }
func TestBuildID(t *testing.T) { testBuildID(t) }

View File

@ -53,5 +53,7 @@ func Test5986(t *testing.T) { test5986(t) }
func Test7665(t *testing.T) { test7665(t) }
func TestNaming(t *testing.T) { testNaming(t) }
func Test7560(t *testing.T) { test7560(t) }
func Test5242(t *testing.T) { test5242(t) }
func Test8092(t *testing.T) { test8092(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }

View File

@ -0,0 +1,31 @@
// 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.
// Issue 5242. Cgo incorrectly computed the alignment of structs
// with no Go accessible fields as 0, and then panicked on
// modulo-by-zero computations.
package cgotest
/*
typedef struct {
} foo;
typedef struct {
int x : 1;
} bar;
int issue5242(foo f, bar b) {
return 5242;
}
*/
import "C"
import "testing"
func test5242(t *testing.T) {
if got := C.issue5242(C.foo{}, C.bar{}); got != 5242 {
t.Errorf("got %v", got)
}
}

View File

@ -14,13 +14,14 @@ import "C"
//export issue5548FromC
func issue5548FromC(s string, i int) int {
if len(s) == 4 && s == "test" && i == 42 {
return 1
return 12345
}
return 0
println("got", len(s), i)
return 9876
}
func test5548(t *testing.T) {
if C.issue5548_in_c() == 0 {
t.Fail()
if x := C.issue5548_in_c(); x != 12345 {
t.Errorf("issue5548_in_c = %d, want %d", x, 12345)
}
}

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// This test depends on running C code on Go stacks. Not allowed anymore.
// Demo of deferred C function with untrue prototype
// breaking stack copying. See golang.org/issue/7695.

View File

@ -0,0 +1,36 @@
// 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.
// Issue 8092. Test that linker defined symbols (e.g., text, data) don't
// conflict with C symbols.
package cgotest
/*
char text[] = "text";
char data[] = "data";
char *ctext(void) { return text; }
char *cdata(void) { return data; }
*/
import "C"
import "testing"
func test8092(t *testing.T) {
tests := []struct {
s string
a, b *C.char
}{
{"text", &C.text[0], C.ctext()},
{"data", &C.data[0], C.cdata()},
}
for _, test := range tests {
if test.a != test.b {
t.Errorf("%s: pointer mismatch: %v != %v", test.s, test.a, test.b)
}
if got := C.GoString(test.a); got != test.s {
t.Errorf("%s: points at %#v, want %#v", test.s, got, test.s)
}
}
}

View File

@ -0,0 +1,52 @@
// 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.
// This test fails on older versions of OS X because they use older buggy
// versions of Clang that emit ambiguous DWARF info. See issue 8611.
// +build !darwin
package cgotest
// Issue 8428. Cgo inconsistently translated zero size arrays.
/*
struct issue8428one {
char b;
char rest[];
};
struct issue8428two {
void *p;
char b;
char rest[0];
};
struct issue8428three {
char w[1][2][3][0];
char x[2][3][0][1];
char y[3][0][1][2];
char z[0][1][2][3];
};
*/
import "C"
import "unsafe"
var _ = C.struct_issue8428one{
b: C.char(0),
rest: [0]C.char{},
}
var _ = C.struct_issue8428two{
p: unsafe.Pointer(nil),
b: C.char(0),
rest: [0]C.char{},
}
var _ = C.struct_issue8428three{
w: [1][2][3][0]C.char{},
x: [2][3][0][1]C.char{},
y: [3][0][1][2]C.char{},
z: [0][1][2][3]C.char{},
}

View File

@ -56,4 +56,5 @@ typedef struct timespec {
import "C"
type CdefsTest C.struct_cdefsTest
type PackedTest C.struct_packedTest
//type PackedTest C.struct_packedTest

View File

@ -17,6 +17,8 @@ struct CdefsOrig {
int8 **array5[20][20];
};
// Packed structs are no longer supported for -cdefs.
/*
typedef struct PackedOrig PackedOrig;
#pragma pack on
struct PackedOrig {
@ -25,14 +27,15 @@ struct PackedOrig {
int64 third;
};
#pragma pack off
*/
void
main·test(int32 ret)
{
CdefsOrig o;
CdefsTest t;
PackedOrig po;
PackedTest pt;
// PackedOrig po;
// PackedTest pt;
ret = 0;
if(sizeof(t.array1) != sizeof(o.array1) || offsetof(CdefsTest, array1[0]) != offsetof(CdefsOrig, array1[0])) {
@ -55,6 +58,7 @@ main·test(int32 ret)
runtime·printf("array5: size, offset = %d, %d, want %d, %d\n", sizeof(t.array5), offsetof(CdefsTest, array5[0][0]), sizeof(o.array5), offsetof(CdefsOrig, array5[0][0]));
ret = 1;
}
/*
if(sizeof(pt.first) != sizeof(po.first) || offsetof(PackedTest, first) != offsetof(PackedOrig, first)) {
runtime·printf("first: size, offset = %d, %d, want %d, %d\n", sizeof(pt.first), offsetof(PackedTest, first), sizeof(po.first), offsetof(PackedOrig, first));
ret = 1;
@ -67,5 +71,6 @@ main·test(int32 ret)
runtime·printf("third: size, offset = %d, %d, want %d, %d\n", sizeof(pt.third), offsetof(PackedTest, third), sizeof(po.third), offsetof(PackedOrig, third));
ret = 1;
}
*/
FLUSH(&ret); // flush return value
}

View File

@ -30,7 +30,7 @@ import (
"strings"
"code.google.com/p/goauth2/oauth"
"code.google.com/p/google-api-go-client/storage/v1beta2"
storage "code.google.com/p/google-api-go-client/storage/v1beta2"
)
var (
@ -154,6 +154,7 @@ func main() {
log.Fatalln("setupOAuthClient:", err)
}
}
ok := true
for _, targ := range flag.Args() {
var b Build
if m := fileRe.FindStringSubmatch(targ); m != nil {
@ -205,8 +206,12 @@ func main() {
}
if err := b.Do(); err != nil {
log.Printf("%s: %v", targ, err)
ok = false
}
}
if !ok {
os.Exit(1)
}
}
type Build struct {

View File

@ -1,12 +1,14 @@
Native Client
=============
This document outlines the basics of building and developing the Go runtime and programs in the Native Client (NaCl) environment.
This document outlines the basics of building and developing the Go runtime and
programs in the Native Client (NaCl) environment.
Go 1.3 supports three architectures
* nacl/386 which is standard 386.
* nacl/amd64p32 which is a 64 bit architecture, where the address space is limited to a 4gb window.
* nacl/amd64p32 which is a 64 bit architecture, where the address space is
limited to a 4gb window.
* nacl/arm which is 32-bit ARMv7A architecture with 1GB address space.
For background it is recommended that you read http://golang.org/s/go13nacl.
@ -14,34 +16,48 @@ For background it is recommended that you read http://golang.org/s/go13nacl.
Prerequisites
-------------
Native Client programs are executed inside a sandbox, the NaCl runtime. This runtime must be installed before you can use NaCl programs.
Native Client programs are executed inside a sandbox, the NaCl runtime. This
runtime must be installed before you can use NaCl programs.
The NaCl distribution comes with an installer which ensures you have access to the latest version of the runtime. The version tracks the Chrome numbering scheme.
The NaCl distribution comes with an installer which ensures you have access to
the latest version of the runtime. The version tracks the Chrome numbering
scheme.
# Download NaCl
Download nacl_sdk.zip file from https://developers.google.com/native-client/dev/sdk/download, and unpack it. I chose /opt/nacl_sdk
Download nacl_sdk.zip file from
https://developers.google.com/native-client/dev/sdk/download
and unpack it. I chose /opt/nacl_sdk.
# Update
The zip file contains a small skeleton that can be used to download the correct sdk. These are released every 6-8 weeks, in line with Chrome releases.
The zip file contains a small skeleton that can be used to download the correct
sdk. These are released every 6-8 weeks, in line with Chrome releases.
% cd /opt/nacl_sdk
% ./naclsdk update
At this time pepper_33 is the stable version. If naclsdk downloads a later version, please adjust accordingly. As of June 2014, only the canary sdk provides support for nacl/arm.
At this time pepper_34 is the stable version. If naclsdk downloads a later
version, please adjust accordingly. As of June 2014, only the canary sdk
provides support for nacl/arm.
The cmd/go helper scripts expect that the runtime loaders, sel_ldr_{x86_{32,64},arm} and nacl_helper_bootstrap_arm are in your path. I find it easiest to make a symlink from the NaCl distribution to my $GOPATH/bin directory.
The cmd/go helper scripts expect that the loaders sel_ldr_{x86_{32,64},arm} and
nacl_helper_bootstrap_arm are in your path. I find it easiest to make a symlink
from the NaCl distribution to my $GOPATH/bin directory.
% ln -nfs /opt/nacl_sdk/pepper_33/tools/sel_ldr_x86_32 $GOPATH/bin/sel_ldr_x86_32
% ln -nfs /opt/nacl_sdk/pepper_33/tools/sel_ldr_x86_64 $GOPATH/bin/sel_ldr_x86_64
% ln -nfs /opt/nacl_sdk/pepper_34/tools/sel_ldr_x86_32 $GOPATH/bin/sel_ldr_x86_32
% ln -nfs /opt/nacl_sdk/pepper_34/tools/sel_ldr_x86_64 $GOPATH/bin/sel_ldr_x86_64
% ln -nfs /opt/nacl_sdk/pepper_canary/tools/sel_ldr_arm $GOPATH/bin/sel_ldr_arm
% ln -nfs /opt/nacl_sdk/pepper_canary/tools/nacl_helper_bootstrap_arm $GOPATH/bin/nacl_helper_bootstrap_arm # only required for NaCl/ARM.
Additionally, for NaCl/ARM only:
% ln -nfs /opt/nacl_sdk/pepper_canary/tools/nacl_helper_bootstrap_arm $GOPATH/bin/nacl_helper_bootstrap_arm
Support scripts
---------------
Symlink the two scripts in this directory into your $PATH, just as you did with NaCl sdk above.
Symlink the two scripts in this directory into your $PATH, just as you did with
NaCl sdk above.
% ln -nfs $GOROOT/go/misc/nacl/go_nacl_amd64p32_exec $GOPATH/bin/go_nacl_amd64p32_exec
% ln -nfs $GOROOT/go/misc/nacl/go_nacl_386_exec $GOPATH/bin/go_nacl_386_exec
@ -50,18 +66,57 @@ Symlink the two scripts in this directory into your $PATH, just as you did with
Building and testing
--------------------
Building for NaCl is similar to cross compiling for other platforms. However, as it is not possible to ever build in a `native` NaCl environment, the cmd/go tool has been enhanced to allow the full build, all.bash, to be executed, rather than just the compile stage, make.bash.
Building for NaCl is similar to cross compiling for other platforms. However,
as it is not possible to ever build in a `native` NaCl environment, the cmd/go
tool has been enhanced to allow the full build, all.bash, to be executed,
rather than just the compile stage, make.bash.
The cmd/go tool knows that if GOOS is set to `nacl` it should not try to execute any binaries itself. Instead it passes their execution to a support script which sets up a Native Client environment and invokes the NaCl sandbox.
The cmd/go tool knows that if GOOS is set to `nacl` it should not try to
execute any binaries itself. Instead it passes their execution to a support
script which sets up a Native Client environment and invokes the NaCl sandbox.
The script's name has a special format, go_$GOOS_$GOARCH_exec, so cmd/go can find it.
The script's name has a special format, go_$GOOS_$GOARCH_exec, so cmd/go can
find it.
In short, if the support scripts are in place, the cmd/go tool can be used as per normal.
In short, if the support scripts are in place, the cmd/go tool can be used as
per normal.
# Build and test Go for NaCl
NaCl does not permit direct file system access. Instead, package syscall provides a simulated file system served by in-memory data. The script nacltest.bash is the NaCl equivalent of all.bash. It builds NaCl with an in-memory file system containing files needed for tests, and then it runs the tests.
NaCl does not permit direct file system access. Instead, package syscall
provides a simulated file system served by in-memory data. The script
nacltest.bash is the NaCl equivalent of all.bash. It builds NaCl with an
in-memory file system containing files needed for tests, and then it runs the
tests.
% cd go/src
% env GOARCH=amd64p32 ./nacltest.bash
Debugging
---------
Assuming that you have built nacl/amd64p32 binary ./mybin and can run as:
% sel_ldr_x86_64 -l /dev/null -S -e ./mybin
Create the nacl manifest file mybin.manifest with the following contents:
{ "program": { "x86-64": { "url": "mybin" } } }
url is the path to the binary relative to the manifest file.
Then, run the program as:
% sel_ldr_x86_64 -g -l /dev/null -S -e ./mybin
The -g flag instructs the loader to stop at startup. Then, in another console:
% /opt/nacl_sdk/pepper_34/toolchain/linux_x86_glibc/bin/x86_64-nacl-gdb
% nacl-manifest mybin.manifest
% target remote :4014
If you see that the program is stopped in _rt0_amd64p32_nacl, then symbols are
loaded successfully and you can type 'c' to start the program.
Next time you can automate it as:
% /opt/nacl_sdk/pepper_34/toolchain/linux_x86_glibc/bin/x86_64-nacl-gdb \
-ex 'nacl-manifest mybin.manifest' -ex 'target remote :4014'

View File

@ -10,7 +10,12 @@ usr src=../misc/nacl/testdata
go src=..
src
cmd
internal
objfile
objfile.go
gofmt
gofmt.go
gofmt_test.go
testdata
+
link

View File

@ -47,7 +47,9 @@ ln -s $GOROOT/src/cmd $FAKE_GOROOT/src/cmd
ln -s $GOROOT/src/pkg $FAKE_GOROOT/src/pkg
ln -s $GOROOT/test $FAKE_GOROOT/test
ln -s $GOROOT/lib $FAKE_GOROOT/lib
adb sync data
echo '# Syncing test files to android device'
time adb sync data &> /dev/null
echo ''
rm -rf "$ANDROID_PRODUCT_OUT"
# Run standard build and tests.

View File

@ -46,7 +46,7 @@ _cgen(Node *n, Node *nn, int inrel)
}
if(n == Z || n->type == T)
return;
if(typesuv[n->type->etype]) {
if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
sugen(n, nn, n->type->width);
return;
}
@ -75,7 +75,7 @@ _cgen(Node *n, Node *nn, int inrel)
if(r != Z && r->complex >= FNX)
switch(o) {
default:
regret(&nod, r);
regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
@ -107,7 +107,7 @@ _cgen(Node *n, Node *nn, int inrel)
if(l->addable >= INDEXED && l->complex < FNX) {
if(nn != Z || r->addable < INDEXED) {
if(r->complex >= FNX && nn == Z)
regret(&nod, r);
regret(&nod, r, 0, 0);
else
regalloc(&nod, r, nn);
cgen(r, &nod);
@ -348,7 +348,7 @@ _cgen(Node *n, Node *nn, int inrel)
if(l->op != OIND)
diag(n, "bad function call");
regret(&nod, l->left);
regret(&nod, l->left, 0, 0);
cgen(l->left, &nod);
regsalloc(&nod1, l->left);
gopcode(OAS, &nod, Z, &nod1);
@ -377,11 +377,11 @@ _cgen(Node *n, Node *nn, int inrel)
if(REGARG >= 0)
if(o != reg[REGARG])
reg[REGARG]--;
if(nn != Z) {
regret(&nod, n);
gopcode(OAS, &nod, Z, nn);
regret(&nod, n, l->type, 1);
if(nn != Z)
gmove(&nod, nn);
if(nod.op == OREGISTER)
regfree(&nod);
}
break;
case OIND:
@ -823,7 +823,7 @@ boolgen(Node *n, int true, Node *nn)
if(true)
o = comrel[relindex(o)];
if(l->complex >= FNX && r->complex >= FNX) {
regret(&nod, r);
regret(&nod, r, 0, 0);
cgenrel(r, &nod);
regsalloc(&nod1, r);
gopcode(OAS, &nod, Z, &nod1);
@ -957,7 +957,7 @@ sugen(Node *n, Node *nn, int32 w)
if(nn != Z && side(nn)) {
nod1 = *n;
nod1.type = typ(TIND, n->type);
regret(&nod2, &nod1);
regret(&nod2, &nod1, 0, 0);
lcgen(nn, &nod2);
regsalloc(&nod0, &nod1);
gopcode(OAS, &nod2, Z, &nod0);
@ -1036,6 +1036,20 @@ sugen(Node *n, Node *nn, int32 w)
break;
case OFUNC:
if(!hasdotdotdot(n->left->type)) {
cgen(n, Z);
if(nn != Z) {
curarg -= n->type->width;
regret(&nod1, n, n->left->type, 1);
if(nn->complex >= FNX) {
regsalloc(&nod2, n);
cgen(&nod1, &nod2);
nod1 = nod2;
}
cgen(&nod1, nn);
}
break;
}
if(nn == Z) {
sugen(n, nodrat, w);
break;

View File

@ -210,7 +210,7 @@ void usedset(Node*, int);
void xcom(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
vlong argsize(void);
vlong argsize(int);
/*
* cgen.c
@ -236,7 +236,7 @@ Node* nodconst(int32);
Node* nod32const(vlong);
Node* nodfconst(double);
void nodreg(Node*, Node*, int);
void regret(Node*, Node*);
void regret(Node*, Node*, Type*, int);
int tmpreg(void);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);

View File

@ -36,7 +36,7 @@ gtext(Sym *s, int32 stkoff)
{
int32 a;
a = argsize();
a = argsize(1);
if((textflag & NOSPLIT) != 0 && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");

View File

@ -374,10 +374,11 @@ align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
int w;
int w, packw;
o = i;
w = 1;
packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
@ -388,7 +389,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1)
w = 1;
if(packflg)
w = packflg;
packw = packflg;
break;
case Ael1: /* initial align of struct element */
@ -404,7 +405,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1 || w > SZ_LONG)
fatal(Z, "align");
if(packflg)
w = packflg;
packw = packflg;
break;
case Ael2: /* width of a struct element */
@ -440,6 +441,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
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 != nil && *maxalign < w)
*maxalign = w;

View File

@ -274,15 +274,43 @@ nodreg(Node *n, Node *nn, int reg)
}
void
regret(Node *n, Node *nn)
regret(Node *n, Node *nn, Type *t, int mode)
{
int r;
r = REGRET;
if(typefd[nn->type->etype])
r = FREGRET+NREG;
nodreg(n, nn, r);
reg[r]++;
if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
r = REGRET;
if(typefd[nn->type->etype])
r = FREGRET+NREG;
nodreg(n, nn, r);
reg[r]++;
return;
}
if(mode == 1) {
// fetch returned value after call.
// already called gargs, so curarg is set.
curarg = (curarg+3) & ~3;
regaalloc(n, nn);
return;
}
if(mode == 2) {
// store value to be returned.
// must compute arg offset.
if(t->etype != TFUNC)
fatal(Z, "bad regret func %T", t);
*n = *nn;
n->op = ONAME;
n->class = CPARAM;
n->sym = slookup(".ret");
n->complex = nodret->complex;
n->xoffset = argsize(0);
n->addable = 20;
return;
}
fatal(Z, "bad regret");
}
int

View File

@ -254,7 +254,6 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
goto sbop;
@ -1635,7 +1634,10 @@ int
componentgen(Node *nr, Node *nl)
{
Node nodl, nodr, tmp;
Type *t;
int freel, freer;
vlong fldcount;
vlong loffset, roffset;
freel = 0;
freer = 0;
@ -1645,8 +1647,33 @@ componentgen(Node *nr, Node *nl)
goto no;
case TARRAY:
if(!isslice(nl->type))
t = nl->type;
// Slices are ok.
if(isslice(t))
break;
// Small arrays are ok.
if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
break;
goto no;
case TSTRUCT:
// Small structs with non-fat types are ok.
// Zero-sized structs are treated separately elsewhere.
fldcount = 0;
for(t=nl->type->type; t; t=t->down) {
if(isfat(t->type))
goto no;
if(t->etype != TFIELD)
fatal("componentgen: not a TFIELD: %lT", t);
fldcount++;
}
if(fldcount == 0 || fldcount > 4)
goto no;
break;
case TSTRING:
case TINTER:
break;
@ -1674,6 +1701,7 @@ componentgen(Node *nr, Node *nl)
freer = 1;
}
// nl and nr are 'cadable' which basically means they are names (variables) now.
// If they are the same variable, don't generate any code, because the
// VARDEF we generate will mark the old value as dead incorrectly.
@ -1683,8 +1711,25 @@ componentgen(Node *nr, Node *nl)
switch(nl->type->etype) {
case TARRAY:
// componentgen for arrays.
if(nl->op == ONAME)
gvardef(nl);
t = nl->type;
if(!isslice(t)) {
nodl.type = t->type;
nodr.type = nodl.type;
for(fldcount=0; fldcount < t->bound; fldcount++) {
if(nr == N)
clearslim(&nodl);
else
gmove(&nodr, &nodl);
nodl.xoffset += t->type->width;
nodr.xoffset += t->type->width;
}
goto yes;
}
// componentgen for slices.
nodl.xoffset += Array_array;
nodl.type = ptrto(nl->type->type);
@ -1759,6 +1804,31 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
goto yes;
case TSTRUCT:
if(nl->op == ONAME)
gvardef(nl);
loffset = nodl.xoffset;
roffset = nodr.xoffset;
// funarg structs may not begin at offset zero.
if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
loffset -= nl->type->type->width;
if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
roffset -= nr->type->type->width;
for(t=nl->type->type; t; t=t->down) {
nodl.xoffset = loffset + t->width;
nodl.type = t->type;
if(nr == N)
clearslim(&nodl);
else {
nodr.xoffset = roffset + t->width;
nodr.type = nodl.type;
gmove(&nodr, &nodl);
}
}
goto yes;
}
no:

View File

@ -1599,7 +1599,6 @@ optoas(int op, Type *t)
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
case CASE(OADDPTR, TPTR32):
a = AADD;
break;

View File

@ -1315,6 +1315,7 @@ void
addreg(Adr *a, int rn)
{
a->sym = nil;
a->node = nil;
a->name = D_NONE;
a->type = D_REG;
a->reg = rn;

View File

@ -599,10 +599,10 @@ asmb(void)
if(iself)
goto ElfSym;
case Hplan9:
symo = HEADR+segtext.len+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
break;
ElfSym:
symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
symo = rnd(symo, INITRND);
break;
}

View File

@ -435,49 +435,49 @@ struct
"IRETQ", LTYPE0, AIRETQ,
"IRETW", LTYPE0, AIRETW,
"JOS", LTYPER, AJOS,
"JOS", LTYPER, AJOS, /* overflow set (OF = 1) */
"JO", LTYPER, AJOS, /* alternate */
"JOC", LTYPER, AJOC,
"JOC", LTYPER, AJOC, /* overflow clear (OF = 0) */
"JNO", LTYPER, AJOC, /* alternate */
"JCS", LTYPER, AJCS,
"JCS", LTYPER, AJCS, /* carry set (CF = 1) */
"JB", LTYPER, AJCS, /* alternate */
"JC", LTYPER, AJCS, /* alternate */
"JNAE", LTYPER, AJCS, /* alternate */
"JLO", LTYPER, AJCS, /* alternate */
"JCC", LTYPER, AJCC,
"JCC", LTYPER, AJCC, /* carry clear (CF = 0) */
"JAE", LTYPER, AJCC, /* alternate */
"JNB", LTYPER, AJCC, /* alternate */
"JNC", LTYPER, AJCC, /* alternate */
"JHS", LTYPER, AJCC, /* alternate */
"JEQ", LTYPER, AJEQ,
"JEQ", LTYPER, AJEQ, /* equal (ZF = 1) */
"JE", LTYPER, AJEQ, /* alternate */
"JZ", LTYPER, AJEQ, /* alternate */
"JNE", LTYPER, AJNE,
"JNE", LTYPER, AJNE, /* not equal (ZF = 0) */
"JNZ", LTYPER, AJNE, /* alternate */
"JLS", LTYPER, AJLS,
"JLS", LTYPER, AJLS, /* lower or same (unsigned) (CF = 1 || ZF = 1) */
"JBE", LTYPER, AJLS, /* alternate */
"JNA", LTYPER, AJLS, /* alternate */
"JHI", LTYPER, AJHI,
"JHI", LTYPER, AJHI, /* higher (unsigned) (CF = 0 && ZF = 0) */
"JA", LTYPER, AJHI, /* alternate */
"JNBE", LTYPER, AJHI, /* alternate */
"JMI", LTYPER, AJMI,
"JMI", LTYPER, AJMI, /* negative (minus) (SF = 1) */
"JS", LTYPER, AJMI, /* alternate */
"JPL", LTYPER, AJPL,
"JPL", LTYPER, AJPL, /* non-negative (plus) (SF = 0) */
"JNS", LTYPER, AJPL, /* alternate */
"JPS", LTYPER, AJPS,
"JPS", LTYPER, AJPS, /* parity set (PF = 1) */
"JP", LTYPER, AJPS, /* alternate */
"JPE", LTYPER, AJPS, /* alternate */
"JPC", LTYPER, AJPC,
"JPC", LTYPER, AJPC, /* parity clear (PF = 0) */
"JNP", LTYPER, AJPC, /* alternate */
"JPO", LTYPER, AJPC, /* alternate */
"JLT", LTYPER, AJLT,
"JLT", LTYPER, AJLT, /* less than (signed) (SF != OF) */
"JL", LTYPER, AJLT, /* alternate */
"JNGE", LTYPER, AJLT, /* alternate */
"JGE", LTYPER, AJGE,
"JGE", LTYPER, AJGE, /* greater than or equal (signed) (SF = OF) */
"JNL", LTYPER, AJGE, /* alternate */
"JLE", LTYPER, AJLE,
"JLE", LTYPER, AJLE, /* less than or equal (signed) (ZF = 1 || SF != OF) */
"JNG", LTYPER, AJLE, /* alternate */
"JGT", LTYPER, AJGT,
"JGT", LTYPER, AJGT, /* greater than (signed) (ZF = 0 && SF = OF) */
"JG", LTYPER, AJGT, /* alternate */
"JNLE", LTYPER, AJGT, /* alternate */
"JCXZL", LTYPER, AJCXZL,
@ -612,7 +612,7 @@ struct
"SCASL", LTYPE0, ASCASL,
"SCASQ", LTYPE0, ASCASQ,
"SCASW", LTYPE0, ASCASW,
"SETCC", LTYPE1, ASETCC,
"SETCC", LTYPE1, ASETCC, /* see JCC etc above for condition codes */
"SETCS", LTYPE1, ASETCS,
"SETEQ", LTYPE1, ASETEQ,
"SETGE", LTYPE1, ASETGE,

View File

@ -51,7 +51,7 @@ cgen(Node *n, Node *nn)
}
if(n == Z || n->type == T)
return;
if(typesu[n->type->etype]) {
if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
sugen(n, nn, n->type->width);
return;
}
@ -88,7 +88,7 @@ cgen(Node *n, Node *nn)
if(cond(o) && typesu[l->type->etype])
break;
regret(&nod, r);
regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
@ -135,7 +135,7 @@ cgen(Node *n, Node *nn)
if(!hardleft) {
if(nn != Z || r->addable < INDEXED || hardconst(r)) {
if(r->complex >= FNX && nn == Z)
regret(&nod, r);
regret(&nod, r, 0, 0);
else
regalloc(&nod, r, nn);
cgen(r, &nod);
@ -929,7 +929,7 @@ cgen(Node *n, Node *nn)
if(l->op != OIND)
diag(n, "bad function call");
regret(&nod, l->left);
regret(&nod, l->left, 0, 0);
cgen(l->left, &nod);
regsalloc(&nod1, l->left);
gmove(&nod, &nod1);
@ -956,11 +956,13 @@ cgen(Node *n, Node *nn)
gpcdata(PCDATA_ArgSize, -1);
if(REGARG >= 0 && reg[REGARG])
reg[REGARG]--;
if(nn != Z) {
regret(&nod, n);
regret(&nod, n, l->type, 1); // update maxarg if nothing else
gpcdata(PCDATA_ArgSize, curarg);
gpcdata(PCDATA_ArgSize, -1);
if(nn != Z)
gmove(&nod, nn);
if(nod.op == OREGISTER)
regfree(&nod);
}
break;
case OIND:
@ -1382,7 +1384,7 @@ boolgen(Node *n, int true, Node *nn)
if(true)
o = comrel[relindex(o)];
if(l->complex >= FNX && r->complex >= FNX) {
regret(&nod, r);
regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
gmove(&nod, &nod1);
@ -1535,7 +1537,7 @@ sugen(Node *n, Node *nn, int32 w)
if(nn != Z && side(nn)) {
nod1 = *n;
nod1.type = typ(TIND, n->type);
regret(&nod2, &nod1);
regret(&nod2, &nod1, 0, 0);
lcgen(nn, &nod2);
regsalloc(&nod0, &nod1);
cgen(&nod2, &nod0);
@ -1617,6 +1619,20 @@ sugen(Node *n, Node *nn, int32 w)
break;
case OFUNC:
if(!hasdotdotdot(n->left->type)) {
cgen(n, Z);
if(nn != Z) {
curarg -= n->type->width;
regret(&nod1, n, n->left->type, 1);
if(nn->complex >= FNX) {
regsalloc(&nod2, n);
cgen(&nod1, &nod2);
nod1 = nod2;
}
cgen(&nod1, nn);
}
break;
}
if(nn == Z) {
sugen(n, nodrat, w);
break;

View File

@ -210,7 +210,7 @@ void xcom(Node*);
void indx(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
vlong argsize(void);
vlong argsize(int);
/*
* cgen.c
@ -239,7 +239,7 @@ Node* nodfconst(double);
Node* nodgconst(vlong, Type*);
int nodreg(Node*, Node*, int);
int isreg(Node*, int);
void regret(Node*, Node*);
void regret(Node*, Node*, Type*, int);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
void regialloc(Node*, Node*, Node*);

View File

@ -36,7 +36,7 @@ gtext(Sym *s, int32 stkoff)
{
vlong v;
v = ((uvlong)argsize() << 32) | (stkoff & 0xffffffff);
v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
if((textflag & NOSPLIT) && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");
@ -124,10 +124,7 @@ xcom(Node *n)
break;
case ONAME:
if(flag_largemodel)
n->addable = 9;
else
n->addable = 10;
n->addable = 9;
if(n->class == CPARAM || n->class == CAUTO)
n->addable = 11;
break;

View File

@ -250,10 +250,11 @@ align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
int w;
int w, packw;
o = i;
w = 1;
packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
@ -264,7 +265,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1)
w = 1;
if(packflg)
w = packflg;
packw = packflg;
break;
case Ael1: /* initial align of struct element */
@ -277,7 +278,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1 || w > SZ_VLONG)
fatal(Z, "align");
if(packflg)
w = packflg;
packw = packflg;
break;
case Ael2: /* width of a struct element */
@ -331,6 +332,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
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;

View File

@ -351,15 +351,43 @@ nodreg(Node *n, Node *nn, int r)
}
void
regret(Node *n, Node *nn)
regret(Node *n, Node *nn, Type *t, int mode)
{
int r;
if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
r = REGRET;
if(typefd[nn->type->etype])
r = FREGRET;
nodreg(n, nn, r);
reg[r]++;
return;
}
if(mode == 1) {
// fetch returned value after call.
// already called gargs, so curarg is set.
curarg = (curarg+7) & ~7;
regaalloc(n, nn);
return;
}
r = REGRET;
if(typefd[nn->type->etype])
r = FREGRET;
nodreg(n, nn, r);
reg[r]++;
if(mode == 2) {
// store value to be returned.
// must compute arg offset.
if(t->etype != TFUNC)
fatal(Z, "bad regret func %T", t);
*n = *nn;
n->op = ONAME;
n->class = CPARAM;
n->sym = slookup(".ret");
n->complex = nodret->complex;
n->addable = 20;
n->xoffset = argsize(0);
return;
}
fatal(Z, "bad regret");
}
void

View File

@ -247,7 +247,6 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
if(a == AIMULB) {
@ -752,12 +751,7 @@ agenr(Node *n, Node *a, Node *res)
regalloc(&n3, types[tptr], res);
p1 = gins(ALEAQ, N, &n3);
datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
if(flag_largemodel) {
gins(AADDQ, &n2, &n3);
} else {
p1->from.scale = 1;
p1->from.index = n2.val.u.reg;
}
gins(AADDQ, &n2, &n3);
goto indexdone;
}

View File

@ -51,7 +51,6 @@ void allocparams(void);
void checklabels(void);
void ginscall(Node*, int);
int gen_as_init(Node*);
void clearslim(Node*);
/*
* cgen.c

View File

@ -943,7 +943,7 @@ cgen_hmul(Node *nl, Node *nr, Node *res)
if(t->width == 1) {
// byte multiply behaves differently.
nodreg(&ax, t, D_AH);
nodreg(&dx, t, D_DL);
nodreg(&dx, t, D_DX);
gmove(&ax, &dx);
}
nodreg(&dx, t, D_DX);

View File

@ -598,11 +598,8 @@ ismem(Node *n)
case ONAME:
case OPARAM:
case OCLOSUREVAR:
return 1;
case OADDR:
if(flag_largemodel)
return 1;
break;
return 1;
}
return 0;
}
@ -1540,14 +1537,12 @@ optoas(int op, Type *t)
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
case CASE(OADDPTR, TPTR32):
a = AADDL;
break;
case CASE(OADD, TINT64):
case CASE(OADD, TUINT64):
case CASE(OADD, TPTR64):
case CASE(OADDPTR, TPTR64):
a = AADDQ;
break;

View File

@ -838,6 +838,11 @@ copyu(Prog *p, Adr *v, Adr *s)
static int
copyas(Adr *a, Adr *v)
{
if(D_AL <= a->type && a->type <= D_R15B)
fatal("use of byte register");
if(D_AL <= v->type && v->type <= D_R15B)
fatal("use of byte register");
if(a->type != v->type)
return 0;
if(regtyp(v))

View File

@ -844,7 +844,7 @@ prop(Reg *r, Bits ref, Bits cal)
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
for(; v1 != nil; v1 = v1->nextinnode) {
j = v1 - var;
cal.b[j/32] |= 1<<(j&31);
cal.b[j/32] |= 1UL<<(j&31);
}
}
}
@ -1191,6 +1191,7 @@ void
addreg(Adr *a, int rn)
{
a->sym = nil;
a->node = nil;
a->offset = 0;
a->type = rn;

View File

@ -290,7 +290,6 @@ elfreloc1(Reloc *r, vlong sectoff)
break;
case R_CALL:
case R_PCREL:
if(r->siz == 4) {
if(r->xsym->type == SDYNIMPORT)
VPUT(R_X86_64_GOTPCREL | (uint64)elfsym<<32);
@ -299,7 +298,14 @@ elfreloc1(Reloc *r, vlong sectoff)
} else
return -1;
break;
case R_PCREL:
if(r->siz == 4) {
VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
} else
return -1;
break;
case R_TLS:
if(r->siz == 4) {
if(flag_shared)
@ -323,7 +329,7 @@ machoreloc1(Reloc *r, vlong sectoff)
rs = r->xsym;
if(rs->type == SHOSTOBJ) {
if(rs->type == SHOSTOBJ || r->type == R_PCREL) {
if(rs->dynid < 0) {
diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
return -1;
@ -345,10 +351,13 @@ machoreloc1(Reloc *r, vlong sectoff)
v |= MACHO_X86_64_RELOC_UNSIGNED<<28;
break;
case R_CALL:
case R_PCREL:
v |= 1<<24; // pc-relative bit
v |= MACHO_X86_64_RELOC_BRANCH<<28;
break;
case R_PCREL:
// NOTE: Only works with 'external' relocation. Forced above.
v |= 1<<24; // pc-relative bit
v |= MACHO_X86_64_RELOC_SIGNED<<28;
}
switch(r->siz) {
@ -689,10 +698,10 @@ asmb(void)
case Hplan9:
case Helf:
debug['s'] = 1;
symo = HEADR+segtext.len+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
break;
case Hdarwin:
symo = rnd(HEADR+segtext.len, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
symo = segdata.fileoff+rnd(segdata.filelen, INITRND)+machlink;
break;
case Hlinux:
case Hfreebsd:
@ -701,11 +710,11 @@ asmb(void)
case Hdragonfly:
case Hsolaris:
case Hnacl:
symo = rnd(HEADR+segtext.len, INITRND)+rnd(segrodata.len, INITRND)+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
symo = rnd(symo, INITRND);
break;
case Hwindows:
symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
symo = rnd(symo, PEFILEALIGN);
break;
}

View File

@ -352,49 +352,49 @@ struct
"IRETL", LTYPE0, AIRETL,
"IRETW", LTYPE0, AIRETW,
"JOS", LTYPER, AJOS,
"JOS", LTYPER, AJOS, /* overflow set (OF = 1) */
"JO", LTYPER, AJOS, /* alternate */
"JOC", LTYPER, AJOC,
"JOC", LTYPER, AJOC, /* overflow clear (OF = 0) */
"JNO", LTYPER, AJOC, /* alternate */
"JCS", LTYPER, AJCS,
"JCS", LTYPER, AJCS, /* carry set (CF = 1) */
"JB", LTYPER, AJCS, /* alternate */
"JC", LTYPER, AJCS, /* alternate */
"JNAE", LTYPER, AJCS, /* alternate */
"JLO", LTYPER, AJCS, /* alternate */
"JCC", LTYPER, AJCC,
"JCC", LTYPER, AJCC, /* carry clear (CF = 0) */
"JAE", LTYPER, AJCC, /* alternate */
"JNB", LTYPER, AJCC, /* alternate */
"JNC", LTYPER, AJCC, /* alternate */
"JHS", LTYPER, AJCC, /* alternate */
"JEQ", LTYPER, AJEQ,
"JEQ", LTYPER, AJEQ, /* equal (ZF = 1) */
"JE", LTYPER, AJEQ, /* alternate */
"JZ", LTYPER, AJEQ, /* alternate */
"JNE", LTYPER, AJNE,
"JNE", LTYPER, AJNE, /* not equal (ZF = 0) */
"JNZ", LTYPER, AJNE, /* alternate */
"JLS", LTYPER, AJLS,
"JLS", LTYPER, AJLS, /* lower or same (unsigned) (CF = 1 || ZF = 1) */
"JBE", LTYPER, AJLS, /* alternate */
"JNA", LTYPER, AJLS, /* alternate */
"JHI", LTYPER, AJHI,
"JHI", LTYPER, AJHI, /* higher (unsigned) (CF = 0 && ZF = 0) */
"JA", LTYPER, AJHI, /* alternate */
"JNBE", LTYPER, AJHI, /* alternate */
"JMI", LTYPER, AJMI,
"JMI", LTYPER, AJMI, /* negative (minus) (SF = 1) */
"JS", LTYPER, AJMI, /* alternate */
"JPL", LTYPER, AJPL,
"JPL", LTYPER, AJPL, /* non-negative (plus) (SF = 0) */
"JNS", LTYPER, AJPL, /* alternate */
"JPS", LTYPER, AJPS,
"JPS", LTYPER, AJPS, /* parity set (PF = 1) */
"JP", LTYPER, AJPS, /* alternate */
"JPE", LTYPER, AJPS, /* alternate */
"JPC", LTYPER, AJPC,
"JPC", LTYPER, AJPC, /* parity clear (PF = 0) */
"JNP", LTYPER, AJPC, /* alternate */
"JPO", LTYPER, AJPC, /* alternate */
"JLT", LTYPER, AJLT,
"JLT", LTYPER, AJLT, /* less than (signed) (SF != OF) */
"JL", LTYPER, AJLT, /* alternate */
"JNGE", LTYPER, AJLT, /* alternate */
"JGE", LTYPER, AJGE,
"JGE", LTYPER, AJGE, /* greater than or equal (signed) (SF = OF) */
"JNL", LTYPER, AJGE, /* alternate */
"JLE", LTYPER, AJLE,
"JLE", LTYPER, AJLE, /* less than or equal (signed) (ZF = 1 || SF != OF) */
"JNG", LTYPER, AJLE, /* alternate */
"JGT", LTYPER, AJGT,
"JGT", LTYPER, AJGT, /* greater than (signed) (ZF = 0 && SF = OF) */
"JG", LTYPER, AJGT, /* alternate */
"JNLE", LTYPER, AJGT, /* alternate */
@ -493,7 +493,7 @@ struct
"SCASB", LTYPE0, ASCASB,
"SCASL", LTYPE0, ASCASL,
"SCASW", LTYPE0, ASCASW,
"SETCC", LTYPE1, ASETCC,
"SETCC", LTYPE1, ASETCC, /* see JCC etc above for condition codes */
"SETCS", LTYPE1, ASETCS,
"SETEQ", LTYPE1, ASETEQ,
"SETGE", LTYPE1, ASETGE,

View File

@ -49,7 +49,7 @@ cgen(Node *n, Node *nn)
}
if(n == Z || n->type == T)
return;
if(typesuv[n->type->etype]) {
if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
sugen(n, nn, n->type->width);
return;
}
@ -86,7 +86,7 @@ cgen(Node *n, Node *nn)
if(cond(o) && typesuv[l->type->etype])
break;
regret(&nod, r);
regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
@ -147,7 +147,7 @@ cgen(Node *n, Node *nn)
if(!hardleft) {
if(nn != Z || r->addable < INDEXED) {
if(r->complex >= FNX && nn == Z)
regret(&nod, r);
regret(&nod, r, 0, 0);
else
regalloc(&nod, r, nn);
cgen(r, &nod);
@ -922,7 +922,7 @@ cgen(Node *n, Node *nn)
if(l->op != OIND)
diag(n, "bad function call");
regret(&nod, l->left);
regret(&nod, l->left, 0, 0);
cgen(l->left, &nod);
regsalloc(&nod1, l->left);
gmove(&nod, &nod1);
@ -949,12 +949,12 @@ cgen(Node *n, Node *nn)
gpcdata(PCDATA_ArgSize, -1);
if(REGARG >= 0 && reg[REGARG])
reg[REGARG]--;
if(nn != Z) {
regret(&nod, n);
regret(&nod, n, l->type, 1); // update maxarg if nothing else
if(nn != Z)
gmove(&nod, nn);
if(nod.op == OREGISTER)
regfree(&nod);
} else
if(typefd[n->type->etype])
if(nn == Z && hasdotdotdot(l->type) && typefd[n->type->etype])
gins(AFMOVDP, &fregnode0, &fregnode0);
break;
@ -1374,7 +1374,7 @@ boolgen(Node *n, int true, Node *nn)
if(true)
o = comrel[relindex(o)];
if(l->complex >= FNX && r->complex >= FNX) {
regret(&nod, r);
regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
gmove(&nod, &nod1);
@ -1567,7 +1567,7 @@ sugen(Node *n, Node *nn, int32 w)
if(nn != Z && side(nn)) {
nod1 = *n;
nod1.type = typ(TIND, n->type);
regret(&nod2, &nod1);
regret(&nod2, &nod1, 0, 0);
lcgen(nn, &nod2);
regsalloc(&nod0, &nod1);
cgen(&nod2, &nod0);
@ -1649,6 +1649,20 @@ sugen(Node *n, Node *nn, int32 w)
break;
case OFUNC:
if(!hasdotdotdot(n->left->type)) {
cgen(n, Z);
if(nn != Z) {
curarg -= n->type->width;
regret(&nod1, n, n->left->type, 1);
if(nn->complex >= FNX) {
regsalloc(&nod2, n);
cgen(&nod1, &nod2);
nod1 = nod2;
}
cgen(&nod1, nn);
}
break;
}
if(nn == Z) {
sugen(n, nodrat, w);
break;

View File

@ -210,7 +210,7 @@ void xcom(Node*);
void indx(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
vlong argsize(void);
vlong argsize(int);
/*
* cgen.c
@ -244,7 +244,7 @@ Node* nodconst(int32);
Node* nodfconst(double);
int nodreg(Node*, Node*, int);
int isreg(Node*, int);
void regret(Node*, Node*);
void regret(Node*, Node*, Type*, int);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
void regialloc(Node*, Node*, Node*);

View File

@ -35,7 +35,7 @@ gtext(Sym *s, int32 stkoff)
{
int32 a;
a = argsize();
a = argsize(1);
if((textflag & NOSPLIT) != 0 && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");

View File

@ -255,10 +255,11 @@ align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
int w;
int w, packw;
o = i;
w = 1;
packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
@ -269,7 +270,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1)
w = 1;
if(packflg)
w = packflg;
packw = packflg;
break;
case Ael1: /* initial align of struct element */
@ -285,7 +286,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1 || w > SZ_LONG)
fatal(Z, "align");
if(packflg)
w = packflg;
packw = packflg;
break;
case Ael2: /* width of a struct element */
@ -320,6 +321,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
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;

View File

@ -311,15 +311,43 @@ nodreg(Node *n, Node *nn, int r)
}
void
regret(Node *n, Node *nn)
regret(Node *n, Node *nn, Type *t, int mode)
{
int r;
r = REGRET;
if(typefd[nn->type->etype])
r = FREGRET;
nodreg(n, nn, r);
reg[r]++;
if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
r = REGRET;
if(typefd[nn->type->etype])
r = FREGRET;
nodreg(n, nn, r);
reg[r]++;
return;
}
if(mode == 1) {
// fetch returned value after call.
// already called gargs, so curarg is set.
curarg = (curarg+3) & ~3;
regaalloc(n, nn);
return;
}
if(mode == 2) {
// store value to be returned.
// must compute arg offset.
if(t->etype != TFUNC)
fatal(Z, "bad regret func %T", t);
*n = *nn;
n->op = ONAME;
n->class = CPARAM;
n->sym = slookup(".retx");
n->complex = 0;
n->addable = 20;
n->xoffset = argsize(0);
return;
}
fatal(Z, "bad regret");
}
void

View File

@ -242,7 +242,6 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
if(a == AIMULB) {
@ -1367,7 +1366,10 @@ int
componentgen(Node *nr, Node *nl)
{
Node nodl, nodr;
Type *t;
int freel, freer;
vlong fldcount;
vlong loffset, roffset;
freel = 0;
freer = 0;
@ -1377,8 +1379,33 @@ componentgen(Node *nr, Node *nl)
goto no;
case TARRAY:
if(!isslice(nl->type))
t = nl->type;
// Slices are ok.
if(isslice(t))
break;
// Small arrays are ok.
if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
break;
goto no;
case TSTRUCT:
// Small structs with non-fat types are ok.
// Zero-sized structs are treated separately elsewhere.
fldcount = 0;
for(t=nl->type->type; t; t=t->down) {
if(isfat(t->type))
goto no;
if(t->etype != TFIELD)
fatal("componentgen: not a TFIELD: %lT", t);
fldcount++;
}
if(fldcount == 0 || fldcount > 4)
goto no;
break;
case TSTRING:
case TINTER:
break;
@ -1399,7 +1426,7 @@ componentgen(Node *nr, Node *nl)
freer = 1;
}
}
// nl and nr are 'cadable' which basically means they are names (variables) now.
// If they are the same variable, don't generate any code, because the
// VARDEF we generate will mark the old value as dead incorrectly.
@ -1409,8 +1436,25 @@ componentgen(Node *nr, Node *nl)
switch(nl->type->etype) {
case TARRAY:
// componentgen for arrays.
if(nl->op == ONAME)
gvardef(nl);
t = nl->type;
if(!isslice(t)) {
nodl.type = t->type;
nodr.type = nodl.type;
for(fldcount=0; fldcount < t->bound; fldcount++) {
if(nr == N)
clearslim(&nodl);
else
gmove(&nodr, &nodl);
nodl.xoffset += t->type->width;
nodr.xoffset += t->type->width;
}
goto yes;
}
// componentgen for slices.
nodl.xoffset += Array_array;
nodl.type = ptrto(nl->type->type);
@ -1422,7 +1466,7 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
nodl.xoffset += Array_nel-Array_array;
nodl.type = types[TUINT32];
nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_nel-Array_array;
@ -1432,7 +1476,7 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
nodl.xoffset += Array_cap-Array_nel;
nodl.type = types[TUINT32];
nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_cap-Array_nel;
@ -1457,7 +1501,7 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
nodl.xoffset += Array_nel-Array_array;
nodl.type = types[TUINT32];
nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_nel-Array_array;
@ -1492,6 +1536,31 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
goto yes;
case TSTRUCT:
if(nl->op == ONAME)
gvardef(nl);
loffset = nodl.xoffset;
roffset = nodr.xoffset;
// funarg structs may not begin at offset zero.
if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
loffset -= nl->type->type->width;
if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
roffset -= nr->type->type->width;
for(t=nl->type->type; t; t=t->down) {
nodl.xoffset = loffset + t->width;
nodl.type = t->type;
if(nr == N)
clearslim(&nodl);
else {
nodr.xoffset = roffset + t->width;
nodr.type = nodl.type;
gmove(&nodr, &nodl);
}
}
goto yes;
}
no:

View File

@ -991,7 +991,7 @@ cgen_hmul(Node *nl, Node *nr, Node *res)
if(t->width == 1) {
// byte multiply behaves differently.
nodreg(&ax, t, D_AH);
nodreg(&dx, t, D_DL);
nodreg(&dx, t, D_DX);
gmove(&ax, &dx);
}
nodreg(&dx, t, D_DX);

View File

@ -430,7 +430,6 @@ optoas(int op, Type *t)
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
case CASE(OADDPTR, TPTR32):
a = AADDL;
break;

View File

@ -636,6 +636,11 @@ copyu(Prog *p, Adr *v, Adr *s)
static int
copyas(Adr *a, Adr *v)
{
if(D_AL <= a->type && a->type <= D_BL)
fatal("use of byte register");
if(D_AL <= v->type && v->type <= D_BL)
fatal("use of byte register");
if(a->type != v->type)
return 0;
if(regtyp(v))

View File

@ -1168,6 +1168,7 @@ void
addreg(Adr *a, int rn)
{
a->sym = nil;
a->node = nil;
a->offset = 0;
a->type = rn;

View File

@ -619,17 +619,17 @@ asmb(void)
if(iself)
goto Elfsym;
case Hplan9:
symo = HEADR+segtext.filelen+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
break;
case Hdarwin:
symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
symo = segdata.fileoff+rnd(segdata.filelen, INITRND)+machlink;
break;
Elfsym:
symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
symo = rnd(symo, INITRND);
break;
case Hwindows:
symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
symo = rnd(symo, PEFILEALIGN);
break;
}

View File

@ -45,7 +45,7 @@ cgen(Node *n, Node *nn)
}
if(n == Z || n->type == T)
return;
if(typesu[n->type->etype]) {
if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
sugen(n, nn, n->type->width);
return;
}
@ -74,7 +74,7 @@ cgen(Node *n, Node *nn)
if(r != Z && r->complex >= FNX)
switch(o) {
default:
regret(&nod, r);
regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
@ -324,7 +324,7 @@ cgen(Node *n, Node *nn)
if(l->op != OIND)
diag(n, "bad function call");
regret(&nod, l->left);
regret(&nod, l->left, 0, 0);
cgen(l->left, &nod);
regsalloc(&nod1, l->left);
gopcode(OAS, &nod, Z, &nod1);
@ -353,11 +353,13 @@ cgen(Node *n, Node *nn)
if(REGARG>=0)
if(o != reg[REGARG])
reg[REGARG]--;
if(nn != Z) {
regret(&nod, n);
regret(&nod, n, l->type, 1); // update maxarg if nothing else
gpcdata(PCDATA_ArgSize, curarg);
gpcdata(PCDATA_ArgSize, -1);
if(nn != Z)
gopcode(OAS, &nod, Z, nn);
if(nod.op == OREGISTER)
regfree(&nod);
}
break;
case OIND:
@ -759,7 +761,7 @@ boolgen(Node *n, int true, Node *nn)
if(true)
o = comrel[relindex(o)];
if(l->complex >= FNX && r->complex >= FNX) {
regret(&nod, r);
regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
gopcode(OAS, &nod, Z, &nod1);
@ -966,6 +968,20 @@ sugen(Node *n, Node *nn, int32 w)
break;
case OFUNC:
if(!hasdotdotdot(n->left->type)) {
cgen(n, Z);
if(nn != Z) {
curarg -= n->type->width;
regret(&nod1, n, n->left->type, 1);
if(nn->complex >= FNX) {
regsalloc(&nod2, n);
cgen(&nod1, &nod2);
nod1 = nod2;
}
cgen(&nod1, nn);
}
break;
}
if(nn == Z) {
sugen(n, nodrat, w);
break;

View File

@ -141,7 +141,6 @@ extern int hintabsize;
EXTERN int32 maxargsafe;
EXTERN Multab multab[20];
EXTERN int mnstring;
EXTERN int retok;
EXTERN Node* nodrat;
EXTERN Node* nodret;
EXTERN Node* nodsafe;
@ -212,7 +211,7 @@ void noretval(int);
void xcom(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
vlong argsize(void);
vlong argsize(int);
/*
* cgen.c
@ -238,7 +237,7 @@ Node* nod32const(vlong);
Node* nodfconst(double);
Node* nodgconst(vlong v, Type *t);
void nodreg(Node*, Node*, int);
void regret(Node*, Node*);
void regret(Node*, Node*, Type*, int);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
void regialloc(Node*, Node*, Node*);

View File

@ -34,7 +34,7 @@ gtext(Sym *s, int32 stkoff)
{
vlong v;
v = ((uvlong)argsize() << 32) | (stkoff & 0xffffffff);
v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
if((textflag & NOSPLIT) && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");

View File

@ -324,10 +324,11 @@ align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
int w;
int w, packw;
o = i;
w = 1;
packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
@ -338,7 +339,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1)
w = 1;
if(packflg)
w = packflg;
packw = packflg;
break;
case Ael1: /* initial allign of struct element */
@ -351,7 +352,7 @@ align(int32 i, Type *t, int op, int32 *maxalign)
if(w < 1 || w > SZ_VLONG)
fatal(Z, "align");
if(packflg)
w = packflg;
packw = packflg;
break;
case Ael2: /* width of a struct element */
@ -386,6 +387,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
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;

View File

@ -319,15 +319,43 @@ nodreg(Node *n, Node *nn, int reg)
}
void
regret(Node *n, Node *nn)
regret(Node *n, Node *nn, Type *t, int mode)
{
int r;
if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
r = REGRET;
if(typefd[nn->type->etype])
r = FREGRET+NREG;
nodreg(n, nn, r);
reg[r]++;
return;
}
if(mode == 1) {
// fetch returned value after call.
// already called gargs, so curarg is set.
curarg = (curarg+7) & ~7;
regaalloc(n, nn);
return;
}
r = REGRET;
if(typefd[nn->type->etype])
r = FREGRET+NREG;
nodreg(n, nn, r);
reg[r]++;
if(mode == 2) {
// store value to be returned.
// must compute arg offset.
if(t->etype != TFUNC)
fatal(Z, "bad regret func %T", t);
*n = *nn;
n->op = ONAME;
n->class = CPARAM;
n->sym = slookup(".ret");
n->complex = nodret->complex;
n->addable = 20;
n->xoffset = argsize(0);
return;
}
fatal(Z, "bad regret");
}
void

View File

@ -260,7 +260,6 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
goto sbop;

View File

@ -49,7 +49,6 @@ void allocparams(void);
void checklabels(void);
void ginscall(Node*, int);
int gen_as_init(Node*);
void clearslim(Node*);
/*
* cgen.c

View File

@ -614,11 +614,8 @@ ismem(Node *n)
case ONAME:
case OPARAM:
case OCLOSUREVAR:
return 1;
case OADDR:
//if(flag_largemodel)
return 1;
break;
return 1;
}
return 0;
}
@ -1474,11 +1471,9 @@ optoas(int op, Type *t)
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
case CASE(OADDPTR, TPTR32):
case CASE(OADD, TINT64):
case CASE(OADD, TUINT64):
case CASE(OADD, TPTR64):
case CASE(OADDPTR, TPTR64):
a = AADD;
break;

View File

@ -245,10 +245,10 @@ asmb(void)
if(iself)
goto ElfSym;
case Hplan9:
symo = HEADR+segtext.len+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
break;
ElfSym:
symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+segdata.filelen;
symo = segdata.fileoff+segdata.filelen;
symo = rnd(symo, INITRND);
break;
}

View File

@ -19,17 +19,14 @@ package main
import (
"bufio"
"debug/elf"
"debug/gosym"
"debug/macho"
"debug/pe"
"debug/plan9obj"
"flag"
"fmt"
"log"
"os"
"strconv"
"strings"
"cmd/internal/objfile"
)
func printUsage(w *os.File) {
@ -60,18 +57,12 @@ func main() {
usage()
}
f, err := os.Open(flag.Arg(0))
f, err := objfile.Open(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
textStart, symtab, pclntab, err := loadTables(f)
if err != nil {
log.Fatalf("reading %s: %v", flag.Arg(0), err)
}
pcln := gosym.NewLineTable(pclntab, textStart)
tab, err := gosym.NewTable(symtab, pcln)
tab, err := f.PCLineTable()
if err != nil {
log.Fatalf("reading %s: %v", flag.Arg(0), err)
}
@ -102,145 +93,3 @@ func main() {
}
stdout.Flush()
}
func loadTables(f *os.File) (textStart uint64, symtab, pclntab []byte, err error) {
if obj, err := elf.NewFile(f); err == nil {
if sect := obj.Section(".text"); sect != nil {
textStart = sect.Addr
}
if sect := obj.Section(".gosymtab"); sect != nil {
if symtab, err = sect.Data(); err != nil {
return 0, nil, nil, err
}
}
if sect := obj.Section(".gopclntab"); sect != nil {
if pclntab, err = sect.Data(); err != nil {
return 0, nil, nil, err
}
}
return textStart, symtab, pclntab, nil
}
if obj, err := macho.NewFile(f); err == nil {
if sect := obj.Section("__text"); sect != nil {
textStart = sect.Addr
}
if sect := obj.Section("__gosymtab"); sect != nil {
if symtab, err = sect.Data(); err != nil {
return 0, nil, nil, err
}
}
if sect := obj.Section("__gopclntab"); sect != nil {
if pclntab, err = sect.Data(); err != nil {
return 0, nil, nil, err
}
}
return textStart, symtab, pclntab, nil
}
if obj, err := pe.NewFile(f); err == nil {
var imageBase uint64
switch oh := obj.OptionalHeader.(type) {
case *pe.OptionalHeader32:
imageBase = uint64(oh.ImageBase)
case *pe.OptionalHeader64:
imageBase = oh.ImageBase
default:
return 0, nil, nil, fmt.Errorf("pe file format not recognized")
}
if sect := obj.Section(".text"); sect != nil {
textStart = imageBase + uint64(sect.VirtualAddress)
}
if pclntab, err = loadPETable(obj, "pclntab", "epclntab"); err != nil {
return 0, nil, nil, err
}
if symtab, err = loadPETable(obj, "symtab", "esymtab"); err != nil {
return 0, nil, nil, err
}
return textStart, symtab, pclntab, nil
}
if obj, err := plan9obj.NewFile(f); err == nil {
textStart = obj.LoadAddress + obj.HdrSize
if pclntab, err = loadPlan9Table(obj, "pclntab", "epclntab"); err != nil {
return 0, nil, nil, err
}
if symtab, err = loadPlan9Table(obj, "symtab", "esymtab"); err != nil {
return 0, nil, nil, err
}
return textStart, symtab, pclntab, nil
}
return 0, nil, nil, fmt.Errorf("unrecognized binary format")
}
func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) {
for _, s := range f.Symbols {
if s.Name != name {
continue
}
if s.SectionNumber <= 0 {
return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber)
}
if len(f.Sections) < int(s.SectionNumber) {
return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections))
}
return s, nil
}
return nil, fmt.Errorf("no %s symbol found", name)
}
func loadPETable(f *pe.File, sname, ename string) ([]byte, error) {
ssym, err := findPESymbol(f, sname)
if err != nil {
return nil, err
}
esym, err := findPESymbol(f, ename)
if err != nil {
return nil, err
}
if ssym.SectionNumber != esym.SectionNumber {
return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename)
}
sect := f.Sections[ssym.SectionNumber-1]
data, err := sect.Data()
if err != nil {
return nil, err
}
return data[ssym.Value:esym.Value], nil
}
func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) {
syms, err := f.Symbols()
if err != nil {
return nil, err
}
for _, s := range syms {
if s.Name != name {
continue
}
return &s, nil
}
return nil, fmt.Errorf("no %s symbol found", name)
}
func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) {
ssym, err := findPlan9Symbol(f, sname)
if err != nil {
return nil, err
}
esym, err := findPlan9Symbol(f, ename)
if err != nil {
return nil, err
}
sect := f.Section("text")
if sect == nil {
return nil, err
}
data, err := sect.Data()
if err != nil {
return nil, err
}
textStart := f.LoadAddress + f.HdrSize
return data[ssym.Value-textStart : esym.Value-textStart], nil
}

View File

@ -378,7 +378,51 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) {
}
if w.context != nil && file == fmt.Sprintf("zruntime_defs_%s_%s.go", w.context.GOOS, w.context.GOARCH) {
// Just enough to keep the api checker happy.
src := "package runtime; type maptype struct{}; type _type struct{}; type alg struct{}; type mspan struct{}; type m struct{}; type lock struct{}; type slicetype struct{};"
src := "package runtime; type (" +
" _defer struct{};" +
" _func struct{};" +
" _panic struct{};" +
" _select struct{}; " +
" _type struct{};" +
" alg struct{};" +
" chantype struct{};" +
" context struct{};" + // windows
" eface struct{};" +
" funcval struct{};" +
" g struct{};" +
" gobuf struct{};" +
" hchan struct{};" +
" iface struct{};" +
" interfacetype struct{};" +
" itab struct{};" +
" m struct{};" +
" maptype struct{};" +
" mcache struct{};" +
" mspan struct{};" +
" mutex struct{};" +
" note struct{};" +
" slicetype struct{};" +
" stkframe struct{};" +
" sudog struct{};" +
" waitq struct{};" +
" wincallbackcontext struct{};" +
" keventt struct{};" +
" timespec struct{};" +
" epollevent struct{};" +
"); " +
"const (" +
" cb_max = 2000;" +
" _CacheLineSize = 64;" +
" _Gidle = 1;" +
" _Grunnable = 2;" +
" _Grunning = 3;" +
" _Gsyscall = 4;" +
" _Gwaiting = 5;" +
" _Gdead = 6;" +
" _Genqueue = 7;" +
" _Gcopystack = 8;" +
" _NSIG = 32;" +
")"
f, err = parser.ParseFile(fset, filename, src, 0)
if err != nil {
log.Fatalf("incorrect generated file: %s", err)

View File

@ -98,11 +98,9 @@ func prepGoPath() string {
if err == nil {
username = u.Username
} else {
// Only need to handle Unix here, as Windows's os/user uses
// native syscall and should work fine without cgo.
username = os.Getenv("USER")
if username == "" {
log.Fatalf("Error getting current user: %v", err)
username = "nobody"
}
}

View File

@ -794,7 +794,7 @@ void xcom(Node*);
int32 exreg(Type*);
int32 align(int32, Type*, int, int32*);
int32 maxround(int32, int32);
int hasdotdotdot(void);
int hasdotdotdot(Type*);
void linkarchinit(void);
extern schar ewidth[];

View File

@ -1043,6 +1043,7 @@ complex:
}
| LSTRUCT sbody
{
diag(Z, "struct must have tag");
taggen++;
sprint(symb, "_%d_", taggen);
$$ = dotag(lookup(), TSTRUCT, autobn);

View File

@ -697,7 +697,8 @@ argmark(Node *n, int pass)
{
Type *t;
autoffset = align(0, thisfn->link, Aarg0, nil);
if(hasdotdotdot(thisfn->link))
autoffset = align(0, thisfn->link, Aarg0, nil);
stkoff = 0;
for(; n->left != Z; n = n->left) {
if(n->op != OFUNC || n->left->op != ONAME)
@ -1401,6 +1402,10 @@ xdecl(int c, Type *t, Sym *s)
}
tmerge(t, s);
s->type = t;
if(c == CTYPEDEF && (typechlv[t->etype] || typefd[t->etype])) {
s->type = copytyp(t);
s->type->tag = s;
}
s->class = c;
s->block = 0;
s->offset = o;
@ -1481,12 +1486,9 @@ edecl(int c, Type *t, Sym *s)
{
Type *t1;
if(s == S) {
if(!typesu[t->etype])
diag(Z, "unnamed structure element must be struct/union");
if(c != CXXX)
diag(Z, "unnamed structure element cannot have class");
} else
if(s == S)
diag(Z, "unnamed structure elements not supported");
else
if(c != CXXX)
diag(Z, "structure element cannot have class: %s", s->name);
t1 = t;

View File

@ -154,7 +154,6 @@ static void
printtypename(Type *t)
{
Sym *s;
Type *t1;
int w;
char *n;
@ -188,60 +187,27 @@ printtypename(Type *t)
switch(t->etype) {
case TINT:
Bprint(&outbuf, "int32");
break;
case TUINT:
Bprint(&outbuf, "uint32");
break;
case TCHAR:
Bprint(&outbuf, "int8");
break;
case TUCHAR:
Bprint(&outbuf, "uint8");
break;
case TSHORT:
Bprint(&outbuf, "int16");
break;
case TUSHORT:
Bprint(&outbuf, "uint16");
break;
case TLONG:
// The 32/64-bit ambiguous types (int,uint,uintptr)
// are assigned a TLONG/TULONG to distinguish them
// from always 32-bit types which get a TINT/TUINT.
// (See int_x/uint_x in pkg/runtime/runtime.h.)
// For LONG and VLONG types, we generate the
// unqualified Go type when appropriate.
// This makes it easier to write Go code that
// modifies objects with autogenerated-from-C types.
if(ewidth[TIND] == 4)
Bprint(&outbuf, "int");
else
Bprint(&outbuf, "int32");
break;
case TULONG:
if(ewidth[TIND] == 4)
Bprint(&outbuf, "uint");
else
Bprint(&outbuf, "uint32");
break;
case TVLONG:
if(ewidth[TIND] == 8)
Bprint(&outbuf, "int");
else
Bprint(&outbuf, "int64");
break;
case TUVLONG:
if(ewidth[TIND] == 8)
Bprint(&outbuf, "uint");
else
Bprint(&outbuf, "uint64");
break;
case TFLOAT:
Bprint(&outbuf, "float32");
break;
case TDOUBLE:
Bprint(&outbuf, "float64");
// All names used in the runtime code should be typedefs.
if(t->tag != nil) {
if(strcmp(t->tag->name, "intgo") == 0)
Bprint(&outbuf, "int");
else if(strcmp(t->tag->name, "uintgo") == 0)
Bprint(&outbuf, "uint");
else
Bprint(&outbuf, "%s", t->tag->name);
} else
Bprint(&outbuf, "C.%T", t);
break;
case TUNION:
case TSTRUCT:
@ -251,27 +217,18 @@ printtypename(Type *t)
n = s->name;
else if(t->tag)
n = t->tag->name;
if(strcmp(n, "String") == 0){
if(strcmp(n, "String") == 0)
Bprint(&outbuf, "string");
} else if(strcmp(n, "Slice") == 0){
else if(strcmp(n, "Slice") == 0)
Bprint(&outbuf, "[]byte");
} else
else if(strcmp(n, "Eface") == 0)
Bprint(&outbuf, "interface{}");
else
Bprint(&outbuf, "%U", n);
break;
case TFUNC:
Bprint(&outbuf, "func(");
for(t1 = t->down; t1 != T; t1 = t1->down) {
if(t1->etype == TVOID)
break;
if(t1 != t->down)
Bprint(&outbuf, ", ");
printtypename(t1);
}
Bprint(&outbuf, ")");
if(t->link && t->link->etype != TVOID) {
Bprint(&outbuf, " ");
printtypename(t->link);
}
// There's no equivalent to a C function in the Go world.
Bprint(&outbuf, "unsafe.Pointer");
break;
case TDOT:
Bprint(&outbuf, "...interface{}");
@ -360,9 +317,9 @@ godefvar(Sym *s)
switch(t->etype) {
case TENUM:
if(!typefd[t->etype])
Bprint(&outbuf, "const %U = %lld\n", s->name, s->vconst);
Bprint(&outbuf, "const %s = %lld\n", s->name, s->vconst);
else
Bprint(&outbuf, "const %U = %f\n;", s->name, s->fconst);
Bprint(&outbuf, "const %s = %f\n;", s->name, s->fconst);
break;
case TFUNC:

View File

@ -56,24 +56,24 @@ makefuncdatasym(char *namefmt, int64 funcdatakind)
}
int
hasdotdotdot(void)
hasdotdotdot(Type *t)
{
Type *t;
for(t=thisfn->down; t!=T; t=t->down)
for(t=t->down; t!=T; t=t->down)
if(t->etype == TDOT)
return 1;
return 0;
}
vlong
argsize(void)
argsize(int doret)
{
Type *t;
int32 s;
//print("t=%T\n", thisfn);
s = align(0, thisfn->link, Aarg0, nil);
s = 0;
if(hasdotdotdot(thisfn))
s = align(s, thisfn->link, Aarg0, nil);
for(t=thisfn->down; t!=T; t=t->down) {
switch(t->etype) {
case TVOID:
@ -93,6 +93,14 @@ argsize(void)
s = (s+7) & ~7;
else
s = (s+3) & ~3;
if(doret && thisfn->link->etype != TVOID) {
s = align(s, thisfn->link, Aarg1, nil);
s = align(s, thisfn->link, Aarg2, nil);
if(thechar == '6')
s = (s+7) & ~7;
else
s = (s+3) & ~3;
}
return s;
}
@ -123,13 +131,14 @@ codgen(Node *n, Node *nn)
nearln = nn->lineno;
p = gtext(n1->sym, stkoff);
p->from.sym->cfunc = 1;
sp = p;
/*
* generate funcdata symbol for this function.
* data is filled in at the end of codgen().
*/
isvarargs = hasdotdotdot();
isvarargs = hasdotdotdot(thisfn);
gcargs = nil;
if(!isvarargs)
gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps);
@ -212,7 +221,7 @@ supgen(Node *n)
void
gen(Node *n)
{
Node *l, nod;
Node *l, nod, nod1;
Prog *sp, *spc, *spb;
Case *cn;
long sbc, scc;
@ -273,14 +282,26 @@ loop:
gbranch(ORETURN);
break;
}
if(typecmplx[n->type->etype] && !hasdotdotdot(thisfn)) {
regret(&nod, n, thisfn, 2);
sugen(l, &nod, n->type->width);
noretval(3);
gbranch(ORETURN);
break;
}
if(typecmplx[n->type->etype]) {
sugen(l, nodret, n->type->width);
noretval(3);
gbranch(ORETURN);
break;
}
regret(&nod, n);
regret(&nod1, n, thisfn, 2);
nod = nod1;
if(nod.op != OREGISTER)
regalloc(&nod, n, Z);
cgen(l, &nod);
if(nod1.op != OREGISTER)
gmove(&nod, &nod1);
regfree(&nod);
if(typefd[n->type->etype])
noretval(1);
@ -729,9 +750,11 @@ dumpgcargs(Type *fn, Sym *sym)
symoffset = 0;
gextern(sym, nodconst(1), symoffset, 4);
symoffset += 4;
argbytes = (argsize() + ewidth[TIND] - 1);
argbytes = (argsize(1) + ewidth[TIND] - 1);
bv = bvalloc((argbytes / ewidth[TIND]) * BitsPerPointer);
argoffset = align(0, fn->link, Aarg0, nil);
argoffset = 0;
if(hasdotdotdot(thisfn))
argoffset = align(0, fn->link, Aarg0, nil);
if(argoffset > 0) {
// The C calling convention returns structs by copying them to a
// location pointed to by a hidden first argument. This first

View File

@ -229,7 +229,8 @@ func (p *Package) guessKinds(f *File) []*Name {
// Determine kinds for names we already know about,
// like #defines or 'struct foo', before bothering with gcc.
var names, needType []*Name
for _, n := range f.Name {
for _, key := range nameKeys(f.Name) {
n := f.Name[key]
// If we've already found this name as a #define
// and we can translate it as a constant value, do so.
if n.Define != "" {
@ -331,6 +332,7 @@ func (p *Package) guessKinds(f *File) []*Name {
const (
notType = 1 << iota
notConst
notDeclared
)
for _, line := range strings.Split(stderr, "\n") {
if !strings.Contains(line, ": error:") {
@ -365,7 +367,7 @@ func (p *Package) guessKinds(f *File) []*Name {
completed = true
case "not-declared":
error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:]))
sniff[i] |= notDeclared
case "not-type":
sniff[i] |= notType
case "not-const":
@ -374,12 +376,12 @@ func (p *Package) guessKinds(f *File) []*Name {
}
if !completed {
fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr)
}
for i, n := range names {
switch sniff[i] {
case 0:
default:
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
case notType:
n.Kind = "const"
@ -390,6 +392,14 @@ func (p *Package) guessKinds(f *File) []*Name {
}
}
if nerrors > 0 {
// Check if compiling the preamble by itself causes any errors,
// because the messages we've printed out so far aren't helpful
// to users debugging preamble mistakes. See issue 8442.
preambleErrors := p.gccErrors([]byte(f.Preamble))
if len(preambleErrors) > 0 {
error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors)
}
fatalf("unresolved names")
}
@ -649,7 +659,13 @@ func (p *Package) rewriteRef(f *File) {
f.Name[fpName] = name
}
r.Name = name
expr = ast.NewIdent(name.Mangle)
// Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
// function is defined in out.go and simply returns its argument. See
// issue 7757.
expr = &ast.CallExpr{
Fun: &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"},
Args: []ast.Expr{ast.NewIdent(name.Mangle)},
}
} else if r.Name.Kind == "type" {
// Okay - might be new(T)
expr = r.Name.Type.Go
@ -1068,12 +1084,6 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
return t
}
// clang won't generate DW_AT_byte_size for pointer types,
// so we have to fix it here.
if dt, ok := base(dtype).(*dwarf.PtrType); ok && dt.ByteSize == -1 {
dt.ByteSize = c.ptrSize
}
t := new(Type)
t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
t.Align = -1
@ -1097,12 +1107,20 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
t.Go = c.Opaque(t.Size)
break
}
count := dt.Count
if count == -1 {
// Indicates flexible array member, which Go doesn't support.
// Translate to zero-length array instead.
count = 0
}
sub := c.Type(dt.Type, pos)
t.Align = sub.Align
t.Go = &ast.ArrayType{
Len: c.intExpr(dt.Count),
Len: c.intExpr(count),
Elt: sub.Go,
}
// Recalculate t.Size now that we know sub.Size.
t.Size = count * sub.Size
t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
case *dwarf.BoolType:
@ -1203,6 +1221,11 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
}
case *dwarf.PtrType:
// Clang doesn't emit DW_AT_byte_size for pointer types.
if t.Size != c.ptrSize && t.Size != -1 {
fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype)
}
t.Size = c.ptrSize
t.Align = c.ptrSize
if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
@ -1374,34 +1397,24 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
}
}
if t.Size <= 0 {
// Clang does not record the size of a pointer in its DWARF entry,
// so if dtype is an array, the call to dtype.Size at the top of the function
// computed the size as the array length * 0 = 0.
// The type switch called Type (this function) recursively on the pointer
// entry, and the code near the top of the function updated the size to
// be correct, so calling dtype.Size again will produce the correct value.
t.Size = dtype.Size()
if t.Size < 0 {
// Unsized types are [0]byte, unless they're typedefs of other types
// or structs with tags.
// if so, use the name we've already defined.
t.Size = 0
switch dt := dtype.(type) {
case *dwarf.TypedefType:
// ok
case *dwarf.StructType:
if dt.StructName != "" {
break
}
t.Go = c.Opaque(0)
default:
t.Go = c.Opaque(0)
if t.Size < 0 {
// Unsized types are [0]byte, unless they're typedefs of other types
// or structs with tags.
// if so, use the name we've already defined.
t.Size = 0
switch dt := dtype.(type) {
case *dwarf.TypedefType:
// ok
case *dwarf.StructType:
if dt.StructName != "" {
break
}
if t.C.Empty() {
t.C.Set("void")
}
return t
t.Go = c.Opaque(0)
default:
t.Go = c.Opaque(0)
}
if t.C.Empty() {
t.C.Set("void")
}
}
@ -1533,6 +1546,9 @@ func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
// Struct conversion: return Go and (6g) C syntax for type.
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
// Minimum alignment for a struct is 1 byte.
align = 1
var buf bytes.Buffer
buf.WriteString("struct {")
fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field

View File

@ -58,16 +58,14 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
if *importSyscall {
fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
}
if !*gccgo && *importRuntimeCgo {
fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
}
fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
if *importSyscall {
fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int32) { *dst = syscall.Errno(x) }\n")
fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
fmt.Fprintf(fgo2, "var _ syscall.Errno\n")
}
fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
typedefNames := make([]string, 0, len(typedef))
for name := range typedef {
@ -87,9 +85,10 @@ func (p *Package) writeDefs() {
}
if *gccgo {
fmt.Fprintf(fc, p.cPrologGccgo())
fmt.Fprint(fc, p.cPrologGccgo())
} else {
fmt.Fprintf(fc, cProlog)
fmt.Fprint(fc, cProlog)
fmt.Fprint(fgo2, goProlog)
}
gccgoSymbolPrefix := p.gccgoSymbolPrefix()
@ -296,10 +295,6 @@ func (p *Package) structType(n *Name) (string, int64) {
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
off += pad
}
if n.AddError {
fmt.Fprint(&buf, "\t\tint e[2*sizeof(void *)/sizeof(int)]; /* error */\n")
off += 2 * p.PtrSize
}
if off == 0 {
fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
}
@ -334,19 +329,18 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
}
// Builtins defined in the C prolog.
inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" || name == "_CMalloc"
inProlog := builtinDefs[name] != ""
cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
paramnames := []string(nil)
for i, param := range d.Type.Params.List {
paramName := fmt.Sprintf("p%d", i)
param.Names = []*ast.Ident{ast.NewIdent(paramName)}
paramnames = append(paramnames, paramName)
}
if *gccgo {
// Gccgo style hooks.
fmt.Fprint(fgo2, "\n")
cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
paramnames := []string(nil)
for i, param := range d.Type.Params.List {
paramName := fmt.Sprintf("p%d", i)
param.Names = []*ast.Ident{ast.NewIdent(paramName)}
paramnames = append(paramnames, paramName)
}
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n")
if !inProlog {
@ -383,7 +377,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
fmt.Fprint(fgo2, "}\n")
// declare the C function.
fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
fmt.Fprintf(fgo2, "//extern %s\n", cname)
d.Name = ast.NewIdent(cname)
if n.AddError {
l := d.Type.Results.List
@ -394,61 +388,49 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
return
}
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, "\n")
if inProlog {
fmt.Fprint(fgo2, builtinDefs[name])
return
}
var argSize int64
_, argSize = p.structType(n)
// C wrapper calls into gcc, passing a pointer to the argument frame.
fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangle)
fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
fmt.Fprintf(fc, "\n")
fmt.Fprintf(fc, "void\n")
if argSize == 0 {
argSize++
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname)
fmt.Fprintf(fc, "void %s(void*);\n", cname)
fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname)
nret := 0
if !void {
d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")}
nret = 1
}
// TODO(rsc): The struct here should declare pointers only where
// there are pointers in the actual argument frame.
// This is a workaround for golang.org/issue/6397.
fmt.Fprintf(fc, "·%s(struct{", n.Mangle)
if n := argSize / p.PtrSize; n > 0 {
fmt.Fprintf(fc, "void *y[%d];", n)
}
if n := argSize % p.PtrSize; n > 0 {
fmt.Fprintf(fc, "uint8 x[%d];", n)
}
fmt.Fprintf(fc, "}p)\n")
fmt.Fprintf(fc, "{\n")
fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
if n.AddError {
// gcc leaves errno in first word of interface at end of p.
// check whether it is zero; if so, turn interface into nil.
// if not, turn interface into errno.
// Go init function initializes ·_Cerrno with an os.Errno
// for us to copy.
fmt.Fprintln(fc, ` {
int32 e;
void **v;
v = (void**)(&p+1) - 2; /* v = final two void* of p */
e = *(int32*)v;
v[0] = (void*)0xdeadbeef;
v[1] = (void*)0xdeadbeef;
if(e == 0) {
/* nil interface */
v[0] = 0;
v[1] = 0;
} else {
·_Cerrno(v, e); /* fill in v as error for errno e */
}
}`)
d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")}
}
fmt.Fprintf(fc, "}\n")
fmt.Fprintf(fc, "\n")
fmt.Fprint(fgo2, "\n")
fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname)
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n")
// NOTE: Using uintptr to hide from escape analysis.
arg := "0"
if len(paramnames) > 0 {
arg = "uintptr(unsafe.Pointer(&p0))"
} else if !void {
arg = "uintptr(unsafe.Pointer(&r1))"
}
prefix := ""
if n.AddError {
prefix = "errno := "
}
fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg)
if n.AddError {
fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n")
}
fmt.Fprintf(fgo2, "\treturn\n")
fmt.Fprintf(fgo2, "}\n")
}
// writeOutput creates stubs for a specific source file to be compiled by 6g
@ -521,7 +503,11 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
// Gcc wrapper unpacks the C argument struct
// and calls the actual C function.
fmt.Fprintf(fgcc, "void\n")
if n.AddError {
fmt.Fprintf(fgcc, "int\n")
} else {
fmt.Fprintf(fgcc, "void\n")
}
fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
fmt.Fprintf(fgcc, "{\n")
if n.AddError {
@ -557,7 +543,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
}
fmt.Fprintf(fgcc, ");\n")
if n.AddError {
fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n")
fmt.Fprintf(fgcc, "\treturn errno;\n")
}
fmt.Fprintf(fgcc, "}\n")
fmt.Fprintf(fgcc, "\n")
@ -1166,46 +1152,74 @@ const cProlog = `
#include "runtime.h"
#include "cgocall.h"
static void *cgocall_errno = runtime·cgocall_errno;
void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
static void *runtime_gostring = runtime·gostring;
void *·_cgo_runtime_gostring = &runtime_gostring;
static void *runtime_gostringn = runtime·gostringn;
void *·_cgo_runtime_gostringn = &runtime_gostringn;
static void *runtime_gobytes = runtime·gobytes;
void *·_cgo_runtime_gobytes = &runtime_gobytes;
static void *runtime_cmalloc = runtime·cmalloc;
void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
void ·_Cerrno(void*, int32);
`
void
·_Cfunc_GoString(int8 *p, String s)
{
s = runtime·gostring((byte*)p);
FLUSH(&s);
}
const goProlog = `
var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32
var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer
`
void
·_Cfunc_GoStringN(int8 *p, int32 l, String s)
{
s = runtime·gostringn((byte*)p, l);
FLUSH(&s);
}
void
·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
{
s = runtime·gobytes((byte*)p, l);
FLUSH(&s);
}
void
·_Cfunc_CString(String s, int8 *p)
{
p = runtime·cmalloc(s.len+1);
runtime·memmove((byte*)p, s.str, s.len);
p[s.len] = 0;
FLUSH(&p);
}
void
·_Cfunc__CMalloc(uintptr n, int8 *p)
{
p = runtime·cmalloc(n);
FLUSH(&p);
const goStringDef = `
var _cgo_runtime_gostring func(*_Ctype_char) string
func _Cfunc_GoString(p *_Ctype_char) string {
return _cgo_runtime_gostring(p)
}
`
const goStringNDef = `
var _cgo_runtime_gostringn func(*_Ctype_char, int) string
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
return _cgo_runtime_gostringn(p, int(l))
}
`
const goBytesDef = `
var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
return _cgo_runtime_gobytes(p, int(l))
}
`
const cStringDef = `
func _Cfunc_CString(s string) *_Ctype_char {
p := _cgo_runtime_cmalloc(uintptr(len(s)+1))
pp := (*[1<<30]byte)(p)
copy(pp[:], s)
pp[len(s)] = 0
return (*_Ctype_char)(p)
}
`
const cMallocDef = `
func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer {
return _cgo_runtime_cmalloc(uintptr(n))
}
`
var builtinDefs = map[string]string{
"GoString": goStringDef,
"GoStringN": goStringNDef,
"GoBytes": goBytesDef,
"CString": cStringDef,
"_CMalloc": cMallocDef,
}
func (p *Package) cPrologGccgo() string {
return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1)
}

4
src/cmd/dist/a.h vendored
View File

@ -108,9 +108,6 @@ void mkzexperiment(char*, char*);
// buildgo.c
void mkzdefaultcc(char*, char*);
// goc2c.c
void goc2c(char*, char*);
// main.c
extern int vflag;
extern int sflag;
@ -129,6 +126,7 @@ bool isfile(char *p);
char* lastelem(char*);
Time mtime(char*);
void readfile(Buf*, char*);
void copyfile(char*, char*, int);
void run(Buf *b, char *dir, int mode, char *cmd, ...);
void runv(Buf *b, char *dir, int mode, Vec *argv);
void bgrunv(char *dir, int mode, Vec *argv);

2
src/cmd/dist/buf.c vendored
View File

@ -202,7 +202,7 @@ vadd(Vec *v, char *p)
}
// vaddn adds a string consisting of the n bytes at p to the vector.
void
static void
vaddn(Vec *v, char *p, int n)
{
char *q;

47
src/cmd/dist/build.c vendored
View File

@ -35,7 +35,6 @@ bool rebuildall;
bool defaultclang;
static bool shouldbuild(char*, char*);
static void copy(char*, char*, int);
static void dopack(char*, char*, char**, int);
static char *findgoversion(void);
@ -628,7 +627,6 @@ char *depsuffix[] = {
".h",
".s",
".go",
".goc",
};
// gentab records how to generate some trivial files.
@ -661,7 +659,7 @@ install(char *dir)
{
char *name, *p, *elem, *prefix, *exe;
bool islib, ispkg, isgo, stale, ispackcmd;
Buf b, b1, path;
Buf b, b1, path, final_path, final_name;
Vec compile, files, link, go, missing, clean, lib, extra;
Time ttarg, t;
int i, j, k, n, doclean, targ;
@ -676,6 +674,8 @@ install(char *dir)
binit(&b);
binit(&b1);
binit(&path);
binit(&final_path);
binit(&final_name);
vinit(&compile);
vinit(&files);
vinit(&link);
@ -688,11 +688,12 @@ install(char *dir)
// path = full path to dir.
bpathf(&path, "%s/src/%s", goroot, dir);
bpathf(&final_path, "%s/src/%s", goroot_final, dir);
name = lastelem(dir);
// For misc/prof, copy into the tool directory and we're done.
if(hasprefix(dir, "misc/")) {
copy(bpathf(&b, "%s/%s", tooldir, name),
copyfile(bpathf(&b, "%s/%s", tooldir, name),
bpathf(&b1, "%s/misc/%s", goroot, name), 1);
goto out;
}
@ -904,17 +905,19 @@ install(char *dir)
// For package runtime, copy some files into the work space.
if(streq(dir, "pkg/runtime")) {
copy(bpathf(&b, "%s/arch_GOARCH.h", workdir),
copyfile(bpathf(&b, "%s/arch_GOARCH.h", workdir),
bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
copyfile(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
if(isfile(p))
copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
copy(bpathf(&b, "%s/os_GOOS.h", workdir),
copyfile(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
copyfile(bpathf(&b, "%s/os_GOOS.h", workdir),
bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
copy(bpathf(&b, "%s/signals_GOOS.h", workdir),
copyfile(bpathf(&b, "%s/signals_GOOS.h", workdir),
bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0);
copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
}
// Generate any missing files; regenerate existing ones.
@ -948,26 +951,10 @@ install(char *dir)
// The last batch was required for the generators.
// This one is generated.
if(streq(dir, "pkg/runtime")) {
copy(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
copyfile(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0);
}
// Generate .c files from .goc files.
if(streq(dir, "pkg/runtime")) {
for(i=0; i<files.len; i++) {
p = files.p[i];
if(!hassuffix(p, ".goc"))
continue;
// b = path/zp but with _goos_goarch.c instead of .goc
bprintf(&b, "%s%sz%s", bstr(&path), slash, lastelem(p));
b.len -= 4;
bwritef(&b, "_%s_%s.c", goos, goarch);
goc2c(p, bstr(&b));
vadd(&files, bstr(&b));
}
vuniq(&files);
}
if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
@ -1138,9 +1125,9 @@ nobuild:
// In package runtime, we install runtime.h and cgocall.h too,
// for use by cgo compilation.
if(streq(dir, "pkg/runtime")) {
copy(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
copyfile(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
bpathf(&b1, "%s/src/pkg/runtime/cgocall.h", goroot), 0);
copy(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
copyfile(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
bpathf(&b1, "%s/src/pkg/runtime/runtime.h", goroot), 0);
}
@ -1277,8 +1264,8 @@ out:
}
// copy copies the file src to dst, via memory (so only good for small files).
static void
copy(char *dst, char *src, int exec)
void
copyfile(char *dst, char *src, int exec)
{
Buf b;

View File

@ -112,7 +112,7 @@ mkzgoos(char *dir, char *file)
bwritestr(&out, "// auto generated by go tool dist\n\n");
if (streq(goos, "linux")) {
if(streq(goos, "linux")) {
bwritestr(&out, "// +build !android\n\n");
}
@ -169,11 +169,12 @@ mkzasm(char *dir, char *file)
{
int i, n;
char *aggr, *p;
Buf in, b, out, exp;
Buf in, b, b1, out, exp;
Vec argv, lines, fields;
binit(&in);
binit(&b);
binit(&b1);
binit(&out);
binit(&exp);
vinit(&argv);
@ -181,6 +182,10 @@ mkzasm(char *dir, char *file)
vinit(&fields);
bwritestr(&out, "// auto generated by go tool dist\n\n");
if(streq(goos, "linux")) {
bwritestr(&out, "// +build !android\n\n");
}
for(i=0; i<nelem(zasmhdr); i++) {
if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
bwritestr(&out, zasmhdr[i].hdr);
@ -190,6 +195,9 @@ mkzasm(char *dir, char *file)
fatal("unknown $GOOS/$GOARCH in mkzasm");
ok:
copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c
// to get acid [sic] output. Run once without the -a -o workdir/proc.acid in order to
// report compilation failures (the -o redirects all messages, unfortunately).
@ -201,6 +209,8 @@ ok:
vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
vadd(&argv, "-I");
vadd(&argv, bprintf(&b, "%s", workdir));
vadd(&argv, "-I");
vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
vadd(&argv, "-n");
vadd(&argv, "-a");
vadd(&argv, "-o");
@ -241,6 +251,8 @@ ok:
aggr = "seh";
else if(streq(fields.p[1], "Alg"))
aggr = "alg";
else if(streq(fields.p[1], "Panic"))
aggr = "panic";
}
if(hasprefix(lines.p[i], "}"))
aggr = nil;
@ -273,6 +285,7 @@ ok:
bfree(&in);
bfree(&b);
bfree(&b1);
bfree(&out);
bfree(&exp);
vfree(&argv);
@ -294,6 +307,10 @@ mkzsys(char *dir, char *file)
binit(&out);
bwritestr(&out, "// auto generated by go tool dist\n\n");
if(streq(goos, "linux")) {
bwritestr(&out, "// +build !android\n\n");
}
if(streq(goos, "windows")) {
bwritef(&out,
"// runtime·callbackasm is called by external code to\n"
@ -346,13 +363,24 @@ mkzruntimedefs(char *dir, char *file)
vinit(&seen);
bwritestr(&out, "// auto generated by go tool dist\n"
"\n"
"\n");
if(streq(goos, "linux")) {
bwritestr(&out, "// +build !android\n\n");
}
bwritestr(&out,
"package runtime\n"
"import \"unsafe\"\n"
"var _ unsafe.Pointer\n"
"\n"
);
// Do not emit definitions for these.
vadd(&seen, "true");
vadd(&seen, "false");
vadd(&seen, "raceenabled");
vadd(&seen, "allgs");
// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q -n -o workdir/runtimedefs
// on each of the runtimedefs C files.
@ -363,6 +391,8 @@ mkzruntimedefs(char *dir, char *file)
vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
vadd(&argv, "-I");
vadd(&argv, bprintf(&b, "%s", workdir));
vadd(&argv, "-I");
vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
vadd(&argv, "-q");
vadd(&argv, "-n");
vadd(&argv, "-o");
@ -382,15 +412,15 @@ mkzruntimedefs(char *dir, char *file)
splitlines(&lines, bstr(&in));
for(i=0; i<lines.len; i++) {
p = lines.p[i];
// Drop comment, func, and const lines.
if(hasprefix(p, "//") || hasprefix(p, "const") || hasprefix(p, "func"))
// Drop comment and func lines.
if(hasprefix(p, "//") || hasprefix(p, "func"))
continue;
// Note beginning of type or var decl, which can be multiline.
// Remove duplicates. The linear check of seen here makes the
// whole processing quadratic in aggregate, but there are only
// about 100 declarations, so this is okay (and simple).
if(hasprefix(p, "type ") || hasprefix(p, "var ")) {
if(hasprefix(p, "type ") || hasprefix(p, "var ") || hasprefix(p, "const ")) {
splitfields(&fields, p);
if(fields.len < 2)
continue;
@ -401,6 +431,17 @@ mkzruntimedefs(char *dir, char *file)
}
vadd(&seen, fields.p[1]);
}
// Const lines are printed in original case (usually upper). Add a leading _ as needed.
if(hasprefix(p, "const ")) {
if('A' <= p[6] && p[6] <= 'Z')
bwritestr(&out, "const _");
else
bwritestr(&out, "const ");
bwritestr(&out, p+6);
continue;
}
if(skip) {
if(hasprefix(p, "}"))
skip = 0;
@ -409,6 +450,11 @@ mkzruntimedefs(char *dir, char *file)
bwritestr(&out, p);
}
// Some windows specific const.
if(streq(goos, "windows")) {
bwritestr(&out, bprintf(&b, "const cb_max = %d\n", MAXWINCB));
}
writefile(&out, file, 0);

833
src/cmd/dist/goc2c.c vendored
View File

@ -1,833 +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.
#include "a.h"
/*
* Translate a .goc file into a .c file. A .goc file is a combination
* of a limited form of Go with C.
*/
/*
package PACKAGENAME
{# line}
func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] \{
C code with proper brace nesting
\}
*/
/*
* We generate C code which implements the function such that it can
* be called from Go and executes the C code.
*/
static char *input;
static Buf *output;
#define EOF -1
enum
{
use64bitint = 1,
};
static int
xgetchar(void)
{
int c;
c = *input;
if(c == 0)
return EOF;
input++;
return c;
}
static void
xungetc(void)
{
input--;
}
static void
xputchar(char c)
{
bwrite(output, &c, 1);
}
static int
xisspace(int c)
{
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
/* Whether we're emitting for gcc */
static int gcc;
/* File and line number */
static const char *file;
static unsigned int lineno;
/* List of names and types. */
struct params {
struct params *next;
char *name;
char *type;
};
/* index into type_table */
enum {
Bool,
Float,
Int,
Uint,
Uintptr,
String,
Slice,
Eface,
Complex128,
Float32,
Float64,
};
static struct {
char *name;
int size;
int rnd; // alignment
} type_table[] = {
/*
* variable sized first, for easy replacement.
* order matches enum above.
* default is 32-bit architecture sizes.
* spelling as in package runtime, so intgo/uintgo not int/uint.
*/
{"bool", 1},
{"float", 4},
{"intgo", 4},
{"uintgo", 4},
{"uintptr", 4},
{"String", 8},
{"Slice", 12},
{"Eface", 8},
{"Complex128", 16},
/* fixed size */
{"float32", 4},
{"float64", 8},
{"byte", 1},
{"int8", 1},
{"uint8", 1},
{"int16", 2},
{"uint16", 2},
{"int32", 4},
{"rune", 4},
{"uint32", 4},
{"int64", 8},
{"uint64", 8},
{nil, 0},
};
/* Fixed structure alignment (non-gcc only) */
int structround = 4;
/* Unexpected EOF. */
static void
bad_eof(void)
{
fatal("%s:%d: unexpected EOF\n", file, lineno);
}
/* Free a list of parameters. */
static void
free_params(struct params *p)
{
while (p != nil) {
struct params *next;
next = p->next;
xfree(p->name);
xfree(p->type);
xfree(p);
p = next;
}
}
/* Read a character, tracking lineno. */
static int
getchar_update_lineno(void)
{
int c;
c = xgetchar();
if (c == '\n')
++lineno;
return c;
}
/* Read a character, giving an error on EOF, tracking lineno. */
static int
getchar_no_eof(void)
{
int c;
c = getchar_update_lineno();
if (c == EOF)
bad_eof();
return c;
}
/* Read a character, skipping comments. */
static int
getchar_skipping_comments(void)
{
int c;
while (1) {
c = getchar_update_lineno();
if (c != '/')
return c;
c = xgetchar();
if (c == '/') {
do {
c = getchar_update_lineno();
} while (c != EOF && c != '\n');
return c;
} else if (c == '*') {
while (1) {
c = getchar_update_lineno();
if (c == EOF)
return EOF;
if (c == '*') {
do {
c = getchar_update_lineno();
} while (c == '*');
if (c == '/')
break;
}
}
} else {
xungetc();
return '/';
}
}
}
/*
* Read and return a token. Tokens are string or character literals
* or else delimited by whitespace or by [(),{}].
* The latter are all returned as single characters.
*/
static char *
read_token(void)
{
int c, q;
char *buf;
unsigned int alc, off;
char* delims = "(),{}";
while (1) {
c = getchar_skipping_comments();
if (c == EOF)
return nil;
if (!xisspace(c))
break;
}
alc = 16;
buf = xmalloc(alc + 1);
off = 0;
if(c == '"' || c == '\'') {
q = c;
buf[off] = c;
++off;
while (1) {
if (off+2 >= alc) { // room for c and maybe next char
alc *= 2;
buf = xrealloc(buf, alc + 1);
}
c = getchar_no_eof();
buf[off] = c;
++off;
if(c == q)
break;
if(c == '\\') {
buf[off] = getchar_no_eof();
++off;
}
}
} else if (xstrrchr(delims, c) != nil) {
buf[off] = c;
++off;
} else {
while (1) {
if (off >= alc) {
alc *= 2;
buf = xrealloc(buf, alc + 1);
}
buf[off] = c;
++off;
c = getchar_skipping_comments();
if (c == EOF)
break;
if (xisspace(c) || xstrrchr(delims, c) != nil) {
if (c == '\n')
lineno--;
xungetc();
break;
}
}
}
buf[off] = '\0';
return buf;
}
/* Read a token, giving an error on EOF. */
static char *
read_token_no_eof(void)
{
char *token = read_token();
if (token == nil)
bad_eof();
return token;
}
/* Read the package clause, and return the package name. */
static char *
read_package(void)
{
char *token;
token = read_token_no_eof();
if (token == nil)
fatal("%s:%d: no token\n", file, lineno);
if (!streq(token, "package")) {
fatal("%s:%d: expected \"package\", got \"%s\"\n",
file, lineno, token);
}
return read_token_no_eof();
}
/* Read and copy preprocessor lines. */
static void
read_preprocessor_lines(void)
{
int first;
first = 1;
while (1) {
int c;
do {
c = getchar_skipping_comments();
} while (xisspace(c));
if (c != '#') {
xungetc();
break;
}
if(first) {
first = 0;
xputchar('\n');
}
xputchar(c);
do {
c = getchar_update_lineno();
xputchar(c);
} while (c != '\n');
}
}
/*
* Read a type in Go syntax and return a type in C syntax. We only
* permit basic types and pointers.
*/
static char *
read_type(void)
{
char *p, *op, *q;
int pointer_count;
unsigned int len;
p = read_token_no_eof();
if (*p != '*' && !streq(p, "int") && !streq(p, "uint"))
return p;
op = p;
pointer_count = 0;
while (*p == '*') {
++pointer_count;
++p;
}
len = xstrlen(p);
q = xmalloc(len + 2 + pointer_count + 1);
xmemmove(q, p, len);
// Turn int/uint into intgo/uintgo.
if((len == 3 && xmemcmp(q, "int", 3) == 0) || (len == 4 && xmemcmp(q, "uint", 4) == 0)) {
q[len++] = 'g';
q[len++] = 'o';
}
while (pointer_count-- > 0)
q[len++] = '*';
q[len] = '\0';
xfree(op);
return q;
}
/* Return the size of the given type. */
static int
type_size(char *p, int *rnd)
{
int i;
if(p[xstrlen(p)-1] == '*') {
*rnd = type_table[Uintptr].rnd;
return type_table[Uintptr].size;
}
if(streq(p, "Iface"))
p = "Eface";
for(i=0; type_table[i].name; i++)
if(streq(type_table[i].name, p)) {
*rnd = type_table[i].rnd;
return type_table[i].size;
}
fatal("%s:%d: unknown type %s\n", file, lineno, p);
return 0;
}
/*
* Read a list of parameters. Each parameter is a name and a type.
* The list ends with a ')'. We have already read the '('.
*/
static struct params *
read_params(int *poffset)
{
char *token;
struct params *ret, **pp, *p;
int offset, size, rnd;
ret = nil;
pp = &ret;
token = read_token_no_eof();
offset = 0;
if (!streq(token, ")")) {
while (1) {
p = xmalloc(sizeof(struct params));
p->name = token;
p->next = nil;
*pp = p;
pp = &p->next;
if(streq(token, "...")) {
p->type = xstrdup("");
} else {
p->type = read_type();
rnd = 0;
size = type_size(p->type, &rnd);
if(rnd > structround)
rnd = structround;
if(offset%rnd)
offset += rnd - offset%rnd;
offset += size;
}
token = read_token_no_eof();
if (!streq(token, ","))
break;
token = read_token_no_eof();
}
}
if (!streq(token, ")")) {
fatal("%s:%d: expected '('\n",
file, lineno);
}
if (poffset != nil)
*poffset = offset;
return ret;
}
/*
* Read a function header. This reads up to and including the initial
* '{' character. Returns 1 if it read a header, 0 at EOF.
*/
static int
read_func_header(char **name, struct params **params, int *paramwid, struct params **rets)
{
int lastline;
char *token;
lastline = -1;
while (1) {
read_preprocessor_lines();
token = read_token();
if (token == nil)
return 0;
if (streq(token, "func")) {
if(lastline != -1)
bwritef(output, "\n");
break;
}
if (lastline != lineno) {
if (lastline == lineno-1)
bwritef(output, "\n");
else
bwritef(output, "\n#line %d \"%s\"\n", lineno, file);
lastline = lineno;
}
bwritef(output, "%s ", token);
}
*name = read_token_no_eof();
token = read_token();
if (token == nil || !streq(token, "(")) {
fatal("%s:%d: expected \"(\"\n",
file, lineno);
}
*params = read_params(paramwid);
token = read_token();
if (token == nil || !streq(token, "("))
*rets = nil;
else {
*rets = read_params(nil);
token = read_token();
}
if (token == nil || !streq(token, "{")) {
fatal("%s:%d: expected \"{\"\n",
file, lineno);
}
return 1;
}
/* Write out parameters. */
static void
write_params(struct params *params, int *first)
{
struct params *p;
for (p = params; p != nil; p = p->next) {
if (*first)
*first = 0;
else
bwritef(output, ", ");
bwritef(output, "%s %s", p->type, p->name);
}
}
/* Write a 6g function header. */
static void
write_6g_func_header(char *package, char *name, struct params *params,
int paramwid, struct params *rets)
{
int first, n;
struct params *p;
bwritef(output, "void\n");
if(!contains(name, "·"))
bwritef(output, "%s·", package);
bwritef(output, "%s(", name);
first = 1;
write_params(params, &first);
/* insert padding to align output struct */
if(rets != nil && paramwid%structround != 0) {
n = structround - paramwid%structround;
if(n & 1)
bwritef(output, ", uint8");
if(n & 2)
bwritef(output, ", uint16");
if(n & 4)
bwritef(output, ", uint32");
}
write_params(rets, &first);
bwritef(output, ")\n{\n");
for (p = rets; p != nil; p = p->next) {
if(streq(p->name, "..."))
continue;
if(streq(p->type, "Slice"))
bwritef(output, "\t%s.array = 0;\n\t%s.len = 0;\n\t%s.cap = 0;\n", p->name, p->name, p->name);
else if(streq(p->type, "String"))
bwritef(output, "\t%s.str = 0;\n\t%s.len = 0;\n", p->name, p->name);
else if(streq(p->type, "Eface"))
bwritef(output, "\t%s.type = 0;\n\t%s.data = 0;\n", p->name, p->name);
else if(streq(p->type, "Iface"))
bwritef(output, "\t%s.tab = 0;\n\t%s.data = 0;\n", p->name, p->name);
else if(streq(p->type, "Complex128"))
bwritef(output, "\t%s.real = 0;\n\t%s.imag = 0;\n", p->name, p->name);
else
bwritef(output, "\t%s = 0;\n", p->name);
bwritef(output, "\tFLUSH(&%s);\n", p->name);
}
}
/* Write a 6g function trailer. */
static void
write_6g_func_trailer(struct params *rets)
{
struct params *p;
for (p = rets; p != nil; p = p->next)
if(!streq(p->name, "..."))
bwritef(output, "\tFLUSH(&%s);\n", p->name);
bwritef(output, "}\n");
}
/* Define the gcc function return type if necessary. */
static void
define_gcc_return_type(char *package, char *name, struct params *rets)
{
struct params *p;
if (rets == nil || rets->next == nil)
return;
bwritef(output, "struct %s_%s_ret {\n", package, name);
for (p = rets; p != nil; p = p->next)
bwritef(output, " %s %s;\n", p->type, p->name);
bwritef(output, "};\n");
}
/* Write out the gcc function return type. */
static void
write_gcc_return_type(char *package, char *name, struct params *rets)
{
if (rets == nil)
bwritef(output, "void");
else if (rets->next == nil)
bwritef(output, "%s", rets->type);
else
bwritef(output, "struct %s_%s_ret", package, name);
}
/* Write out a gcc function header. */
static void
write_gcc_func_header(char *package, char *name, struct params *params,
struct params *rets)
{
int first;
struct params *p;
define_gcc_return_type(package, name, rets);
write_gcc_return_type(package, name, rets);
bwritef(output, " %s_%s(", package, name);
first = 1;
write_params(params, &first);
bwritef(output, ") asm (\"%s.%s\");\n", package, name);
write_gcc_return_type(package, name, rets);
bwritef(output, " %s_%s(", package, name);
first = 1;
write_params(params, &first);
bwritef(output, ")\n{\n");
for (p = rets; p != nil; p = p->next)
bwritef(output, " %s %s;\n", p->type, p->name);
}
/* Write out a gcc function trailer. */
static void
write_gcc_func_trailer(char *package, char *name, struct params *rets)
{
if (rets == nil) {
// nothing to do
}
else if (rets->next == nil)
bwritef(output, "return %s;\n", rets->name);
else {
struct params *p;
bwritef(output, " {\n struct %s_%s_ret __ret;\n", package, name);
for (p = rets; p != nil; p = p->next)
bwritef(output, " __ret.%s = %s;\n", p->name, p->name);
bwritef(output, " return __ret;\n }\n");
}
bwritef(output, "}\n");
}
/* Write out a function header. */
static void
write_func_header(char *package, char *name,
struct params *params, int paramwid,
struct params *rets)
{
if (gcc)
write_gcc_func_header(package, name, params, rets);
else
write_6g_func_header(package, name, params, paramwid, rets);
bwritef(output, "#line %d \"%s\"\n", lineno, file);
}
/* Write out a function trailer. */
static void
write_func_trailer(char *package, char *name,
struct params *rets)
{
if (gcc)
write_gcc_func_trailer(package, name, rets);
else
write_6g_func_trailer(rets);
}
/*
* Read and write the body of the function, ending in an unnested }
* (which is read but not written).
*/
static void
copy_body(void)
{
int nesting = 0;
while (1) {
int c;
c = getchar_no_eof();
if (c == '}' && nesting == 0)
return;
xputchar(c);
switch (c) {
default:
break;
case '{':
++nesting;
break;
case '}':
--nesting;
break;
case '/':
c = getchar_update_lineno();
xputchar(c);
if (c == '/') {
do {
c = getchar_no_eof();
xputchar(c);
} while (c != '\n');
} else if (c == '*') {
while (1) {
c = getchar_no_eof();
xputchar(c);
if (c == '*') {
do {
c = getchar_no_eof();
xputchar(c);
} while (c == '*');
if (c == '/')
break;
}
}
}
break;
case '"':
case '\'':
{
int delim = c;
do {
c = getchar_no_eof();
xputchar(c);
if (c == '\\') {
c = getchar_no_eof();
xputchar(c);
c = '\0';
}
} while (c != delim);
}
break;
}
}
}
/* Process the entire file. */
static void
process_file(void)
{
char *package, *name, *p, *n;
struct params *params, *rets;
int paramwid;
package = read_package();
read_preprocessor_lines();
while (read_func_header(&name, &params, &paramwid, &rets)) {
// name may have a package override already
n = xstrstr(name, "·");
if(n != nil) {
p = xmalloc(n - name + 1);
xmemmove(p, name, n - name);
p[n - name] = 0;
n += xstrlen("·");
} else {
p = package;
n = name;
}
write_func_header(p, n, params, paramwid, rets);
copy_body();
write_func_trailer(p, n, rets);
xfree(name);
if(p != package) xfree(p);
free_params(params);
free_params(rets);
}
xfree(package);
}
void
goc2c(char *goc, char *c)
{
int i;
Buf in, out;
binit(&in);
binit(&out);
file = goc;
readfile(&in, goc);
// TODO: set gcc=1 when using gcc
if(!gcc) {
if(contains(goarch, "64p32")) {
type_table[Uintptr].size = 4;
type_table[Int].size = 4;
structround = 8;
} else if(contains(goarch, "64")) {
type_table[Uintptr].size = 8;
if(use64bitint) {
type_table[Int].size = 8;
} else {
type_table[Int].size = 4;
}
structround = 8;
} else {
// NOTE: These are set in the initializer,
// but they might have been changed by a
// previous invocation of goc2c, so we have
// to restore them.
type_table[Uintptr].size = 4;
type_table[Int].size = 4;
structround = 4;
}
type_table[Uint].size = type_table[Int].size;
type_table[Slice].size = type_table[Uintptr].size+2*type_table[Int].size;
type_table[Eface].size = 2*type_table[Uintptr].size;
type_table[String].size = 2*type_table[Uintptr].size;
for(i=0; i<nelem(type_table); i++)
type_table[i].rnd = type_table[i].size;
type_table[String].rnd = type_table[Uintptr].rnd;
type_table[Slice].rnd = type_table[Uintptr].rnd;
type_table[Eface].rnd = type_table[Uintptr].rnd;
type_table[Complex128].rnd = type_table[Float64].rnd;
}
bprintf(&out, "// auto generated by go tool dist\n// goos=%s goarch=%s\n\n", goos, goarch);
input = bstr(&in);
output = &out;
lineno = 1;
process_file();
writefile(&out, c, 0);
}

View File

@ -23,7 +23,7 @@ bprintf(Buf *b, char *fmt, ...)
{
va_list arg;
char buf[4096];
breset(b);
va_start(arg, fmt);
vsnprintf(buf, sizeof buf, fmt, arg);
@ -572,10 +572,10 @@ bool
hassuffix(char *p, char *suffix)
{
int np, ns;
np = strlen(p);
ns = strlen(suffix);
return np >= ns && strcmp(p+np-ns, suffix) == 0;
return np >= ns && streq(p+np-ns, suffix);
}
// hasprefix reports whether p begins with prefix.

16
src/cmd/dist/unix.c vendored
View File

@ -431,7 +431,7 @@ xremoveall(char *p)
}
bfree(&b);
vfree(&dir);
vfree(&dir);
}
// xreaddir replaces dst with a list of the names of the files in dir.
@ -441,13 +441,13 @@ xreaddir(Vec *dst, char *dir)
{
DIR *d;
struct dirent *dp;
vreset(dst);
d = opendir(dir);
if(d == nil)
fatal("opendir %s: %s", dir, strerror(errno));
while((dp = readdir(d)) != nil) {
if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
if(streq(dp->d_name, ".") || streq(dp->d_name, ".."))
continue;
vadd(dst, dp->d_name);
}
@ -461,7 +461,7 @@ xworkdir(void)
{
Buf b;
char *p;
binit(&b);
xgetenv(&b, "TMPDIR");
@ -546,10 +546,10 @@ bool
hassuffix(char *p, char *suffix)
{
int np, ns;
np = strlen(p);
ns = strlen(suffix);
return np >= ns && strcmp(p+np-ns, suffix) == 0;
return np >= ns && streq(p+np-ns, suffix);
}
// hasprefix reports whether p begins with prefix.
@ -716,7 +716,7 @@ main(int argc, char **argv)
fatal("unknown architecture: %s", u.machine);
}
if(strcmp(gohostarch, "arm") == 0)
if(streq(gohostarch, "arm"))
maxnbg = 1;
// The OS X 10.6 linker does not support external linking mode.
@ -728,7 +728,7 @@ main(int argc, char **argv)
//
// Roughly, OS X 10.N shows up as uname release (N+4),
// so OS X 10.6 is uname version 10 and OS X 10.8 is uname version 12.
if(strcmp(gohostos, "darwin") == 0) {
if(streq(gohostos, "darwin")) {
if(uname(&u) < 0)
fatal("uname: %s", strerror(errno));
osx = atoi(u.release) - 4;

View File

@ -770,10 +770,10 @@ bool
hassuffix(char *p, char *suffix)
{
int np, ns;
np = strlen(p);
ns = strlen(suffix);
return np >= ns && strcmp(p+np-ns, suffix) == 0;
return np >= ns && streq(p+np-ns, suffix);
}
bool

View File

@ -27,7 +27,7 @@ rewrites are idempotent, so that it is safe to apply fix to updated
or partially updated code even without using the -r flag.
Fix prints the full list of fixes it can apply in its help output;
to see them, run go tool fix -?.
to see them, run go tool fix -help.
Fix does not make backup copies of the files that it edits.
Instead, use a version control system's ``diff'' functionality to inspect

View File

@ -9,11 +9,12 @@ char *runtimeimport =
"func @\"\".throwreturn ()\n"
"func @\"\".throwinit ()\n"
"func @\"\".panicwrap (? string, ? string, ? string)\n"
"func @\"\".panic (? interface {})\n"
"func @\"\".recover (? *int32) (? interface {})\n"
"func @\"\".gopanic (? interface {})\n"
"func @\"\".gorecover (? *int32) (? interface {})\n"
"func @\"\".printbool (? bool)\n"
"func @\"\".printfloat (? float64)\n"
"func @\"\".printint (? int64)\n"
"func @\"\".printhex (? uint64)\n"
"func @\"\".printuint (? uint64)\n"
"func @\"\".printcomplex (? complex128)\n"
"func @\"\".printstring (? string)\n"
@ -64,7 +65,6 @@ char *runtimeimport =
"func @\"\".efaceeq (@\"\".i1·2 any, @\"\".i2·3 any) (@\"\".ret·1 bool)\n"
"func @\"\".ifacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n"
"func @\"\".efacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n"
"func @\"\".equal (@\"\".typ·2 *byte, @\"\".x1·3 any, @\"\".x2·4 any) (@\"\".ret·1 bool)\n"
"func @\"\".makemap (@\"\".mapType·2 *byte, @\"\".hint·3 int64) (@\"\".hmap·1 map[any]any)\n"
"func @\"\".mapaccess1 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 *any) (@\"\".val·1 *any)\n"
"func @\"\".mapaccess1_fast32 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
@ -96,12 +96,12 @@ char *runtimeimport =
"func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\n"
"func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int64) (@\"\".ary·1 []any)\n"
"func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr)\n"
"func @\"\".memequal (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
"func @\"\".memequal8 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
"func @\"\".memequal16 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
"func @\"\".memequal32 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
"func @\"\".memequal64 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
"func @\"\".memequal128 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
"func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
"func @\"\".memequal8 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
"func @\"\".memequal16 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
"func @\"\".memequal32 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
"func @\"\".memequal64 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
"func @\"\".memequal128 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
"func @\"\".int64div (? int64, ? int64) (? int64)\n"
"func @\"\".uint64div (? uint64, ? uint64) (? uint64)\n"
"func @\"\".int64mod (? int64, ? int64) (? int64)\n"

View File

@ -108,6 +108,9 @@ bvnext(Bvec *bv, int32 i)
{
uint32 w;
if(i >= bv->n)
return -1;
// Jump i ahead to next word with bits.
if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) {
i &= ~WORDMASK;
@ -117,7 +120,7 @@ bvnext(Bvec *bv, int32 i)
}
if(i >= bv->n)
return -1;
// Find 1 bit.
w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK);
while((w&1) == 0) {

View File

@ -1566,7 +1566,6 @@ isgoconst(Node *n)
case ORSH:
case OSUB:
case OXOR:
case OCONV:
case OIOTA:
case OCOMPLEX:
case OREAL:
@ -1574,7 +1573,12 @@ isgoconst(Node *n)
if(isgoconst(n->left) && (n->right == N || isgoconst(n->right)))
return 1;
break;
case OCONV:
if(okforconst[n->type->etype] && isgoconst(n->left))
return 1;
break;
case OLEN:
case OCAP:
l = n->left;

Some files were not shown because too many files have changed in this diff Show More