родитель
02913563df
коммит
07fb3a0cad
3 изменённых файлов: 36 добавлений и 9 удалений
|
@ -6,6 +6,7 @@ package compiler
|
|||
// interface-lowering.go for more details.
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
@ -335,7 +336,11 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||
if field.Embedded() {
|
||||
flags |= structFieldFlagIsEmbedded
|
||||
}
|
||||
data := string(flags) + field.Name() + "\x00"
|
||||
|
||||
var offsBytes [binary.MaxVarintLen32]byte
|
||||
offLen := binary.PutUvarint(offsBytes[:], offset)
|
||||
|
||||
data := string(flags) + string(offsBytes[:offLen]) + field.Name() + "\x00"
|
||||
if typ.Tag(i) != "" {
|
||||
if len(typ.Tag(i)) > 0xff {
|
||||
c.addError(field.Pos(), fmt.Sprintf("struct tag is %d bytes which is too long, max is 255", len(typ.Tag(i))))
|
||||
|
@ -352,7 +357,6 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||
fieldType := c.getTypeCode(field.Type())
|
||||
fields = append(fields, llvm.ConstNamedStruct(structFieldType, []llvm.Value{
|
||||
fieldType,
|
||||
llvm.ConstInt(c.ctx.Int32Type(), uint64(offset), false),
|
||||
llvm.ConstGEP(dataGlobal.GlobalValueType(), dataGlobal, []llvm.Value{
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
|
|
|
@ -463,7 +463,6 @@ type structType struct {
|
|||
|
||||
type structField struct {
|
||||
fieldType *rawType
|
||||
offset uint32
|
||||
data unsafe.Pointer // various bits of information, packed in a byte array
|
||||
}
|
||||
|
||||
|
@ -624,7 +623,7 @@ func (t *rawType) Field(i int) StructField {
|
|||
}
|
||||
}
|
||||
|
||||
func rawStructFieldFromPointer(descriptor *structType, fieldType *rawType, data unsafe.Pointer, flagsByte uint8, name string, offset uintptr) rawStructField {
|
||||
func rawStructFieldFromPointer(descriptor *structType, fieldType *rawType, data unsafe.Pointer, flagsByte uint8, name string, offset uint32) rawStructField {
|
||||
// Read the field tag, if there is one.
|
||||
var tag string
|
||||
if flagsByte&structFieldFlagHasTag != 0 {
|
||||
|
@ -651,7 +650,7 @@ func rawStructFieldFromPointer(descriptor *structType, fieldType *rawType, data
|
|||
Type: fieldType,
|
||||
Tag: StructTag(tag),
|
||||
Anonymous: flagsByte&structFieldFlagAnonymous != 0,
|
||||
Offset: offset,
|
||||
Offset: uintptr(offset),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -673,13 +672,14 @@ func (t *rawType) rawField(n int) rawStructField {
|
|||
// lookup faster), but by calculating it on-the-fly a bit of storage can be
|
||||
// saved.
|
||||
field := (*structField)(unsafe.Add(unsafe.Pointer(&descriptor.fields[0]), uintptr(n)*unsafe.Sizeof(structField{})))
|
||||
offset := uintptr(field.offset)
|
||||
data := field.data
|
||||
|
||||
// Read some flags of this field, like whether the field is an embedded
|
||||
// field. See structFieldFlagAnonymous and similar flags.
|
||||
flagsByte := *(*byte)(data)
|
||||
data = unsafe.Add(data, 1)
|
||||
offset, lenOffs := uvarint32(unsafe.Slice((*byte)(data), maxVarintLen32))
|
||||
data = unsafe.Add(data, lenOffs)
|
||||
|
||||
name := readStringZ(data)
|
||||
data = unsafe.Add(data, len(name))
|
||||
|
@ -729,10 +729,12 @@ func (t *rawType) rawFieldByName(n string) (rawStructField, []int, bool) {
|
|||
flagsByte := *(*byte)(data)
|
||||
data = unsafe.Add(data, 1)
|
||||
|
||||
offset, lenOffs := uvarint32(unsafe.Slice((*byte)(data), maxVarintLen32))
|
||||
data = unsafe.Add(data, lenOffs)
|
||||
|
||||
name := readStringZ(data)
|
||||
data = unsafe.Add(data, len(name))
|
||||
if name == n {
|
||||
offset := uintptr(field.offset)
|
||||
found = append(found, result{
|
||||
rawStructFieldFromPointer(descriptor, field.fieldType, data, flagsByte, name, offset),
|
||||
append(ll.index, int(i)),
|
||||
|
@ -1284,3 +1286,25 @@ func StructOf([]StructField) Type {
|
|||
func MapOf(key, value Type) Type {
|
||||
panic("unimplemented: reflect.MapOf()")
|
||||
}
|
||||
|
||||
const maxVarintLen32 = 5
|
||||
|
||||
// encoding/binary.Uvarint, specialized for uint32
|
||||
func uvarint32(buf []byte) (uint32, int) {
|
||||
var x uint32
|
||||
var s uint
|
||||
for i, b := range buf {
|
||||
if i == maxVarintLen32 {
|
||||
return 0, -(i + 1) // overflow
|
||||
}
|
||||
if b < 0x80 {
|
||||
if i == maxVarintLen32-1 && b > 1 {
|
||||
return 0, -(i + 1) // overflow
|
||||
}
|
||||
return x | uint32(b)<<s, i + 1
|
||||
}
|
||||
x |= uint32(b&0x7f) << s
|
||||
s += 7
|
||||
}
|
||||
return 0, 0
|
||||
}
|
||||
|
|
|
@ -96,8 +96,7 @@ func interfaceTypeAssert(ok bool) {
|
|||
|
||||
type structField struct {
|
||||
typecode unsafe.Pointer // type of this struct field
|
||||
offset uint32
|
||||
data *uint8 // pointer to byte array containing name, tag, and 'embedded' flag
|
||||
data *uint8 // pointer to byte array containing name, tag, and 'embedded' flag
|
||||
}
|
||||
|
||||
// Pseudo function call used during a type assert. It is used during interface
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче