-(*===-- llvm/llvm.ml - LLVM Ocaml Interface --------------------------------===*
+(*===-- llvm/llvm.ml - LLVM OCaml Interface -------------------------------===*
*
* The LLVM Compiler Infrastructure
*
type lluse
type llbasicblock
type llbuilder
+type llattrkind
+type llattribute
type llmemorybuffer
type llmdkind
+exception FeatureDisabled of string
+
+let () = Callback.register_exception "Llvm.FeatureDisabled" (FeatureDisabled "")
+
module TypeKind = struct
type t =
| Void
| Vector
| Metadata
| X86_mmx
+ | Token
end
module Linkage = struct
| Protected
end
+module DLLStorageClass = struct
+ type t =
+ | Default
+ | DLLImport
+ | DLLExport
+end
+
module CallConv = struct
let c = 0
let fast = 8
let x86_fastcall = 65
end
+module AttrRepr = struct
+ type t =
+ | Enum of llattrkind * int64
+ | String of string * string
+end
+
+module AttrIndex = struct
+ type t =
+ | Function
+ | Return
+ | Param of int
+
+ let to_int index =
+ match index with
+ | Function -> -1
+ | Return -> 0
+ | Param(n) -> 1 + n
+end
+
module Attribute = struct
type t =
| Zext
| AtomicRMW
| Resume
| LandingPad
+ | AddrSpaceCast
+ | CleanupRet
+ | CatchRet
+ | CatchPad
+ | CleanupPad
+ | CatchSwitch
end
module LandingPadClauseTy = struct
| ConstantVector
| Function
| GlobalAlias
+ | GlobalIFunc
| GlobalVariable
| UndefValue
| Instruction of Opcode.t
end
+module DiagnosticSeverity = struct
+ type t =
+ | Error
+ | Warning
+ | Remark
+ | Note
+end
+
exception IoError of string
-external register_exns : exn -> unit = "llvm_register_core_exns"
-let _ = register_exns (IoError "")
+let () = Callback.register_exception "Llvm.IoError" (IoError "")
external install_fatal_error_handler : (string -> unit) -> unit
= "llvm_install_fatal_error_handler"
= "llvm_reset_fatal_error_handler"
external enable_pretty_stacktrace : unit -> unit
= "llvm_enable_pretty_stacktrace"
+external parse_command_line_options : ?overview:string -> string array -> unit
+ = "llvm_parse_command_line_options"
type ('a, 'b) llpos =
| At_end of 'a
| At_start of 'a
| After of 'b
+
+(*===-- Context error handling --------------------------------------------===*)
+module Diagnostic = struct
+ type t
+
+ external description : t -> string = "llvm_get_diagnostic_description"
+ external severity : t -> DiagnosticSeverity.t
+ = "llvm_get_diagnostic_severity"
+end
+
+external set_diagnostic_handler
+ : llcontext -> (Diagnostic.t -> unit) option -> unit
+ = "llvm_set_diagnostic_handler"
+
(*===-- Contexts ----------------------------------------------------------===*)
external create_context : unit -> llcontext = "llvm_create_context"
external dispose_context : llcontext -> unit = "llvm_dispose_context"
external global_context : unit -> llcontext = "llvm_global_context"
external mdkind_id : llcontext -> string -> llmdkind = "llvm_mdkind_id"
+(*===-- Attributes --------------------------------------------------------===*)
+exception UnknownAttribute of string
+
+let () = Callback.register_exception "Llvm.UnknownAttribute"
+ (UnknownAttribute "")
+
+external enum_attr_kind : string -> llattrkind = "llvm_enum_attr_kind"
+external llvm_create_enum_attr : llcontext -> llattrkind -> int64 ->
+ llattribute
+ = "llvm_create_enum_attr_by_kind"
+external is_enum_attr : llattribute -> bool = "llvm_is_enum_attr"
+external get_enum_attr_kind : llattribute -> llattrkind
+ = "llvm_get_enum_attr_kind"
+external get_enum_attr_value : llattribute -> int64
+ = "llvm_get_enum_attr_value"
+external llvm_create_string_attr : llcontext -> string -> string ->
+ llattribute
+ = "llvm_create_string_attr"
+external is_string_attr : llattribute -> bool = "llvm_is_string_attr"
+external get_string_attr_kind : llattribute -> string
+ = "llvm_get_string_attr_kind"
+external get_string_attr_value : llattribute -> string
+ = "llvm_get_string_attr_value"
+
+let create_enum_attr context name value =
+ llvm_create_enum_attr context (enum_attr_kind name) value
+let create_string_attr context kind value =
+ llvm_create_string_attr context kind value
+
+let attr_of_repr context repr =
+ match repr with
+ | AttrRepr.Enum(kind, value) -> llvm_create_enum_attr context kind value
+ | AttrRepr.String(key, value) -> llvm_create_string_attr context key value
+
+let repr_of_attr attr =
+ if is_enum_attr attr then
+ AttrRepr.Enum(get_enum_attr_kind attr, get_enum_attr_value attr)
+ else if is_string_attr attr then
+ AttrRepr.String(get_string_attr_kind attr, get_string_attr_value attr)
+ else assert false
+
(*===-- Modules -----------------------------------------------------------===*)
external create_module : llcontext -> string -> llmodule = "llvm_create_module"
external dispose_module : llmodule -> unit = "llvm_dispose_module"
= "llvm_struct_element_types"
external is_packed : lltype -> bool = "llvm_is_packed"
external is_opaque : lltype -> bool = "llvm_is_opaque"
+external is_literal : lltype -> bool = "llvm_is_literal"
(*--... Operations on pointer, vector, and array types .....................--*)
+
+external subtypes : lltype -> lltype array = "llvm_subtypes"
external array_type : lltype -> int -> lltype = "llvm_array_type"
external pointer_type : lltype -> lltype = "llvm_pointer_type"
external qualified_pointer_type : lltype -> int -> lltype
(*--... Operations on users ................................................--*)
external operand : llvalue -> int -> llvalue = "llvm_operand"
+external operand_use : llvalue -> int -> lluse = "llvm_operand_use"
external set_operand : llvalue -> int -> llvalue -> unit = "llvm_set_operand"
external num_operands : llvalue -> int = "llvm_num_operands"
(*--... Operations on metadata .......,.....................................--*)
external mdstring : llcontext -> string -> llvalue = "llvm_mdstring"
external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode"
+external mdnull : llcontext -> llvalue = "llvm_mdnull"
external get_mdstring : llvalue -> string option = "llvm_get_mdstring"
+external get_mdnode_operands : llvalue -> llvalue array
+ = "llvm_get_mdnode_operands"
external get_named_metadata : llmodule -> string -> llvalue array
= "llvm_get_namedmd"
external add_named_metadata_operand : llmodule -> string -> llvalue -> unit
external const_int_of_string : lltype -> string -> int -> llvalue
= "llvm_const_int_of_string"
external const_float : lltype -> float -> llvalue = "llvm_const_float"
+external float_of_const : llvalue -> float option
+ = "llvm_float_of_const"
external const_float_of_string : lltype -> string -> llvalue
= "llvm_const_float_of_string"
external is_declaration : llvalue -> bool = "llvm_is_declaration"
external linkage : llvalue -> Linkage.t = "llvm_linkage"
external set_linkage : Linkage.t -> llvalue -> unit = "llvm_set_linkage"
+external unnamed_addr : llvalue -> bool = "llvm_unnamed_addr"
+external set_unnamed_addr : bool -> llvalue -> unit = "llvm_set_unnamed_addr"
external section : llvalue -> string = "llvm_section"
external set_section : string -> llvalue -> unit = "llvm_set_section"
external visibility : llvalue -> Visibility.t = "llvm_visibility"
external set_visibility : Visibility.t -> llvalue -> unit = "llvm_set_visibility"
+external dll_storage_class : llvalue -> DLLStorageClass.t = "llvm_dll_storage_class"
+external set_dll_storage_class : DLLStorageClass.t -> llvalue -> unit = "llvm_set_dll_storage_class"
external alignment : llvalue -> int = "llvm_alignment"
external set_alignment : int -> llvalue -> unit = "llvm_set_alignment"
external is_global_constant : llvalue -> bool = "llvm_is_global_constant"
let fold_right_functions f m init =
fold_right_function_range f (function_end m) (At_start m) init
-external llvm_add_function_attr : llvalue -> int32 -> unit
+external llvm_add_function_attr : llvalue -> llattribute -> int -> unit
= "llvm_add_function_attr"
-external llvm_remove_function_attr : llvalue -> int32 -> unit
- = "llvm_remove_function_attr"
-external llvm_function_attr : llvalue -> int32 = "llvm_function_attr"
-
-let pack_attr (attr:Attribute.t) : int32 =
- match attr with
- Attribute.Zext -> Int32.shift_left 1l 0
- | Attribute.Sext -> Int32.shift_left 1l 1
- | Attribute.Noreturn -> Int32.shift_left 1l 2
- | Attribute.Inreg -> Int32.shift_left 1l 3
- | Attribute.Structret -> Int32.shift_left 1l 4
- | Attribute.Nounwind -> Int32.shift_left 1l 5
- | Attribute.Noalias -> Int32.shift_left 1l 6
- | Attribute.Byval -> Int32.shift_left 1l 7
- | Attribute.Nest -> Int32.shift_left 1l 8
- | Attribute.Readnone -> Int32.shift_left 1l 9
- | Attribute.Readonly -> Int32.shift_left 1l 10
- | Attribute.Noinline -> Int32.shift_left 1l 11
- | Attribute.Alwaysinline -> Int32.shift_left 1l 12
- | Attribute.Optsize -> Int32.shift_left 1l 13
- | Attribute.Ssp -> Int32.shift_left 1l 14
- | Attribute.Sspreq -> Int32.shift_left 1l 15
- | Attribute.Alignment n -> Int32.shift_left (Int32.of_int n) 16
- | Attribute.Nocapture -> Int32.shift_left 1l 21
- | Attribute.Noredzone -> Int32.shift_left 1l 22
- | Attribute.Noimplicitfloat -> Int32.shift_left 1l 23
- | Attribute.Naked -> Int32.shift_left 1l 24
- | Attribute.Inlinehint -> Int32.shift_left 1l 25
- | Attribute.Stackalignment n -> Int32.shift_left (Int32.of_int n) 26
- | Attribute.ReturnsTwice -> Int32.shift_left 1l 29
- | Attribute.UWTable -> Int32.shift_left 1l 30
- | Attribute.NonLazyBind -> Int32.shift_left 1l 31
-
-let unpack_attr (a : int32) : Attribute.t list =
- let l = ref [] in
- let check attr =
- Int32.logand (pack_attr attr) a in
- let checkattr attr =
- if (check attr) <> 0l then begin
- l := attr :: !l
- end
- in
- checkattr Attribute.Zext;
- checkattr Attribute.Sext;
- checkattr Attribute.Noreturn;
- checkattr Attribute.Inreg;
- checkattr Attribute.Structret;
- checkattr Attribute.Nounwind;
- checkattr Attribute.Noalias;
- checkattr Attribute.Byval;
- checkattr Attribute.Nest;
- checkattr Attribute.Readnone;
- checkattr Attribute.Readonly;
- checkattr Attribute.Noinline;
- checkattr Attribute.Alwaysinline;
- checkattr Attribute.Optsize;
- checkattr Attribute.Ssp;
- checkattr Attribute.Sspreq;
- let align = Int32.logand (Int32.shift_right_logical a 16) 31l in
- if align <> 0l then
- l := Attribute.Alignment (Int32.to_int align) :: !l;
- checkattr Attribute.Nocapture;
- checkattr Attribute.Noredzone;
- checkattr Attribute.Noimplicitfloat;
- checkattr Attribute.Naked;
- checkattr Attribute.Inlinehint;
- let stackalign = Int32.logand (Int32.shift_right_logical a 26) 7l in
- if stackalign <> 0l then
- l := Attribute.Stackalignment (Int32.to_int stackalign) :: !l;
- checkattr Attribute.ReturnsTwice;
- checkattr Attribute.UWTable;
- checkattr Attribute.NonLazyBind;
- !l;;
-
-let add_function_attr llval attr =
- llvm_add_function_attr llval (pack_attr attr)
-
-external add_target_dependent_function_attr
- : llvalue -> string -> string -> unit
- = "llvm_add_target_dependent_function_attr"
-
-let remove_function_attr llval attr =
- llvm_remove_function_attr llval (pack_attr attr)
-
-let function_attr f = unpack_attr (llvm_function_attr f)
+external llvm_function_attrs : llvalue -> int -> llattribute array
+ = "llvm_function_attrs"
+external llvm_remove_enum_function_attr : llvalue -> llattrkind -> int -> unit
+ = "llvm_remove_enum_function_attr"
+external llvm_remove_string_function_attr : llvalue -> string -> int -> unit
+ = "llvm_remove_string_function_attr"
+
+let add_function_attr f a i =
+ llvm_add_function_attr f a (AttrIndex.to_int i)
+let function_attrs f i =
+ llvm_function_attrs f (AttrIndex.to_int i)
+let remove_enum_function_attr f k i =
+ llvm_remove_enum_function_attr f k (AttrIndex.to_int i)
+let remove_string_function_attr f k i =
+ llvm_remove_string_function_attr f k (AttrIndex.to_int i)
(*--... Operations on params ...............................................--*)
external params : llvalue -> llvalue array = "llvm_params"
external param : llvalue -> int -> llvalue = "llvm_param"
-external llvm_param_attr : llvalue -> int32 = "llvm_param_attr"
-let param_attr p = unpack_attr (llvm_param_attr p)
external param_parent : llvalue -> llvalue = "LLVMGetParamParent"
external param_begin : llvalue -> (llvalue, llvalue) llpos = "llvm_param_begin"
external param_succ : llvalue -> (llvalue, llvalue) llpos = "llvm_param_succ"
let fold_right_params f fn init =
fold_right_param_range f init (param_end fn) (At_start fn)
-external llvm_add_param_attr : llvalue -> int32 -> unit
- = "llvm_add_param_attr"
-external llvm_remove_param_attr : llvalue -> int32 -> unit
- = "llvm_remove_param_attr"
-
-let add_param_attr llval attr =
- llvm_add_param_attr llval (pack_attr attr)
-
-let remove_param_attr llval attr =
- llvm_remove_param_attr llval (pack_attr attr)
-
-external set_param_alignment : llvalue -> int -> unit
- = "llvm_set_param_alignment"
-
(*--... Operations on basic blocks .........................................--*)
external value_of_block : llbasicblock -> llvalue = "LLVMBasicBlockAsValue"
external value_is_block : llvalue -> bool = "llvm_value_is_block"
external instr_opcode : llvalue -> Opcode.t = "llvm_instr_get_opcode"
external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate"
+external fcmp_predicate : llvalue -> Fcmp.t option = "llvm_instr_fcmp_predicate"
+external instr_clone : llvalue -> llvalue = "llvm_instr_clone"
let rec iter_instrs_range f i e =
if i = e then () else
external set_instruction_call_conv: int -> llvalue -> unit
= "llvm_set_instruction_call_conv"
-external llvm_add_instruction_param_attr : llvalue -> int -> int32 -> unit
- = "llvm_add_instruction_param_attr"
-external llvm_remove_instruction_param_attr : llvalue -> int -> int32 -> unit
- = "llvm_remove_instruction_param_attr"
-
-let add_instruction_param_attr llval i attr =
- llvm_add_instruction_param_attr llval i (pack_attr attr)
-
-let remove_instruction_param_attr llval i attr =
- llvm_remove_instruction_param_attr llval i (pack_attr attr)
-
-(*--... Operations on call instructions (only) .............................--*)
+external llvm_add_call_site_attr : llvalue -> llattribute -> int -> unit
+ = "llvm_add_call_site_attr"
+external llvm_call_site_attrs : llvalue -> int -> llattribute array
+ = "llvm_call_site_attrs"
+external llvm_remove_enum_call_site_attr : llvalue -> llattrkind -> int -> unit
+ = "llvm_remove_enum_call_site_attr"
+external llvm_remove_string_call_site_attr : llvalue -> string -> int -> unit
+ = "llvm_remove_string_call_site_attr"
+
+let add_call_site_attr f a i =
+ llvm_add_call_site_attr f a (AttrIndex.to_int i)
+let call_site_attrs f i =
+ llvm_call_site_attrs f (AttrIndex.to_int i)
+let remove_enum_call_site_attr f k i =
+ llvm_remove_enum_call_site_attr f k (AttrIndex.to_int i)
+let remove_string_call_site_attr f k i =
+ llvm_remove_string_call_site_attr f k (AttrIndex.to_int i)
+
+(*--... Operations on call and invoke instructions (only) ..................--*)
+external num_arg_operands : llvalue -> int = "llvm_num_arg_operands"
external is_tail_call : llvalue -> bool = "llvm_is_tail_call"
external set_tail_call : bool -> llvalue -> unit = "llvm_set_tail_call"
+external get_normal_dest : llvalue -> llbasicblock = "LLVMGetNormalDest"
+external get_unwind_dest : llvalue -> llbasicblock = "LLVMGetUnwindDest"
(*--... Operations on load/store instructions (only) .......................--*)
external is_volatile : llvalue -> bool = "llvm_is_volatile"
external set_volatile : bool -> llvalue -> unit = "llvm_set_volatile"
+(*--... Operations on terminators ..........................................--*)
+
+let is_terminator llv =
+ let open ValueKind in
+ let open Opcode in
+ match classify_value llv with
+ | Instruction (Br | IndirectBr | Invoke | Resume | Ret | Switch | Unreachable)
+ -> true
+ | _ -> false
+
+external successor : llvalue -> int -> llbasicblock = "llvm_successor"
+external set_successor : llvalue -> int -> llbasicblock -> unit
+ = "llvm_set_successor"
+external num_successors : llvalue -> int = "llvm_num_successors"
+
+let successors llv =
+ if not (is_terminator llv) then
+ raise (Invalid_argument "Llvm.successors can only be used on terminators")
+ else
+ Array.init (num_successors llv) (successor llv)
+
+let iter_successors f llv =
+ if not (is_terminator llv) then
+ raise (Invalid_argument "Llvm.iter_successors can only be used on terminators")
+ else
+ for i = 0 to num_successors llv - 1 do
+ f (successor llv i)
+ done
+
+let fold_successors f llv z =
+ if not (is_terminator llv) then
+ raise (Invalid_argument "Llvm.fold_successors can only be used on terminators")
+ else
+ let n = num_successors llv in
+ let rec aux i acc =
+ if i >= n then acc
+ else begin
+ let llb = successor llv i in
+ aux (i+1) (f llb acc)
+ end
+ in aux 0 z
+
+
+(*--... Operations on branches .............................................--*)
+external condition : llvalue -> llvalue = "llvm_condition"
+external set_condition : llvalue -> llvalue -> unit
+ = "llvm_set_condition"
+external is_conditional : llvalue -> bool = "llvm_is_conditional"
+
+let get_branch llv =
+ if classify_value llv <> ValueKind.Instruction Opcode.Br then
+ None
+ else if is_conditional llv then
+ Some (`Conditional (condition llv, successor llv 0, successor llv 1))
+ else
+ Some (`Unconditional (successor llv 0))
+
(*--... Operations on phi nodes ............................................--*)
external add_incoming : (llvalue * llbasicblock) -> llvalue -> unit
= "llvm_add_incoming"
(*--... Miscellaneous instructions .........................................--*)
external build_phi : (llvalue * llbasicblock) list -> string -> llbuilder ->
llvalue = "llvm_build_phi"
+external build_empty_phi : lltype -> string -> llbuilder -> llvalue
+ = "llvm_build_empty_phi"
external build_call : llvalue -> llvalue array -> string -> llbuilder -> llvalue
= "llvm_build_call"
external build_select : llvalue -> llvalue -> llvalue -> string -> llbuilder ->