Translate call instruction and construct call graph.

master
Rohan Jacob-Rao 10 years ago
parent 9ebb365bef
commit 37a4709a0f

@ -53,6 +53,7 @@ type instruction =
| Load of variable * typ * variable
| Store of operand * typ * variable
| Alloc of variable * typ * int (* return variable, element type, number of elements *)
| Call of variable * variable * (typ * operand) list (* return variable, function pointer, arguments *)
| Binop
type annotation = Annotation of int

@ -261,6 +261,9 @@ real_instruction:
| var = variable EQUALS LOAD tp = ptr_typ ptr = variable align? { Load (var, tp, ptr) }
| STORE val_tp = typ value = operand COMMA ptr_tp = ptr_typ var = variable align? { Store (value, val_tp, var) }
(* don't yet know why val_tp and ptr_tp would be different *)
(* Function call *)
| ret_var = variable EQUALS CALL ret_typ func_var = variable LPAREN
args = separated_list(COMMA, pair(typ, operand)) RPAREN { Call (ret_var, func_var, args) }
| variable EQUALS binop { Binop }
debug_instruction:

@ -54,6 +54,9 @@ let location_of_annotation_option (metadata : LAst.metadata_map)
"without line number as first component."))
end
let procname_of_function_variable (func_var : LAst.variable) : Procname.t =
Procname.from_string_c_fun (LAst.string_of_variable func_var)
(* Generate list of SIL instructions and list of local variables *)
let rec trans_annotated_instructions
(cfg : Cfg.cfg) (procdesc : Cfg.Procdesc.t) (metadata : LAst.metadata_map)
@ -77,7 +80,7 @@ let rec trans_annotated_instructions
| Store (op, tp, var) ->
let new_sil_instr =
Sil.Set (trans_variable var, trans_typ tp, trans_operand op, location) in
(new_sil_instr :: sil_instrs, locals)
(new_sil_instr :: sil_instrs, locals)
| Alloc (var, tp, num_elems) ->
(* num_elems currently ignored *)
begin match var with
@ -86,13 +89,30 @@ let rec trans_annotated_instructions
(sil_instrs, new_local :: locals)
| _ -> raise (ImproperTypeError "Not expecting alloca instruction to a numbered variable.")
end
| Call (ret_var, func_var, typed_args) ->
let new_sil_instr = Sil.Call ([ident_of_variable ret_var],
Sil.Const (Sil.Cfun (procname_of_function_variable func_var)),
list_map (fun (tp, arg) -> (trans_operand arg, trans_typ tp)) typed_args,
location, Sil.cf_default) in
(new_sil_instr :: sil_instrs, locals)
| _ -> raise (Unimplemented "Need to translate instruction to SIL.")
end
let callees_of_function_def : LAst.function_def -> Procname.t list = function
FunctionDef (_, _, _, annotated_instrs) ->
let callee_of_instruction : LAst.instruction -> Procname.t option = begin function
| Call (_, func_var, _) -> Some (procname_of_function_variable func_var)
| _ -> None
end in
list_flatten_options (list_map
(fun annotated_instr -> callee_of_instruction (fst annotated_instr))
annotated_instrs)
(* Update CFG and call graph with new function definition *)
let trans_function_def (cfg : Cfg.cfg) (cg: Cg.t) (metadata : LAst.metadata_map)
: LAst.function_def -> unit = function
(func_def : LAst.function_def) : unit = match func_def with
FunctionDef (func_name, ret_tp_opt, params, annotated_instrs) ->
let procname = procname_of_function_variable func_name in
let (proc_attrs : Sil.proc_attributes) =
let open Sil in
{ access = Sil.Default;
@ -109,7 +129,7 @@ let trans_function_def (cfg : Cfg.cfg) (cg: Cg.t) (metadata : LAst.metadata_map)
let (procdesc_builder : Cfg.Procdesc.proc_desc_builder) =
let open Cfg.Procdesc in
{ cfg = cfg;
name = Procname.from_string_c_fun (LAst.string_of_variable func_name);
name = procname;
is_defined = true; (** is defined and not just declared *)
proc_attributes = proc_attrs;
ret_type = (match ret_tp_opt with
@ -121,7 +141,6 @@ let trans_function_def (cfg : Cfg.cfg) (cg: Cg.t) (metadata : LAst.metadata_map)
loc = Sil.dummy_location
} in
let procdesc = Cfg.Procdesc.create procdesc_builder in
let procname = Cfg.Procdesc.get_proc_name procdesc in
let start_kind = Cfg.Node.Start_node procdesc in
let start_node = Cfg.Node.create cfg Sil.dummy_location start_kind [] procdesc [] in
let exit_kind = Cfg.Node.Exit_node procdesc in
@ -139,7 +158,8 @@ let trans_function_def (cfg : Cfg.cfg) (cg: Cg.t) (metadata : LAst.metadata_map)
Cfg.Procdesc.set_exit_node procdesc exit_node;
link_nodes start_node nodes;
Cfg.Node.add_locals_ret_declaration start_node locals;
Cg.add_node cg procname
Cg.add_node cg procname;
list_iter (Cg.add_edge cg procname) (callees_of_function_def func_def)
let trans_program : LAst.program -> Cfg.cfg * Cg.t * Sil.tenv = function
Program (func_defs, metadata) ->

@ -0,0 +1,17 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
int *always_null(void) {
return 0;
}
void foo(void) {
int *p = always_null();
*p = 42;
}

@ -0,0 +1,59 @@
; Copyright (c) 2015 - present Facebook, Inc.
; All rights reserved.
;
; This source code is licensed under the BSD style license found in the
; LICENSE file in the root directory of this source tree. An additional grant
; of patent rights can be found in the PATENTS file in the same directory.
; ModuleID = 'interproc.c'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.10.0"
; Function Attrs: nounwind ssp uwtable
define i32* @always_null() #0 {
ret i32* null, !dbg !16
}
; Function Attrs: nounwind ssp uwtable
define void @foo() #0 {
%p = alloca i32*, align 8
call void @llvm.dbg.declare(metadata !{i32** %p}, metadata !17), !dbg !18
%1 = call i32* @always_null(), !dbg !19
store i32* %1, i32** %p, align 8, !dbg !19
%2 = load i32** %p, align 8, !dbg !20
store i32 42, i32* %2, align 4, !dbg !20
ret void, !dbg !21
}
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata) #1
attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind readnone }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!13, !14}
!llvm.ident = !{!15}
!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [/Users/rohanjr/infer/infer/tests/codetoanalyze/llvm/interproc.c] [DW_LANG_C99]
!1 = metadata !{metadata !"interproc.c", metadata !"/Users/rohanjr/infer/infer/tests/codetoanalyze/llvm"}
!2 = metadata !{}
!3 = metadata !{metadata !4, metadata !10}
!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"always_null", metadata !"always_null", metadata !"", i32 10, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32* ()* @always_null, null, null, metadata !2, i32 10} ; [ DW_TAG_subprogram ] [line 10] [def] [always_null]
!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/Users/rohanjr/infer/infer/tests/codetoanalyze/llvm/interproc.c]
!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
!7 = metadata !{metadata !8}
!8 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int]
!9 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
!10 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 14, metadata !11, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @foo, null, null, metadata !2, i32 14} ; [ DW_TAG_subprogram ] [line 14] [def] [foo]
!11 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !12, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
!12 = metadata !{null}
!13 = metadata !{i32 2, metadata !"Dwarf Version", i32 2}
!14 = metadata !{i32 2, metadata !"Debug Info Version", i32 602053001}
!15 = metadata !{metadata !"Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)"}
!16 = metadata !{i32 11, i32 4, metadata !4, null} ; [ DW_TAG_lexical_block ] [/]
!17 = metadata !{i32 786688, metadata !10, metadata !"p", metadata !5, i32 15, metadata !8, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [p] [line 15]
!18 = metadata !{i32 15, i32 9, metadata !10, null}
!19 = metadata !{i32 15, i32 13, metadata !10, null}
!20 = metadata !{i32 16, i32 4, metadata !10, null}
!21 = metadata !{i32 17, i32 1, metadata !10, null}
Loading…
Cancel
Save