summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Tryzelaar <idadesub@users.sourceforge.net>2010-02-28 09:46:06 +0000
committerErick Tryzelaar <idadesub@users.sourceforge.net>2010-02-28 09:46:06 +0000
commitc59286bff1cca8c4fa15f390c9002db94117614e (patch)
treea814f992425526d661e141c95d4a273cc32bd19a
parent46c80e0c5653e11ada7cebcb46f9a8f7df758e41 (diff)
downloadllvm-c59286bff1cca8c4fa15f390c9002db94117614e.tar.gz
llvm-c59286bff1cca8c4fa15f390c9002db94117614e.tar.bz2
llvm-c59286bff1cca8c4fa15f390c9002db94117614e.tar.xz
Add indirect br support to llvm-c and ocaml.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97376 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--bindings/ocaml/llvm/llvm.ml5
-rw-r--r--bindings/ocaml/llvm/llvm.mli18
-rw-r--r--bindings/ocaml/llvm/llvm_ocaml.c14
-rw-r--r--include/llvm-c/Core.h6
-rw-r--r--lib/VMCore/Core.cpp13
-rw-r--r--test/Bindings/Ocaml/vmcore.ml17
6 files changed, 73 insertions, 0 deletions
diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml
index 837f6a3b74..7017b4ada0 100644
--- a/bindings/ocaml/llvm/llvm.ml
+++ b/bindings/ocaml/llvm/llvm.ml
@@ -351,6 +351,7 @@ external const_extractvalue : llvalue -> int array -> llvalue
= "llvm_const_extractvalue"
external const_insertvalue : llvalue -> llvalue -> int array -> llvalue
= "llvm_const_insertvalue"
+external block_address : llvalue -> llbasicblock -> llvalue = "LLVMBlockAddress"
(*--... Operations on global variables, functions, and aliases (globals) ...--*)
external global_parent : llvalue -> llmodule = "LLVMGetGlobalParent"
@@ -729,6 +730,10 @@ external build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue
= "llvm_build_switch"
external add_case : llvalue -> llvalue -> llbasicblock -> unit
= "llvm_add_case"
+external build_indirect_br : llvalue -> int -> llbuilder -> llvalue
+ = "llvm_build_indirect_br"
+external add_destination : llvalue -> llbasicblock -> unit
+ = "llvm_add_destination"
external build_invoke : llvalue -> llvalue array -> llbasicblock ->
llbasicblock -> string -> llbuilder -> llvalue
= "llvm_build_invoke_bc" "llvm_build_invoke_nat"
diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli
index 5a156428bf..c7fa30a96f 100644
--- a/bindings/ocaml/llvm/llvm.mli
+++ b/bindings/ocaml/llvm/llvm.mli
@@ -950,6 +950,10 @@ external const_extractvalue : llvalue -> int array -> llvalue
external const_insertvalue : llvalue -> llvalue -> int array -> llvalue
= "llvm_const_insertvalue"
+(** [block_address f bb] returns the address of the basic block [bb] in the
+ function [f]. See the method [llvm::BasicBlock::get]. *)
+external block_address : llvalue -> llbasicblock -> llvalue = "LLVMBlockAddress"
+
(** {7 Operations on global variables, functions, and aliases (globals)} *)
@@ -1562,6 +1566,20 @@ external build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue
external add_case : llvalue -> llvalue -> llbasicblock -> unit
= "llvm_add_case"
+(** [build_indirect_br addr count b] creates a
+ [indirectbr %addr]
+ instruction at the position specified by the instruction builder [b] with
+ space reserved for [count] destinations.
+ See the method [llvm::LLVMBuilder::CreateIndirectBr]. *)
+external build_indirect_br : llvalue -> int -> llbuilder -> llvalue
+ = "llvm_build_indirect_br"
+
+(** [add_destination br bb] adds the basic block [bb] as a possible branch
+ location for the indirectbr instruction [br].
+ See the method [llvm::IndirectBrInst::addDestination]. **)
+external add_destination : llvalue -> llbasicblock -> unit
+ = "llvm_add_destination"
+
(** [build_invoke fn args tobb unwindbb name b] creates an
[%name = invoke %fn(args) to %tobb unwind %unwindbb]
instruction at the position specified by the instruction builder [b].
diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c
index e56af1e753..3964ff7487 100644
--- a/bindings/ocaml/llvm/llvm_ocaml.c
+++ b/bindings/ocaml/llvm/llvm_ocaml.c
@@ -1138,6 +1138,20 @@ CAMLprim value llvm_add_case(LLVMValueRef Switch, LLVMValueRef OnVal,
return Val_unit;
}
+/* llvalue -> llbasicblock -> llbuilder -> llvalue */
+CAMLprim LLVMValueRef llvm_build_indirect_br(LLVMValueRef Addr,
+ value EstimatedDests,
+ value B) {
+ return LLVMBuildIndirectBr(Builder_val(B), Addr, EstimatedDests);
+}
+
+/* llvalue -> llvalue -> llbasicblock -> unit */
+CAMLprim value llvm_add_destination(LLVMValueRef IndirectBr,
+ LLVMBasicBlockRef Dest) {
+ LLVMAddDestination(IndirectBr, Dest);
+ return Val_unit;
+}
+
/* llvalue -> llvalue array -> llbasicblock -> llbasicblock -> string ->
llbuilder -> llvalue */
CAMLprim LLVMValueRef llvm_build_invoke_nat(LLVMValueRef Fn, value Args,
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index 1a29463e14..17bd99dacc 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -655,6 +655,7 @@ LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant,
LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty,
const char *AsmString, const char *Constraints,
LLVMBool HasSideEffects, LLVMBool IsAlignStack);
+LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB);
/* Operations on global variables, functions, and aliases (globals) */
LLVMModuleRef LLVMGetGlobalParent(LLVMValueRef Global);
@@ -805,6 +806,8 @@ LLVMValueRef LLVMBuildCondBr(LLVMBuilderRef, LLVMValueRef If,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Else);
LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef, LLVMValueRef V,
LLVMBasicBlockRef Else, unsigned NumCases);
+LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr,
+ unsigned NumDests);
LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
@@ -816,6 +819,9 @@ LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal,
LLVMBasicBlockRef Dest);
+/* Add a destination to the indirectbr instruction */
+void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest);
+
/* Arithmetic */
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS,
const char *Name);
diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp
index 9f1ee17c54..b15f039e38 100644
--- a/lib/VMCore/Core.cpp
+++ b/lib/VMCore/Core.cpp
@@ -1013,6 +1013,10 @@ LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty, const char *AsmString,
Constraints, HasSideEffects, IsAlignStack));
}
+LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB) {
+ return wrap(BlockAddress::get(unwrap<Function>(F), unwrap(BB)));
+}
+
/*--.. Operations on global variables, functions, and aliases (globals) ....--*/
LLVMModuleRef LLVMGetGlobalParent(LLVMValueRef Global) {
@@ -1696,6 +1700,11 @@ LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef B, LLVMValueRef V,
return wrap(unwrap(B)->CreateSwitch(unwrap(V), unwrap(Else), NumCases));
}
+LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr,
+ unsigned NumDests) {
+ return wrap(unwrap(B)->CreateIndirectBr(unwrap(Addr), NumDests));
+}
+
LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
@@ -1718,6 +1727,10 @@ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal,
unwrap<SwitchInst>(Switch)->addCase(unwrap<ConstantInt>(OnVal), unwrap(Dest));
}
+void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest) {
+ unwrap<IndirectBrInst>(IndirectBr)->addDestination(unwrap(Dest));
+}
+
/*--.. Arithmetic ..........................................................--*/
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS,
diff --git a/test/Bindings/Ocaml/vmcore.ml b/test/Bindings/Ocaml/vmcore.ml
index 57a842583f..9a2f547531 100644
--- a/test/Bindings/Ocaml/vmcore.ml
+++ b/test/Bindings/Ocaml/vmcore.ml
@@ -897,6 +897,23 @@ let test_builder () =
let si = build_switch p1 bb3 1 (builder_at_end context bb1) in
ignore (add_case si (const_int i32_type 2) bb2)
end;
+
+ group "indirectbr"; begin
+ (* RUN: grep {indirectbr i8\\* blockaddress(@X7, %IBRBlock2), \\\[label %IBRBlock2, label %IBRBlock3\\\]} < %t.ll
+ *)
+ let bb1 = append_block context "IBRBlock1" fn in
+
+ let bb2 = append_block context "IBRBlock2" fn in
+ ignore (build_unreachable (builder_at_end context bb2));
+
+ let bb3 = append_block context "IBRBlock3" fn in
+ ignore (build_unreachable (builder_at_end context bb3));
+
+ let addr = block_address fn bb2 in
+ let ibr = build_indirect_br addr 2 (builder_at_end context bb1) in
+ ignore (add_destination ibr bb2);
+ ignore (add_destination ibr bb3)
+ end;
group "invoke"; begin
(* RUN: grep {build_invoke.*invoke.*P1.*P2} < %t.ll