|
45 | 45 | package struct Debugger: ~Copyable { |
46 | 46 | package enum Error: Swift.Error { |
47 | 47 | case entrypointFunctionNotFound |
| 48 | + case unknownCurrentFunctionForResumedBreakpoint(UnsafeMutablePointer<UInt64>) |
48 | 49 | case noInstructionMappingAvailable(Int) |
| 50 | + case noReverseInstructionMappingAvailable(UnsafeMutablePointer<UInt64>) |
49 | 51 | } |
50 | 52 |
|
51 | 53 | private let valueStack: Sp |
|
66 | 68 |
|
67 | 69 | private(set) var breakpoints = [Int: CodeSlot]() |
68 | 70 |
|
69 | | - private var currentBreakpoint: Execution.Breakpoint? |
| 71 | + private var currentBreakpoint: (iseq: Execution.Breakpoint, wasmPc: Int)? |
70 | 72 |
|
71 | 73 | private var pc = Pc.allocate(capacity: 1) |
72 | 74 |
|
|
131 | 133 | /// Returns: `[Value]` result of `entrypointFunction` if current instance ran to completion, `nil` if it stopped at a breakpoint. |
132 | 134 | package mutating func run() throws -> [Value]? { |
133 | 135 | do { |
134 | | - return try self.execution.executeWasm( |
135 | | - threadingModel: self.threadingModel, |
136 | | - function: self.entrypointFunction.handle, |
137 | | - type: self.entrypointFunction.type, |
138 | | - arguments: [], |
139 | | - sp: self.valueStack, |
140 | | - pc: self.pc |
141 | | - ) |
| 136 | + if let currentBreakpoint { |
| 137 | + // Remove the breakpoint before resuming |
| 138 | + try self.disableBreakpoint(address: currentBreakpoint.wasmPc) |
| 139 | + self.execution.resetError() |
| 140 | + |
| 141 | + var sp = currentBreakpoint.iseq.sp |
| 142 | + var pc = currentBreakpoint.iseq.pc |
| 143 | + var md: Md = nil |
| 144 | + var ms: Ms = 0 |
| 145 | + |
| 146 | + guard let currentFunction = sp.currentFunction else { |
| 147 | + throw Error.unknownCurrentFunctionForResumedBreakpoint(sp) |
| 148 | + } |
| 149 | + |
| 150 | + Execution.CurrentMemory.mayUpdateCurrentInstance( |
| 151 | + instance: currentFunction.instance, |
| 152 | + from: self.instance.handle, |
| 153 | + md: &md, |
| 154 | + ms: &ms |
| 155 | + ) |
| 156 | + |
| 157 | + do { |
| 158 | + switch self.threadingModel { |
| 159 | + case .direct: |
| 160 | + try self.execution.runDirectThreaded(sp: sp, pc: pc, md: md, ms: ms) |
| 161 | + case .token: |
| 162 | + try self.execution.runTokenThreaded(sp: &sp, pc: &pc, md: &md, ms: &ms) |
| 163 | + } |
| 164 | + } catch is Execution.EndOfExecution { |
| 165 | + } |
| 166 | + |
| 167 | + let type = self.store.engine.funcTypeInterner.resolve(currentFunction.type) |
| 168 | + return type.results.enumerated().map { (i, type) in |
| 169 | + sp[VReg(i)].cast(to: type) |
| 170 | + } |
| 171 | + } else { |
| 172 | + return try self.execution.executeWasm( |
| 173 | + threadingModel: self.threadingModel, |
| 174 | + function: self.entrypointFunction.handle, |
| 175 | + type: self.entrypointFunction.type, |
| 176 | + arguments: [], |
| 177 | + sp: self.valueStack, |
| 178 | + pc: self.pc |
| 179 | + ) |
| 180 | + } |
142 | 181 | } catch let breakpoint as Execution.Breakpoint { |
143 | | - self.currentBreakpoint = breakpoint |
| 182 | + let pc = breakpoint.pc |
| 183 | + guard let wasmPc = self.instance.handle.iseqToWasmMapping[pc] else { |
| 184 | + throw Error.noReverseInstructionMappingAvailable(pc) |
| 185 | + } |
| 186 | + |
| 187 | + self.currentBreakpoint = (breakpoint, wasmPc) |
144 | 188 | return nil |
145 | 189 | } |
146 | 190 | } |
|
151 | 195 | return [] |
152 | 196 | } |
153 | 197 |
|
154 | | - var result = Execution.captureBacktrace(sp: currentBreakpoint.sp, store: self.store).symbols.compactMap { |
| 198 | + var result = Execution.captureBacktrace(sp: currentBreakpoint.iseq.sp, store: self.store).symbols.compactMap { |
155 | 199 | return self.instance.handle.iseqToWasmMapping[$0.address] |
156 | 200 | } |
157 | | - if let wasmPc = self.instance.handle.iseqToWasmMapping[currentBreakpoint.pc] { |
158 | | - result.append(wasmPc) |
159 | | - } |
| 201 | + result.append(currentBreakpoint.wasmPc) |
160 | 202 |
|
161 | 203 | return result |
162 | 204 | } |
|
0 commit comments