[OCaml] Handle nullptr in Llvm.global_initializer

LLVMGetInitializer returns nullptr in case there is no initializer.
There is not much that can be done with nullptr in OCaml, not even
test if it is null. Also, there does not seem to be a C or OCaml API
to test if there is an initializer. So this diff changes
Llvm.global_initializer to return an option.

Reviewed By: whitequark

Differential Revision: https://reviews.llvm.org/D65195
This commit is contained in:
Timotej Kapus 2021-03-17 12:47:32 +00:00 committed by Josh Berdine
parent 4a8c01a02b
commit 2571a09367
5 changed files with 19 additions and 7 deletions

View File

@ -739,7 +739,7 @@ external define_qualified_global : string -> llvalue -> int -> llmodule ->
external lookup_global : string -> llmodule -> llvalue option
= "llvm_lookup_global"
external delete_global : llvalue -> unit = "llvm_delete_global"
external global_initializer : llvalue -> llvalue = "LLVMGetInitializer"
external global_initializer : llvalue -> llvalue option = "llvm_global_initializer"
external set_initializer : llvalue -> llvalue -> unit = "llvm_set_initializer"
external remove_initializer : llvalue -> unit = "llvm_remove_initializer"
external is_thread_local : llvalue -> bool = "llvm_is_thread_local"

View File

@ -1504,9 +1504,9 @@ val is_global_constant : llvalue -> bool
See the method [llvm::GlobalVariable::setConstant]. *)
val set_global_constant : bool -> llvalue -> unit
(** [global_initializer gv] returns the initializer for the global variable
[gv]. See the method [llvm::GlobalVariable::getInitializer]. *)
val global_initializer : llvalue -> llvalue
(** [global_initializer gv] If global variable [gv] has an initializer it is returned,
otherwise returns [None]. See the method [llvm::GlobalVariable::getInitializer]. *)
val global_initializer : llvalue -> llvalue option
(** [set_initializer c gv] sets the initializer for the global variable
[gv] to the constant [c].

View File

@ -1334,6 +1334,18 @@ CAMLprim value llvm_delete_global(LLVMValueRef GlobalVar) {
return Val_unit;
}
/* llvalue -> llvalue option */
CAMLprim value llvm_global_initializer(LLVMValueRef GlobalVar) {
CAMLparam0();
LLVMValueRef Init;
if ((Init = LLVMGetInitializer(GlobalVar))) {
value Option = alloc(1, 0);
Field(Option, 0) = (value) Init;
CAMLreturn(Option);
}
CAMLreturn(Val_int(0));
}
/* llvalue -> llvalue -> unit */
CAMLprim value llvm_set_initializer(LLVMValueRef ConstantVal,
LLVMValueRef GlobalVar) {

View File

@ -548,14 +548,14 @@ let test_global_variables () =
set_initializer forty_two32 in
insist (not (is_declaration g));
insist (not (is_declaration g2));
insist ((global_initializer g) == (global_initializer g2));
insist ((global_initializer g) = (global_initializer g2));
let g = define_qualified_global "QGVar02" forty_two32 3 m in
let g2 = declare_qualified_global i32_type "QGVar03" 3 m ++
set_initializer forty_two32 in
insist (not (is_declaration g));
insist (not (is_declaration g2));
insist ((global_initializer g) == (global_initializer g2));
insist ((global_initializer g) = (global_initializer g2));
end;
(* CHECK: GVar04{{.*}}thread_local

View File

@ -38,7 +38,7 @@ let test_irreader () =
let m = parse_ir context buf in
match lookup_global "foo" m with
| Some foo ->
insist ((global_initializer foo) = (const_int (i32_type context) 42))
insist ((global_initializer foo) = (Some (const_int (i32_type context) 42)))
| None ->
failwith "global"
end;