aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/util
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/util')
-rw-r--r--lib/hipe/util/Makefile109
-rw-r--r--lib/hipe/util/hipe_digraph.erl238
-rwxr-xr-xlib/hipe/util/hipe_dot.erl217
-rw-r--r--lib/hipe/util/hipe_timing.erl131
-rw-r--r--lib/hipe/util/hipe_vectors.erl111
-rw-r--r--lib/hipe/util/hipe_vectors.hrl28
6 files changed, 834 insertions, 0 deletions
diff --git a/lib/hipe/util/Makefile b/lib/hipe/util/Makefile
new file mode 100644
index 0000000000..27cacedf11
--- /dev/null
+++ b/lib/hipe/util/Makefile
@@ -0,0 +1,109 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+ifndef EBIN
+EBIN = ../ebin
+endif
+
+ifndef DOCS
+DOCS = ../doc
+endif
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(HIPE_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/hipe-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+ifdef HIPE_ENABLED
+HIPE_MODULES = hipe_vectors
+else
+HIPE_MODULES =
+endif
+MODULES = hipe_timing hipe_dot hipe_digraph $(HIPE_MODULES)
+
+HRL_FILES=
+ERL_FILES= $(MODULES:%=%.erl)
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
+
+# APP_FILE=
+# APP_SRC= $(APP_FILE).src
+# APP_TARGET= $(EBIN)/$(APP_FILE)
+#
+# APPUP_FILE=
+# APPUP_SRC= $(APPUP_FILE).src
+# APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+include ../native.mk
+
+ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt: $(TARGET_FILES)
+
+docs: $(DOC_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f core
+
+$(DOCS)/%.html:%.erl
+ erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/util
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/util
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+
+release_docs_spec:
+
+
+$(EBIN)/hipe_timing.beam: ../main/hipe.hrl
+$(EBIN)/hipe_vectors.beam: hipe_vectors.hrl
diff --git a/lib/hipe/util/hipe_digraph.erl b/lib/hipe/util/hipe_digraph.erl
new file mode 100644
index 0000000000..a62e913fe5
--- /dev/null
+++ b/lib/hipe/util/hipe_digraph.erl
@@ -0,0 +1,238 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%-----------------------------------------------------------------------
+%% File : hipe_digraph.erl
+%% Author : Tobias Lindahl <[email protected]>
+%% Purpose : Provides a simple implementation of a directed graph.
+%%
+%% Created : 9 Feb 2005 by Tobias Lindahl <[email protected]>
+%%-----------------------------------------------------------------------
+-module(hipe_digraph).
+
+-export([new/0, add_edge/3, add_node/2, add_node_list/2,
+ from_list/1, to_list/1, get_parents/2, get_children/2]).
+-export([reverse_preorder_sccs/1]).
+
+%%------------------------------------------------------------------------
+
+-type ordset(T) :: [T]. % XXX: temporarily
+
+-record(hipe_digraph, {edges = dict:new() :: dict(),
+ rev_edges = dict:new() :: dict(),
+ leaves = ordsets:new() :: ordset(_), % ???
+ nodes = sets:new() :: set()}).
+
+-opaque hdg() :: #hipe_digraph{}.
+
+%%------------------------------------------------------------------------
+
+-spec new() -> hdg().
+
+new() ->
+ #hipe_digraph{edges = dict:new(), rev_edges = dict:new(),
+ leaves = ordsets:new(), nodes = sets:new()}.
+
+-spec from_list([_]) -> hdg().
+
+from_list(List) ->
+ Edges = lists:foldl(fun({From, To}, Dict) ->
+ Fun = fun(Set) -> ordsets:add_element(To, Set) end,
+ dict:update(From, Fun, [To], Dict)
+ end,
+ dict:new(), List),
+ RevEdges = lists:foldl(fun({From, To}, Dict) ->
+ Fun = fun(Set) ->
+ ordsets:add_element(From, Set)
+ end,
+ dict:update(To, Fun, [From], Dict)
+ end,
+ dict:new(), List),
+ Keys1 = sets:from_list(dict:fetch_keys(Edges)),
+ Keys2 = sets:from_list(dict:fetch_keys(RevEdges)),
+ Nodes = sets:union(Keys1, Keys2),
+ #hipe_digraph{edges = Edges, rev_edges = RevEdges,
+ leaves = [], nodes = Nodes}.
+
+-spec to_list(hdg()) -> [_].
+
+to_list(#hipe_digraph{edges = Edges}) ->
+ List1 = dict:to_list(Edges),
+ List2 = lists:foldl(fun({From, ToList}, Acc) ->
+ [[{From, To} || To <- ToList]|Acc]
+ end, [], List1),
+ lists:flatten(List2).
+
+-spec add_node(_, hdg()) -> hdg().
+
+add_node(NewNode, DG = #hipe_digraph{nodes=Nodes}) ->
+ DG#hipe_digraph{nodes = sets:add_element(NewNode, Nodes)}.
+
+-spec add_node_list([_], hdg()) -> hdg().
+
+add_node_list(NewNodes, DG = #hipe_digraph{nodes=Nodes}) ->
+ Set = sets:from_list(NewNodes),
+ DG#hipe_digraph{nodes = sets:union(Set, Nodes)}.
+
+-spec add_edge(_, _, hdg()) -> hdg().
+
+add_edge(From, To, #hipe_digraph{edges = Edges, rev_edges = RevEdges,
+ leaves = Leaves, nodes = Nodes}) ->
+ Fun1 = fun(Set) -> ordsets:add_element(To, Set) end,
+ NewEdges = dict:update(From, Fun1, [To], Edges),
+ Fun2 = fun(Set) -> ordsets:add_element(From, Set) end,
+ NewRevEdges = dict:update(To, Fun2, [From], RevEdges),
+ NewLeaves = ordsets:del_element(From, Leaves),
+ #hipe_digraph{edges = NewEdges,
+ rev_edges = NewRevEdges,
+ leaves = NewLeaves,
+ nodes = sets:add_element(From, sets:add_element(To, Nodes))}.
+
+%%-------------------------------------------------------------------------
+
+-spec take_indep_scc(hdg()) -> 'none' | {'ok', [_], hdg()}.
+
+take_indep_scc(DG = #hipe_digraph{edges = Edges, rev_edges = RevEdges,
+ leaves = Leaves, nodes = Nodes}) ->
+ case sets:size(Nodes) =:= 0 of
+ true -> none;
+ false ->
+ {SCC, NewLeaves} =
+ case Leaves of
+ [H|T] ->
+ {[H], T};
+ [] ->
+ case find_all_leaves(Edges) of
+ [] ->
+ {[Node|_], _} = dfs(Nodes, RevEdges),
+ {SCC1, _} = dfs(Node, Edges),
+ {SCC1, []};
+ [H|T] ->
+ {[H], T}
+ end
+ end,
+ NewEdges = remove_edges(SCC, Edges, RevEdges),
+ NewRevEdges = remove_edges(SCC, RevEdges, Edges),
+ NewNodes = sets:subtract(Nodes, sets:from_list(SCC)),
+ {ok, reverse_preorder(SCC, Edges),
+ DG#hipe_digraph{edges = NewEdges, rev_edges = NewRevEdges,
+ leaves = NewLeaves, nodes = NewNodes}}
+ end.
+
+find_all_leaves(Edges) ->
+ List = dict:fold(fun(Key, [Key], Acc) -> [Key|Acc];
+ (_, _, Acc) -> Acc
+ end, [], Edges),
+ ordsets:from_list(List).
+
+remove_edges(Nodes0, Edges, RevEdges) ->
+ Nodes = ordsets:from_list(Nodes0),
+ Fun = fun(N, Dict) -> dict:erase(N, Dict) end,
+ Edges1 = lists:foldl(Fun, Edges, Nodes),
+ remove_edges_in(Nodes, Edges1, RevEdges).
+
+remove_edges_in([Node|Nodes], Edges, RevEdges) ->
+ NewEdges =
+ case dict:find(Node, RevEdges) of
+ error ->
+ Edges;
+ {ok, Set} ->
+ Fun = fun(Key, Dict) ->
+ case dict:find(Key, Dict) of
+ error ->
+ Dict;
+ {ok, OldTo} ->
+ case ordsets:del_element(Node, OldTo) of
+ [] -> dict:store(Key, [Key], Dict);
+ NewSet -> dict:store(Key, NewSet, Dict)
+ end
+ end
+ end,
+ lists:foldl(Fun, Edges, Set)
+ end,
+ remove_edges_in(Nodes, NewEdges, RevEdges);
+remove_edges_in([], Edges, _RevEdges) ->
+ Edges.
+
+reverse_preorder([_] = Nodes, _Edges) ->
+ Nodes;
+reverse_preorder([N|_] = Nodes, Edges) ->
+ NodeSet = sets:from_list(Nodes),
+ {PreOrder, _} = dfs(N, Edges),
+ DFS = [X || X <- PreOrder, sets:is_element(X, NodeSet)],
+ lists:reverse(DFS).
+
+%%---------------------------------------------------------------------
+
+-spec reverse_preorder_sccs(hdg()) -> [[_]].
+
+reverse_preorder_sccs(DG) ->
+ reverse_preorder_sccs(DG, []).
+
+reverse_preorder_sccs(DG, Acc) ->
+ case take_indep_scc(DG) of
+ none -> lists:reverse(Acc);
+ {ok, SCC, DG1} -> reverse_preorder_sccs(DG1, [SCC|Acc])
+ end.
+
+%%---------------------------------------------------------------------
+
+-spec get_parents(_, hdg()) -> [_].
+
+get_parents(Node, #hipe_digraph{rev_edges = RevEdges}) ->
+ case dict:is_key(Node, RevEdges) of
+ true -> dict:fetch(Node, RevEdges);
+ false -> []
+ end.
+
+-spec get_children(_, hdg()) -> [_].
+
+get_children(Node, #hipe_digraph{edges = Edges}) ->
+ case dict:is_key(Node, Edges) of
+ true -> dict:fetch(Node, Edges);
+ false -> []
+ end.
+
+%%---------------------------------------------------------------------
+%% dfs/2 returns a preordered depth first search and the nodes visited.
+
+dfs(Node, Edges) ->
+ case sets:is_set(Node) of
+ true ->
+ dfs(sets:to_list(Node), Edges, sets:new(), []);
+ false ->
+ dfs([Node], Edges, sets:new(), [])
+ end.
+
+dfs([Node|Left], Edges, Visited, Order) ->
+ case sets:is_element(Node, Visited) of
+ true ->
+ dfs(Left, Edges, Visited, Order);
+ false ->
+ NewVisited = sets:add_element(Node, Visited),
+ case dict:find(Node, Edges) of
+ error ->
+ dfs(Left, Edges, NewVisited, [Node|Order]);
+ {ok, Succ} ->
+ {NewOrder, NewVisited1} = dfs(Succ, Edges, NewVisited, Order),
+ dfs(Left, Edges, NewVisited1, [Node|NewOrder])
+ end
+ end;
+dfs([], _Edges, Visited, Order) ->
+ {Order, Visited}.
diff --git a/lib/hipe/util/hipe_dot.erl b/lib/hipe/util/hipe_dot.erl
new file mode 100755
index 0000000000..d6ef801c88
--- /dev/null
+++ b/lib/hipe/util/hipe_dot.erl
@@ -0,0 +1,217 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%
+%%% %CopyrightBegin%
+%%%
+%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%%
+%%% The contents of this file are subject to the Erlang Public License,
+%%% Version 1.1, (the "License"); you may not use this file except in
+%%% compliance with the License. You should have received a copy of the
+%%% Erlang Public License along with this software. If not, it can be
+%%% retrieved online at http://www.erlang.org/.
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%%% the License for the specific language governing rights and limitations
+%%% under the License.
+%%%
+%%% %CopyrightEnd%
+%%%
+%%%-------------------------------------------------------------------
+%%% File : hipe_dot.erl
+%%% Author : Per Gustafsson <[email protected]>
+%%% Description :
+%%%
+%%% Created : 25 Nov 2004 by Per Gustafsson <[email protected]>
+%%%-------------------------------------------------------------------
+
+-module(hipe_dot).
+
+-export([translate_digraph/3, translate_digraph/5,
+ translate_list/3, translate_list/4, translate_list/5]).
+
+%%--------------------------------------------------------------------
+
+-type gnode() :: any().
+-type edge() :: {gnode(), gnode()}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% This module creates .dot representations of graphs from their
+%% Erlang representations. There are two different forms of Erlang
+%% representations that the module accepts, digraphs and lists of two
+%% tuples (where each tuple represents a directed edge).
+%%
+%% The functions also require a FileName and a name of the graph. The
+%% filename is the name of the resulting .dot file the GraphName is
+%% pretty much useless.
+%%
+%% The resulting .dot reprsentation will be stored in the flie FileName.
+%%
+%% Interfaces:
+%%
+%% translate_list(Graph::[{Node,Node}], FileName::string(),
+%% GraphName::string()) -> ok
+%%
+%% translate_list(Graph::[{Node,Node}], FileName::string(),
+%% GraphName::string(), Options::[option] ) -> ok
+%%
+%% translate_list(Graph::[{Node,Node}], FileName::string(),
+%% GraphName::string(), Fun::fun(term() -> string()),
+%% Options::[option]) -> ok
+%%
+%% The optional Fun argument dictates how the node/names should be output.
+%%
+%% The option list can be used to pass options to .dot to decide how
+%% different nodes and edges should be displayed.
+%%
+%% translate_digraph has the same interface as translate_list except
+%% it takes a digraph rather than a list.
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-spec translate_digraph(digraph(), string(), string()) -> 'ok'.
+
+translate_digraph(G, FileName, GName) ->
+ translate_digraph(G, FileName, GName,
+ fun(X) -> io_lib:format("~p", [X]) end, []).
+
+-spec translate_digraph(digraph(), string(), string(),
+ fun((_) -> string()), [_]) -> 'ok'.
+
+translate_digraph(G, FileName, GName, Fun, Opts) ->
+ Edges = [digraph:edge(G, X) || X <- digraph:edges(G)],
+ EdgeList = [{X, Y} || {_, X, Y, _} <- Edges],
+ translate_list(EdgeList, FileName, GName, Fun, Opts).
+
+%%--------------------------------------------------------------------
+
+-spec translate_list([edge()], string(), string()) -> 'ok'.
+
+translate_list(List, FileName, GName) ->
+ translate_list(List, FileName, GName,
+ fun(X) -> lists:flatten(io_lib:format("~p", [X])) end, []).
+
+-spec translate_list([edge()], string(), string(), [_]) -> 'ok'.
+
+translate_list(List, FileName, GName, Opts) ->
+ translate_list(List, FileName, GName,
+ fun(X) -> lists:flatten(io_lib:format("~p", [X])) end, Opts).
+
+-spec translate_list([edge()], string(), string(),
+ fun((_) -> string()), [_]) -> 'ok'.
+
+translate_list(List, FileName, GName, Fun, Opts) ->
+ {NodeList1, NodeList2} = lists:unzip(List),
+ NodeList = NodeList1 ++ NodeList2,
+ NodeSet = ordsets:from_list(NodeList),
+ Start = ["digraph ",GName ," {"],
+ VertexList = [node_format(Opts, Fun, V) ||V <- NodeSet],
+ End = ["graph [", GName, "=", GName, "]}"],
+ EdgeList = [edge_format(Opts, Fun, X, Y) || {X,Y} <- List],
+ String = [Start, VertexList, EdgeList, End],
+ %% io:format("~p~n", [lists:flatten([String])]),
+ ok = file:write_file(FileName, list_to_binary(String)).
+
+%%--------------------------------------------------------------------
+
+node_format(Opt, Fun, V) ->
+ OptText = nodeoptions(Opt, Fun ,V),
+ Tmp = io_lib:format("~p", [Fun(V)]),
+ String = lists:flatten(Tmp),
+ %% io:format("~p", [String]),
+ {Width, Heigth} = calc_dim(String),
+ W = ((Width div 7) + 1) * 0.55,
+ H = Heigth * 0.4,
+ SL = io_lib:format("~f", [W]),
+ SH = io_lib:format("~f", [H]),
+ [String, " [width=", SL, " heigth=", SH, " ", OptText,"];\n"].
+
+edge_format(Opt, Fun, V1, V2) ->
+ OptText =
+ case lists:flatten(edgeoptions(Opt, Fun ,V1, V2)) of
+ [] ->
+ [];
+ [_|X] ->
+ X
+ end,
+ String = [io_lib:format("~p", [Fun(V1)]), " -> ",
+ io_lib:format("~p", [Fun(V2)])],
+ [String, " [", OptText, "];\n"].
+
+calc_dim(String) ->
+ calc_dim(String, 1, 0, 0).
+
+calc_dim("\\n" ++ T, H, TmpW, MaxW) ->
+ calc_dim(T, H+1, 0, erlang:max(TmpW, MaxW));
+calc_dim([_|T], H, TmpW, MaxW) ->
+ calc_dim(T, H, TmpW+1, MaxW);
+calc_dim([], H, TmpW, MaxW) ->
+ {erlang:max(TmpW, MaxW), H}.
+
+edgeoptions([{all_edges, {OptName, OptVal}}|T], Fun, V1, V2) ->
+ case legal_edgeoption(OptName) of
+ true ->
+ [io_lib:format(",~p=~p ", [OptName, OptVal])|edgeoptions(T, Fun, V1, V2)]
+ %% false ->
+ %% edgeoptions(T, Fun, V1, V2)
+ end;
+edgeoptions([{N1, N2, {OptName, OptVal}}|T], Fun, V1, V2) ->
+ case %% legal_edgeoption(OptName) andalso
+ Fun(N1) =:= Fun(V1) andalso Fun(N2) =:= Fun(V2) of
+ true ->
+ [io_lib:format(",~p=~p ", [OptName, OptVal])|edgeoptions(T, Fun, V1, V2)];
+ false ->
+ edgeoptions(T, Fun, V1, V2)
+ end;
+edgeoptions([_|T], Fun, V1, V2) ->
+ edgeoptions(T, Fun, V1, V2);
+edgeoptions([], _, _, _) ->
+ [].
+
+nodeoptions([{all_nodes, {OptName, OptVal}}|T], Fun, V) ->
+ case legal_nodeoption(OptName) of
+ true ->
+ [io_lib:format(",~p=~p ", [OptName, OptVal])|nodeoptions(T, Fun, V)];
+ false ->
+ nodeoptions(T, Fun, V)
+ end;
+nodeoptions([{Node, {OptName, OptVal}}|T], Fun, V) ->
+ case Fun(Node) =:= Fun(V) andalso legal_nodeoption(OptName) of
+ true ->
+ [io_lib:format("~p=~p ", [OptName, OptVal])|nodeoptions(T, Fun, V)];
+ false ->
+ nodeoptions(T, Fun, V)
+ end;
+nodeoptions([_|T], Fun, V) ->
+ nodeoptions(T, Fun, V);
+nodeoptions([], _Fun, _V) ->
+ [].
+
+legal_nodeoption(bottomlabel) -> true;
+legal_nodeoption(color) -> true;
+legal_nodeoption(comment) -> true;
+legal_nodeoption(distortion) -> true;
+legal_nodeoption(fillcolor) -> true;
+legal_nodeoption(fixedsize) -> true;
+legal_nodeoption(fontcolor) -> true;
+legal_nodeoption(fontname) -> true;
+legal_nodeoption(fontsize) -> true;
+legal_nodeoption(group) -> true;
+legal_nodeoption(height) -> true;
+legal_nodeoption(label) -> true;
+legal_nodeoption(layer) -> true;
+legal_nodeoption(orientation) -> true;
+legal_nodeoption(peripheries) -> true;
+legal_nodeoption(regular) -> true;
+legal_nodeoption(shape) -> true;
+legal_nodeoption(shapefile) -> true;
+legal_nodeoption(sides) -> true;
+legal_nodeoption(skew) -> true;
+legal_nodeoption(style) -> true;
+legal_nodeoption(toplabel) -> true;
+legal_nodeoption('URL') -> true;
+legal_nodeoption(z) -> true;
+legal_nodeoption(Option) when is_atom(Option) -> false.
+
+legal_edgeoption(Option) when is_atom(Option) -> true.
diff --git a/lib/hipe/util/hipe_timing.erl b/lib/hipe/util/hipe_timing.erl
new file mode 100644
index 0000000000..191db497e2
--- /dev/null
+++ b/lib/hipe/util/hipe_timing.erl
@@ -0,0 +1,131 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%====================================================================
+%% Note: Uses the process keys:
+%% hipe_time - Indicates what to time.
+%% hipe_timers - A stack of timers.
+%% {hipe_timer,T} - Delata times for named timers.
+%% T - Acc times for all named timers T.
+%%====================================================================
+
+-module(hipe_timing).
+-export([start/2, stop/2,
+ %% start_timer/0, stop_timer/1,
+ %% get_hipe_timer_val/1, set_hipe_timer_val/2,
+ %% start_hipe_timer/1, stop_hipe_timer/1,
+ start_optional_timer/2, stop_optional_timer/2]).
+
+-include("../main/hipe.hrl").
+
+%%=====================================================================
+
+-spec start(string(), atom()) -> 'ok'.
+
+start(Text, Mod) when is_atom(Mod) ->
+ Timers =
+ case get(hipe_timers) of
+ undefined -> [];
+ Ts -> Ts
+ end,
+ Space = [$| || _ <- Timers],
+ Total = start_timer(),
+ put(hipe_timers, [Total|Timers]),
+ ?msg("[@~7w]" ++ Space ++ "> ~s~n", [Total,Text]).
+
+-spec stop(string(), atom()) -> 'ok'.
+
+stop(Text, Mod) when is_atom(Mod) ->
+ {Total,_Last} = erlang:statistics(runtime),
+ case get(hipe_timers) of
+ [StartTime|Timers] ->
+ Space = [$| || _ <- Timers],
+ put(hipe_timers,Timers),
+ ?msg("[@~7w]" ++ Space ++ "< ~s: ~w~n", [Total, Text, Total-StartTime]);
+ _ ->
+ put(hipe_timers, []),
+ ?msg("[@~7w]< ~s: ~w~n", [Total, Text, Total])
+ end.
+
+-spec start_optional_timer(string(), atom()) -> 'ok'.
+
+start_optional_timer(Text, Mod) ->
+ case get(hipe_time) of
+ true -> start(Text, Mod);
+ all -> start(Text, Mod);
+ Mod -> start(Text, Mod);
+ List when is_list(List) ->
+ case lists:member(Mod, List) of
+ true -> start(Text, Mod);
+ false -> ok
+ end;
+ _ -> ok
+ end.
+
+-spec stop_optional_timer(string(), atom()) -> 'ok'.
+
+stop_optional_timer(Text, Mod) ->
+ case get(hipe_time) of
+ true -> stop(Text, Mod);
+ all -> stop(Text, Mod);
+ Mod -> stop(Text, Mod);
+ List when is_list(List) ->
+ case lists:member(Mod, List) of
+ true -> stop(Text, Mod);
+ false -> ok
+ end;
+ _ -> ok
+ end.
+
+-spec start_timer() -> non_neg_integer().
+
+start_timer() ->
+ {Total, _Last} = erlang:statistics(runtime),
+ Total.
+
+%% stop_timer(T) ->
+%% {Total, _Last} = erlang:statistics(runtime),
+%% Total - T.
+%%
+%% start_hipe_timer(Timer) ->
+%% Time = erlang:statistics(runtime),
+%% put({hipe_timer,Timer}, Time).
+%%
+%% stop_hipe_timer(Timer) ->
+%% {T2, _} = erlang:statistics(runtime),
+%% T1 =
+%% case get({hipe_timer,Timer}) of
+%% {T0, _} -> T0;
+%% _ -> 0
+%% end,
+%% AccT =
+%% case get(Timer) of
+%% T when is_integer(T) -> T;
+%% _ -> 0
+%% end,
+%% put(Timer,AccT+T2-T1).
+%%
+%% get_hipe_timer_val(Timer) ->
+%% case get(Timer) of
+%% T when is_integer(T) -> T;
+%% _ -> 0
+%% end.
+%%
+%% set_hipe_timer_val(Timer, Val) ->
+%% put(Timer, Val).
diff --git a/lib/hipe/util/hipe_vectors.erl b/lib/hipe/util/hipe_vectors.erl
new file mode 100644
index 0000000000..d153f3a50d
--- /dev/null
+++ b/lib/hipe/util/hipe_vectors.erl
@@ -0,0 +1,111 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% VECTORS IN ERLANG
+%%
+%% Abstract interface to vectors, indexed from 0 to size-1.
+
+-module(hipe_vectors).
+-export([new/2,
+ set/3,
+ get/2,
+ size/1,
+ vector_to_list/1,
+ %% list_to_vector/1,
+ list/1]).
+
+-include("hipe_vectors.hrl").
+
+%% ---------------------------------------------------------------------
+
+-ifdef(USE_TUPLES).
+
+new(N, V) ->
+ erlang:make_tuple(N, V).
+
+size(V) -> erlang:tuple_size(V).
+
+list(Vec) ->
+ index(tuple_to_list(Vec), 0).
+
+index([X|Xs],N) ->
+ [{N,X} | index(Xs,N+1)];
+index([],_) ->
+ [].
+
+%% list_to_vector(Xs) ->
+%% list_to_tuple(Xs).
+
+vector_to_list(V) ->
+ tuple_to_list(V).
+
+set(Vec, Ix, V) ->
+ setelement(Ix+1, Vec, V).
+
+get(Vec, Ix) -> element(Ix+1, Vec).
+
+-endif. %% ifdef USE_TUPLES
+
+%% ---------------------------------------------------------------------
+
+-ifdef(USE_GBTREES).
+
+-spec new(non_neg_integer(), _) -> hipe_vector().
+new(N, V) when is_integer(N), N >= 0 ->
+ gb_trees:from_orddict(mklist(N, V)).
+
+mklist(N, V) ->
+ mklist(0, N, V).
+
+mklist(M, N, V) when M < N ->
+ [{M, V} | mklist(M+1, N, V)];
+mklist(_, _, _) ->
+ [].
+
+-spec size(hipe_vector()) -> non_neg_integer().
+size(V) -> gb_trees:size(V).
+
+-spec list(hipe_vector()) -> [{_, _}].
+list(Vec) ->
+ gb_trees:to_list(Vec).
+
+%% -spec list_to_vector([_]) -> hipe_vector().
+%% list_to_vector(Xs) ->
+%% gb_trees:from_orddict(index(Xs, 0)).
+%%
+%% index([X|Xs], N) ->
+%% [{N, X} | index(Xs, N+1)];
+%% index([],_) ->
+%% [].
+
+-spec vector_to_list(hipe_vector()) -> [_].
+vector_to_list(V) ->
+ gb_trees:values(V).
+
+-spec set(hipe_vector(), non_neg_integer(), _) -> hipe_vector().
+set(Vec, Ix, V) ->
+ gb_trees:update(Ix, V, Vec).
+
+-spec get(hipe_vector(), non_neg_integer()) -> any().
+get(Vec, Ix) ->
+ gb_trees:get(Ix, Vec).
+
+-endif. %% ifdef USE_GBTREES
diff --git a/lib/hipe/util/hipe_vectors.hrl b/lib/hipe/util/hipe_vectors.hrl
new file mode 100644
index 0000000000..043faf4c91
--- /dev/null
+++ b/lib/hipe/util/hipe_vectors.hrl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%-define(USE_TUPLES, true).
+-define(USE_GBTREES, true).
+
+-ifdef(USE_TUPLES).
+-type hipe_vector() :: tuple().
+-endif.
+
+-ifdef(USE_GBTREES).
+-type hipe_vector() :: gb_tree().
+-endif.