diff options
author | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2010-03-03 10:25:25 +0000 |
---|---|---|
committer | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2010-03-03 10:25:25 +0000 |
commit | 93d89c2b5e8497365be152fb53cb6cd4c5764d34 (patch) | |
tree | 0de8d05bbd0eeaeb5e4b85395f8dd576984b6a9e /cil/src/ext/reachingdefs.ml | |
parent | 891377ce1962cdb31357d6580d6546ec22df2b4f (diff) | |
download | compcert-93d89c2b5e8497365be152fb53cb6cd4c5764d34.tar.gz compcert-93d89c2b5e8497365be152fb53cb6cd4c5764d34.zip |
Getting rid of CIL
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@1270 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'cil/src/ext/reachingdefs.ml')
-rw-r--r-- | cil/src/ext/reachingdefs.ml | 511 |
1 files changed, 0 insertions, 511 deletions
diff --git a/cil/src/ext/reachingdefs.ml b/cil/src/ext/reachingdefs.ml deleted file mode 100644 index b6af37cb..00000000 --- a/cil/src/ext/reachingdefs.ml +++ /dev/null @@ -1,511 +0,0 @@ -(* Calculate reaching definitions for each instruction. - * Determine when it is okay to replace some variables with - * expressions. - * - * After calling computeRDs on a fundec, - * ReachingDef.stmtStartData will contain a mapping from - * statement ids to data about which definitions reach each - * statement. ReachingDef.defIdStmtHash will contain a - * mapping from definition ids to the statement in which - * that definition takes place. - * - * instrRDs takes a list of instructions, and the - * definitions that reach the first instruction, and - * for each instruction figures out which definitions - * reach into or out of each instruction. - * - *) - -open Cil -open Pretty - -module E = Errormsg -module DF = Dataflow -module UD = Usedef -module IH = Inthash -module U = Util -module S = Stats - -let debug_fn = ref "" - -module IOS = - Set.Make(struct - type t = int option - let compare io1 io2 = - match io1, io2 with - Some i1, Some i2 -> Pervasives.compare i1 i2 - | Some i1, None -> 1 - | None, Some i2 -> -1 - | None, None -> 0 - end) - -let debug = ref false - -(* return the intersection of - Inthashes ih1 and ih2 *) -let ih_inter ih1 ih2 = - let ih' = IH.copy ih1 in - IH.iter (fun id vi -> - if not(IH.mem ih2 id) then - IH.remove ih' id else - ()) ih1; - ih' - -let ih_union ih1 ih2 = - let ih' = IH.copy ih1 in - IH.iter (fun id vi -> - if not(IH.mem ih' id) - then IH.add ih' id vi - else ()) ih2; - ih' - -(* Lookup varinfo in iosh. If the set contains None - or is not a singleton, return None, otherwise - return Some of the singleton *) -(* IOS.t IH.t -> varinfo -> int option *) -let iosh_singleton_lookup iosh vi = - if IH.mem iosh vi.vid then - let ios = IH.find iosh vi.vid in - if not (IOS.cardinal ios = 1) then None - else IOS.choose ios - else None - -(* IOS.t IH.t -> varinfo -> IOS.t *) -let iosh_lookup iosh vi = - if IH.mem iosh vi.vid - then Some(IH.find iosh vi.vid) - else None - -(* return Some(vid) if iosh contains defId. - return None otherwise *) -(* IOS.t IH.t -> int -> int option *) -let iosh_defId_find iosh defId = - (* int -> IOS.t -> int option -> int option*) - let get_vid vid ios io = - match io with - Some(i) -> Some(i) - | None -> - let there = IOS.exists - (function None -> false - | Some(i') -> defId = i') ios in - if there then Some(vid) else None - in - IH.fold get_vid iosh None - -(* The resulting iosh will contain the - union of the same entries from iosh1 and - iosh2. If iosh1 has an entry that iosh2 - does not, then the result will contain - None in addition to the things from the - entry in iosh1. *) -(* XXX this function is a performance bottleneck *) -let iosh_combine iosh1 iosh2 = - let iosh' = IH.copy iosh1 in - IH.iter (fun id ios1 -> - try let ios2 = IH.find iosh2 id in - let newset = IOS.union ios1 ios2 in - IH.replace iosh' id newset; - with Not_found -> - let newset = IOS.add None ios1 in - IH.replace iosh' id newset) iosh1; - IH.iter (fun id ios2 -> - if not(IH.mem iosh1 id) then - let newset = IOS.add None ios2 in - IH.add iosh' id newset) iosh2; - iosh' - - -(* determine if two IOS.t IH.t s are the same *) -let iosh_equals iosh1 iosh2 = -(* if IH.length iosh1 = 0 && not(IH.length iosh2 = 0) || - IH.length iosh2 = 0 && not(IH.length iosh1 = 0)*) - if not(IH.length iosh1 = IH.length iosh2) - then - (if !debug then ignore(E.log "iosh_equals: length not same\n"); - false) - else - IH.fold (fun vid ios b -> - if not b then b else - try let ios2 = IH.find iosh2 vid in - if not(IOS.compare ios ios2 = 0) then - (if !debug then ignore(E.log "iosh_equals: sets for vid %d not equal\n" vid); - false) - else true - with Not_found -> - (if !debug then ignore(E.log "iosh_equals: vid %d not in iosh2\n" vid); - false)) iosh1 true - -(* replace an entire set with a singleton. - if nothing was there just add the singleton *) -(* IOS.t IH.t -> int -> varinfo -> unit *) -let iosh_replace iosh i vi = - if IH.mem iosh vi.vid then - let newset = IOS.singleton (Some i) in - IH.replace iosh vi.vid newset - else - let newset = IOS.singleton (Some i) in - IH.add iosh vi.vid newset - -(* remove definitions that are killed. - add definitions that are gend *) -(* Takes the defs, the data, and a function for - obtaining the next def id *) -(* VS.t -> IOS.t IH.t -> (unit->int) -> unit *) -let proc_defs vs iosh f = - let pd vi = - let newi = f() in - (*if !debug then - ignore (E.log "proc_defs: genning %d\n" newi);*) - iosh_replace iosh newi vi - in - UD.VS.iter pd vs - -let idMaker () start = - let counter = ref start in - fun () -> - let ret = !counter in - counter := !counter + 1; - ret - -(* given reaching definitions into a list of - instructions, figure out the definitions that - reach in/out of each instruction *) -(* if out is true then calculate the definitions that - go out of each instruction, if it is false then - calculate the definitions reaching into each instruction *) -(* instr list -> int -> (varinfo IH.t * int) -> bool -> (varinfo IH.t * int) list *) -let iRDsHtbl = Hashtbl.create 128 -let instrRDs il sid (ivih, s, iosh) out = - if Hashtbl.mem iRDsHtbl (sid,out) then Hashtbl.find iRDsHtbl (sid,out) else - -(* let print_instr i (_,s', iosh') = *) -(* let d = d_instr () i ++ line in *) -(* fprint stdout 80 d; *) -(* flush stdout *) -(* in *) - - let proc_one hil i = - match hil with - | [] -> - let _, defd = UD.computeUseDefInstr i in - if UD.VS.is_empty defd - then ((*if !debug then print_instr i ((), s, iosh);*) - [((), s, iosh)]) - else - let iosh' = IH.copy iosh in - proc_defs defd iosh' (idMaker () s); - (*if !debug then - print_instr i ((), s + UD.VS.cardinal defd, iosh');*) - ((), s + UD.VS.cardinal defd, iosh')::hil - | (_, s', iosh')::hrst as l -> - let _, defd = UD.computeUseDefInstr i in - if UD.VS.is_empty defd - then - ((*if !debug then - print_instr i ((),s', iosh');*) - ((), s', iosh')::l) - else let iosh'' = IH.copy iosh' in - proc_defs defd iosh'' (idMaker () s'); - (*if !debug then - print_instr i ((), s' + UD.VS.cardinal defd, iosh'');*) - ((),s' + UD.VS.cardinal defd, iosh'')::l - in - let folded = List.fold_left proc_one [((),s,iosh)] il in - let foldedout = List.tl (List.rev folded) in - let foldednotout = List.rev (List.tl folded) in - Hashtbl.add iRDsHtbl (sid,true) foldedout; - Hashtbl.add iRDsHtbl (sid,false) foldednotout; - if out then foldedout else foldednotout - - - -(* The right hand side of an assignment is either - a function call or an expression *) -type rhs = RDExp of exp | RDCall of instr - -(* take the id number of a definition and return - the rhs of the definition if there is one. - Returns None if, for example, the definition is - caused by an assembly instruction *) -(* stmt IH.t -> (()*int*IOS.t IH.t) IH.t -> int -> (rhs * int * IOS.t IH.t) option *) -let rhsHtbl = IH.create 64 (* to avoid recomputation *) -let getDefRhs didstmh stmdat defId = - if IH.mem rhsHtbl defId then IH.find rhsHtbl defId else - let stm = - try IH.find didstmh defId - with Not_found -> E.s (E.error "getDefRhs: defId %d not found\n" defId) in - let (_,s,iosh) = - try IH.find stmdat stm.sid - with Not_found -> E.s (E.error "getDefRhs: sid %d not found \n" stm.sid) in - match stm.skind with - Instr il -> - let ivihl = instrRDs il stm.sid ((),s,iosh) true in (* defs that reach out of each instr *) - let ivihl_in = instrRDs il stm.sid ((),s,iosh) false in (* defs that reach into each instr *) - let iihl = List.combine (List.combine il ivihl) ivihl_in in - (try let ((i,(_,_,diosh)),(_,_,iosh_in)) = List.find (fun ((i,(_,_,iosh')),_) -> - match S.time "iosh_defId_find" (iosh_defId_find iosh') defId with - Some vid -> - (match i with - Set((Var vi',NoOffset),_,_) -> vi'.vid = vid (* _ -> NoOffset *) - | Call(Some(Var vi',NoOffset),_,_,_) -> vi'.vid = vid (* _ -> NoOffset *) - | Call(None,_,_,_) -> false - | Asm(_,_,sll,_,_,_) -> List.exists - (function (_,(Var vi',NoOffset)) -> vi'.vid = vid | _ -> false) sll - | _ -> false) - | None -> false) iihl in - (match i with - Set((lh,_),e,_) -> - (match lh with - Var(vi') -> - (IH.add rhsHtbl defId (Some(RDExp(e),stm.sid,iosh_in)); - Some(RDExp(e), stm.sid, iosh_in)) - | _ -> E.s (E.error "Reaching Defs getDefRhs: right vi not first\n")) - | Call(lvo,e,el,_) -> - (IH.add rhsHtbl defId (Some(RDCall(i),stm.sid,iosh_in)); - Some(RDCall(i), stm.sid, iosh_in)) - | Asm(a,sl,slvl,sel,sl',_) -> None) (* ? *) - with Not_found -> - (if !debug then ignore (E.log "getDefRhs: No instruction defines %d\n" defId); - IH.add rhsHtbl defId None; - None)) - | _ -> E.s (E.error "getDefRhs: defining statement not an instruction list %d\n" defId) - (*None*) - -let prettyprint didstmh stmdat () (_,s,iosh) = text "" - (*seq line (fun (vid,ios) -> - num vid ++ text ": " ++ - IOS.fold (fun io d -> match io with - None -> d ++ text "None " - | Some i -> - let stm = IH.find didstmh i in - match getDefRhs didstmh stmdat i with - None -> d ++ num i - | Some(RDExp(e),_,_) -> - d ++ num i ++ text " " ++ (d_exp () e) - | Some(RDCall(c),_,_) -> - d ++ num i ++ text " " ++ (d_instr () c)) - ios nil) - (IH.tolist iosh)*) - -module ReachingDef = - struct - - let name = "Reaching Definitions" - - let debug = debug - - (* Should the analysis calculate may-reach - or must-reach *) - let mayReach = ref false - - - (* An integer that tells the id number of - the first definition *) - (* Also a hash from variable ids to a set of - definition ids that reach this statement. - None means there is a path to this point on which - there is no definition of the variable *) - type t = (unit * int * IOS.t IH.t) - - let copy (_, i, iosh) = ((), i, IH.copy iosh) - - (* entries for starting statements must - be added before calling compute *) - let stmtStartData = IH.create 32 - - (* a mapping from definition ids to - the statement corresponding to that id *) - let defIdStmtHash = IH.create 32 - - (* mapping from statement ids to statements - for better performance of ok_to_replace *) - let sidStmtHash = IH.create 64 - - (* pretty printer *) - let pretty = prettyprint defIdStmtHash stmtStartData - - - (* The first id to use when computeFirstPredecessor - is next called *) - let nextDefId = ref 0 - - (* Count the number of variable definitions in - a statement *) - let num_defs stm = - match stm.skind with - Instr(il) -> List.fold_left (fun s i -> - let _, d = UD.computeUseDefInstr i in - s + UD.VS.cardinal d) 0 il - | _ -> let _, d = UD.computeUseDefStmtKind stm.skind in - UD.VS.cardinal d - - (* the first predecessor is just the data in along with - the id of the first definition of the statement, - which we get from nextDefId *) - let computeFirstPredecessor stm (_, s, iosh) = - let startDefId = max !nextDefId s in - let numds = num_defs stm in - let rec loop n = - if n < 0 - then () - else - (if !debug then - ignore (E.log "RD: defId %d -> stm %d\n" (startDefId + n) stm.sid); - IH.add defIdStmtHash (startDefId + n) stm; - loop (n-1)) - in - loop (numds - 1); - nextDefId := startDefId + numds; - ((), startDefId, IH.copy iosh) - - - let combinePredecessors (stm:stmt) ~(old:t) ((_, s, iosh):t) = - match old with (_, os, oiosh) -> - if S.time "iosh_equals" (iosh_equals oiosh) iosh then None else - Some((), os, S.time "iosh_combine" (iosh_combine oiosh) iosh) - - (* return an action that removes things that - are redefinied and adds the generated defs *) - let doInstr inst (_, s, iosh) = - let transform (_, s', iosh') = - let _, defd = UD.computeUseDefInstr inst in - proc_defs defd iosh' (idMaker () s'); - ((), s' + UD.VS.cardinal defd, iosh') - in - DF.Post transform - - (* all the work gets done at the instruction level *) - let doStmt stm (_, s, iosh) = - if not(IH.mem sidStmtHash stm.sid) then - IH.add sidStmtHash stm.sid stm; - if !debug then ignore(E.log "RD: looking at %a\n" d_stmt stm); - DF.SDefault - - let doGuard condition _ = DF.GDefault - - let filterStmt stm = true - -end - -module RD = DF.ForwardsDataFlow(ReachingDef) - -(* map all variables in vil to a set containing - None in iosh *) -(* IOS.t IH.t -> varinfo list -> () *) -let iosh_none_fill iosh vil = - List.iter (fun vi -> - IH.add iosh vi.vid (IOS.singleton None)) - vil - -(* Computes the reaching definitions for a - function. *) -(* Cil.fundec -> unit *) -let computeRDs fdec = - try - if compare fdec.svar.vname (!debug_fn) = 0 then - (debug := true; - ignore (E.log "%s =\n%a\n" (!debug_fn) d_block fdec.sbody)); - let bdy = fdec.sbody in - let slst = bdy.bstmts in - let _ = IH.clear ReachingDef.stmtStartData in - let _ = IH.clear ReachingDef.defIdStmtHash in - let _ = IH.clear rhsHtbl in - let _ = Hashtbl.clear iRDsHtbl in - let _ = ReachingDef.nextDefId := 0 in - let fst_stm = List.hd slst in - let fst_iosh = IH.create 32 in - let _ = UD.onlyNoOffsetsAreDefs := false in - (*let _ = iosh_none_fill fst_iosh fdec.sformals in*) - let _ = IH.add ReachingDef.stmtStartData fst_stm.sid ((), 0, fst_iosh) in - let _ = ReachingDef.computeFirstPredecessor fst_stm ((), 0, fst_iosh) in - if !debug then - ignore (E.log "computeRDs: fst_stm.sid=%d\n" fst_stm.sid); - RD.compute [fst_stm]; - if compare fdec.svar.vname (!debug_fn) = 0 then - debug := false - (* now ReachingDef.stmtStartData has the reaching def data in it *) - with Failure "hd" -> if compare fdec.svar.vname (!debug_fn) = 0 then - debug := false - -(* return the definitions that reach the statement - with statement id sid *) -let getRDs sid = - try - Some (IH.find ReachingDef.stmtStartData sid) - with Not_found -> - None -(* E.s (E.error "getRDs: sid %d not found\n" sid) *) - -let getDefIdStmt defid = - try - Some(IH.find ReachingDef.defIdStmtHash defid) - with Not_found -> - None - -let getStmt sid = - try Some(IH.find ReachingDef.sidStmtHash sid) - with Not_found -> None - -(* Pretty print the reaching definition data for - a function *) -let ppFdec fdec = - seq line (fun stm -> - let ivih = IH.find ReachingDef.stmtStartData stm.sid in - ReachingDef.pretty () ivih) fdec.sbody.bstmts - - -(* If this class is extended with a visitor on expressions, - then the current rd data is available at each expression *) -class rdVisitorClass = object (self) - inherit nopCilVisitor - - (* the statement being worked on *) - val mutable sid = -1 - - (* if a list of instructions is being processed, - then this is the corresponding list of - reaching definitions *) - val mutable rd_dat_lst = [] - - (* these are the reaching defs for the current - instruction if there is one *) - val mutable cur_rd_dat = None - - method vstmt stm = - sid <- stm.sid; - match getRDs sid with - None -> - if !debug then ignore(E.log "rdVis: stm %d had no data\n" sid); - cur_rd_dat <- None; - DoChildren - | Some(_,s,iosh) -> - match stm.skind with - Instr il -> - if !debug then ignore(E.log "rdVis: visit il\n"); - rd_dat_lst <- instrRDs il stm.sid ((),s,iosh) false; - DoChildren - | _ -> - if !debug then ignore(E.log "rdVis: visit non-il\n"); - cur_rd_dat <- None; - DoChildren - - method vinst i = - if !debug then ignore(E.log "rdVis: before %a, rd_dat_lst is %d long\n" - d_instr i (List.length rd_dat_lst)); - try - cur_rd_dat <- Some(List.hd rd_dat_lst); - rd_dat_lst <- List.tl rd_dat_lst; - DoChildren - with Failure "hd" -> - if !debug then ignore(E.log "rdVis: il rd_dat_lst mismatch\n"); - DoChildren - - method get_cur_iosh () = - match cur_rd_dat with - None -> (match getRDs sid with - None -> None - | Some(_,_,iosh) -> Some iosh) - | Some(_,_,iosh) -> Some iosh - -end - |