//----------------------------------------------------------------------
// [Assignment Instructions]
//
// There are many types of instrs that essentially copy the
// points-to set of a variable to another.
//
// Cast instrs such as `bitcast` fall to this category. Often
// the returned type of a `@malloc` func call is different than
// the declared type of the target variable. The LLVM IR adds a
// temporary variable of type `i8*` to hold the result and then an
// intermediate `bitcast` instr that casts this temporary
// variable to the right type.
//
// Another class of assignment instrs are the interprocedural
// assignments. This way we can model the implicit flow from (i) the
// actual arguments to the formal parameters, and from (ii) the return
// value of the called func to the variable that is assigned the
// result of the `call instr`.
//
// A simple field-insensitive approach would also treat getelementptr as an
// assignment instr.
//----------------------------------------------------------------------

.decl assign_instr(?toVar: Variable, ?value: Operand)
// `bitcast` instrs
assign_instr(?toVar, ?value) :-
   any_reachable_func(?instrFunc),
   instr_func(?instr, ?instrFunc),
   bitcast_instr_from_operand(?instr, ?value),  // TODO: consider adding type check
   instr_assigns_to(?instr, ?toVar).

// `ptrtoint` instrs
assign_instr(?toVar, ?value) :-
   any_reachable_func(?instrFunc),
   instr_func(?instr, ?instrFunc),
   ptrtoint_instr_from_operand(?instr, ?value),
   instr_assigns_to(?instr, ?toVar).

// `phi` instrs: treat every possible pair value as a potential
// assignment to the target variable
assign_instr(?toVar, ?value) :-
   any_reachable_func(?instrFunc),
   instr_func(?instr, ?instrFunc),
   phi_instr_pair(?instr, _, ?value, _),
   instr_assigns_to(?instr, ?toVar).

// `select` instrs; similar to `phi` instrs
assign_instr(?toVar, ?value) :-
   any_reachable_func(?instrFunc),
   instr_func(?instr, ?instrFunc),
   select_instr(?instr),
   ( select_instr_first_operand(?instr, ?value)
   ; select_instr_second_operand(?instr, ?value) ),
   instr_assigns_to(?instr, ?toVar),
   instr_returns_type(?instr, ?type),
   !vector_type(?type).

// TODO: support `cmpxchg` and `atomicrmw` instrs
// TODO: support `invoke` and `landingpad` instrs
