1
0
mirror of https://github.com/golang/go synced 2024-09-29 17:14:29 -06:00

reflect: StructOf set abi.TFlagRegularMemory

Complete a TODO.

Change-Id: I791d27266ccee69c371524e298120765f5736cf8
GitHub-Last-Rev: 8878003efa
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>
This commit is contained in:
qiulaidongfeng 2024-01-06 07:25:05 +00:00 committed by Keith Randall
parent 4605ce2d34
commit 99e12bee44
3 changed files with 91 additions and 1 deletions

View File

@ -166,3 +166,5 @@ func SetArgRegs(ints, floats int, floatSize uintptr) (oldInts, oldFloats int, ol
var MethodValueCallCodePtr = methodValueCallCodePtr
var InternalIsZero = isZero
var IsRegularMemory = isRegularMemory

View File

@ -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)

View File

@ -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)
}
})
}
}