[objc][blocks] Load block instruction

Summary:
## Problem
In method specialization, we don't translate the loads of specialized blocks (e.g. `n$0 = block:_fn_`) and only add them to the id map. Later on, when the block is called with arguments (`n$0(arg1,..argn))` we lookup the id and use the substitution for the block. However, this means, if the program uses the id loading the block (n$0) anywhere else in the program, we have no declaration for it.

## When does this happen?
For blocks that return a nullable result, objC programs usually do a null check as in the following example:

```
typedef id _Nullable (^BlockType)(id object);

+ (void)useBlock:(int) x
          myBlock:(BlockType)myBlock{
  if (myBlock){
    myBlock(x);
  }
}

+ (void)callUseBlock{
  [X useBlock 1 myBlock:^id(id object) {
      return nil;
    }];
}
```
Here, method specialization currently ignores the loads of this block (`n$0=*&myBlock:_fn_(*)`) which results in having variables in prune nodes that are not defined anywhere in the CFG (like `n$0`).

This confuses control variable analysis when the conditional is wrapped in a loop because  it cannot lookup where `n$0` is coming from.

## Fix
This diff fixes the issue by translating the loading of the blocks.

Reviewed By: dulmarod

Differential Revision: D21642924

fbshipit-source-id: 2bc0442ff
master
Ezgi Çiçek 5 years ago committed by Facebook GitHub Bot
parent 7abc631c71
commit 7b75ee7f5a

@ -225,11 +225,10 @@ let with_block_args_instrs resolved_pdesc substitutions =
(call_instr :: instrs, id_map)
in
match instr with
| Sil.Load {id; e= Exp.Lvar block_param}
| Sil.Load {id; e= Exp.Lvar block_param as origin_exp; root_typ; typ; loc}
when Mangled.Map.mem (Pvar.get_name block_param) substitutions ->
let id_map = Ident.Map.add id (Pvar.get_name block_param) id_map in
(* we don't need the load the block param instruction anymore *)
(instrs, id_map)
(Sil.Load {id; e= convert_exp origin_exp; root_typ; typ; loc} :: instrs, id_map)
| Sil.Load {id; e= origin_exp; root_typ; typ; loc} ->
(Sil.Load {id; e= convert_exp origin_exp; root_typ; typ; loc} :: instrs, id_map)
| Sil.Store {e1= assignee_exp; root_typ= origin_typ; e2= Exp.Var id; loc}

Loading…
Cancel
Save