Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / exp / ogle / rtype.go
blobfd77f1bc2483f3f2c659bdac741058de7f70e562
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package ogle
7 import (
8 "debug/proc"
9 "exp/eval"
10 "fmt"
11 "log"
14 const debugParseRemoteType = false
16 // A remoteType is the local representation of a type in a remote process.
17 type remoteType struct {
18 eval.Type
19 // The size of values of this type in bytes.
20 size int
21 // The field alignment of this type. Only used for
22 // manually-constructed types.
23 fieldAlign int
24 // The maker function to turn a remote address of a value of
25 // this type into an interpreter Value.
26 mk maker
29 var manualTypes = make(map[Arch]map[eval.Type]*remoteType)
31 // newManualType constructs a remote type from an interpreter Type
32 // using the size and alignment properties of the given architecture.
33 // Most types are parsed directly out of the remote process, but to do
34 // so we need to layout the structures that describe those types ourselves.
35 func newManualType(t eval.Type, arch Arch) *remoteType {
36 if nt, ok := t.(*eval.NamedType); ok {
37 t = nt.Def
40 // Get the type map for this architecture
41 typeMap := manualTypes[arch]
42 if typeMap == nil {
43 typeMap = make(map[eval.Type]*remoteType)
44 manualTypes[arch] = typeMap
46 // Construct basic types for this architecture
47 basicType := func(t eval.Type, mk maker, size int, fieldAlign int) {
48 t = t.(*eval.NamedType).Def
49 if fieldAlign == 0 {
50 fieldAlign = size
52 typeMap[t] = &remoteType{t, size, fieldAlign, mk}
54 basicType(eval.Uint8Type, mkUint8, 1, 0)
55 basicType(eval.Uint32Type, mkUint32, 4, 0)
56 basicType(eval.UintptrType, mkUintptr, arch.PtrSize(), 0)
57 basicType(eval.Int16Type, mkInt16, 2, 0)
58 basicType(eval.Int32Type, mkInt32, 4, 0)
59 basicType(eval.IntType, mkInt, arch.IntSize(), 0)
60 basicType(eval.StringType, mkString, arch.PtrSize()+arch.IntSize(), arch.PtrSize())
63 if rt, ok := typeMap[t]; ok {
64 return rt
67 var rt *remoteType
68 switch t := t.(type) {
69 case *eval.PtrType:
70 var elem *remoteType
71 mk := func(r remote) eval.Value { return remotePtr{r, elem} }
72 rt = &remoteType{t, arch.PtrSize(), arch.PtrSize(), mk}
73 // Construct the element type after registering the
74 // type to break cycles.
75 typeMap[eval.Type(t)] = rt
76 elem = newManualType(t.Elem, arch)
78 case *eval.ArrayType:
79 elem := newManualType(t.Elem, arch)
80 mk := func(r remote) eval.Value { return remoteArray{r, t.Len, elem} }
81 rt = &remoteType{t, elem.size * int(t.Len), elem.fieldAlign, mk}
83 case *eval.SliceType:
84 elem := newManualType(t.Elem, arch)
85 mk := func(r remote) eval.Value { return remoteSlice{r, elem} }
86 rt = &remoteType{t, arch.PtrSize() + 2*arch.IntSize(), arch.PtrSize(), mk}
88 case *eval.StructType:
89 layout := make([]remoteStructField, len(t.Elems))
90 offset := 0
91 fieldAlign := 0
92 for i, f := range t.Elems {
93 elem := newManualType(f.Type, arch)
94 if fieldAlign == 0 {
95 fieldAlign = elem.fieldAlign
97 offset = arch.Align(offset, elem.fieldAlign)
98 layout[i].offset = offset
99 layout[i].fieldType = elem
100 offset += elem.size
102 mk := func(r remote) eval.Value { return remoteStruct{r, layout} }
103 rt = &remoteType{t, offset, fieldAlign, mk}
105 default:
106 log.Panicf("cannot manually construct type %T", t)
109 typeMap[t] = rt
110 return rt
113 var prtIndent = ""
115 // parseRemoteType parses a Type structure in a remote process to
116 // construct the corresponding interpreter type and remote type.
117 func parseRemoteType(a aborter, rs remoteStruct) *remoteType {
118 addr := rs.addr().base
119 p := rs.addr().p
121 // We deal with circular types by discovering cycles at
122 // NamedTypes. If a type cycles back to something other than
123 // a named type, we're guaranteed that there will be a named
124 // type somewhere in that cycle. Thus, we continue down,
125 // re-parsing types until we reach the named type in the
126 // cycle. In order to still create one remoteType per remote
127 // type, we insert an empty remoteType in the type map the
128 // first time we encounter the type and re-use that structure
129 // the second time we encounter it.
131 rt, ok := p.types[addr]
132 if ok && rt.Type != nil {
133 return rt
134 } else if !ok {
135 rt = &remoteType{}
136 p.types[addr] = rt
139 if debugParseRemoteType {
140 sym := p.syms.SymByAddr(uint64(addr))
141 name := "<unknown>"
142 if sym != nil {
143 name = sym.Name
145 log.Printf("%sParsing type at %#x (%s)", prtIndent, addr, name)
146 prtIndent += " "
147 defer func() { prtIndent = prtIndent[0 : len(prtIndent)-1] }()
150 // Get Type header
151 itype := proc.Word(rs.field(p.f.Type.Typ).(remoteUint).aGet(a))
152 typ := rs.field(p.f.Type.Ptr).(remotePtr).aGet(a).(remoteStruct)
154 // Is this a named type?
155 var nt *eval.NamedType
156 uncommon := typ.field(p.f.CommonType.UncommonType).(remotePtr).aGet(a)
157 if uncommon != nil {
158 name := uncommon.(remoteStruct).field(p.f.UncommonType.Name).(remotePtr).aGet(a)
159 if name != nil {
160 // TODO(austin) Declare type in appropriate remote package
161 nt = eval.NewNamedType(name.(remoteString).aGet(a))
162 rt.Type = nt
166 // Create type
167 var t eval.Type
168 var mk maker
169 switch itype {
170 case p.runtime.PBoolType:
171 t = eval.BoolType
172 mk = mkBool
173 case p.runtime.PUint8Type:
174 t = eval.Uint8Type
175 mk = mkUint8
176 case p.runtime.PUint16Type:
177 t = eval.Uint16Type
178 mk = mkUint16
179 case p.runtime.PUint32Type:
180 t = eval.Uint32Type
181 mk = mkUint32
182 case p.runtime.PUint64Type:
183 t = eval.Uint64Type
184 mk = mkUint64
185 case p.runtime.PUintType:
186 t = eval.UintType
187 mk = mkUint
188 case p.runtime.PUintptrType:
189 t = eval.UintptrType
190 mk = mkUintptr
191 case p.runtime.PInt8Type:
192 t = eval.Int8Type
193 mk = mkInt8
194 case p.runtime.PInt16Type:
195 t = eval.Int16Type
196 mk = mkInt16
197 case p.runtime.PInt32Type:
198 t = eval.Int32Type
199 mk = mkInt32
200 case p.runtime.PInt64Type:
201 t = eval.Int64Type
202 mk = mkInt64
203 case p.runtime.PIntType:
204 t = eval.IntType
205 mk = mkInt
206 case p.runtime.PFloat32Type:
207 t = eval.Float32Type
208 mk = mkFloat32
209 case p.runtime.PFloat64Type:
210 t = eval.Float64Type
211 mk = mkFloat64
212 case p.runtime.PFloatType:
213 t = eval.FloatType
214 mk = mkFloat
215 case p.runtime.PStringType:
216 t = eval.StringType
217 mk = mkString
219 case p.runtime.PArrayType:
220 // Cast to an ArrayType
221 typ := p.runtime.ArrayType.mk(typ.addr()).(remoteStruct)
222 len := int64(typ.field(p.f.ArrayType.Len).(remoteUint).aGet(a))
223 elem := parseRemoteType(a, typ.field(p.f.ArrayType.Elem).(remotePtr).aGet(a).(remoteStruct))
224 t = eval.NewArrayType(len, elem.Type)
225 mk = func(r remote) eval.Value { return remoteArray{r, len, elem} }
227 case p.runtime.PStructType:
228 // Cast to a StructType
229 typ := p.runtime.StructType.mk(typ.addr()).(remoteStruct)
230 fs := typ.field(p.f.StructType.Fields).(remoteSlice).aGet(a)
232 fields := make([]eval.StructField, fs.Len)
233 layout := make([]remoteStructField, fs.Len)
234 for i := range fields {
235 f := fs.Base.(remoteArray).elem(int64(i)).(remoteStruct)
236 elemrs := f.field(p.f.StructField.Typ).(remotePtr).aGet(a).(remoteStruct)
237 elem := parseRemoteType(a, elemrs)
238 fields[i].Type = elem.Type
239 name := f.field(p.f.StructField.Name).(remotePtr).aGet(a)
240 if name == nil {
241 fields[i].Anonymous = true
242 } else {
243 fields[i].Name = name.(remoteString).aGet(a)
245 layout[i].offset = int(f.field(p.f.StructField.Offset).(remoteUint).aGet(a))
246 layout[i].fieldType = elem
249 t = eval.NewStructType(fields)
250 mk = func(r remote) eval.Value { return remoteStruct{r, layout} }
252 case p.runtime.PPtrType:
253 // Cast to a PtrType
254 typ := p.runtime.PtrType.mk(typ.addr()).(remoteStruct)
255 elem := parseRemoteType(a, typ.field(p.f.PtrType.Elem).(remotePtr).aGet(a).(remoteStruct))
256 t = eval.NewPtrType(elem.Type)
257 mk = func(r remote) eval.Value { return remotePtr{r, elem} }
259 case p.runtime.PSliceType:
260 // Cast to a SliceType
261 typ := p.runtime.SliceType.mk(typ.addr()).(remoteStruct)
262 elem := parseRemoteType(a, typ.field(p.f.SliceType.Elem).(remotePtr).aGet(a).(remoteStruct))
263 t = eval.NewSliceType(elem.Type)
264 mk = func(r remote) eval.Value { return remoteSlice{r, elem} }
266 case p.runtime.PMapType, p.runtime.PChanType, p.runtime.PFuncType, p.runtime.PInterfaceType, p.runtime.PUnsafePointerType, p.runtime.PDotDotDotType:
267 // TODO(austin)
268 t = eval.UintptrType
269 mk = mkUintptr
271 default:
272 sym := p.syms.SymByAddr(uint64(itype))
273 name := "<unknown symbol>"
274 if sym != nil {
275 name = sym.Name
277 err := fmt.Sprintf("runtime type at %#x has unexpected type %#x (%s)", addr, itype, name)
278 a.Abort(FormatError(err))
281 // Fill in the remote type
282 if nt != nil {
283 nt.Complete(t)
284 } else {
285 rt.Type = t
287 rt.size = int(typ.field(p.f.CommonType.Size).(remoteUint).aGet(a))
288 rt.mk = mk
290 return rt