func (c *PkgContext) loadStruct(array, target string, s *types.Struct) { view := c.newVariable("_view") c.Printf("%s = new DataView(%s.buffer, %s.byteOffset);", view, array, array) var fields []*types.Var var collectFields func(s *types.Struct, path string) collectFields = func(s *types.Struct, path string) { for i := 0; i < s.NumFields(); i++ { field := s.Field(i) if fs, isStruct := field.Type().Underlying().(*types.Struct); isStruct { collectFields(fs, path+"."+field.Name()) continue } fields = append(fields, types.NewVar(0, nil, path+"."+field.Name(), field.Type())) } } collectFields(s, target) offsets := sizes32.Offsetsof(fields) for i, field := range fields { switch t := field.Type().Underlying().(type) { case *types.Basic: if t.Info()&types.IsNumeric != 0 { if is64Bit(t) { c.Printf("%s = new %s(%s.getUint32(%d, true), %s.getUint32(%d, true));", field.Name(), c.typeName(field.Type()), view, offsets[i]+4, view, offsets[i]) continue } c.Printf("%s = %s.get%s(%d, true);", field.Name(), view, toJavaScriptType(t), offsets[i]) } continue case *types.Array: c.Printf("%s = new %s(%s.buffer, Go$min(%s.byteOffset + %d, %s.buffer.byteLength));", field.Name(), toArrayType(t.Elem()), array, array, offsets[i], array) continue } c.Printf("// skipped: %s %s", field.Name(), field.Type().String()) } }
func fieldName(t *types.Struct, i int) string { name := t.Field(i).Name() if name == "_" || reservedKeywords[name] { return fmt.Sprintf("%s$%d", name, i) } return name }
func (c *funcContext) loadStruct(array, target string, s *types.Struct) string { view := c.newVariable("_view") code := fmt.Sprintf("%s = new DataView(%s.buffer, %s.byteOffset)", view, array, array) var fields []*types.Var var collectFields func(s *types.Struct, path string) collectFields = func(s *types.Struct, path string) { for i := 0; i < s.NumFields(); i++ { field := s.Field(i) if fs, isStruct := field.Type().Underlying().(*types.Struct); isStruct { collectFields(fs, path+"."+fieldName(s, i)) continue } fields = append(fields, types.NewVar(0, nil, path+"."+fieldName(s, i), field.Type())) } } collectFields(s, target) offsets := sizes32.Offsetsof(fields) for i, field := range fields { switch t := field.Type().Underlying().(type) { case *types.Basic: if t.Info()&types.IsNumeric != 0 { if is64Bit(t) { code += fmt.Sprintf(", %s = new %s(%s.getUint32(%d, true), %s.getUint32(%d, true))", field.Name(), c.typeName(field.Type()), view, offsets[i]+4, view, offsets[i]) break } code += fmt.Sprintf(", %s = %s.get%s(%d, true)", field.Name(), view, toJavaScriptType(t), offsets[i]) } case *types.Array: code += fmt.Sprintf(`, %s = new ($nativeArray("%s"))(%s.buffer, $min(%s.byteOffset + %d, %s.buffer.byteLength))`, field.Name(), typeKind(t.Elem()), array, array, offsets[i], array) } } return code }
// matchStructArgType reports whether all the elements of the struct match the expected // type. For instance, with "%d" all the elements must be printable with the "%d" format. func (f *File) matchStructArgType(t printfArgType, typ *types.Struct, arg ast.Expr, inProgress map[types.Type]bool) bool { for i := 0; i < typ.NumFields(); i++ { if !f.matchArgTypeInternal(t, typ.Field(i).Type(), arg, inProgress) { return false } } return true }
func fieldIndex(s *types.Struct, name string) int { for i := 0; i < s.NumFields(); i++ { f := s.Field(i) if f.Name() == name { return i } } return -1 }
func (m *TypeMap) descriptorStruct(t *types.Struct, name string) TypeDebugDescriptor { members := make([]DebugDescriptor, t.NumFields()) for i := range members { f := t.Field(i) member := NewMemberDerivedType(m.TypeDebugDescriptor(f.Type())) member.Name = f.Name() members[i] = member } dt := NewStructCompositeType(members) dt.Name = name return dt }
// For a given struct type and (promoted) field Id, findEmbeddedField // returns the path of implicit anonymous field selections, and the // field index of the explicit (=outermost) selection. // // TODO(gri): if go/types/operand.go's lookupFieldBreadthFirst were to // record (e.g. call a client-provided callback) the implicit field // selection path discovered for a particular ast.SelectorExpr, we could // eliminate this function. // func findPromotedField(st *types.Struct, id Id) (*anonFieldPath, int) { // visited records the types that have been searched already. // Invariant: keys are all *types.Named. // (types.Type is not a sound map key in general.) visited := make(map[types.Type]bool) var list, next []*anonFieldPath i := 0 st.ForEachField(func(f *types.Field) { if f.IsAnonymous { list = append(list, &anonFieldPath{nil, i, f}) } i++ }) // Search the current level if there is any work to do and collect // embedded types of the next lower level in the next list. for { // look for name in all types at this level for _, node := range list { typ := node.field.Type.Deref().(*types.Named) if visited[typ] { continue } visited[typ] = true switch typ := typ.Underlying().(type) { case *types.Struct: for i, n := 0, typ.NumFields(); i < n; i++ { f := typ.Field(i) if MakeId(f.Name, f.Pkg) == id { return node, i } } i := 0 typ.ForEachField(func(f *types.Field) { if f.IsAnonymous { next = append(next, &anonFieldPath{node, i, f}) } i++ }) } } if len(next) == 0 { panic("field not found: " + id.String()) } // No match so far. list, next = next, list[:0] // reuse arrays } panic("unreachable") }
func (tm *llvmTypeMap) structLLVMType(s *types.Struct, name string) llvm.Type { typ, ok := tm.types.At(s).(llvm.Type) if !ok { typ = llvm.GlobalContext().StructCreateNamed(name) tm.types.Set(s, typ) elements := make([]llvm.Type, s.NumFields()) for i := range elements { f := s.Field(i) ft := f.Type() elements[i] = tm.ToLLVM(ft) } typ.StructSetBody(elements, false) } return typ }
func (tm *LLVMTypeMap) structLLVMType(tstr string, s *types.Struct) llvm.Type { typ, ok := tm.types[tstr] if !ok { typ = llvm.GlobalContext().StructCreateNamed("") tm.types[tstr] = typ elements := make([]llvm.Type, s.NumFields()) for i := range elements { f := s.Field(i) ft := f.Type elements[i] = tm.ToLLVM(ft) } typ.StructSetBody(elements, false) } return typ }
func (w *Walker) emitStructType(name string, typ *types.Struct) { typeStruct := fmt.Sprintf("type %s struct", name) w.emitf(typeStruct) defer w.pushScope(typeStruct)() for i := 0; i < typ.NumFields(); i++ { f := typ.Field(i) if !f.IsExported() { continue } typ := f.Type() if f.Anonymous() { w.emitf("embedded %s", w.typeString(typ)) continue } w.emitf("%s %s", f.Name(), w.typeString(typ)) } }
func (tm *TypeMap) structRuntimeType(s *types.Struct) (global, ptr llvm.Value) { rtype := tm.makeRtype(s, reflect.Struct) structType := llvm.ConstNull(tm.runtime.structType.llvm) structType = llvm.ConstInsertValue(structType, rtype, []uint32{0}) global, ptr = tm.makeRuntimeTypeGlobal(structType, typeString(s)) tm.types.Set(s, runtimeTypeInfo{global, ptr}) fieldVars := make([]*types.Var, s.NumFields()) for i := range fieldVars { fieldVars[i] = s.Field(i) } offsets := tm.Offsetsof(fieldVars) structFields := make([]llvm.Value, len(fieldVars)) for i := range structFields { field := fieldVars[i] structField := llvm.ConstNull(tm.runtime.structField.llvm) if !field.Anonymous() { name := tm.globalStringPtr(field.Name()) name = llvm.ConstBitCast(name, tm.runtime.structField.llvm.StructElementTypes()[0]) structField = llvm.ConstInsertValue(structField, name, []uint32{0}) } if !ast.IsExported(field.Name()) { pkgpath := tm.globalStringPtr(field.Pkg().Path()) pkgpath = llvm.ConstBitCast(pkgpath, tm.runtime.structField.llvm.StructElementTypes()[1]) structField = llvm.ConstInsertValue(structField, pkgpath, []uint32{1}) } fieldType := tm.ToRuntime(field.Type()) structField = llvm.ConstInsertValue(structField, fieldType, []uint32{2}) if tag := s.Tag(i); tag != "" { tag := tm.globalStringPtr(tag) tag = llvm.ConstBitCast(tag, tm.runtime.structField.llvm.StructElementTypes()[3]) structField = llvm.ConstInsertValue(structField, tag, []uint32{3}) } offset := llvm.ConstInt(tm.runtime.structField.llvm.StructElementTypes()[4], uint64(offsets[i]), false) structField = llvm.ConstInsertValue(structField, offset, []uint32{4}) structFields[i] = structField } structFieldsSliceType := tm.runtime.structType.llvm.StructElementTypes()[1] structFieldsSlice := tm.makeSlice(structFields, structFieldsSliceType) structType = llvm.ConstInsertValue(structType, structFieldsSlice, []uint32{1}) global.SetInitializer(structType) return global, ptr }