From cb8cf0aefeb4726d5d1138bfc7fa78ab4f114df3 Mon Sep 17 00:00:00 2001
From: Kostis Sagonas <kostis@it.uu.se>
Date: Tue, 29 Apr 2014 11:01:18 +0200
Subject: Translate the has_map_fields and get_map_elements BEAM instructions
 to ICode

---
 lib/hipe/icode/hipe_beam_to_icode.erl | 36 +++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

(limited to 'lib')

diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index dcd547fd5f..02fe773edb 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -1125,6 +1125,23 @@ trans_fun([{trim,N,NY}|Instructions], Env) ->
 trans_fun([{line,_}|Instructions], Env) ->
   trans_fun(Instructions,Env);
 %%--------------------------------------------------------------------
+%% Map instructions added in Spring 2014 (17.0).
+%%--------------------------------------------------------------------
+trans_fun([{test,has_map_fields,{f,Lbl},Map,{list,Keys}}|Instructions], Env) ->
+  {MapMove, MapVar, Env1} = mk_move_and_var(Map, Env),
+  %% We assume that hipe_icode:mk_call has no side-effects, and reuse
+  %% the help function of get_map_elements below, discarding the value
+  %% assignment instruction list.
+  {TestInstructions, _GetInstructions, Env2} =
+    trans_map_query(MapVar, map_label(Lbl), Env1,
+		    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) ->
+  {MapMove, MapVar, Env1} = mk_move_and_var(Map, Env),
+  {TestInstructions, GetInstructions, Env2} =
+    trans_map_query(MapVar, map_label(Lbl), Env1, KVPs),
+  [MapMove, TestInstructions, GetInstructions | trans_fun(Instructions, Env2)];
+%%--------------------------------------------------------------------
 %%--- ERROR HANDLING ---
 %%--------------------------------------------------------------------
 trans_fun([X|_], _) ->
@@ -1504,6 +1521,25 @@ trans_type_test2(function2, Lbl, Arg, Arity, Env) ->
 			 hipe_icode:label_name(True), map_label(Lbl)),
   {[Move1,Move2,I,True],Env2}.
 
+%%
+%% Handles the get_map_elements instruction and the has_map_fields
+%% test instruction.
+%%
+trans_map_query(_MapVar, _FailLabel, Env, []) ->
+  {[], [], Env};
+trans_map_query(MapVar, FailLabel, Env, [Key,Val|KVPs]) ->
+  {Move,KeyVar,Env1} = mk_move_and_var(Key,Env),
+  PassLabel = mk_label(new),
+  BoolVar = hipe_icode:mk_new_var(),
+  ValVar = mk_var(Val),
+  IsKeyCall = hipe_icode:mk_call([BoolVar], maps, is_key, [KeyVar, MapVar],
+				 remote),
+  TrueTest = hipe_icode:mk_if('=:=', [BoolVar, hipe_icode:mk_const(true)],
+			      hipe_icode:label_name(PassLabel), FailLabel),
+  GetCall = hipe_icode:mk_call([ValVar], maps, get,  [KeyVar, MapVar], remote),
+  {TestList, GetList, Env2} = trans_map_query(MapVar, FailLabel, Env1, KVPs),
+  {[Move, IsKeyCall, TrueTest, PassLabel|TestList], [GetCall|GetList], Env2}.
+
 %%-----------------------------------------------------------------------
 %% trans_puts(Code, Environment) -> 
 %%            {Movs, Code, Vars, NewEnv}
-- 
cgit v1.2.3