compiler, internal/abi: implement FuncPCABI0, FuncPCABIInternal

The Go 1.18 standard library uses an internal/abi package with two
functions that are implemented in the compiler. This patch implements
them in the gofrontend, to support the upcoming update to 1.18.

Change-Id: I645f0c65ccf18646b212f23add94a618843bff7c
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/383514
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
diff --git a/go/expressions.cc b/go/expressions.cc
index 7970282..1e6890a 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -12177,6 +12177,50 @@
           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 0000000..c4a1088
--- /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 0534290..343f13b 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 _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 4fc8c84..f3097dc 100644
--- a/libgo/libgo-packages.txt
+++ b/libgo/libgo-packages.txt
@@ -113,6 +113,7 @@
 image/jpeg
 image/png
 index/suffixarray
+internal/abi
 internal/buildcfg
 internal/bytealg
 internal/cfg