Skip to content

Commit

Permalink
compiler, libgo: support bootstrapping gc compiler
Browse files Browse the repository at this point in the history
In the Go 1.21 release the package internal/profile imports
internal/lazyregexp.  That works when bootstrapping with Go 1.17,
because that compiler has internal/lazyregep and permits importing it.
We also have internal/lazyregexp in libgo, but since it is not installed
it is not available for importing.  This CL adds internal/lazyregexp
to the list of internal packages that are installed for bootstrapping.

The Go 1.21, and earlier, releases have a couple of functions in
the internal/abi package that are always fully intrinsified.
The gofrontend recognizes and intrinsifies those functions as well.
However, the gofrontend was also building function descriptors
for references to the functions without calling them, which
failed because there was nothing to refer to.  That is OK for the
gc compiler, which guarantees that the functions are only called,
not referenced.  This CL arranges to not generate function descriptors
for these functions.

For golang/go#60913

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/504798
  • Loading branch information
ianlancetaylor committed Jun 23, 2023
1 parent 13709b5 commit 6b72442
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 11 deletions.
2 changes: 1 addition & 1 deletion gcc/go/gofrontend/MERGE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
195060166e6045408a2cb95e6aa88c6f0b98f20b
68a756b6aadc901534cfddddad2b1e73fae9e34f

The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
3 changes: 2 additions & 1 deletion gcc/go/gofrontend/expressions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12272,7 +12272,8 @@ Call_expression::intrinsify(Gogo* gogo,
return Runtime::make_call(code, loc, 3, a1, a2, a3);
}
}
else if (package == "internal/abi")
else if (package == "internal/abi"
|| package == "bootstrap/internal/abi") // for bootstrapping gc
{
if (is_method)
return NULL;
Expand Down
31 changes: 30 additions & 1 deletion gcc/go/gofrontend/gogo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3296,6 +3296,9 @@ class Create_function_descriptors : public Traverse
int
expression(Expression**);

static bool
skip_descriptor(Gogo* gogo, const Named_object*);

private:
Gogo* gogo_;
};
Expand All @@ -3306,6 +3309,9 @@ class Create_function_descriptors : public Traverse
int
Create_function_descriptors::function(Named_object* no)
{
if (Create_function_descriptors::skip_descriptor(this->gogo_, no))
return TRAVERSE_CONTINUE;

if (no->is_function()
&& no->func_value()->enclosing() == NULL
&& !no->func_value()->is_method()
Expand Down Expand Up @@ -3393,6 +3399,28 @@ Create_function_descriptors::expression(Expression** pexpr)
return TRAVERSE_CONTINUE;
}

// The gc compiler has some special cases that it always compiles as
// intrinsics. For those we don't want to generate a function
// descriptor, as there will be no code for it to refer to.

bool
Create_function_descriptors::skip_descriptor(Gogo* gogo,
const Named_object* no)
{
const std::string& pkgpath(no->package() == NULL
? gogo->pkgpath()
: no->package()->pkgpath());

// internal/abi is the standard library package,
// bootstrap/internal/abi is the name used when bootstrapping the gc
// compiler.

return ((pkgpath == "internal/abi"
|| pkgpath == "bootstrap/internal/abi")
&& (no->name() == "FuncPCABI0"
|| no->name() == "FuncPCABIInternal"));
}

// Create function descriptors as needed. We need a function
// descriptor for all exported functions and for all functions that
// are referenced without being called.
Expand All @@ -3414,7 +3442,8 @@ Gogo::create_function_descriptors()
if (no->is_function_declaration()
&& !no->func_declaration_value()->type()->is_method()
&& !Linemap::is_predeclared_location(no->location())
&& !Gogo::is_hidden_name(no->name()))
&& !Gogo::is_hidden_name(no->name())
&& !Create_function_descriptors::skip_descriptor(this, no))
fndecls.push_back(no);
}
for (std::vector<Named_object*>::const_iterator p = fndecls.begin();
Expand Down
1 change: 1 addition & 0 deletions libgo/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ toolexeclibgounicode_DATA = \
# Some internal packages are needed to bootstrap the gc toolchain.
toolexeclibgointernaldir = $(toolexeclibgodir)/internal
toolexeclibgointernal_DATA = \
internal/lazyregexp.gox \
internal/reflectlite.gox \
internal/unsafeheader.gox

Expand Down
1 change: 1 addition & 0 deletions libgo/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,7 @@ toolexeclibgounicode_DATA = \
# Some internal packages are needed to bootstrap the gc toolchain.
toolexeclibgointernaldir = $(toolexeclibgodir)/internal
toolexeclibgointernal_DATA = \
internal/lazyregexp.gox \
internal/reflectlite.gox \
internal/unsafeheader.gox

Expand Down
10 changes: 2 additions & 8 deletions libgo/go/internal/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ package abi
// compile-time error.
//
// Implemented as a compile intrinsic.
func FuncPCABI0(f any) uintptr {
// The compiler should remove all calls.
panic("FuncPCABI0")
}
func FuncPCABI0(f any) uintptr

// FuncPCABIInternal returns the entry PC of the function f. If f is a
// direct reference of a function, it must be defined as ABIInternal.
Expand All @@ -29,7 +26,4 @@ func FuncPCABI0(f any) uintptr {
// the behavior is undefined.
//
// Implemented as a compile intrinsic.
func FuncPCABIInternal(f any) uintptr {
// The compiler should remove all calls.
panic("FuncPCABIInternal")
}
func FuncPCABIInternal(f any) uintptr

0 comments on commit 6b72442

Please sign in to comment.