let rec translate_mexpr mexpr =
let t_mexpr = mexpr.mexpr_type in
match mexpr.mexpr_t with
| CTTMexpWrite(lv, fields, None, e2) ->
let lv, i1 = translate_lvalue lv in
let v2, i2 = translate_mexpr e2 in
v2, make_il0 (IL0stmtWrite(lv,fields,v2)) :: (i1 @ i2)
| CTTMexpWrite(lv, fields, Some(binop,tcast), e2) ->
let lv, i1 = translate_lvalue lv in
let v2, i2 = translate_mexpr e2 in
let tv_pre, i3 = gentemp_read (lv,fields) t_mexpr in
let (tv_pre_c, i4), tc =
match tcast with
None -> (tv_pre, []), t_mexpr
| Some tc ->
let tv_pre_c, i4 = gentemp (ILexpCoerce(tc,tv_pre)) tc
in (tv_pre_c, [i4]), tc
in
let tv, i5 = gentemp (ILexpBinop(cvt_binop binop,tv_pre_c,v2)) tc in
let tv, i6 = match tcast with
None -> tv, []
| Some _ -> let tv, i6 = gentemp (ILexpCoerce(t_mexpr,tv)) t_mexpr in
tv, [i6]
in
let is = i5 :: i3 :: make_il0 (IL0stmtWrite(lv,fields,tv))::(i6 @ i4 @ i1 @ i2) in
(match binop with
| CTTbinPostPlusVV | CTTbinPostMinusVV
| CTTbinPostPlusPV | CTTbinPostMinusPV -> tv_pre
| _ -> tv), is
| CTTMexpComma(e1,e2) ->
let v1, i1 = translate_mexpr e1 in
let v2, i2 = translate_mexpr e2 in
v2, [enclose_sequence [enclose_parallel i1; enclose_parallel i2]]
| CTTMexpRead(lv, fields) ->
let lv, i1 = translate_lvalue ~allow_invoke:true lv in
let tv_pre, i3 = gentemp_read (lv,fields) t_mexpr in
tv_pre, i3::i1
| CTTMexpConstant(c) ->
let v, i = gentemp (ILexpConstant c) t_mexpr in
v, [i]
| CTTMexpBinExpr(binop, e1, e2) ->
let v1, i1 = translate_mexpr e1 in
let v2, i2 = translate_mexpr e2 in
let v, i = gentemp (ILexpBinop (cvt_binop binop, v1, v2)) t_mexpr in
v, (i :: i1) @ i2
| CTTMexpCoerce (t1, e1) ->
let v1, i1 = translate_mexpr e1 in
let v, i = gentemp (ILexpCoerce (t1, v1)) t_mexpr in
v, i :: i1
| CTTMexpUnaryExpr (uop, e1) ->
let v1, i1 = translate_mexpr e1 in
let v, i = gentemp (ILexpUnaryop (uop, v1)) t_mexpr in
v, i :: i1
| CTTMexpConditional(e1,e2,e3) ->
let v1, i1 = translate_mexpr e1 in
let v2, i2 = translate_mexpr e2 in
let v3, i3 = translate_mexpr e3 in
let vt = new_tempid () in
let s1, s2 = make_label(), make_label() in
vt, [enclose_sequence
[enclose_parallel i1;
make_il0 (IL0stmtIf(IFNOT, v1, s1));
enclose_parallel i2;
make_il0 (IL0stmtDefTemp(vt, e2.mexpr_type, ILexpIdent v2));
make_il0 (IL0stmtGoto s2);
make_il0 (IL0stmtLabel s1);
enclose_parallel i3;
make_il0 (IL0stmtDefTemp(vt, e2.mexpr_type, ILexpIdent v3));
make_il0 (IL0stmtLabel s2)]]
| CTTMexpInvoke(lhs,rhs) ->
let ts = List.map translate_mexpr rhs in
let vs, is = List.split ts in
let is = List.flatten is in
let lv, ilv = translate_lvalue lhs in
let v, i = gentemp (ILexpInvoke(lv, vs)) t_mexpr in
v, [enclose_sequence
[enclose_parallel (is @ ilv);
i]]
| CTTMexpAddress(lv,fields) ->
let lv, i1 = translate_lvalue lv in
let v, i = gentemp (ILexpAddress(lv,fields)) t_mexpr in
v, i :: i1
and translate_lvalue ?(allow_invoke = false) lv =
match lv with
CTTMlvPtr e1 ->
let v1, i1 = translate_mexpr e1 in
ILlvPtr(v1), i1
| CTTMlvVar(v1,t1) ->
ILlvVar(v1,t1), []
| CTTMlvInvoke (lhs,rhs,t1) ->
if allow_invoke then begin
let ts = List.map translate_mexpr rhs in
let vs, is = List.split ts in
let is = List.flatten is in
let lv, ilv = translate_lvalue lhs in
let v, i = gentemp (ILexpInvoke(lv, vs)) t1 in
ILlvTemp(v), [enclose_sequence
[enclose_parallel (is @ ilv);
i]]
end else
failwith "non-lvalue not allowed (result of function invocation)"