1%% -*- erlang-indent-level: 2 -*- 2%% 3%% Licensed under the Apache License, Version 2.0 (the "License"); 4%% you may not use this file except in compliance with the License. 5%% You may obtain a copy of the License at 6%% 7%% http://www.apache.org/licenses/LICENSE-2.0 8%% 9%% Unless required by applicable law or agreed to in writing, software 10%% distributed under the License is distributed on an "AS IS" BASIS, 11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12%% See the License for the specific language governing permissions and 13%% limitations under the License. 14 15-module(hipe_x86_cfg). 16 17-export([init/1, 18 labels/1, start_label/1, 19 succ/2, pred/2, 20 bb/2, bb_add/3, map_bbs/2, fold_bbs/3]). 21-export([postorder/1, reverse_postorder/1]). 22-export([linearise/1, params/1, arity/1, redirect_jmp/3, branch_preds/1]). 23 24%%% these tell cfg.inc what to define (ugly as hell) 25-define(PRED_NEEDED,true). 26-define(BREADTH_ORDER,true). 27-define(PARAMS_NEEDED,true). 28-define(START_LABEL_UPDATE_NEEDED,true). 29-define(MAP_FOLD_NEEDED,true). 30 31-include("hipe_x86.hrl"). 32-include("../flow/cfg.hrl"). 33-include("../flow/cfg.inc"). 34 35init(Defun) -> 36 %% XXX: this assumes that the code starts with a label insn. 37 %% Is that guaranteed? 38 Code = hipe_x86:defun_code(Defun), 39 StartLab = hipe_x86:label_label(hd(Code)), 40 Data = hipe_x86:defun_data(Defun), 41 IsClosure = hipe_x86:defun_is_closure(Defun), 42 MFA = hipe_x86:defun_mfa(Defun), 43 IsLeaf = hipe_x86:defun_is_leaf(Defun), 44 Formals = hipe_x86:defun_formals(Defun), 45 CFG0 = mk_empty_cfg(MFA, StartLab, Data, IsClosure, IsLeaf, Formals), 46 take_bbs(Code, CFG0). 47 48is_branch(I) -> 49 case I of 50 #jmp_fun{} -> true; 51 #jmp_label{} -> true; 52 #jmp_switch{} -> true; 53 #pseudo_call{} -> true; 54 #pseudo_jcc{} -> true; 55 #pseudo_tailcall{} -> true; 56 #ret{} -> true; 57 _ -> false 58 end. 59 60branch_successors(Branch) -> 61 case Branch of 62 #jmp_fun{} -> []; 63 #jmp_label{label=Label} -> [Label]; 64 #jmp_switch{labels=Labels} -> Labels; 65 #pseudo_call{contlab=ContLab, sdesc=#x86_sdesc{exnlab=ExnLab}} -> 66 case ExnLab of 67 [] -> [ContLab]; 68 _ -> [ContLab,ExnLab] 69 end; 70 #pseudo_jcc{true_label=TrueLab,false_label=FalseLab} -> [FalseLab,TrueLab]; 71 #pseudo_tailcall{} -> []; 72 #ret{} -> [] 73 end. 74 75branch_preds(Branch) -> 76 case Branch of 77 #jmp_switch{labels=Labels} -> 78 Prob = 1.0/length(Labels), 79 [{L, Prob} || L <- Labels]; 80 #pseudo_call{contlab=ContLab, sdesc=#x86_sdesc{exnlab=[]}} -> 81 %% A function can still cause an exception, even if we won't catch it 82 [{ContLab, 1.0-hipe_bb_weights:call_exn_pred()}]; 83 #pseudo_call{contlab=ContLab, sdesc=#x86_sdesc{exnlab=ExnLab}} -> 84 CallExnPred = hipe_bb_weights:call_exn_pred(), 85 [{ContLab, 1.0-CallExnPred}, {ExnLab, CallExnPred}]; 86 #pseudo_jcc{true_label=TrueLab,false_label=FalseLab,pred=Pred} -> 87 [{FalseLab, 1.0-Pred}, {TrueLab, Pred}]; 88 _ -> 89 case branch_successors(Branch) of 90 [] -> []; 91 [Single] -> [{Single, 1.0}] 92 end 93 end. 94 95-ifdef(REMOVE_TRIVIAL_BBS_NEEDED). 96fails_to(_Instr) -> []. 97-endif. 98 99redirect_jmp(I, Old, New) -> 100 case I of 101 #jmp_label{label=Label} -> 102 if Old =:= Label -> I#jmp_label{label=New}; 103 true -> I 104 end; 105 #pseudo_jcc{true_label=TrueLab, false_label=FalseLab} -> 106 J0 = if Old =:= TrueLab -> I#pseudo_jcc{true_label=New}; 107 true -> I 108 end, 109 if Old =:= FalseLab -> J0#pseudo_jcc{false_label=New}; 110 true -> J0 111 end; 112 %% handle pseudo_call too? 113 _ -> I 114 end. 115 116%%% XXX: fix if labels can occur in operands 117%% redirect_ops(_Labels, CFG, _Map) -> 118%% CFG. 119 120mk_goto(Label) -> 121 hipe_x86:mk_jmp_label(Label). 122 123is_label(I) -> 124 case I of #label{} -> true; _ -> false end. 125 126label_name(Label) -> 127 hipe_x86:label_label(Label). 128 129mk_label(Name) -> 130 hipe_x86:mk_label(Name). 131 132%% is_comment(I) -> 133%% hipe_x86:is_comment(I). 134%% 135%% is_goto(I) -> 136%% hipe_x86:is_jmp_label(I). 137 138linearise(CFG) -> % -> defun, not insn list 139 MFA = function(CFG), 140 Formals = params(CFG), 141 Code = linearize_cfg(CFG), 142 Data = data(CFG), 143 VarRange = hipe_gensym:var_range(x86), 144 LabelRange = hipe_gensym:label_range(x86), 145 IsClosure = is_closure(CFG), 146 IsLeaf = is_leaf(CFG), 147 hipe_x86:mk_defun(MFA, Formals, IsClosure, IsLeaf, 148 Code, Data, VarRange, LabelRange). 149 150arity(CFG) -> 151 {_M,_F,A} = function(CFG), 152 A. 153 154%% init_gensym(CFG) -> 155%% HighestVar = find_highest_var(CFG), 156%% HighestLabel = find_highest_label(CFG), 157%% hipe_gensym:init(), 158%% hipe_gensym:set_var(x86, HighestVar), 159%% hipe_gensym:set_label(x86, HighestLabel). 160%% 161%% highest_var(Code) -> 162%% hipe_x86:highest_temp(Code). 163