aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorqiulaidongfeng <2645477756@qq.com>2024-01-06 07:25:05 +0000
committerKeith Randall <khr@golang.org>2024-01-23 00:36:00 +0000
commit99e12bee441ac82f53bbb0e5cf2fdad716aba5a6 (patch)
tree1fc488e5ca2f2f8879fff50e5c0da3f5af49bbb4
parent4605ce2d344d9e25c1d58898acb28edab93af97f (diff)
downloadgo-99e12bee441ac82f53bbb0e5cf2fdad716aba5a6.tar.xz
reflect: StructOf set abi.TFlagRegularMemory
Complete a TODO. Change-Id: I791d27266ccee69c371524e298120765f5736cf8 GitHub-Last-Rev: 8878003efa2f9f3d8609b88073c982d21ece774b GitHub-Pull-Request: golang/go#64617 Reviewed-on: https://go-review.googlesource.com/c/go/+/548435 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org>
-rw-r--r--src/reflect/export_test.go2
-rw-r--r--src/reflect/type.go47
-rw-r--r--src/reflect/type_test.go43
3 files changed, 91 insertions, 1 deletions
diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go
index 1648eb3624..55eb50a425 100644
--- a/src/reflect/export_test.go
+++ b/src/reflect/export_test.go
@@ -166,3 +166,5 @@ func SetArgRegs(ints, floats int, floatSize uintptr) (oldInts, oldFloats int, ol
var MethodValueCallCodePtr = methodValueCallCodePtr
var InternalIsZero = isZero
+
+var IsRegularMemory = isRegularMemory
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 89c5015530..dfa2ff6ddf 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -2152,6 +2152,47 @@ func isValidFieldName(fieldName string) bool {
return len(fieldName) > 0
}
+// This must match cmd/compile/internal/compare.IsRegularMemory
+func isRegularMemory(t Type) bool {
+ switch t.Kind() {
+ case Array:
+ return isRegularMemory(t.Elem())
+ case Int8, Int16, Int32, Int64, Int, Uint8, Uint16, Uint32, Uint64, Uint, Uintptr, Chan, Pointer, Bool, UnsafePointer:
+ return true
+ case Struct:
+ num := t.NumField()
+ switch num {
+ case 0:
+ return true
+ case 1:
+ field := t.Field(0)
+ if field.Name == "_" {
+ return false
+ }
+ return isRegularMemory(field.Type)
+ default:
+ for i := range num {
+ field := t.Field(i)
+ if field.Name == "_" || !isRegularMemory(field.Type) || isPaddedField(t, i) {
+ return false
+ }
+ }
+ return true
+ }
+ }
+ return false
+}
+
+// isPaddedField reports whether the i'th field of struct type t is followed
+// by padding.
+func isPaddedField(t Type, i int) bool {
+ field := t.Field(i)
+ if i+1 < t.NumField() {
+ return field.Offset+field.Type.Size() != t.Field(i+1).Offset
+ }
+ return field.Offset+field.Type.Size() != t.Size()
+}
+
// StructOf returns the struct type containing fields.
// The Offset and Index fields are ignored and computed as they would be
// by the compiler.
@@ -2445,7 +2486,11 @@ func StructOf(fields []StructField) Type {
}
typ.Str = resolveReflectName(newName(str, "", false, false))
- typ.TFlag = 0 // TODO: set tflagRegularMemory
+ if isRegularMemory(toType(&typ.Type)) {
+ typ.TFlag = abi.TFlagRegularMemory
+ } else {
+ typ.TFlag = 0
+ }
typ.Hash = hash
typ.Size_ = size
typ.PtrBytes = typeptrdata(&typ.Type)
diff --git a/src/reflect/type_test.go b/src/reflect/type_test.go
index 9e124273a2..d53bbe553d 100644
--- a/src/reflect/type_test.go
+++ b/src/reflect/type_test.go
@@ -57,3 +57,46 @@ func TestStructOfEmbeddedIfaceMethodCall(t *testing.T) {
_ = x.Name()
})
}
+
+func TestIsRegularMemory(t *testing.T) {
+ type args struct {
+ t reflect.Type
+ }
+ type S struct {
+ int
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ }{
+ {"struct{i int}", args{reflect.TypeOf(struct{ i int }{})}, true},
+ {"struct{}", args{reflect.TypeOf(struct{}{})}, true},
+ {"struct{i int; s S}", args{reflect.TypeOf(struct {
+ i int
+ s S
+ }{})}, true},
+ {"map[int][int]", args{reflect.TypeOf(map[int]int{})}, false},
+ {"[4]chan int", args{reflect.TypeOf([4]chan int{})}, true},
+ {"struct{i int; _ S}", args{reflect.TypeOf(struct {
+ i int
+ _ S
+ }{})}, false},
+ {"struct{a int16; b int32}", args{reflect.TypeOf(struct {
+ a int16
+ b int32
+ }{})}, false},
+ {"struct {x int32; y int16}", args{reflect.TypeOf(struct {
+ x int32
+ y int16
+ }{})}, false},
+ {"struct {_ int32 }", args{reflect.TypeOf(struct{ _ int32 }{})}, false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := reflect.IsRegularMemory(tt.args.t); got != tt.want {
+ t.Errorf("isRegularMemory() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}