diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index 2714af19814..c2226b10da1 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -35,6 +35,7 @@ module TypeKind = struct | Opaque | Vector | Metadata + | Union end module Linkage = struct @@ -198,9 +199,15 @@ external param_types : lltype -> lltype array = "llvm_param_types" external struct_type : llcontext -> lltype array -> lltype = "llvm_struct_type" external packed_struct_type : llcontext -> lltype array -> lltype = "llvm_packed_struct_type" -external element_types : lltype -> lltype array = "llvm_element_types" +external struct_element_types : lltype -> lltype array + = "llvm_struct_element_types" external is_packed : lltype -> bool = "llvm_is_packed" +(*--... Operations on union types ..........................................--*) +external union_type : llcontext -> lltype array -> lltype = "llvm_union_type" +external union_element_types : lltype -> lltype array + = "llvm_union_element_types" + (*--... Operations on pointer, vector, and array types .....................--*) external array_type : lltype -> int -> lltype = "llvm_array_type" external pointer_type : lltype -> lltype = "llvm_pointer_type" @@ -257,6 +264,7 @@ external const_struct : llcontext -> llvalue array -> llvalue external const_packed_struct : llcontext -> llvalue array -> llvalue = "llvm_const_packed_struct" external const_vector : llvalue array -> llvalue = "llvm_const_vector" +external const_union : lltype -> llvalue -> llvalue = "LLVMConstUnion" (*--... Constant expressions ...............................................--*) external align_of : lltype -> llvalue = "LLVMAlignOf" @@ -892,11 +900,14 @@ let rec string_of_lltype ty = | TypeKind.Pointer -> (string_of_lltype (element_type ty)) ^ "*" | TypeKind.Struct -> let s = "{ " ^ (concat2 ", " ( - Array.map string_of_lltype (element_types ty) + Array.map string_of_lltype (struct_element_types ty) )) ^ " }" in if is_packed ty then "<" ^ s ^ ">" else s + | TypeKind.Union -> "union { " ^ (concat2 ", " ( + Array.map string_of_lltype (union_element_types ty) + )) ^ " }" | TypeKind.Array -> "[" ^ (string_of_int (array_length ty)) ^ " x " ^ (string_of_lltype (element_type ty)) ^ "]" | TypeKind.Vector -> "<" ^ (string_of_int (vector_size ty)) ^ diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index 9afddf11530..2eaee9e25a9 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -73,6 +73,7 @@ module TypeKind : sig | Opaque | Vector | Metadata + | Union end (** The linkage of a global value, accessed with {!linkage} and @@ -381,15 +382,29 @@ external struct_type : llcontext -> lltype array -> lltype external packed_struct_type : llcontext -> lltype array -> lltype = "llvm_packed_struct_type" -(** [element_types sty] returns the constituent types of the struct type [sty]. - See the method [llvm::StructType::getElementType]. *) -external element_types : lltype -> lltype array = "llvm_element_types" +(** [struct_element_types sty] returns the constituent types of the struct type + [sty]. See the method [llvm::StructType::getElementType]. *) +external struct_element_types : lltype -> lltype array + = "llvm_struct_element_types" (** [is_packed sty] returns [true] if the structure type [sty] is packed, [false] otherwise. See the method [llvm::StructType::isPacked]. *) external is_packed : lltype -> bool = "llvm_is_packed" +(** {7 Operations on union types} *) + +(** [union_type context tys] returns the union type in the context [context] + containing the types in the array [tys]. See the method + [llvm::UnionType::get] *) +external union_type : llcontext -> lltype array -> lltype = "llvm_union_type" + +(** [union_element_types uty] returns the constituent types of the union type + [uty]. See the method [llvm::UnionType::getElementType]. *) +external union_element_types : lltype -> lltype array + = "llvm_union_element_types" + + (** {7 Operations on pointer, vector, and array types} *) (** [array_type ty n] returns the array type containing [n] elements of type @@ -577,6 +592,10 @@ external const_packed_struct : llcontext -> llvalue array -> llvalue values [elts]. See the method [llvm::ConstantVector::get]. *) external const_vector : llvalue array -> llvalue = "llvm_const_vector" +(** [const_union ty v] returns the union constant of type [union_type tys] and + containing the value [v]. See the method [llvm::ConstantUnion::get]. *) +external const_union : lltype -> llvalue -> llvalue = "LLVMConstUnion" + (** {7 Constant expressions} *) diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index 1e934c0e675..9000c38303c 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -283,7 +283,7 @@ CAMLprim LLVMTypeRef llvm_packed_struct_type(LLVMContextRef C, } /* lltype -> lltype array */ -CAMLprim value llvm_element_types(LLVMTypeRef StructTy) { +CAMLprim value llvm_struct_element_types(LLVMTypeRef StructTy) { value Tys = alloc(LLVMCountStructElementTypes(StructTy), 0); LLVMGetStructElementTypes(StructTy, (LLVMTypeRef *) Tys); return Tys; @@ -294,6 +294,21 @@ CAMLprim value llvm_is_packed(LLVMTypeRef StructTy) { return Val_bool(LLVMIsPackedStruct(StructTy)); } +/*--... Operations on union types ..........................................--*/ + +/* llcontext -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_union_type(LLVMContextRef C, value ElementTypes) { + return LLVMUnionTypeInContext(C, (LLVMTypeRef *) ElementTypes, + Wosize_val(ElementTypes)); +} + +/* lltype -> lltype array */ +CAMLprim value llvm_union_element_types(LLVMTypeRef UnionTy) { + value Tys = alloc(LLVMCountUnionElementTypes(UnionTy), 0); + LLVMGetUnionElementTypes(UnionTy, (LLVMTypeRef *) Tys); + return Tys; +} + /*--... Operations on array, pointer, and vector types .....................--*/ /* lltype -> int -> lltype */ diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index fdfc7e90fe9..14654e07554 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -551,6 +551,7 @@ LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count, LLVMBool Packed); LLVMValueRef LLVMConstVector(LLVMValueRef *ScalarConstantVals, unsigned Size); +LLVMValueRef LLVMConstUnion(LLVMTypeRef Ty, LLVMValueRef Val); /* Constant expressions */ LLVMOpcode LLVMGetConstOpcode(LLVMValueRef ConstantVal); diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index d383b3db8d4..747d696a3df 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -567,11 +567,13 @@ LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count, return LLVMConstStructInContext(LLVMGetGlobalContext(), ConstantVals, Count, Packed); } - LLVMValueRef LLVMConstVector(LLVMValueRef *ScalarConstantVals, unsigned Size) { return wrap(ConstantVector::get( unwrap(ScalarConstantVals, Size), Size)); } +LLVMValueRef LLVMConstUnion(LLVMTypeRef Ty, LLVMValueRef Val) { + return wrap(ConstantUnion::get(unwrap(Ty), unwrap(Val))); +} /*--.. Constant expressions ................................................--*/ diff --git a/test/Bindings/Ocaml/vmcore.ml b/test/Bindings/Ocaml/vmcore.ml index 1ae8e606416..10a20ea6f7c 100644 --- a/test/Bindings/Ocaml/vmcore.ml +++ b/test/Bindings/Ocaml/vmcore.ml @@ -288,6 +288,12 @@ let test_constants () = ignore (define_global "const_structure" c m); insist ((struct_type context [| i16_type; i16_type; i32_type; i32_type |]) = (type_of c)); + + group "union"; + let t = union_type context [| i1_type; i16_type; i64_type; double_type |] in + let c = const_union t one in + ignore (define_global "Const_union" c m); + insist (t = (type_of c)); (* RUN: grep {const_null.*zeroinit} < %t.ll *)