primPreLoop merges the basic blocks of the given pre_loop-primitive into a corresponding conceputal basic block for the primitive.
(condBlock, bodyBlock, exitBlock *basicBlock)
| 266 | // primPreLoop merges the basic blocks of the given pre_loop-primitive into a |
| 267 | // corresponding conceputal basic block for the primitive. |
| 268 | func (d *decompiler) primPreLoop(condBlock, bodyBlock, exitBlock *basicBlock) (*basicBlock, error) { |
| 269 | // Handle terminators. |
| 270 | condTerm, ok := condBlock.Term.(*ir.TermCondBr) |
| 271 | if !ok { |
| 272 | return nil, errors.Errorf("invalid cond terminator type; expected *ir.TermCondBr, got %T", condBlock.Term) |
| 273 | } |
| 274 | cond := d.value(condTerm.Cond) |
| 275 | // TODO: Figure out a clean way to check if the exit basic block is the true |
| 276 | // branch or the false branch. If exit is the true branch, negate the |
| 277 | // condition. |
| 278 | if _, ok := bodyBlock.Term.(*ir.TermBr); !ok { |
| 279 | return nil, errors.Errorf("invalid body terminator type; expected *ir.TermBr, got %T", bodyBlock.Term) |
| 280 | } |
| 281 | block := &basicBlock{BasicBlock: &ir.BasicBlock{}} |
| 282 | block.Term = exitBlock.Term |
| 283 | // Handle instructions. |
| 284 | block.stmts = append(block.stmts, d.stmts(condBlock)...) |
| 285 | body := &ast.BlockStmt{ |
| 286 | List: d.stmts(bodyBlock), |
| 287 | } |
| 288 | forStmt := &ast.ForStmt{ |
| 289 | Cond: cond, |
| 290 | Body: body, |
| 291 | } |
| 292 | block.stmts = append(block.stmts, forStmt) |
| 293 | block.stmts = append(block.stmts, d.stmts(exitBlock)...) |
| 294 | return block, nil |
| 295 | } |
| 296 | |
| 297 | // primPostLoop merges the basic blocks of the given post_loop-primitive into a |
| 298 | // corresponding conceputal basic block for the primitive. |