@@ -107,7 +107,6 @@ func NewDisassembly(fn wasm.Function, module *wasm.Module) (*Disassembly, error)
107107 stackDepths .Push (0 )
108108 blockIndices := & stack.Stack {} // a stack of indices to operators which start new blocks
109109 curIndex := 0
110- var lastOpReturn bool
111110
112111 for _ , instr := range instrs {
113112 logger .Printf ("stack top is %d" , stackDepths .Top ())
@@ -129,13 +128,28 @@ func NewDisassembly(fn wasm.Function, module *wasm.Module) (*Disassembly, error)
129128 instr .Unreachable = ! isInstrReachable (blockPolymorphicOps )
130129 }
131130
131+ var blockStartIndex uint64
132+ switch op {
133+ case ops .End , ops .Else :
134+ blockStartIndex = blockIndices .Pop ()
135+ if op == ops .Else {
136+ blockIndices .Push (uint64 (curIndex ))
137+ }
138+ case ops .Block , ops .Loop , ops .If :
139+ blockIndices .Push (uint64 (curIndex ))
140+ }
141+
142+ if instr .Unreachable {
143+ continue
144+ }
145+
132146 logger .Printf ("op: %s, unreachable: %v" , opStr .Name , instr .Unreachable )
133- if ! opStr .Polymorphic && ! instr . Unreachable {
147+ if ! opStr .Polymorphic {
134148 top := int (stackDepths .Top ())
135149 top -= len (opStr .Args )
136150 stackDepths .SetTop (uint64 (top ))
137- if top < - 1 {
138- return nil , ErrStackUnderflow
151+ if top < 0 {
152+ panic ( "underflow during validation" )
139153 }
140154 if opStr .Returns != wasm .ValueType (wasm .BlockTypeEmpty ) {
141155 top ++
@@ -148,23 +162,13 @@ func NewDisassembly(fn wasm.Function, module *wasm.Module) (*Disassembly, error)
148162 case ops .Unreachable :
149163 pushPolymorphicOp (blockPolymorphicOps , curIndex )
150164 case ops .Drop :
151- if ! instr .Unreachable {
152- stackDepths .SetTop (stackDepths .Top () - 1 )
153- }
165+ stackDepths .SetTop (stackDepths .Top () - 1 )
154166 case ops .Select :
155- if ! instr .Unreachable {
156- stackDepths .SetTop (stackDepths .Top () - 2 )
157- }
167+ stackDepths .SetTop (stackDepths .Top () - 2 )
158168 case ops .Return :
159- if ! instr .Unreachable {
160- stackDepths .SetTop (stackDepths .Top () - uint64 (len (fn .Sig .ReturnTypes )))
161- }
169+ stackDepths .SetTop (stackDepths .Top () - uint64 (len (fn .Sig .ReturnTypes )))
162170 pushPolymorphicOp (blockPolymorphicOps , curIndex )
163- lastOpReturn = true
164171 case ops .End , ops .Else :
165- // The max depth reached while execing the current block
166- curDepth := stackDepths .Top ()
167- blockStartIndex := blockIndices .Pop ()
168172 blockSig := disas .Code [blockStartIndex ].Block .Signature
169173 instr .Block = & BlockInfo {
170174 Start : false ,
@@ -175,7 +179,7 @@ func NewDisassembly(fn wasm.Function, module *wasm.Module) (*Disassembly, error)
175179 disas .Code [blockStartIndex ].Block .EndIndex = curIndex
176180 } else { // ops.Else
177181 instr .Block .ElseIfIndex = int (blockStartIndex )
178- disas .Code [blockStartIndex ].Block .IfElseIndex = int (blockStartIndex )
182+ disas .Code [blockStartIndex ].Block .IfElseIndex = int (curIndex )
179183 }
180184
181185 // The max depth reached while execing the last block
@@ -187,60 +191,28 @@ func NewDisassembly(fn wasm.Function, module *wasm.Module) (*Disassembly, error)
187191 prevDepthIndex := stackDepths .Len () - 2
188192 prevDepth := stackDepths .Get (prevDepthIndex )
189193
190- if op != ops .Else && blockSig != wasm .BlockTypeEmpty && ! instr . Unreachable {
194+ if op != ops .Else && blockSig != wasm .BlockTypeEmpty {
191195 stackDepths .Set (prevDepthIndex , prevDepth + 1 )
192196 disas .checkMaxDepth (int (stackDepths .Get (prevDepthIndex )))
193197 }
194198
195- if ! lastOpReturn {
196- elemsDiscard := int (curDepth ) - int (prevDepth )
197- if elemsDiscard < - 1 {
198- return nil , ErrStackUnderflow
199- }
200- instr .NewStack = & StackInfo {
201- StackTopDiff : int64 (elemsDiscard ),
202- PreserveTop : blockSig != wasm .BlockTypeEmpty ,
203- }
204- logger .Printf ("discard %d elements, preserve top: %v" , elemsDiscard , instr .NewStack .PreserveTop )
205- } else {
206- instr .NewStack = & StackInfo {}
207- }
208-
209199 logger .Printf ("setting new stack for %s block (%d)" , disas .Code [blockStartIndex ].Op .Name , blockStartIndex )
210- disas .Code [blockStartIndex ].NewStack = instr .NewStack
211- if ! instr .Unreachable {
212- blockPolymorphicOps = blockPolymorphicOps [:len (blockPolymorphicOps )- 1 ]
213- }
200+ blockPolymorphicOps = blockPolymorphicOps [:len (blockPolymorphicOps )- 1 ]
214201
215202 stackDepths .Pop ()
216203 if op == ops .Else {
217204 stackDepths .Push (stackDepths .Top ())
218- blockIndices .Push (uint64 (curIndex ))
219- if ! instr .Unreachable {
220- blockPolymorphicOps = append (blockPolymorphicOps , []int {})
221- }
205+ blockPolymorphicOps = append (blockPolymorphicOps , []int {})
222206 }
223-
224207 case ops .Block , ops .Loop , ops .If :
225208 sig := instr .Immediates [0 ].(wasm.BlockType )
226209 logger .Printf ("if, depth is %d" , stackDepths .Top ())
227210 stackDepths .Push (stackDepths .Top ())
228- // If this new block is unreachable, its
229- // entire instruction sequence is unreachable
230- // as well. To make sure that isInstrReachable
231- // returns the correct value, we don't push a new
232- // array to blockPolymorphicOps.
233- if ! instr .Unreachable {
234- // Therefore, only push a new array if this instruction
235- // is reachable.
236- blockPolymorphicOps = append (blockPolymorphicOps , []int {})
237- }
211+ blockPolymorphicOps = append (blockPolymorphicOps , []int {})
238212 instr .Block = & BlockInfo {
239213 Start : true ,
240214 Signature : sig ,
241215 }
242-
243- blockIndices .Push (uint64 (curIndex ))
244216 case ops .Br , ops .BrIf :
245217 depth := instr .Immediates [0 ].(uint32 )
246218 if int (depth ) == blockIndices .Len () {
@@ -260,20 +232,21 @@ func NewDisassembly(fn wasm.Function, module *wasm.Module) (*Disassembly, error)
260232
261233 // No need to subtract 2 here, we are getting the block
262234 // we need to branch to.
263- index := blockIndices .Get (blockIndices .Len () - 1 - int (depth ))
264- instr .NewStack = & StackInfo {
265- StackTopDiff : int64 (elemsDiscard ),
266- PreserveTop : disas .Code [index ].Block .Signature != wasm .BlockTypeEmpty ,
235+ // No need Discard one. and PreserveTop.
236+ if elemsDiscard > 1 {
237+ index := blockIndices .Get (blockIndices .Len () - 1 - int (depth ))
238+ instr .NewStack = & StackInfo {
239+ StackTopDiff : int64 (elemsDiscard ),
240+ PreserveTop : disas .Code [index ].Block .Signature != wasm .BlockTypeEmpty ,
241+ }
267242 }
268243 }
269244 if op == ops .Br {
270245 pushPolymorphicOp (blockPolymorphicOps , curIndex )
271246 }
272247
273248 case ops .BrTable :
274- if ! instr .Unreachable {
275- stackDepths .SetTop (stackDepths .Top () - 1 )
276- }
249+ stackDepths .SetTop (stackDepths .Top () - 1 )
277250 targetCount := instr .Immediates [0 ].(uint32 )
278251 for i := uint32 (0 ); i < targetCount ; i ++ {
279252 entry := instr .Immediates [i + 1 ].(uint32 )
@@ -318,42 +291,40 @@ func NewDisassembly(fn wasm.Function, module *wasm.Module) (*Disassembly, error)
318291 pushPolymorphicOp (blockPolymorphicOps , curIndex )
319292 case ops .Call , ops .CallIndirect :
320293 index := instr .Immediates [0 ].(uint32 )
321- if ! instr .Unreachable {
322- var sig * wasm.FunctionSig
323- top := int (stackDepths .Top ())
324- if op == ops .CallIndirect {
325- if module .Types == nil {
326- return nil , errors .New ("missing types section" )
327- }
328- sig = & module .Types .Entries [index ]
329- top --
330- } else {
331- sig = module .GetFunction (int (index )).Sig
294+ var sig * wasm.FunctionSig
295+ top := int (stackDepths .Top ())
296+
297+ switch op {
298+ case ops .CallIndirect :
299+ if module .Types == nil {
300+ return nil , errors .New ("missing types section" )
332301 }
333- top -= len (sig .ParamTypes )
334- top += len (sig .ReturnTypes )
335- stackDepths .SetTop (uint64 (top ))
336- disas .checkMaxDepth (top )
337- }
338- case ops .GetLocal , ops .SetLocal , ops .TeeLocal , ops .GetGlobal , ops .SetGlobal :
339- if ! instr .Unreachable {
340- top := stackDepths .Top ()
341- switch op {
342- case ops .GetLocal , ops .GetGlobal :
343- top ++
344- stackDepths .SetTop (top )
345- disas .checkMaxDepth (int (top ))
346- case ops .SetLocal , ops .SetGlobal :
347- top --
348- stackDepths .SetTop (top )
349- case ops .TeeLocal :
350- // stack remains unchanged for tee_local
302+ sig = & module .Types .Entries [index ]
303+ top --
304+ default :
305+ sig , err = module .GetFunctionSig (index )
306+ if err != nil {
307+ return nil , err
351308 }
352309 }
353- }
354310
355- if op != ops .Return {
356- lastOpReturn = false
311+ top -= len (sig .ParamTypes )
312+ top += len (sig .ReturnTypes )
313+ stackDepths .SetTop (uint64 (top ))
314+ disas .checkMaxDepth (top )
315+ case ops .GetLocal , ops .SetLocal , ops .TeeLocal , ops .GetGlobal , ops .SetGlobal :
316+ top := stackDepths .Top ()
317+ switch op {
318+ case ops .GetLocal , ops .GetGlobal :
319+ top ++
320+ stackDepths .SetTop (top )
321+ disas .checkMaxDepth (int (top ))
322+ case ops .SetLocal , ops .SetGlobal :
323+ top --
324+ stackDepths .SetTop (top )
325+ case ops .TeeLocal :
326+ // stack remains unchanged for tee_local
327+ }
357328 }
358329
359330 disas .Code = append (disas .Code , instr )
0 commit comments