diff options
author | Björn Gustavsson <[email protected]> | 2018-08-13 09:53:58 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2018-08-17 09:51:00 +0200 |
commit | 004257f6fc1ea9efea1c99a93211e2f39b1d14ad (patch) | |
tree | d765a97c8d23e340a2c3415400266daf04e95c9a | |
parent | f107c76b7996c731670e52788801f534fa5326aa (diff) | |
download | otp-004257f6fc1ea9efea1c99a93211e2f39b1d14ad.tar.gz otp-004257f6fc1ea9efea1c99a93211e2f39b1d14ad.tar.bz2 otp-004257f6fc1ea9efea1c99a93211e2f39b1d14ad.zip |
hipe_beam_to_icode: Correct translation of get_map_elements
If one of the destination registers for get_map_elements is
the same as the map source, extract that element last.
-rw-r--r-- | lib/hipe/icode/hipe_beam_to_icode.erl | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl index f429d40272..4f099baab3 100644 --- a/lib/hipe/icode/hipe_beam_to_icode.erl +++ b/lib/hipe/icode/hipe_beam_to_icode.erl @@ -1139,9 +1139,10 @@ trans_fun([{test,has_map_fields,{f,Lbl},Map,{list,Keys}}|Instructions], Env) -> lists:flatten([[K, {r, 0}] || K <- Keys])), [MapMove, TestInstructions | trans_fun(Instructions, Env2)]; trans_fun([{get_map_elements,{f,Lbl},Map,{list,KVPs}}|Instructions], Env) -> + KVPs1 = overwrite_map_last(Map, KVPs), {MapMove, MapVar, Env1} = mk_move_and_var(Map, Env), {TestInstructions, GetInstructions, Env2} = - trans_map_query(MapVar, map_label(Lbl), Env1, KVPs), + trans_map_query(MapVar, map_label(Lbl), Env1, KVPs1), [MapMove, TestInstructions, GetInstructions | trans_fun(Instructions, Env2)]; %%--- put_map_assoc --- trans_fun([{put_map_assoc,{f,Lbl},Map,Dst,_N,{list,Pairs}}|Instructions], Env) -> @@ -1563,6 +1564,21 @@ trans_type_test2(function2, Lbl, Arg, Arity, Env) -> hipe_icode:label_name(True), map_label(Lbl)), {[Move1,Move2,I,True],Env2}. + +%% +%% Makes sure that if a get_map_elements instruction will overwrite +%% the map source, it will be done last. +%% +overwrite_map_last(Map, KVPs) -> + overwrite_map_last2(Map, KVPs, []). + +overwrite_map_last2(Map, [Key,Map|KVPs], _Last) -> + overwrite_map_last2(Map, KVPs, [Key,Map]); +overwrite_map_last2(Map, [Key,Val|KVPs], Last) -> + [Key,Val|overwrite_map_last2(Map, KVPs, Last)]; +overwrite_map_last2(_Map, [], Last) -> + Last. + %% %% Handles the get_map_elements instruction and the has_map_fields %% test instruction. |