diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index f78561c3483..5f4adf9d0e7 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -61f7cf4b9db0587ff099aa36832a355b90ee1bf9 +262cb89fd5ed82ab135a3933b2ddf4eb67683149 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 79702821336..1e6890a3cc5 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -12177,6 +12177,50 @@ Call_expression::intrinsify(Gogo* gogo, return Runtime::make_call(code, loc, 3, a1, a2, a3); } } + else if (package == "internal/abi") + { + if ((name == "FuncPCABI0" || name == "FuncPCABIInternal") + && this->args_ != NULL + && this->args_->size() == 1) + { + // We expect to see a conversion from the expression to "any". + Expression* expr = this->args_->front(); + Type_conversion_expression* tce = expr->conversion_expression(); + if (tce != NULL) + expr = tce->expr(); + Func_expression* fe = expr->func_expression(); + Interface_field_reference_expression* interface_method = + expr->interface_field_reference_expression(); + if (fe != NULL) + { + Named_object* no = fe->named_object(); + Expression* ref = Expression::make_func_code_reference(no, loc); + Type* uintptr_type = Type::lookup_integer_type("uintptr"); + return Expression::make_cast(uintptr_type, ref, loc); + } + else if (interface_method != NULL) + return interface_method->get_function(); + else + { + expr = this->args_->front(); + go_assert(expr->type()->interface_type() != NULL + && expr->type()->interface_type()->is_empty()); + expr = Expression::make_interface_info(expr, + INTERFACE_INFO_OBJECT, + loc); + // Trust that this is a function type, which means that + // it is a direct iface type and we can use EXPR + // directly. The backend representation of this + // function is a pointer to a struct whose first field + // is the actual function to call. + Type* pvoid = Type::make_pointer_type(Type::make_void_type()); + Type* pfntype = Type::make_pointer_type(pvoid); + Expression* ref = make_unsafe_cast(pfntype, expr, loc); + return Expression::make_dereference(ref, NIL_CHECK_NOT_NEEDED, + loc); + } + } + } return NULL; } diff --git a/libgo/go/internal/abi/abi.go b/libgo/go/internal/abi/abi.go new file mode 100644 index 00000000000..c4a108847ca --- /dev/null +++ b/libgo/go/internal/abi/abi.go @@ -0,0 +1,35 @@ +// Copyright 2020 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 abi + +// FuncPC* intrinsics. +// +// CAREFUL: In programs with plugins, FuncPC* can return different values +// for the same function (because there are actually multiple copies of +// the same function in the address space). To be safe, don't use the +// results of this function in any == expression. It is only safe to +// use the result as an address at which to start executing code. + +// FuncPCABI0 returns the entry PC of the function f, which must be a +// direct reference of a function defined as ABI0. Otherwise it is a +// compile-time error. +// +// Implemented as a compile intrinsic. +func FuncPCABI0(f any) uintptr { + // The compiler should remove all calls. + panic("FuncPCABI0") +} + +// FuncPCABIInternal returns the entry PC of the function f. If f is a +// direct reference of a function, it must be defined as ABIInternal. +// Otherwise it is a compile-time error. If f is not a direct reference +// of a defined function, it assumes that f is a func value. Otherwise +// the behavior is undefined. +// +// Implemented as a compile intrinsic. +func FuncPCABIInternal(f any) uintptr { + // The compiler should remove all calls. + panic("FuncPCABIInternal") +} diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go index 05342905ff1..343f13b40f0 100644 --- a/libgo/go/runtime/proc.go +++ b/libgo/go/runtime/proc.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "internal/cpu" "runtime/internal/atomic" "runtime/internal/sys" @@ -4243,11 +4244,11 @@ func _GC() { _GC() } func _LostSIGPROFDuringAtomic64() { _LostSIGPROFDuringAtomic64() } func _VDSO() { _VDSO() } -var _SystemPC = funcPC(_System) -var _ExternalCodePC = funcPC(_ExternalCode) -var _LostExternalCodePC = funcPC(_LostExternalCode) -var _GCPC = funcPC(_GC) -var _LostSIGPROFDuringAtomic64PC = funcPC(_LostSIGPROFDuringAtomic64) +var _SystemPC = abi.FuncPCABIInternal(_System) +var _ExternalCodePC = abi.FuncPCABIInternal(_ExternalCode) +var _LostExternalCodePC = abi.FuncPCABIInternal(_LostExternalCode) +var _GCPC = abi.FuncPCABIInternal(_GC) +var _LostSIGPROFDuringAtomic64PC = abi.FuncPCABIInternal(_LostSIGPROFDuringAtomic64) // Called if we receive a SIGPROF signal. // Called by the signal handler, may run during STW. diff --git a/libgo/libgo-packages.txt b/libgo/libgo-packages.txt index 4fc8c843f02..f3097dc0a6a 100644 --- a/libgo/libgo-packages.txt +++ b/libgo/libgo-packages.txt @@ -113,6 +113,7 @@ image/internal/imageutil image/jpeg image/png index/suffixarray +internal/abi internal/buildcfg internal/bytealg internal/cfg