method vinst =
function
| Set(lv,e,loc) ->
(* Type of [e] has not been changed by retyping formals and return. *)
if isStructOrUnionType (typeOf e) then
ChangeTo (expand_assign lv e (typeOf e) loc)
else SkipChildren
| Call(lvo,callee,args,loc) ->
let args = List.map (fun arg ->
(* Type of [arg] has not been changed. *)
if isStructOrUnionType (typeOf arg) then
match arg.enode with
| Lval lv -> Cabs2cil.mkAddrOfAndMark lv
| _ -> assert false (* Should not be possible *)
else arg
) args in
begin match lvo with
| None ->
(* TODO: free memory for structure return, even if not used.
Check that no temporary is added in every case, which would
make treatment here useless. *)
let call = Call (lvo, callee, args, loc) in
ChangeTo [call]
| Some lv ->
(* Type of [lv] has not been changed. *)
let lvty = typeOfLval lv in
if isStructOrUnionType lvty then
let tmpv = makeTempVar !curFundec (mkTRef lvty) in
let tmplv = Var tmpv, NoOffset in
let call = Call(Some tmplv,callee,args,loc) in
let deref =
new_exp (Lval(mkMem
(new_exp (Lval(Var tmpv,NoOffset)))
NoOffset))
in
let assign = mkassign lv deref loc in
let free = mkfree tmpv loc in
ChangeTo [call;assign;free]
else
let call = Call(lvo,callee,args,loc) in
ChangeTo [call]
end
| Asm _ | Skip _ | Code_annot _ -> SkipChildren