primPostLoop merges the basic blocks of the given post_loop-primitive into a corresponding conceputal basic block for the primitive.
(condBlock, exitBlock *basicBlock)
| 297 | // primPostLoop merges the basic blocks of the given post_loop-primitive into a |
| 298 | // corresponding conceputal basic block for the primitive. |
| 299 | func (d *decompiler) primPostLoop(condBlock, exitBlock *basicBlock) (*basicBlock, error) { |
| 300 | // Handle terminators. |
| 301 | condTerm, ok := condBlock.Term.(*ir.TermCondBr) |
| 302 | if !ok { |
| 303 | return nil, errors.Errorf("invalid cond terminator type; expected *ir.TermCondBr, got %T", condBlock.Term) |
| 304 | } |
| 305 | cond := d.value(condTerm.Cond) |
| 306 | cond = &ast.UnaryExpr{ |
| 307 | Op: token.NOT, |
| 308 | X: cond, |
| 309 | } |
| 310 | // TODO: Figure out a clean way to check if the exit basic block is the true |
| 311 | // branch or the false branch. If exit is the true branch, negate the |
| 312 | // condition. |
| 313 | block := &basicBlock{BasicBlock: &ir.BasicBlock{}} |
| 314 | block.Term = exitBlock.Term |
| 315 | // Handle instructions. |
| 316 | body := &ast.BlockStmt{ |
| 317 | List: d.stmts(condBlock), |
| 318 | } |
| 319 | breakStmt := &ast.BranchStmt{Tok: token.BREAK} |
| 320 | ifBreakStmt := &ast.IfStmt{ |
| 321 | Cond: cond, |
| 322 | Body: &ast.BlockStmt{ |
| 323 | List: []ast.Stmt{breakStmt}, |
| 324 | }, |
| 325 | } |
| 326 | body.List = append(body.List, ifBreakStmt) |
| 327 | forStmt := &ast.ForStmt{ |
| 328 | Body: body, |
| 329 | } |
| 330 | block.stmts = append(block.stmts, forStmt) |
| 331 | block.stmts = append(block.stmts, d.stmts(exitBlock)...) |
| 332 | return block, nil |
| 333 | } |
| 334 | |
| 335 | // primSeq merges the basic blocks of the given seq-primitive into a |
| 336 | // corresponding conceputal basic block for the primitive. |