LEFT | RIGHT |
1 // Package exp/ssa/interp defines an interpreter for the SSA | 1 // Package exp/ssa/interp defines an interpreter for the SSA |
2 // representation of Go programs. | 2 // representation of Go programs. |
3 // | 3 // |
4 // This interpreter is provided as an adjunct for testing the SSA | 4 // This interpreter is provided as an adjunct for testing the SSA |
5 // construction algorithm. Its purpose is to provide a minimal | 5 // construction algorithm. Its purpose is to provide a minimal |
6 // metacircular implementation of the dynamic semantics of each SSA | 6 // metacircular implementation of the dynamic semantics of each SSA |
7 // instruction. It is not, and will never be, a production-quality Go | 7 // instruction. It is not, and will never be, a production-quality Go |
8 // interpreter. | 8 // interpreter. |
9 // | 9 // |
10 // The following is a partial list of Go features that are currently | 10 // The following is a partial list of Go features that are currently |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 case nil: | 101 case nil: |
102 return nil | 102 return nil |
103 case *ssa.Function, *ssa.Builtin: | 103 case *ssa.Function, *ssa.Builtin: |
104 return key | 104 return key |
105 case *ssa.Literal: | 105 case *ssa.Literal: |
106 return literalValue(key) | 106 return literalValue(key) |
107 case *ssa.Global: | 107 case *ssa.Global: |
108 if r, ok := fr.i.globals[key]; ok { | 108 if r, ok := fr.i.globals[key]; ok { |
109 return r | 109 return r |
110 } | 110 } |
111 » default: | 111 » } |
112 » » if r, ok := fr.env[key]; ok { | 112 » if r, ok := fr.env[key]; ok { |
113 » » » return r | 113 » » return r |
114 » » } | 114 » } |
115 » } | 115 » panic(fmt.Sprintf("get: no value for %T: %v", key, key.Name())) |
116 » panic(fmt.Sprintf("get: unexpected type %T", key)) | |
117 } | 116 } |
118 | 117 |
119 // findMethodSet returns the method set for type typ, which may be one | 118 // findMethodSet returns the method set for type typ, which may be one |
120 // of the interpreter's fake types. | 119 // of the interpreter's fake types. |
121 func findMethodSet(i *interpreter, typ types.Type) ssa.MethodSet { | 120 func findMethodSet(i *interpreter, typ types.Type) ssa.MethodSet { |
122 if typ == rtypeType { | 121 if typ == rtypeType { |
123 return i.rtypeMethods | 122 return i.rtypeMethods |
124 } | 123 } |
125 return i.prog.MethodSet(typ) | 124 return i.prog.MethodSet(typ) |
126 } | 125 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 case 1: | 164 case 1: |
166 fr.result = fr.get(instr.Results[0]) | 165 fr.result = fr.get(instr.Results[0]) |
167 default: | 166 default: |
168 var res []value | 167 var res []value |
169 for _, r := range instr.Results { | 168 for _, r := range instr.Results { |
170 res = append(res, copyVal(fr.get(r))) | 169 res = append(res, copyVal(fr.get(r))) |
171 } | 170 } |
172 fr.result = tuple(res) | 171 fr.result = tuple(res) |
173 } | 172 } |
174 return kReturn | 173 return kReturn |
| 174 |
| 175 case *ssa.Panic: |
| 176 panic(targetPanic{fr.get(instr.X)}) |
175 | 177 |
176 case *ssa.Send: | 178 case *ssa.Send: |
177 fr.get(instr.Chan).(chan value) <- copyVal(fr.get(instr.X)) | 179 fr.get(instr.Chan).(chan value) <- copyVal(fr.get(instr.X)) |
178 | 180 |
179 case *ssa.Store: | 181 case *ssa.Store: |
180 *fr.get(instr.Addr).(*value) = copyVal(fr.get(instr.Val)) | 182 *fr.get(instr.Addr).(*value) = copyVal(fr.get(instr.Val)) |
181 | 183 |
182 case *ssa.If: | 184 case *ssa.If: |
183 succ := 1 | 185 succ := 1 |
184 if fr.get(instr.Cond).(bool) { | 186 if fr.get(instr.Cond).(bool) { |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 for i := range fn.Locals { | 472 for i := range fn.Locals { |
471 fr.locals[i] = bad{} | 473 fr.locals[i] = bad{} |
472 } | 474 } |
473 if fr.status == stPanic { | 475 if fr.status == stPanic { |
474 panic(fr.panic) // panic stack is not entirely clean | 476 panic(fr.panic) // panic stack is not entirely clean |
475 } | 477 } |
476 }() | 478 }() |
477 | 479 |
478 for { | 480 for { |
479 if i.mode&EnableTracing != 0 { | 481 if i.mode&EnableTracing != 0 { |
480 » » » fmt.Fprintf(os.Stderr, ".%s:\n", fr.block.Name) | 482 » » » fmt.Fprintf(os.Stderr, ".%s:\n", fr.block) |
481 } | 483 } |
482 block: | 484 block: |
483 for _, instr = range fr.block.Instrs { | 485 for _, instr = range fr.block.Instrs { |
484 if i.mode&EnableTracing != 0 { | 486 if i.mode&EnableTracing != 0 { |
485 if v, ok := instr.(ssa.Value); ok { | 487 if v, ok := instr.(ssa.Value); ok { |
486 fmt.Fprintln(os.Stderr, "\t", v.Name(),
"=", instr) | 488 fmt.Fprintln(os.Stderr, "\t", v.Name(),
"=", instr) |
487 } else { | 489 } else { |
488 fmt.Fprintln(os.Stderr, "\t", instr) | 490 fmt.Fprintln(os.Stderr, "\t", instr) |
489 } | 491 } |
490 } | 492 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 } | 547 } |
546 envs = append(envs, "GOSSAINTERP=1") | 548 envs = append(envs, "GOSSAINTERP=1") |
547 setGlobal(i, pkg, "envs", envs) | 549 setGlobal(i, pkg, "envs", envs) |
548 | 550 |
549 case "runtime": | 551 case "runtime": |
550 // TODO(gri): expose go/types.sizeof so we can | 552 // TODO(gri): expose go/types.sizeof so we can |
551 // avoid this fragile magic number; | 553 // avoid this fragile magic number; |
552 // unsafe.Sizeof(memStats) won't work since gc | 554 // unsafe.Sizeof(memStats) won't work since gc |
553 // and go/types have different sizeof | 555 // and go/types have different sizeof |
554 // functions. | 556 // functions. |
555 » » » setGlobal(i, pkg, "sizeof_C_MStats", uintptr(3450)) | 557 » » » setGlobal(i, pkg, "sizeof_C_MStats", uintptr(3696)) |
556 | 558 |
557 case "os": | 559 case "os": |
558 Args := []value{filename} | 560 Args := []value{filename} |
559 for _, s := range args { | 561 for _, s := range args { |
560 Args = append(Args, s) | 562 Args = append(Args, s) |
561 } | 563 } |
562 setGlobal(i, pkg, "Args", Args) | 564 setGlobal(i, pkg, "Args", Args) |
563 } | 565 } |
564 } | 566 } |
565 | 567 |
(...skipping 28 matching lines...) Expand all Loading... |
594 call(i, nil, token.NoPos, mainpkg.Init, nil) | 596 call(i, nil, token.NoPos, mainpkg.Init, nil) |
595 if mainFn := mainpkg.Func("main"); mainFn != nil { | 597 if mainFn := mainpkg.Func("main"); mainFn != nil { |
596 call(i, nil, token.NoPos, mainFn, nil) | 598 call(i, nil, token.NoPos, mainFn, nil) |
597 exitCode = 0 | 599 exitCode = 0 |
598 } else { | 600 } else { |
599 fmt.Fprintln(os.Stderr, "No main function.") | 601 fmt.Fprintln(os.Stderr, "No main function.") |
600 exitCode = 1 | 602 exitCode = 1 |
601 } | 603 } |
602 return | 604 return |
603 } | 605 } |
LEFT | RIGHT |