-(* RUN: rm -rf %t.builddir
- * RUN: mkdir -p %t.builddir
- * RUN: cp %s %t.builddir
- * RUN: %ocamlopt -warn-error A llvm.cmxa llvm_analysis.cmxa llvm_bitwriter.cmxa %t.builddir/vmcore.ml -o %t
+(* RUN: cp %s %T/vmcore.ml
+ * RUN: %ocamlcomp -g -warn-error A -package llvm.analysis -package llvm.bitwriter -linkpkg %T/vmcore.ml -o %t
* RUN: %t %t.bc
* RUN: llvm-dis < %t.bc > %t.ll
* RUN: FileCheck %s < %t.ll
set_target_triple trip m;
insist (trip = target_triple m)
end;
-
+
begin group "layout";
let layout = "e" in
set_data_layout layout m;
ignore (define_global "const_int" c m);
insist (i32_type = type_of c);
insist (is_constant c);
+ insist (Some (-1L) = int64_of_const c);
(* CHECK: const_sext_int{{.*}}i64{{.*}}-1
*)
let c = const_int i64_type (-1) in
ignore (define_global "const_sext_int" c m);
insist (i64_type = type_of c);
+ insist (Some (-1L) = int64_of_const c);
(* CHECK: const_zext_int64{{.*}}i64{{.*}}4294967295
*)
let c = const_of_int64 i64_type (Int64.of_string "4294967295") false in
ignore (define_global "const_zext_int64" c m);
insist (i64_type = type_of c);
+ insist (Some 4294967295L = int64_of_const c);
(* CHECK: const_int_string{{.*}}i32{{.*}}-1
*)
ignore (define_global "const_int_string" c m);
insist (i32_type = type_of c);
insist (None = (string_of_const c));
+ insist (None = float_of_const c);
+ insist (Some (-1L) = int64_of_const c);
+
+ (* CHECK: const_int64{{.*}}i64{{.*}}9223372036854775807
+ *)
+ group "max int64";
+ let c = const_of_int64 i64_type 9223372036854775807L true in
+ ignore (define_global "const_int64" c m) ;
+ insist (i64_type = type_of c);
+ insist (Some 9223372036854775807L = int64_of_const c);
if Sys.word_size = 64; then begin
group "long int";
(* CHECK: const_single{{.*}}2.75
* CHECK: const_double{{.*}}3.1459
- * CHECK: const_double_string{{.*}}1.25
+ * CHECK: const_double_string{{.*}}2
+ * CHECK: const_fake_fp128{{.*}}0xL00000000000000004000000000000000
+ * CHECK: const_fp128_string{{.*}}0xLF3CB1CCF26FBC178452FB4EC7F91973F
*)
begin group "real";
let cs = const_float float_type 2.75 in
ignore (define_global "const_single" cs m);
insist (float_type = type_of cs);
-
+ insist (float_of_const cs = Some 2.75);
+
let cd = const_float double_type 3.1459 in
ignore (define_global "const_double" cd m);
insist (double_type = type_of cd);
+ insist (float_of_const cd = Some 3.1459);
- let cd = const_float_of_string double_type "1.25" in
+ let cd = const_float_of_string double_type "2" in
ignore (define_global "const_double_string" cd m);
- insist (double_type = type_of cd)
+ insist (double_type = type_of cd);
+ insist (float_of_const cd = Some 2.);
+
+ let cd = const_float fp128_type 2. in
+ ignore (define_global "const_fake_fp128" cd m);
+ insist (fp128_type = type_of cd);
+ insist (float_of_const cd = Some 2.);
+
+ let cd = const_float_of_string fp128_type "1e400" in
+ ignore (define_global "const_fp128_string" cd m);
+ insist (fp128_type = type_of cd);
+ insist (float_of_const cd = None);
end;
-
+
let one = const_int i16_type 1 in
let two = const_int i16_type 2 in
let three = const_int i32_type 3 in
let four = const_int i32_type 4 in
-
+
(* CHECK: const_array{{.*}}[i32 3, i32 4]
*)
group "array";
let c = const_null (packed_struct_type context [| i1_type; i8_type; i64_type;
double_type |]) in
ignore (define_global "const_null" c m);
-
+
(* CHECK: const_all_ones{{.*}}-1
*)
group "all ones";
let c = const_pointer_null (pointer_type i64_type) in
ignore (define_global "const_pointer_null" c m);
end;
-
+
(* CHECK: const_undef{{.*}}undef
*)
group "undef";
ignore (define_global "const_undef" c m);
insist (i1_type = type_of c);
insist (is_undef c);
-
+
group "constant arithmetic";
(* CHECK: @const_neg = global i64 sub
* CHECK: @const_nsw_neg = global i64 sub nsw
ignore (define_global "const_xor" (const_xor foldbomb five) m);
ignore (define_global "const_icmp" (const_icmp Icmp.Sle foldbomb five) m);
ignore (define_global "const_fcmp" (const_fcmp Fcmp.Ole ffoldbomb ffive) m);
-
+
group "constant casts";
(* CHECK: const_trunc{{.*}}trunc
* CHECK: const_sext{{.*}}sext
ignore (define_global "const_sitofp" (const_sitofp foldbomb double_type) m);
ignore (define_global "const_fptoui" (const_fptoui ffoldbomb i32_type) m);
ignore (define_global "const_fptosi" (const_fptosi ffoldbomb i32_type) m);
- ignore (define_global "const_ptrtoint" (const_ptrtoint
+ ignore (define_global "const_ptrtoint" (const_ptrtoint
(const_gep (const_null (pointer_type i8_type))
[| const_int i32_type 1 |])
i32_type) m);
ignore (define_global "const_bitcast" (const_bitcast ffoldbomb i64_type) m);
ignore (define_global "const_intcast"
(const_intcast foldbomb i128_type ~is_signed:false) m);
-
+
group "misc constants";
(* CHECK: const_size_of{{.*}}getelementptr{{.*}}null
* CHECK: const_gep{{.*}}getelementptr
let g = define_global "GVal03" zero32 m ++
set_section "Hanalei" in
insist ("Hanalei" = section g);
-
+
(* CHECK: GVal04{{.*}}hidden
*)
group "visibility";
let g = define_global "GVal04" zero32 m ++
set_visibility Visibility.Hidden in
insist (Visibility.Hidden = visibility g);
-
+
(* CHECK: GVal05{{.*}}align 128
*)
group "alignment";
let g = define_global "GVal05" zero32 m ++
set_alignment 128 in
- insist (128 = alignment g)
+ insist (128 = alignment g);
+
+ (* CHECK: GVal06{{.*}}dllexport
+ *)
+ group "dll_storage_class";
+ let g = define_global "GVal06" zero32 m ++
+ set_dll_storage_class DLLStorageClass.DLLExport in
+ insist (DLLStorageClass.DLLExport = dll_storage_class g)
(*===-- Global Variables --------------------------------------------------===*)
insist (match lookup_global "QGVar01" m with Some x -> x = g
| None -> false);
end;
-
+
group "definitions"; begin
(* CHECK: @GVar02 = global i32 42
* CHECK: @GVar03 = global i32 42
insist (not (is_global_constant g));
set_global_constant true g;
insist (is_global_constant g);
-
+
begin group "iteration";
let m = create_module context "temp" in
-
+
insist (At_end m = global_begin m);
insist (At_start m = global_end m);
-
+
let g1 = declare_global i32_type "One" m in
let g2 = declare_global i32_type "Two" m in
-
+
insist (Before g1 = global_begin m);
insist (Before g2 = global_succ g1);
insist (At_end m = global_succ g2);
-
+
insist (After g2 = global_end m);
insist (After g1 = global_pred g2);
insist (At_start m = global_pred g1);
-
+
let lf s x = s ^ "->" ^ value_name x in
insist ("->One->Two" = fold_left_globals lf "" m);
-
+
let rf x s = value_name x ^ "<-" ^ s in
insist ("One<-Two<-" = fold_right_globals rf m "");
-
+
dispose_module m
end
let test_functions () =
let ty = function_type i32_type [| i32_type; i64_type |] in
let ty2 = function_type i8_type [| i8_type; i64_type |] in
-
+
(* CHECK: declare i32 @Fn1(i32, i64)
*)
begin group "declare";
| None -> false);
insist (m == global_parent fn)
end;
-
+
(* CHECK-NOWHERE-NOT: Fn2
*)
group "delete";
let fn = declare_function "Fn2" ty m in
delete_function fn;
-
+
(* CHECK: define{{.*}}Fn3
*)
group "define";
insist (not (is_declaration fn));
insist (1 = Array.length (basic_blocks fn));
ignore (build_unreachable (builder_at_end context (entry_block fn)));
-
+
(* CHECK: define{{.*}}Fn4{{.*}}Param1{{.*}}Param2
*)
group "params";
set_value_name "Param1" params.(0);
set_value_name "Param2" params.(1);
ignore (build_unreachable (builder_at_end context (entry_block fn)));
-
+
(* CHECK: fastcc{{.*}}Fn5
*)
group "callconv";
set_function_call_conv CallConv.fast fn;
insist (CallConv.fast = function_call_conv fn);
ignore (build_unreachable (builder_at_end context (entry_block fn)));
-
+
begin group "gc";
(* CHECK: Fn6{{.*}}gc{{.*}}shadowstack
*)
set_gc (Some "shadowstack") fn;
ignore (build_unreachable (builder_at_end context (entry_block fn)));
end;
-
+
begin group "iteration";
let m = create_module context "temp" in
-
+
insist (At_end m = function_begin m);
insist (At_start m = function_end m);
-
+
let f1 = define_function "One" ty m in
let f2 = define_function "Two" ty m in
-
+
insist (Before f1 = function_begin m);
insist (Before f2 = function_succ f1);
insist (At_end m = function_succ f2);
-
+
insist (After f2 = function_end m);
insist (After f1 = function_pred f2);
insist (At_start m = function_pred f1);
-
+
let lf s x = s ^ "->" ^ value_name x in
insist ("->One->Two" = fold_left_functions lf "" m);
-
+
let rf x s = value_name x ^ "<-" ^ s in
insist ("One<-Two<-" = fold_right_functions rf m "");
-
+
dispose_module m
end
let test_params () =
begin group "iteration";
let m = create_module context "temp" in
-
+
let vf = define_function "void" (function_type void_type [| |]) m in
-
+
insist (At_end vf = param_begin vf);
insist (At_start vf = param_end vf);
-
+
let ty = function_type void_type [| i32_type; i32_type |] in
let f = define_function "f" ty m in
let p1 = param f 0 in
insist (Before p1 = param_begin f);
insist (Before p2 = param_succ p1);
insist (At_end f = param_succ p2);
-
+
insist (After p2 = param_end f);
insist (After p1 = param_pred p2);
insist (At_start f = param_pred p1);
-
+
let lf s x = s ^ "->" ^ value_name x in
insist ("->One->Two" = fold_left_params lf "" f);
-
+
let rf x s = value_name x ^ "<-" ^ s in
insist ("One<-Two<-" = fold_right_params rf f "");
-
+
dispose_module m
end
let test_basic_blocks () =
let ty = function_type void_type [| |] in
-
+
(* CHECK: Bb1
*)
group "entry";
let bb = append_block context "Bb1" fn in
insist (bb = entry_block fn);
ignore (build_unreachable (builder_at_end context bb));
-
+
(* CHECK-NOWHERE-NOT: Bb2
*)
group "delete";
let fn = declare_function "X2" ty m in
let bb = append_block context "Bb2" fn in
delete_block bb;
-
+
group "insert";
let fn = declare_function "X3" ty m in
let bbb = append_block context "b" fn in
insist ([| bba; bbb |] = basic_blocks fn);
ignore (build_unreachable (builder_at_end context bba));
ignore (build_unreachable (builder_at_end context bbb));
-
+
(* CHECK: Bb3
*)
group "name/value";
let bbv = value_of_block bb in
set_value_name "Bb3" bbv;
insist ("Bb3" = value_name bbv);
-
+
group "casts";
let fn = define_function "X5" ty m in
let bb = entry_block fn in
insist (bb = block_of_value (value_of_block bb));
insist (value_is_block (value_of_block bb));
insist (not (value_is_block (const_null i32_type)));
-
+
begin group "iteration";
let m = create_module context "temp" in
let f = declare_function "Temp" (function_type i32_type [| |]) m in
-
+
insist (At_end f = block_begin f);
insist (At_start f = block_end f);
-
+
let b1 = append_block context "One" f in
let b2 = append_block context "Two" f in
-
+
insist (Before b1 = block_begin f);
insist (Before b2 = block_succ b1);
insist (At_end f = block_succ b2);
-
+
insist (After b2 = block_end f);
insist (After b1 = block_pred b2);
insist (At_start f = block_pred b1);
-
+
let lf s x = s ^ "->" ^ value_name (value_of_block x) in
insist ("->One->Two" = fold_left_blocks lf "" f);
-
+
let rf x s = value_name (value_of_block x) ^ "<-" ^ s in
insist ("One<-Two<-" = fold_right_blocks rf f "");
-
+
dispose_module m
end
let f = define_function "f" fty m in
let bb = entry_block f in
let b = builder_at context (At_end bb) in
-
+
insist (At_end bb = instr_begin bb);
insist (At_start bb = instr_end bb);
-
+
let i1 = build_add (param f 0) (param f 1) "One" b in
let i2 = build_sub (param f 0) (param f 1) "Two" b in
-
+
insist (Before i1 = instr_begin bb);
insist (Before i2 = instr_succ i1);
insist (At_end bb = instr_succ i2);
-
+
insist (After i2 = instr_end bb);
insist (After i1 = instr_pred i2);
insist (At_start bb = instr_pred i1);
-
+
let lf s x = s ^ "->" ^ value_name x in
insist ("->One->Two" = fold_left_instrs lf "" bb);
-
+
let rf x s = value_name x ^ "<-" ^ s in
insist ("One<-Two<-" = fold_right_instrs rf bb "");
-
+
dispose_module m
+ end;
+
+ group "clone instr";
+ begin
+ (* CHECK: %clone = add i32 %0, 2
+ *)
+ let fty = function_type void_type [| i32_type |] in
+ let fn = define_function "BuilderParent" fty m in
+ let bb = entry_block fn in
+ let b = builder_at_end context bb in
+ let p = param fn 0 in
+ let sum = build_add p p "sum" b in
+ let y = const_int i32_type 2 in
+ let clone = instr_clone sum in
+ set_operand clone 0 p;
+ set_operand clone 1 y;
+ insert_into_builder clone "clone" b;
+ ignore (build_ret_void b)
end
let test_builder () =
let (++) x f = f x; x in
-
+
begin group "parent";
insist (try
ignore (insertion_block (builder context));
false
with Not_found ->
true);
-
+
let fty = function_type void_type [| i32_type |] in
let fn = define_function "BuilderParent" fty m in
let bb = entry_block fn in
let p = param fn 0 in
let sum = build_add p p "sum" b in
ignore (build_ret_void b);
-
+
insist (fn = block_parent bb);
insist (fn = param_parent p);
insist (bb = instr_parent sum);
insist (bb = insertion_block b)
end;
-
+
group "ret void";
begin
(* CHECK: ret void
let agg = [| const_int i8_type 4; const_int i64_type 5 |] in
ignore (build_aggregate_ret agg b)
end;
-
+
(* The rest of the tests will use one big function. *)
let fty = function_type i32_type [| i32_type; i32_type |] in
let fn = define_function "X7" fty m in
let p2 = param fn 1 ++ set_value_name "P2" in
let f1 = build_uitofp p1 float_type "F1" atentry in
let f2 = build_uitofp p2 float_type "F2" atentry in
-
+
let bb00 = append_block context "Bb00" fn in
ignore (build_unreachable (builder_at_end context bb00));
* CHECK: %build_is_not_null = icmp ne i8* %X1, null
* CHECK: %build_ptrdiff
*)
- ignore (build_icmp Icmp.Ne p1 p2 "build_icmp_ne" atentry);
- ignore (build_icmp Icmp.Sle p2 p1 "build_icmp_sle" atentry);
- ignore (build_fcmp Fcmp.False f1 f2 "build_fcmp_false" atentry);
- ignore (build_fcmp Fcmp.True f2 f1 "build_fcmp_true" atentry);
+ let c = build_icmp Icmp.Ne p1 p2 "build_icmp_ne" atentry in
+ insist (Some Icmp.Ne = icmp_predicate c);
+ insist (None = fcmp_predicate c);
+
+ let c = build_icmp Icmp.Sle p2 p1 "build_icmp_sle" atentry in
+ insist (Some Icmp.Sle = icmp_predicate c);
+ insist (None = fcmp_predicate c);
+
+ let c = build_fcmp Fcmp.False f1 f2 "build_fcmp_false" atentry in
+ (* insist (Some Fcmp.False = fcmp_predicate c); *)
+ insist (None = icmp_predicate c);
+
+ let c = build_fcmp Fcmp.True f2 f1 "build_fcmp_true" atentry in
+ (* insist (Some Fcmp.True = fcmp_predicate c); *)
+ insist (None = icmp_predicate c);
+
let g0 = declare_global (pointer_type i8_type) "g0" m in
let g1 = declare_global (pointer_type i8_type) "g1" m in
let p0 = build_load g0 "X0" atentry in
*)
let bb02 = append_block context "Bb02" fn in
let b = builder_at_end context bb02 in
- ignore (build_br bb02 b)
+ let br = build_br bb02 b in
+ insist (successors br = [| bb02 |]) ;
+ insist (is_conditional br = false) ;
+ insist (get_branch br = Some (`Unconditional bb02)) ;
end;
-
+
group "cond_br"; begin
(* CHECK: br{{.*}}build_br{{.*}}Bb03{{.*}}Bb00
*)
let bb03 = append_block context "Bb03" fn in
let b = builder_at_end context bb03 in
let cond = build_trunc p1 i1_type "build_br" b in
- ignore (build_cond_br cond bb03 bb00 b)
+ let br = build_cond_br cond bb03 bb00 b in
+ insist (num_successors br = 2) ;
+ insist (successor br 0 = bb03) ;
+ insist (successor br 1 = bb00) ;
+ insist (is_conditional br = true) ;
+ insist (get_branch br = Some (`Conditional (cond, bb03, bb00))) ;
end;
-
+
group "switch"; begin
(* CHECK: switch{{.*}}P1{{.*}}SwiBlock3
* CHECK: 2,{{.*}}SwiBlock2
ignore (add_case si (const_int i32_type 2) bb2);
insist (switch_default_dest si = bb3);
end;
+ insist (num_successors si = 2) ;
+ insist (get_branch si = None) ;
end;
group "malloc/free"; begin
ignore (add_destination ibr bb2);
ignore (add_destination ibr bb3)
end;
-
+
group "invoke"; begin
(* CHECK: build_invoke{{.*}}invoke{{.*}}P1{{.*}}P2
* CHECK: to{{.*}}Bb04{{.*}}unwind{{.*}}Bblpad
let b = builder_at_end context bb04 in
ignore (build_invoke fn [| p1; p2 |] bb04 bblpad "build_invoke" b)
end;
-
+
group "unreachable"; begin
(* CHECK: unreachable
*)
let b = builder_at_end context bb06 in
ignore (build_unreachable b)
end;
-
+
group "arithmetic"; begin
let bb07 = append_block context "Bb07" fn in
let b = builder_at_end context bb07 in
-
+
(* CHECK: %build_add = add i32 %P1, %P2
* CHECK: %build_nsw_add = add nsw i32 %P1, %P2
* CHECK: %build_nuw_add = add nuw i32 %P1, %P2
ignore (build_not p1 "build_not" b);
ignore (build_unreachable b)
end;
-
+
group "memory"; begin
let bb08 = append_block context "Bb08" fn in
let b = builder_at_end context bb08 in
*)
let b1 = append_block context "PhiBlock1" fn in
let b2 = append_block context "PhiBlock2" fn in
-
+
let jb = append_block context "PhiJoinBlock" fn in
ignore (build_br jb (builder_at_end context b1));
ignore (build_br jb (builder_at_end context b2));
let at_jb = builder_at_end context jb in
-
+
let phi = build_phi [(p1, b1)] "PhiNode" at_jb in
insist ([(p1, b1)] = incoming phi);
-
+
add_incoming (p2, b2) phi;
insist ([(p1, b1); (p2, b2)] = incoming phi);
-
+
ignore (build_unreachable at_jb);
end
++ PassManager.run_module m
++ PassManager.dispose)
end;
-
+
begin group "function pass manager";
let fty = function_type void_type [| |] in
let fn = define_function "FunctionPassManager" fty m in
ignore (build_ret_void (builder_at_end context (entry_block fn)));
-
+
ignore (PassManager.create_function m
++ PassManager.initialize
++ PassManager.run_function fn
group "writer";
insist (write_bitcode_file m filename);
-
+
dispose_module m