compiler: recognize Go 1.18 runtime/internal/atomic methods
The Go 1.18 library introduces specific types in runtime/internal/atomic. Recognize and optimize the methods on those types, as we do with the functions in runtime/internal/atomic. While we're here avoid getting confused by methods in any other package that we recognize specially. Change-Id: I75c31f75dcf65ce13f3c69022e8ec36e05eab994 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/383654 Trust: Ian Lance Taylor <iant@golang.org> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Родитель
262cb89fd5
Коммит
3b1e46937d
|
@ -11613,12 +11613,16 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
std::string package = (no->package() != NULL
|
std::string package = (no->package() != NULL
|
||||||
? no->package()->pkgpath()
|
? no->package()->pkgpath()
|
||||||
: gogo->pkgpath());
|
: gogo->pkgpath());
|
||||||
|
bool is_method = ((no->is_function() && no->func_value()->is_method())
|
||||||
|
|| (no->is_function_declaration()
|
||||||
|
&& no->func_declaration_value()->is_method()));
|
||||||
Location loc = this->location();
|
Location loc = this->location();
|
||||||
|
|
||||||
Type* int_type = Type::lookup_integer_type("int");
|
Type* int_type = Type::lookup_integer_type("int");
|
||||||
Type* int32_type = Type::lookup_integer_type("int32");
|
Type* int32_type = Type::lookup_integer_type("int32");
|
||||||
Type* int64_type = Type::lookup_integer_type("int64");
|
Type* int64_type = Type::lookup_integer_type("int64");
|
||||||
Type* uint_type = Type::lookup_integer_type("uint");
|
Type* uint_type = Type::lookup_integer_type("uint");
|
||||||
|
Type* uint8_type = Type::lookup_integer_type("uint8");
|
||||||
Type* uint32_type = Type::lookup_integer_type("uint32");
|
Type* uint32_type = Type::lookup_integer_type("uint32");
|
||||||
Type* uint64_type = Type::lookup_integer_type("uint64");
|
Type* uint64_type = Type::lookup_integer_type("uint64");
|
||||||
Type* uintptr_type = Type::lookup_integer_type("uintptr");
|
Type* uintptr_type = Type::lookup_integer_type("uintptr");
|
||||||
|
@ -11629,6 +11633,9 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
|
|
||||||
if (package == "sync/atomic")
|
if (package == "sync/atomic")
|
||||||
{
|
{
|
||||||
|
if (is_method)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// sync/atomic functions and runtime/internal/atomic functions
|
// sync/atomic functions and runtime/internal/atomic functions
|
||||||
// are very similar. In order not to duplicate code, we just
|
// are very similar. In order not to duplicate code, we just
|
||||||
// redirect to the latter and let the code below to handle them.
|
// redirect to the latter and let the code below to handle them.
|
||||||
|
@ -11694,6 +11701,9 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
|
|
||||||
if (package == "runtime/internal/sys")
|
if (package == "runtime/internal/sys")
|
||||||
{
|
{
|
||||||
|
if (is_method)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// runtime/internal/sys functions and math/bits functions
|
// runtime/internal/sys functions and math/bits functions
|
||||||
// are very similar. In order not to duplicate code, we just
|
// are very similar. In order not to duplicate code, we just
|
||||||
// redirect to the latter and let the code below to handle them.
|
// redirect to the latter and let the code below to handle them.
|
||||||
|
@ -11713,6 +11723,9 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
|
|
||||||
if (package == "runtime")
|
if (package == "runtime")
|
||||||
{
|
{
|
||||||
|
if (is_method)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Handle a couple of special runtime functions. In the runtime
|
// Handle a couple of special runtime functions. In the runtime
|
||||||
// package, getcallerpc returns the PC of the caller, and
|
// package, getcallerpc returns the PC of the caller, and
|
||||||
// getcallersp returns the frame pointer of the caller. Implement
|
// getcallersp returns the frame pointer of the caller. Implement
|
||||||
|
@ -11743,6 +11756,9 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
}
|
}
|
||||||
else if (package == "math/bits")
|
else if (package == "math/bits")
|
||||||
{
|
{
|
||||||
|
if (is_method)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if ((name == "ReverseBytes16" || name == "ReverseBytes32"
|
if ((name == "ReverseBytes16" || name == "ReverseBytes32"
|
||||||
|| name == "ReverseBytes64" || name == "ReverseBytes")
|
|| name == "ReverseBytes64" || name == "ReverseBytes")
|
||||||
&& this->args_ != NULL && this->args_->size() == 1)
|
&& this->args_ != NULL && this->args_->size() == 1)
|
||||||
|
@ -11913,9 +11929,137 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
{
|
{
|
||||||
int memorder = __ATOMIC_SEQ_CST;
|
int memorder = __ATOMIC_SEQ_CST;
|
||||||
|
|
||||||
|
if (is_method)
|
||||||
|
{
|
||||||
|
Function_type* ftype = (no->is_function()
|
||||||
|
? no->func_value()->type()
|
||||||
|
: no->func_declaration_value()->type());
|
||||||
|
Type* rtype = ftype->receiver()->type()->deref();
|
||||||
|
go_assert(rtype->named_type() != NULL);
|
||||||
|
const std::string& rname(rtype->named_type()->name());
|
||||||
|
if (rname == "Int32")
|
||||||
|
{
|
||||||
|
if (name == "Load")
|
||||||
|
name = "LoadInt32";
|
||||||
|
else if (name == "Store")
|
||||||
|
name = "Storeint32";
|
||||||
|
else if (name == "CompareAndSwap")
|
||||||
|
name = "Casint32";
|
||||||
|
else if (name == "Swap")
|
||||||
|
name = "Xchgint32";
|
||||||
|
else if (name == "Add")
|
||||||
|
name = "Xaddint32";
|
||||||
|
else
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
else if (rname == "Int64")
|
||||||
|
{
|
||||||
|
if (name == "Load")
|
||||||
|
name = "LoadInt64";
|
||||||
|
else if (name == "Store")
|
||||||
|
name = "Storeint64";
|
||||||
|
else if (name == "CompareAndSwap")
|
||||||
|
name = "Casint64";
|
||||||
|
else if (name == "Swap")
|
||||||
|
name = "Xchgint64";
|
||||||
|
else if (name == "Add")
|
||||||
|
name = "Xaddint64";
|
||||||
|
else
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
else if (rname == "Uint8")
|
||||||
|
{
|
||||||
|
if (name == "Load")
|
||||||
|
name = "Load8";
|
||||||
|
else if (name == "Store")
|
||||||
|
name = "Store8";
|
||||||
|
else if (name == "And")
|
||||||
|
name = "And8";
|
||||||
|
else if (name == "Or")
|
||||||
|
name = "Or8";
|
||||||
|
else
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
else if (rname == "Uint32")
|
||||||
|
{
|
||||||
|
if (name == "Load")
|
||||||
|
name = "Load";
|
||||||
|
else if (name == "LoadAcquire")
|
||||||
|
name = "LoadAcq";
|
||||||
|
else if (name == "Store")
|
||||||
|
name = "Store";
|
||||||
|
else if (name == "CompareAndSwap")
|
||||||
|
name = "Cas";
|
||||||
|
else if (name == "CompareAndSwapRelease")
|
||||||
|
name = "CasRel";
|
||||||
|
else if (name == "Swap")
|
||||||
|
name = "Xchg";
|
||||||
|
else if (name == "And")
|
||||||
|
name = "And";
|
||||||
|
else if (name == "Or")
|
||||||
|
name = "Or";
|
||||||
|
else if (name == "Add")
|
||||||
|
name = "Xadd";
|
||||||
|
else
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
else if (rname == "Uint64")
|
||||||
|
{
|
||||||
|
if (name == "Load")
|
||||||
|
name = "Load64";
|
||||||
|
else if (name == "Store")
|
||||||
|
name = "Store64";
|
||||||
|
else if (name == "CompareAndSwap")
|
||||||
|
name = "Cas64";
|
||||||
|
else if (name == "Swap")
|
||||||
|
name = "Xchgt64";
|
||||||
|
else if (name == "Add")
|
||||||
|
name = "Xadd64";
|
||||||
|
else
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
else if (rname == "Uintptr")
|
||||||
|
{
|
||||||
|
if (name == "Load")
|
||||||
|
name = "Loaduintptr";
|
||||||
|
else if (name == "LoadAcquire")
|
||||||
|
name = "Loadacquintptr";
|
||||||
|
else if (name == "Store")
|
||||||
|
name = "Storeuintptr";
|
||||||
|
else if (name == "StoreRelease")
|
||||||
|
name = "StoreReluintptr";
|
||||||
|
else if (name == "CompareAndSwap")
|
||||||
|
name = "Casuintptr";
|
||||||
|
else if (name == "Swap")
|
||||||
|
name = "Xchguintptr";
|
||||||
|
else if (name == "Add")
|
||||||
|
name = "Xadduintptr";
|
||||||
|
else
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
else if (rname == "Float64")
|
||||||
|
{
|
||||||
|
// Needs unsafe type conversion. Don't intrinsify for now.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (rname == "UnsafePointer")
|
||||||
|
{
|
||||||
|
if (name == "Load")
|
||||||
|
name = "Loadp";
|
||||||
|
else if (name == "StoreNoWB")
|
||||||
|
name = "StorepoWB";
|
||||||
|
else if (name == "CompareAndSwapNoWB")
|
||||||
|
name = "Casp1";
|
||||||
|
else
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
if ((name == "Load" || name == "Load64" || name == "Loadint64" || name == "Loadp"
|
if ((name == "Load" || name == "Load64" || name == "Loadint64" || name == "Loadp"
|
||||||
|| name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq"
|
|| name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq"
|
||||||
|| name == "Loadint32")
|
|| name == "Loadint32" || name == "Load8")
|
||||||
&& this->args_ != NULL && this->args_->size() == 1)
|
&& this->args_ != NULL && this->args_->size() == 1)
|
||||||
{
|
{
|
||||||
if (int_size < 8 && (name == "Load64" || name == "Loadint64"))
|
if (int_size < 8 && (name == "Load64" || name == "Loadint64"))
|
||||||
|
@ -11972,6 +12116,11 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
res_type = uint32_type;
|
res_type = uint32_type;
|
||||||
memorder = __ATOMIC_ACQUIRE;
|
memorder = __ATOMIC_ACQUIRE;
|
||||||
}
|
}
|
||||||
|
else if (name == "Load8")
|
||||||
|
{
|
||||||
|
code = Runtime::ATOMIC_LOAD_1;
|
||||||
|
res_type = uint8_type;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
go_unreachable();
|
go_unreachable();
|
||||||
Expression* a1 = this->args_->front();
|
Expression* a1 = this->args_->front();
|
||||||
|
@ -12012,6 +12161,8 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
code = Runtime::ATOMIC_STORE_4;
|
code = Runtime::ATOMIC_STORE_4;
|
||||||
memorder = __ATOMIC_RELEASE;
|
memorder = __ATOMIC_RELEASE;
|
||||||
}
|
}
|
||||||
|
else if (name == "Store8")
|
||||||
|
code = Runtime::ATOMIC_STORE_1;
|
||||||
else
|
else
|
||||||
go_unreachable();
|
go_unreachable();
|
||||||
Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
|
Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
|
||||||
|
@ -12179,6 +12330,9 @@ Call_expression::intrinsify(Gogo* gogo,
|
||||||
}
|
}
|
||||||
else if (package == "internal/abi")
|
else if (package == "internal/abi")
|
||||||
{
|
{
|
||||||
|
if (is_method)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if ((name == "FuncPCABI0" || name == "FuncPCABIInternal")
|
if ((name == "FuncPCABI0" || name == "FuncPCABIInternal")
|
||||||
&& this->args_ != NULL
|
&& this->args_ != NULL
|
||||||
&& this->args_->size() == 1)
|
&& this->args_->size() == 1)
|
||||||
|
|
|
@ -478,6 +478,10 @@ DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4",
|
||||||
DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
|
DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
|
||||||
P3(POINTER, UINT64, INT32),
|
P3(POINTER, UINT64, INT32),
|
||||||
R1(UINT64))
|
R1(UINT64))
|
||||||
|
DEF_GO_RUNTIME(ATOMIC_LOAD_1, "__atomic_load_1", P2(POINTER, INT32),
|
||||||
|
R1(UINT8))
|
||||||
|
DEF_GO_RUNTIME(ATOMIC_STORE_1, "__atomic_store_1", P3(POINTER, UINT8, INT32),
|
||||||
|
R0())
|
||||||
DEF_GO_RUNTIME(ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
|
DEF_GO_RUNTIME(ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
|
||||||
P3(POINTER, UINT8, INT32),
|
P3(POINTER, UINT8, INT32),
|
||||||
R1(UINT8))
|
R1(UINT8))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче