aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/typecheck/builtin
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2021-04-09 14:40:28 -0400
committerCherry Zhang <cherryyz@google.com>2021-04-12 22:50:31 +0000
commit49e933fc57c2f858e19c26f4a2e56ba94fc54989 (patch)
tree1b5d3810f94d9dbbd154ca88553b938d975430d7 /src/cmd/compile/internal/typecheck/builtin
parent841bc142160aacde729a983243a0231c8612903d (diff)
downloadgo-49e933fc57c2f858e19c26f4a2e56ba94fc54989.tar.gz
go-49e933fc57c2f858e19c26f4a2e56ba94fc54989.zip
cmd/compile: make interface conversion function selection ABI insensitive
Before register ABI, we always pass argument in memory, and the compiler chooses interface conversion functions solely based on the memory layout. As long as the two types have identical memory layout, it is fine to mix and match, e.g. convT64 takes a uint64 argument, but it can be used for things like float64 or struct { x [4]struct{}; y int64 }. With register ABI, those types may be passed differently, e.g. uint64 is passed in an integer register, float64 is passed in a floating point register, the struct above is passed in memory. I made a few attempts in the previous CLs to try to choose the right function based on the argument type, but none of them is really correct. Instead, this CL changes it to always pass the argument in the same type the runtime expects, and do conversion before the call in the compiler. The conversion can be no-op (e.g. a named type to its underlying type), direct (e.g. int64 to uint64), or through memory (e.g. *(*uint64)(unsafe.Pointer(&arg))). This way, the front end does not need to know the ABI. (It only needs to know how to convert types, and it already does.) TODO: do something similar for map functions. Change-Id: I33fc780a47c3f332b765e09b5e527f52ea1d6b5c Reviewed-on: https://go-review.googlesource.com/c/go/+/309029 Trust: Cherry Zhang <cherryyz@google.com> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/compile/internal/typecheck/builtin')
-rw-r--r--src/cmd/compile/internal/typecheck/builtin/runtime.go17
1 files changed, 10 insertions, 7 deletions
diff --git a/src/cmd/compile/internal/typecheck/builtin/runtime.go b/src/cmd/compile/internal/typecheck/builtin/runtime.go
index 7c9599b54e..b7fb2e6044 100644
--- a/src/cmd/compile/internal/typecheck/builtin/runtime.go
+++ b/src/cmd/compile/internal/typecheck/builtin/runtime.go
@@ -87,13 +87,16 @@ func convI2I(typ *byte, elem any) (ret any)
// Specialized type-to-interface conversion.
// These return only a data pointer.
-func convT16(val any) unsafe.Pointer // val must be uint16-like (same size and alignment as a uint16)
-func convT32(val any) unsafe.Pointer // val must be uint32-like (same size and alignment as a uint32)
-func convT32F(val any) unsafe.Pointer // val must be float32-like
-func convT64(val any) unsafe.Pointer // val must be uint64-like (same size and alignment as a uint64 and contains no pointers)
-func convT64F(val any) unsafe.Pointer // val must be float64-like
-func convTstring(val any) unsafe.Pointer // val must be a string
-func convTslice(val any) unsafe.Pointer // val must be a slice
+// These functions take concrete types in the runtime. But they may
+// be used for a wider range of types, which have the same memory
+// layout as the parameter type. The compiler converts the
+// to-be-converted type to the parameter type before calling the
+// runtime function. This way, the call is ABI-insensitive.
+func convT16(val uint16) unsafe.Pointer
+func convT32(val uint32) unsafe.Pointer
+func convT64(val uint64) unsafe.Pointer
+func convTstring(val string) unsafe.Pointer
+func convTslice(val []uint8) unsafe.Pointer
// Type to empty-interface conversion.
func convT2E(typ *byte, elem *any) (ret any)