From 3e0c83559397c87e06ef29c41385e7adc34573c2 Mon Sep 17 00:00:00 2001 From: Gordon Henriksen Date: Sun, 16 Mar 2008 20:08:03 +0000 Subject: [PATCH] C and Objective Caml bindings for the TargetData class. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48422 91177308-0d34-0410-b5e6-96231b3b80d8 --- Xcode/LLVM.xcodeproj/project.pbxproj | 24 ++++- bindings/ocaml/Makefile | 2 +- bindings/ocaml/target/Makefile | 20 ++++ bindings/ocaml/target/llvm_target.ml | 44 +++++++++ bindings/ocaml/target/llvm_target.mli | 102 ++++++++++++++++++++ bindings/ocaml/target/target_ocaml.c | 109 +++++++++++++++++++++ include/llvm-c/Target.h | 131 ++++++++++++++++++++++++++ lib/Target/Target.cpp | 93 ++++++++++++++++++ test/Bindings/Ocaml/scalar_opts.ml | 12 ++- test/Bindings/Ocaml/target.ml | 51 ++++++++++ 10 files changed, 583 insertions(+), 5 deletions(-) create mode 100644 bindings/ocaml/target/Makefile create mode 100644 bindings/ocaml/target/llvm_target.ml create mode 100644 bindings/ocaml/target/llvm_target.mli create mode 100644 bindings/ocaml/target/target_ocaml.c create mode 100644 include/llvm-c/Target.h create mode 100644 lib/Target/Target.cpp create mode 100644 test/Bindings/Ocaml/target.ml diff --git a/Xcode/LLVM.xcodeproj/project.pbxproj b/Xcode/LLVM.xcodeproj/project.pbxproj index 575c45e3088..5aa55de0f1b 100644 --- a/Xcode/LLVM.xcodeproj/project.pbxproj +++ b/Xcode/LLVM.xcodeproj/project.pbxproj @@ -243,6 +243,13 @@ 9FEDD5F10D8D73AB009F6DF1 /* Scalar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scalar.h; sourceTree = ""; }; 9FEDD5F70D8D797D009F6DF1 /* Scalar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Scalar.cpp; sourceTree = ""; }; 9FEDD6140D8D7C3B009F6DF1 /* scalar_opts.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = scalar_opts.ml; sourceTree = ""; }; + 9FEDD6B60D8D83D0009F6DF1 /* Target.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Target.cpp; sourceTree = ""; }; + 9FEDD6B80D8D83EC009F6DF1 /* Target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Target.h; sourceTree = ""; }; + 9FEDD6BB0D8D8408009F6DF1 /* lto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lto.h; sourceTree = ""; }; + 9FEDD6BD0D8D8426009F6DF1 /* target.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = target.ml; sourceTree = ""; }; + 9FEDD6C10D8D844E009F6DF1 /* llvm_target.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_target.ml; sourceTree = ""; }; + 9FEDD6C20D8D844E009F6DF1 /* llvm_target.mli */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_target.mli; sourceTree = ""; }; + 9FEDD6C40D8D844E009F6DF1 /* target_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = target_ocaml.c; sourceTree = ""; }; CF1ACC9709C9DE4400D3C5EB /* IntrinsicInst.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IntrinsicInst.cpp; path = ../lib/VMCore/IntrinsicInst.cpp; sourceTree = ""; }; CF26835B09178F5500C5F253 /* TargetInstrItineraries.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetInstrItineraries.h; sourceTree = ""; }; CF32AF5C0AEE6A4E00D24CD4 /* LLVMTargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLVMTargetMachine.cpp; sourceTree = ""; }; @@ -1275,6 +1282,7 @@ 9F7C2C520CB9496C00498408 /* bitwriter.ml */, 9F502AEC0D1D8CF8007939DF /* executionengine.ml */, 9FEDD6140D8D7C3B009F6DF1 /* scalar_opts.ml */, + 9FEDD6BD0D8D8426009F6DF1 /* target.ml */, 9F7C2C5D0CB9496C00498408 /* vmcore.ml */, ); path = Ocaml; @@ -1300,12 +1308,13 @@ 9FD3E56F0CA0116100E54D15 /* ocaml */ = { isa = PBXGroup; children = ( - 9F7040170D8D72FF00FD06FF /* transforms */, 9F502ACD0D1D8CA3007939DF /* executionengine */, 9F7C240B0CB81ECD00498408 /* analysis */, 9F4B0E5D0D0E02580061F270 /* bitreader */, 9FD3E5700CA0116100E54D15 /* bitwriter */, 9FD3E57A0CA0116100E54D15 /* llvm */, + 9FEDD6C00D8D844E009F6DF1 /* target */, + 9F7040170D8D72FF00FD06FF /* transforms */, ); path = ocaml; sourceTree = ""; @@ -1350,6 +1359,16 @@ path = Transforms; sourceTree = ""; }; + 9FEDD6C00D8D844E009F6DF1 /* target */ = { + isa = PBXGroup; + children = ( + 9FEDD6C10D8D844E009F6DF1 /* llvm_target.ml */, + 9FEDD6C20D8D844E009F6DF1 /* llvm_target.mli */, + 9FEDD6C40D8D844E009F6DF1 /* target_ocaml.c */, + ); + path = target; + sourceTree = ""; + }; CF8F1B480B64F7AB00BB4199 /* include/llvm-c */ = { isa = PBXGroup; children = ( @@ -1359,6 +1378,8 @@ 9FD3E58E0CA0125F00E54D15 /* Core.h */, 9FEB8C550D1CD1E200EE46BC /* ExecutionEngine.h */, CF8F1B490B64F7AB00BB4199 /* LinkTimeOptimizer.h */, + 9FEDD6BB0D8D8408009F6DF1 /* lto.h */, + 9FEDD6B80D8D83EC009F6DF1 /* Target.h */, 9FEDD5F00D8D73AB009F6DF1 /* Transforms */, ); name = "include/llvm-c"; @@ -1799,6 +1820,7 @@ DE66F09308ABEE6000323D32 /* X86 */, DE66EF1008ABEE5E00323D32 /* TargetRegisterInfo.cpp */, CF9BCD1508C75070001E7011 /* SubtargetFeature.cpp */, + 9FEDD6B60D8D83D0009F6DF1 /* Target.cpp */, DE66F08A08ABEE6000323D32 /* Target.td */, CF47BD860AAF487E00A8B13E /* TargetAsmInfo.cpp */, 9FE25D960CAB1759005383FC /* TargetCallingConv.td */, diff --git a/bindings/ocaml/Makefile b/bindings/ocaml/Makefile index 868b110652f..a89caefb4de 100644 --- a/bindings/ocaml/Makefile +++ b/bindings/ocaml/Makefile @@ -8,7 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL := ../.. -DIRS = llvm bitreader bitwriter analysis executionengine transforms +DIRS = llvm bitreader bitwriter analysis target executionengine transforms ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.ocaml ocamldoc: diff --git a/bindings/ocaml/target/Makefile b/bindings/ocaml/target/Makefile new file mode 100644 index 00000000000..5cd677b7665 --- /dev/null +++ b/bindings/ocaml/target/Makefile @@ -0,0 +1,20 @@ +##===- bindings/ocaml/target/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_target interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_target +DONT_BUILD_RELINKED := 1 +UsedComponents := target +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/target/llvm_target.ml b/bindings/ocaml/target/llvm_target.ml new file mode 100644 index 00000000000..ea5341d5e8b --- /dev/null +++ b/bindings/ocaml/target/llvm_target.ml @@ -0,0 +1,44 @@ +(*===-- llvm_target.ml - LLVM Ocaml Interface ------------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +module Endian = struct + type t = + | Big + | Little +end + +module TargetData = struct + type t + + external create : string -> t = "llvm_targetdata_create" + external add : t -> [ unit + = "llvm_targetdata_add" + external as_string : t -> string = "llvm_targetdata_as_string" + external invalidate_struct_layout : t -> Llvm.lltype -> unit + = "llvm_targetdata_invalidate_struct_layout" + external dispose : t -> unit = "llvm_targetdata_dispose" +end + +external byte_order : TargetData.t -> Endian.t = "llvm_byte_order" +external pointer_size : TargetData.t -> int = "llvm_pointer_size" +external intptr_type : TargetData.t -> Llvm.lltype = "LLVMIntPtrType" +external size_in_bits : TargetData.t -> Llvm.lltype -> Int64.t + = "llvm_size_in_bits" +external store_size : TargetData.t -> Llvm.lltype -> Int64.t = "llvm_store_size" +external abi_size : TargetData.t -> Llvm.lltype -> Int64.t = "llvm_abi_size" +external abi_align : TargetData.t -> Llvm.lltype -> int = "llvm_abi_align" +external stack_align : TargetData.t -> Llvm.lltype -> int = "llvm_stack_align" +external preferred_align : TargetData.t -> Llvm.lltype -> int + = "llvm_preferred_align" +external preferred_align_of_global : TargetData.t -> Llvm.llvalue -> int + = "llvm_preferred_align_of_global" +external element_at_offset : TargetData.t -> Llvm.lltype -> Int64.t -> int + = "llvm_element_at_offset" +external offset_of_element : TargetData.t -> Llvm.lltype -> int -> Int64.t + = "llvm_offset_of_element" diff --git a/bindings/ocaml/target/llvm_target.mli b/bindings/ocaml/target/llvm_target.mli new file mode 100644 index 00000000000..a44758f95b9 --- /dev/null +++ b/bindings/ocaml/target/llvm_target.mli @@ -0,0 +1,102 @@ +(*===-- llvm_target.mli - LLVM Ocaml Interface -----------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Target Information. + + This interface provides an ocaml API for LLVM target information, + the classes in the Target library. *) + +module Endian : sig + type t = + | Big + | Little +end + +module TargetData : sig + type t + + (** [TargetData.create rep] parses the target data string representation [rep]. + See the constructor llvm::TargetData::TargetData. *) + external create : string -> t = "llvm_targetdata_create" + + (** [add_target_data td pm] adds the target data [td] to the pass manager [pm]. + Does not take ownership of the target data. + See the method llvm::PassManagerBase::add. *) + external add : t -> [ unit + = "llvm_targetdata_add" + + (** [as_string td] is the string representation of the target data [td]. + See the constructor llvm::TargetData::TargetData. *) + external as_string : t -> string = "llvm_targetdata_as_string" + + (** Struct layouts are speculatively cached. If a TargetDataRef is alive when + types are being refined and removed, this method must be called whenever a + struct type is removed to avoid a dangling pointer in this cache. + See the method llvm::TargetData::InvalidateStructLayoutInfo. *) + external invalidate_struct_layout : t -> Llvm.lltype -> unit + = "llvm_targetdata_invalidate_struct_layout" + + (** Deallocates a TargetData. + See the destructor llvm::TargetData::~TargetData. *) + external dispose : t -> unit = "llvm_targetdata_dispose" +end + +(** Returns the byte order of a target, either LLVMBigEndian or + LLVMLittleEndian. + See the method llvm::TargetData::isLittleEndian. *) +external byte_order : TargetData.t -> Endian.t = "llvm_byte_order" + +(** Returns the pointer size in bytes for a target. + See the method llvm::TargetData::getPointerSize. *) +external pointer_size : TargetData.t -> int = "llvm_pointer_size" + +(** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::TargetData::getIntPtrType. *) +external intptr_type : TargetData.t -> Llvm.lltype = "LLVMIntPtrType" + +(** Computes the size of a type in bytes for a target. + See the method llvm::TargetData::getTypeSizeInBits. *) +external size_in_bits : TargetData.t -> Llvm.lltype -> Int64.t + = "llvm_size_in_bits" + +(** Computes the storage size of a type in bytes for a target. + See the method llvm::TargetData::getTypeStoreSize. *) +external store_size : TargetData.t -> Llvm.lltype -> Int64.t = "llvm_store_size" + +(** Computes the ABI size of a type in bytes for a target. + See the method llvm::TargetData::getABITypeSize. *) +external abi_size : TargetData.t -> Llvm.lltype -> Int64.t = "llvm_abi_size" + +(** Computes the ABI alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. *) +external abi_align : TargetData.t -> Llvm.lltype -> int = "llvm_abi_align" + +(** Computes the call frame alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. *) +external stack_align : TargetData.t -> Llvm.lltype -> int = "llvm_stack_align" + +(** Computes the preferred alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. *) +external preferred_align : TargetData.t -> Llvm.lltype -> int + = "llvm_preferred_align" + +(** Computes the preferred alignment of a global variable in bytes for a target. + See the method llvm::TargetData::getPreferredAlignment. *) +external preferred_align_of_global : TargetData.t -> Llvm.llvalue -> int + = "llvm_preferred_align_of_global" + +(** Computes the structure element that contains the byte offset for a target. + See the method llvm::StructLayout::getElementContainingOffset. *) +external element_at_offset : TargetData.t -> Llvm.lltype -> Int64.t -> int + = "llvm_element_at_offset" + +(** Computes the byte offset of the indexed struct element for a target. + See the method llvm::StructLayout::getElementContainingOffset. *) +external offset_of_element : TargetData.t -> Llvm.lltype -> int -> Int64.t + = "llvm_offset_of_element" diff --git a/bindings/ocaml/target/target_ocaml.c b/bindings/ocaml/target/target_ocaml.c new file mode 100644 index 00000000000..cc20e8187a7 --- /dev/null +++ b/bindings/ocaml/target/target_ocaml.c @@ -0,0 +1,109 @@ +/*===-- target_ocaml.c - LLVM Ocaml Glue ------------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Target.h" +#include "caml/alloc.h" + +/* string -> TargetData.t */ +CAMLprim LLVMTargetDataRef llvm_targetdata_create(value StringRep) { + return LLVMCreateTargetData(String_val(StringRep)); +} + +/* TargetData.t -> [ unit */ +CAMLprim value llvm_targetdata_add(LLVMTargetDataRef TD, LLVMPassManagerRef PM){ + LLVMAddTargetData(TD, PM); + return Val_unit; +} + +/* TargetData.t -> string */ +CAMLprim value llvm_targetdata_as_string(LLVMTargetDataRef TD) { + char *StringRep = LLVMCopyStringRepOfTargetData(TD); + value Copy = copy_string(StringRep); + LLVMDisposeMessage(StringRep); + return Copy; +} + +/* TargetData.t -> Llvm.lltype -> unit */ +CAMLprim value llvm_targetdata_invalidate_struct_layout(LLVMTargetDataRef TD, + LLVMTypeRef Ty) { + LLVMInvalidateStructLayout(TD, Ty); + return Val_unit; +} + +/* TargetData.t -> unit */ +CAMLprim value llvm_targetdata_dispose(LLVMTargetDataRef TD) { + LLVMDisposeTargetData(TD); + return Val_unit; +} + +/* TargetData.t -> Endian.t */ +CAMLprim value llvm_byte_order(LLVMTargetDataRef TD) { + return Val_int(LLVMByteOrder(TD)); +} + +/* TargetData.t -> int */ +CAMLprim value llvm_pointer_size(LLVMTargetDataRef TD) { + return Val_int(LLVMPointerSize(TD)); +} + +/* TargetData.t -> Llvm.lltype -> Int64.t */ +CAMLprim value llvm_size_in_bits(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return caml_copy_int64(LLVMSizeOfTypeInBits(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> Int64.t */ +CAMLprim value llvm_store_size(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return caml_copy_int64(LLVMStoreSizeOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> Int64.t */ +CAMLprim value llvm_abi_size(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return caml_copy_int64(LLVMABISizeOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> int */ +CAMLprim value llvm_abi_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return Val_int(LLVMABIAlignmentOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> int */ +CAMLprim value llvm_stack_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return Val_int(LLVMCallFrameAlignmentOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> int */ +CAMLprim value llvm_preferred_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return Val_int(LLVMPreferredAlignmentOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.llvalue -> int */ +CAMLprim value llvm_preferred_align_of_global(LLVMTargetDataRef TD, + LLVMValueRef GlobalVar) { + return Val_int(LLVMPreferredAlignmentOfGlobal(TD, GlobalVar)); +} + +/* TargetData.t -> Llvm.lltype -> Int64.t -> int */ +CAMLprim value llvm_element_at_offset(LLVMTargetDataRef TD, LLVMTypeRef Ty, + value Offset) { + return Val_int(LLVMElementAtOffset(TD, Ty, Int_val(Offset))); +} + +/* TargetData.t -> Llvm.lltype -> int -> Int64.t */ +CAMLprim value llvm_offset_of_element(LLVMTargetDataRef TD, LLVMTypeRef Ty, + value Index) { + return caml_copy_int64(LLVMOffsetOfElement(TD, Ty, Int_val(Index))); +} diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h new file mode 100644 index 00000000000..d3b4e2f3f7f --- /dev/null +++ b/include/llvm-c/Target.h @@ -0,0 +1,131 @@ +/*===-- llvm-c/Target.h - Target Lib C Iface --------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMTarget.a, which *| +|* implements target information. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TARGET_H +#define LLVM_C_TARGET_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { LLVMBigEndian, LLVMLittleEndian }; +typedef int LLVMByteOrdering; + +typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; +typedef struct LLVMStructLayout *LLVMStructLayoutRef; + + +/*===-- Target Data -------------------------------------------------------===*/ + +/** Creates target data from a target layout string. + See the constructor llvm::TargetData::TargetData. */ +LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep); + +/** Adds target data information to a pass manager. This does not take ownership + of the target data. + See the method llvm::PassManagerBase::add. */ +void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef); + +/** Converts target data to a target layout string. The string must be disposed + with LLVMDisposeMessage. + See the constructor llvm::TargetData::TargetData. */ +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef); + +/** Returns the byte order of a target, either LLVMBigEndian or + LLVMLittleEndian. + See the method llvm::TargetData::isLittleEndian. */ +LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef); + +/** Returns the pointer size in bytes for a target. + See the method llvm::TargetData::getPointerSize. */ +unsigned LLVMPointerSize(LLVMTargetDataRef); + +/** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::TargetData::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef); + +/** Computes the size of a type in bytes for a target. + See the method llvm::TargetData::getTypeSizeInBits. */ +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the storage size of a type in bytes for a target. + See the method llvm::TargetData::getTypeStoreSize. */ +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the ABI size of a type in bytes for a target. + See the method llvm::TargetData::getABITypeSize. */ +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the ABI alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the call frame alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the preferred alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the preferred alignment of a global variable in bytes for a target. + See the method llvm::TargetData::getPreferredAlignment. */ +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef, + LLVMValueRef GlobalVar); + +/** Computes the structure element that contains the byte offset for a target. + See the method llvm::StructLayout::getElementContainingOffset. */ +unsigned LLVMElementAtOffset(LLVMTargetDataRef, LLVMTypeRef StructTy, + unsigned long long Offset); + +/** Computes the byte offset of the indexed struct element for a target. + See the method llvm::StructLayout::getElementContainingOffset. */ +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef, LLVMTypeRef StructTy, + unsigned Element); + +/** Struct layouts are speculatively cached. If a TargetDataRef is alive when + types are being refined and removed, this method must be called whenever a + struct type is removed to avoid a dangling pointer in this cache. + See the method llvm::TargetData::InvalidateStructLayoutInfo. */ +void LLVMInvalidateStructLayout(LLVMTargetDataRef, LLVMTypeRef StructTy); + +/** Deallocates a TargetData. + See the destructor llvm::TargetData::~TargetData. */ +void LLVMDisposeTargetData(LLVMTargetDataRef); + + +#ifdef __cplusplus +} + +namespace llvm { + class TargetData; + + inline TargetData *unwrap(LLVMTargetDataRef P) { + return reinterpret_cast(P); + } + + inline LLVMTargetDataRef wrap(const TargetData *P) { + return reinterpret_cast(const_cast(P)); + } +} + +#endif /* defined(__cplusplus) */ + +#endif diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp new file mode 100644 index 00000000000..375cd642de7 --- /dev/null +++ b/lib/Target/Target.cpp @@ -0,0 +1,93 @@ +//===-- Target.cpp --------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the C bindings for libLLVMTarget.a, which implements +// target information. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Target.h" +#include "llvm/PassManager.h" +#include "llvm/Target/TargetData.h" + +using namespace llvm; + +LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep) { + return wrap(new TargetData(StringRep)); +} + +void LLVMAddTargetData(LLVMTargetDataRef TD, LLVMPassManagerRef PM) { + unwrap(PM)->add(new TargetData(*unwrap(TD))); +} + +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef TD) { + std::string StringRep = unwrap(TD)->getStringRepresentation(); + return strdup(StringRep.c_str()); +} + +LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef TD) { + return unwrap(TD)->isLittleEndian(); +} + +unsigned LLVMPointerSize(LLVMTargetDataRef TD) { + return unwrap(TD)->getPointerSize(); +} + +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef TD) { + return wrap(unwrap(TD)->getIntPtrType()); +} + +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getTypeSizeInBits(unwrap(Ty)); +} + +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getTypeStoreSize(unwrap(Ty)); +} + +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getABITypeSize(unwrap(Ty)); +} + +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getABITypeAlignment(unwrap(Ty)); +} + +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getCallFrameTypeAlignment(unwrap(Ty)); +} + +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return unwrap(TD)->getPrefTypeAlignment(unwrap(Ty)); +} + +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef TD, + LLVMValueRef GlobalVar) { + return unwrap(TD)->getPreferredAlignment(unwrap(GlobalVar)); +} + +unsigned LLVMElementAtOffset(LLVMTargetDataRef TD, LLVMTypeRef StructTy, + unsigned long long Offset) { + const StructType *STy = unwrap(StructTy); + return unwrap(TD)->getStructLayout(STy)->getElementContainingOffset(Offset); +} + +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD, LLVMTypeRef StructTy, + unsigned Element) { + const StructType *STy = unwrap(StructTy); + return unwrap(TD)->getStructLayout(STy)->getElementOffset(Element); +} + +void LLVMInvalidateStructLayout(LLVMTargetDataRef TD, LLVMTypeRef StructTy) { + unwrap(TD)->InvalidateStructLayoutInfo(unwrap(StructTy)); +} + +void LLVMDisposeTargetData(LLVMTargetDataRef TD) { + delete unwrap(TD); +} diff --git a/test/Bindings/Ocaml/scalar_opts.ml b/test/Bindings/Ocaml/scalar_opts.ml index 2f520b10019..7f850cbeb99 100644 --- a/test/Bindings/Ocaml/scalar_opts.ml +++ b/test/Bindings/Ocaml/scalar_opts.ml @@ -1,4 +1,4 @@ -(* RUN: %ocamlc -warn-error A llvm.cma llvm_scalar_opts.cma %s -o %t +(* RUN: %ocamlc -warn-error A llvm.cma llvm_scalar_opts.cma llvm_target.cma %s -o %t *) (* Note: It takes several seconds for ocamlc to link an executable with @@ -7,6 +7,7 @@ open Llvm open Llvm_scalar_opts +open Llvm_target (* Tiny unit test framework - really just to help find which line is busted *) @@ -31,8 +32,11 @@ let test_transforms () = let fn = define_function "fn" fty m in ignore (build_ret_void (builder_at_end (entry_block fn))); + let td = TargetData.create (target_triple m) in + ignore (PassManager.create_function mp - (* ++ add_instruction_combining Requires target data. *) + ++ TargetData.add td + ++ add_instruction_combining ++ add_reassociation ++ add_gvn ++ add_cfg_simplification @@ -40,7 +44,9 @@ let test_transforms () = ++ PassManager.initialize ++ PassManager.run_function fn ++ PassManager.finalize - ++ PassManager.dispose) + ++ PassManager.dispose); + + TargetData.dispose td (*===-- Driver ------------------------------------------------------------===*) diff --git a/test/Bindings/Ocaml/target.ml b/test/Bindings/Ocaml/target.ml new file mode 100644 index 00000000000..2e83b318d8e --- /dev/null +++ b/test/Bindings/Ocaml/target.ml @@ -0,0 +1,51 @@ +(* RUN: %ocamlc -warn-error A llvm.cma llvm_target.cma %s -o %t + *) + +(* Note: It takes several seconds for ocamlc to link an executable with + libLLVMCore.a, so it's better to write a big test than a bunch of + little ones. *) + +open Llvm +open Llvm_target + + +(* Tiny unit test framework - really just to help find which line is busted *) +let suite name f = + prerr_endline (name ^ ":"); + f () + + +(*===-- Fixture -----------------------------------------------------------===*) + +let filename = Sys.argv.(1) +let m = create_module filename + + +(*===-- Target Data -------------------------------------------------------===*) + +let test_target_data () = + let td = TargetData.create (target_triple m) in + let sty = struct_type [| i32_type; i64_type |] in + + ignore (TargetData.as_string td); + ignore (TargetData.invalidate_struct_layout td sty); + ignore (byte_order td); + ignore (pointer_size td); + ignore (intptr_type td); + ignore (size_in_bits td sty); + ignore (store_size td sty); + ignore (abi_size td sty); + ignore (stack_align td sty); + ignore (preferred_align td sty); + ignore (preferred_align_of_global td (declare_global sty "g" m)); + ignore (element_at_offset td sty (Int64.of_int 1)); + ignore (offset_of_element td sty 1); + + TargetData.dispose td + + +(*===-- Driver ------------------------------------------------------------===*) + +let _ = + suite "target data" test_target_data; + dispose_module m -- 2.34.1