Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / exp / ogle / rvalue.go
blob3d630f936644c678c6a030b250e21d41eb294e44
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"
13 // A RemoteMismatchError occurs when an operation that requires two
14 // identical remote processes is given different process. For
15 // example, this occurs when trying to set a pointer in one process to
16 // point to something in another process.
17 type RemoteMismatchError string
19 func (e RemoteMismatchError) String() string { return string(e) }
21 // A ReadOnlyError occurs when attempting to set or assign to a
22 // read-only value.
23 type ReadOnlyError string
25 func (e ReadOnlyError) String() string { return string(e) }
27 // A maker is a function that converts a remote address into an
28 // interpreter Value.
29 type maker func(remote) eval.Value
31 type remoteValue interface {
32 addr() remote
35 // remote represents an address in a remote process.
36 type remote struct {
37 base proc.Word
38 p *Process
41 func (v remote) Get(a aborter, size int) uint64 {
42 // TODO(austin) This variable might temporarily be in a
43 // register. We could trace the assembly back from the
44 // current PC, looking for the beginning of the function or a
45 // call (both of which guarantee that the variable is in
46 // memory), or an instruction that loads the variable into a
47 // register.
49 // TODO(austin) If this is a local variable, it might not be
50 // live at this PC. In fact, because the compiler reuses
51 // slots, there might even be a different local variable at
52 // this location right now. A simple solution to both
53 // problems is to include the range of PC's over which a local
54 // variable is live in the symbol table.
56 // TODO(austin) We need to prevent the remote garbage
57 // collector from collecting objects out from under us.
58 var arr [8]byte
59 buf := arr[0:size]
60 _, err := v.p.Peek(v.base, buf)
61 if err != nil {
62 a.Abort(err)
64 return uint64(v.p.ToWord(buf))
67 func (v remote) Set(a aborter, size int, x uint64) {
68 var arr [8]byte
69 buf := arr[0:size]
70 v.p.FromWord(proc.Word(x), buf)
71 _, err := v.p.Poke(v.base, buf)
72 if err != nil {
73 a.Abort(err)
77 func (v remote) plus(x proc.Word) remote { return remote{v.base + x, v.p} }
79 func tryRVString(f func(a aborter) string) string {
80 var s string
81 err := try(func(a aborter) { s = f(a) })
82 if err != nil {
83 return fmt.Sprintf("<error: %v>", err)
85 return s
89 * Bool
92 type remoteBool struct {
93 r remote
96 func (v remoteBool) String() string {
97 return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) })
100 func (v remoteBool) Assign(t *eval.Thread, o eval.Value) {
101 v.Set(t, o.(eval.BoolValue).Get(t))
104 func (v remoteBool) Get(t *eval.Thread) bool { return v.aGet(t) }
106 func (v remoteBool) aGet(a aborter) bool { return v.r.Get(a, 1) != 0 }
108 func (v remoteBool) Set(t *eval.Thread, x bool) {
109 v.aSet(t, x)
112 func (v remoteBool) aSet(a aborter, x bool) {
113 if x {
114 v.r.Set(a, 1, 1)
115 } else {
116 v.r.Set(a, 1, 0)
120 func (v remoteBool) addr() remote { return v.r }
122 func mkBool(r remote) eval.Value { return remoteBool{r} }
125 * Uint
128 type remoteUint struct {
129 r remote
130 size int
133 func (v remoteUint) String() string {
134 return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) })
137 func (v remoteUint) Assign(t *eval.Thread, o eval.Value) {
138 v.Set(t, o.(eval.UintValue).Get(t))
141 func (v remoteUint) Get(t *eval.Thread) uint64 {
142 return v.aGet(t)
145 func (v remoteUint) aGet(a aborter) uint64 { return v.r.Get(a, v.size) }
147 func (v remoteUint) Set(t *eval.Thread, x uint64) {
148 v.aSet(t, x)
151 func (v remoteUint) aSet(a aborter, x uint64) { v.r.Set(a, v.size, x) }
153 func (v remoteUint) addr() remote { return v.r }
155 func mkUint8(r remote) eval.Value { return remoteUint{r, 1} }
157 func mkUint16(r remote) eval.Value { return remoteUint{r, 2} }
159 func mkUint32(r remote) eval.Value { return remoteUint{r, 4} }
161 func mkUint64(r remote) eval.Value { return remoteUint{r, 8} }
163 func mkUint(r remote) eval.Value { return remoteUint{r, r.p.IntSize()} }
165 func mkUintptr(r remote) eval.Value { return remoteUint{r, r.p.PtrSize()} }
168 * Int
171 type remoteInt struct {
172 r remote
173 size int
176 func (v remoteInt) String() string {
177 return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) })
180 func (v remoteInt) Assign(t *eval.Thread, o eval.Value) {
181 v.Set(t, o.(eval.IntValue).Get(t))
184 func (v remoteInt) Get(t *eval.Thread) int64 { return v.aGet(t) }
186 func (v remoteInt) aGet(a aborter) int64 { return int64(v.r.Get(a, v.size)) }
188 func (v remoteInt) Set(t *eval.Thread, x int64) {
189 v.aSet(t, x)
192 func (v remoteInt) aSet(a aborter, x int64) { v.r.Set(a, v.size, uint64(x)) }
194 func (v remoteInt) addr() remote { return v.r }
196 func mkInt8(r remote) eval.Value { return remoteInt{r, 1} }
198 func mkInt16(r remote) eval.Value { return remoteInt{r, 2} }
200 func mkInt32(r remote) eval.Value { return remoteInt{r, 4} }
202 func mkInt64(r remote) eval.Value { return remoteInt{r, 8} }
204 func mkInt(r remote) eval.Value { return remoteInt{r, r.p.IntSize()} }
207 * Float
210 type remoteFloat struct {
211 r remote
212 size int
215 func (v remoteFloat) String() string {
216 return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) })
219 func (v remoteFloat) Assign(t *eval.Thread, o eval.Value) {
220 v.Set(t, o.(eval.FloatValue).Get(t))
223 func (v remoteFloat) Get(t *eval.Thread) float64 {
224 return v.aGet(t)
227 func (v remoteFloat) aGet(a aborter) float64 {
228 bits := v.r.Get(a, v.size)
229 switch v.size {
230 case 4:
231 return float64(v.r.p.ToFloat32(uint32(bits)))
232 case 8:
233 return v.r.p.ToFloat64(bits)
235 panic("Unexpected float size")
238 func (v remoteFloat) Set(t *eval.Thread, x float64) {
239 v.aSet(t, x)
242 func (v remoteFloat) aSet(a aborter, x float64) {
243 var bits uint64
244 switch v.size {
245 case 4:
246 bits = uint64(v.r.p.FromFloat32(float32(x)))
247 case 8:
248 bits = v.r.p.FromFloat64(x)
249 default:
250 panic("Unexpected float size")
252 v.r.Set(a, v.size, bits)
255 func (v remoteFloat) addr() remote { return v.r }
257 func mkFloat32(r remote) eval.Value { return remoteFloat{r, 4} }
259 func mkFloat64(r remote) eval.Value { return remoteFloat{r, 8} }
261 func mkFloat(r remote) eval.Value { return remoteFloat{r, r.p.FloatSize()} }
264 * String
267 type remoteString struct {
268 r remote
271 func (v remoteString) String() string {
272 return tryRVString(func(a aborter) string { return v.aGet(a) })
275 func (v remoteString) Assign(t *eval.Thread, o eval.Value) {
276 v.Set(t, o.(eval.StringValue).Get(t))
279 func (v remoteString) Get(t *eval.Thread) string {
280 return v.aGet(t)
283 func (v remoteString) aGet(a aborter) string {
284 rs := v.r.p.runtime.String.mk(v.r).(remoteStruct)
285 str := proc.Word(rs.field(v.r.p.f.String.Str).(remoteUint).aGet(a))
286 len := rs.field(v.r.p.f.String.Len).(remoteInt).aGet(a)
288 bytes := make([]uint8, len)
289 _, err := v.r.p.Peek(str, bytes)
290 if err != nil {
291 a.Abort(err)
293 return string(bytes)
296 func (v remoteString) Set(t *eval.Thread, x string) {
297 v.aSet(t, x)
300 func (v remoteString) aSet(a aborter, x string) {
301 // TODO(austin) This isn't generally possible without the
302 // ability to allocate remote memory.
303 a.Abort(ReadOnlyError("remote strings cannot be assigned to"))
306 func mkString(r remote) eval.Value { return remoteString{r} }
309 * Array
312 type remoteArray struct {
313 r remote
314 len int64
315 elemType *remoteType
318 func (v remoteArray) String() string {
319 res := "{"
320 for i := int64(0); i < v.len; i++ {
321 if i > 0 {
322 res += ", "
324 res += v.elem(i).String()
326 return res + "}"
329 func (v remoteArray) Assign(t *eval.Thread, o eval.Value) {
330 // TODO(austin) Could do a bigger memcpy if o is a
331 // remoteArray in the same Process.
332 oa := o.(eval.ArrayValue)
333 for i := int64(0); i < v.len; i++ {
334 v.Elem(t, i).Assign(t, oa.Elem(t, i))
338 func (v remoteArray) Get(t *eval.Thread) eval.ArrayValue {
339 return v
342 func (v remoteArray) Elem(t *eval.Thread, i int64) eval.Value {
343 return v.elem(i)
346 func (v remoteArray) elem(i int64) eval.Value {
347 return v.elemType.mk(v.r.plus(proc.Word(int64(v.elemType.size) * i)))
350 func (v remoteArray) Sub(i int64, len int64) eval.ArrayValue {
351 return remoteArray{v.r.plus(proc.Word(int64(v.elemType.size) * i)), len, v.elemType}
355 * Struct
358 type remoteStruct struct {
359 r remote
360 layout []remoteStructField
363 type remoteStructField struct {
364 offset int
365 fieldType *remoteType
368 func (v remoteStruct) String() string {
369 res := "{"
370 for i := range v.layout {
371 if i > 0 {
372 res += ", "
374 res += v.field(i).String()
376 return res + "}"
379 func (v remoteStruct) Assign(t *eval.Thread, o eval.Value) {
380 // TODO(austin) Could do a bigger memcpy.
381 oa := o.(eval.StructValue)
382 l := len(v.layout)
383 for i := 0; i < l; i++ {
384 v.Field(t, i).Assign(t, oa.Field(t, i))
388 func (v remoteStruct) Get(t *eval.Thread) eval.StructValue {
389 return v
392 func (v remoteStruct) Field(t *eval.Thread, i int) eval.Value {
393 return v.field(i)
396 func (v remoteStruct) field(i int) eval.Value {
397 f := &v.layout[i]
398 return f.fieldType.mk(v.r.plus(proc.Word(f.offset)))
401 func (v remoteStruct) addr() remote { return v.r }
404 * Pointer
407 // TODO(austin) Comparing two remote pointers for equality in the
408 // interpreter will crash it because the Value's returned from
409 // remotePtr.Get() will be structs.
411 type remotePtr struct {
412 r remote
413 elemType *remoteType
416 func (v remotePtr) String() string {
417 return tryRVString(func(a aborter) string {
418 e := v.aGet(a)
419 if e == nil {
420 return "<nil>"
422 return "&" + e.String()
426 func (v remotePtr) Assign(t *eval.Thread, o eval.Value) {
427 v.Set(t, o.(eval.PtrValue).Get(t))
430 func (v remotePtr) Get(t *eval.Thread) eval.Value {
431 return v.aGet(t)
434 func (v remotePtr) aGet(a aborter) eval.Value {
435 addr := proc.Word(v.r.Get(a, v.r.p.PtrSize()))
436 if addr == 0 {
437 return nil
439 return v.elemType.mk(remote{addr, v.r.p})
442 func (v remotePtr) Set(t *eval.Thread, x eval.Value) {
443 v.aSet(t, x)
446 func (v remotePtr) aSet(a aborter, x eval.Value) {
447 if x == nil {
448 v.r.Set(a, v.r.p.PtrSize(), 0)
449 return
451 xr, ok := x.(remoteValue)
452 if !ok || v.r.p != xr.addr().p {
453 a.Abort(RemoteMismatchError("remote pointer must point within the same process"))
455 v.r.Set(a, v.r.p.PtrSize(), uint64(xr.addr().base))
458 func (v remotePtr) addr() remote { return v.r }
461 * Slice
464 type remoteSlice struct {
465 r remote
466 elemType *remoteType
469 func (v remoteSlice) String() string {
470 return tryRVString(func(a aborter) string {
471 b := v.aGet(a).Base
472 if b == nil {
473 return "<nil>"
475 return b.String()
479 func (v remoteSlice) Assign(t *eval.Thread, o eval.Value) {
480 v.Set(t, o.(eval.SliceValue).Get(t))
483 func (v remoteSlice) Get(t *eval.Thread) eval.Slice {
484 return v.aGet(t)
487 func (v remoteSlice) aGet(a aborter) eval.Slice {
488 rs := v.r.p.runtime.Slice.mk(v.r).(remoteStruct)
489 base := proc.Word(rs.field(v.r.p.f.Slice.Array).(remoteUint).aGet(a))
490 nel := rs.field(v.r.p.f.Slice.Len).(remoteInt).aGet(a)
491 cap := rs.field(v.r.p.f.Slice.Cap).(remoteInt).aGet(a)
492 if base == 0 {
493 return eval.Slice{nil, nel, cap}
495 return eval.Slice{remoteArray{remote{base, v.r.p}, nel, v.elemType}, nel, cap}
498 func (v remoteSlice) Set(t *eval.Thread, x eval.Slice) {
499 v.aSet(t, x)
502 func (v remoteSlice) aSet(a aborter, x eval.Slice) {
503 rs := v.r.p.runtime.Slice.mk(v.r).(remoteStruct)
504 if x.Base == nil {
505 rs.field(v.r.p.f.Slice.Array).(remoteUint).aSet(a, 0)
506 } else {
507 ar, ok := x.Base.(remoteArray)
508 if !ok || v.r.p != ar.r.p {
509 a.Abort(RemoteMismatchError("remote slice must point within the same process"))
511 rs.field(v.r.p.f.Slice.Array).(remoteUint).aSet(a, uint64(ar.r.base))
513 rs.field(v.r.p.f.Slice.Len).(remoteInt).aSet(a, x.Len)
514 rs.field(v.r.p.f.Slice.Cap).(remoteInt).aSet(a, x.Cap)