diff options
Diffstat (limited to 'bindings')
81 files changed, 5570 insertions, 1377 deletions
diff --git a/bindings/Makefile b/bindings/Makefile index c545b28..70e9e6c 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -11,6 +11,10 @@ LEVEL := .. include $(LEVEL)/Makefile.config -PARALLEL_DIRS = $(BINDINGS_TO_BUILD) +PARALLEL_DIRS = + +ifneq (,$(filter ocaml,$(BINDINGS_TO_BUILD))) +PARALLEL_DIRS += ocaml +endif include $(LEVEL)/Makefile.common diff --git a/bindings/go/README.txt b/bindings/go/README.txt new file mode 100644 index 0000000..2fc4afa --- /dev/null +++ b/bindings/go/README.txt @@ -0,0 +1,53 @@ +This directory contains LLVM bindings for the Go programming language +(http://golang.org). + +Prerequisites +------------- + +* Go 1.2+. +* CMake (to build LLVM). + +Using the bindings +------------------ + +The package path "llvm.org/llvm/bindings/go/llvm" can be used to +import the latest development version of LLVM from SVN. Paths such as +"llvm.org/llvm.v36/bindings/go/llvm" refer to released versions of LLVM. + +It is recommended to use the "-d" flag with "go get" to download the +package or a dependency, as an additional step is required to build LLVM +(see "Building LLVM" below). + +Building LLVM +------------- + +The script "build.sh" in this directory can be used to build LLVM and prepare +it to be used by the bindings. If you receive an error message from "go build" +like this: + + ./analysis.go:4:84: fatal error: llvm-c/Analysis.h: No such file or directory + #include <llvm-c/Analysis.h> // If you are getting an error here read bindings/go/README.txt + +or like this: + + ./llvm_dep.go:5: undefined: run_build_sh + +it means that LLVM needs to be built or updated by running the script. + + $ $GOPATH/src/llvm.org/llvm/bindings/go/build.sh + +Any command line arguments supplied to the script are passed to LLVM's CMake +build system. A good set of arguments to use during development are: + + $ $GOPATH/src/llvm.org/llvm/bindings/go/build.sh -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD=host -DBUILD_SHARED_LIBS=ON + +Note that CMake keeps a cache of build settings so once you have built +LLVM there is no need to pass these arguments again after updating. + +Alternatively, you can build LLVM yourself, but you must then set the +CGO_CPPFLAGS, CGO_CXXFLAGS and CGO_LDFLAGS environment variables: + + $ export CGO_CPPFLAGS="`/path/to/llvm-build/bin/llvm-config --cppflags`" + $ export CGO_CXXFLAGS=-std=c++11 + $ export CGO_LDFLAGS="`/path/to/llvm-build/bin/llvm-config --ldflags --libs --system-libs all`" + $ go build -tags byollvm diff --git a/bindings/go/build.sh b/bindings/go/build.sh new file mode 100755 index 0000000..3177852 --- /dev/null +++ b/bindings/go/build.sh @@ -0,0 +1,28 @@ +#!/bin/sh -xe + +gollvmdir=$(dirname "$0")/llvm + +workdir=$gollvmdir/workdir +llvmdir=$gollvmdir/../../.. +llvm_builddir=$workdir/llvm_build + +mkdir -p $llvm_builddir + +cmake_flags="../../../../.. $@" +llvm_config="$llvm_builddir/bin/llvm-config" +llvm_go="$llvm_builddir/bin/llvm-go" + +if test -n "`which ninja`" ; then + # If Ninja is available, we can speed up the build by building only the + # required subset of LLVM. + (cd $llvm_builddir && cmake -G Ninja $cmake_flags) + ninja -C $llvm_builddir llvm-config llvm-go + llvm_components="$($llvm_go print-components)" + llvm_buildtargets="$($llvm_config --libs $llvm_components | sed -e 's/-l//g')" + ninja -C $llvm_builddir $llvm_buildtargets FileCheck +else + (cd $llvm_builddir && cmake $cmake_flags) + make -C $llvm_builddir -j4 +fi + +$llvm_go print-config > $gollvmdir/llvm_config.go diff --git a/bindings/go/conftest.go b/bindings/go/conftest.go new file mode 100644 index 0000000..d97fb89 --- /dev/null +++ b/bindings/go/conftest.go @@ -0,0 +1,16 @@ +package main + +import ( + "go/build" + "os" +) + +// Tests that the Go compiler is at least version 1.2. +func main() { + for _, tag := range build.Default.ReleaseTags { + if tag == "go1.2" { + os.Exit(0) + } + } + os.Exit(1) +} diff --git a/bindings/go/llvm/DIBuilderBindings.cpp b/bindings/go/llvm/DIBuilderBindings.cpp new file mode 100644 index 0000000..94fa96f --- /dev/null +++ b/bindings/go/llvm/DIBuilderBindings.cpp @@ -0,0 +1,222 @@ +//===- DIBuilderBindings.cpp - Bindings for DIBuilder ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines C bindings for the DIBuilder class. +// +//===----------------------------------------------------------------------===// + +#include "DIBuilderBindings.h" + +#include "llvm/IR/Module.h" +#include "llvm/IR/DIBuilder.h" + +using namespace llvm; + +namespace { +template <typename T> +T unwrapDI(LLVMValueRef v) { + return v ? T(unwrap<MDNode>(v)) : T(); +} +} + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBuilder, LLVMDIBuilderRef) + +LLVMDIBuilderRef LLVMNewDIBuilder(LLVMModuleRef mref) { + Module *m = unwrap(mref); + return wrap(new DIBuilder(*m)); +} + +void LLVMDIBuilderDestroy(LLVMDIBuilderRef dref) { + DIBuilder *d = unwrap(dref); + delete d; +} + +void LLVMDIBuilderFinalize(LLVMDIBuilderRef dref) { unwrap(dref)->finalize(); } + +LLVMValueRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef Dref, + unsigned Lang, const char *File, + const char *Dir, + const char *Producer, int Optimized, + const char *Flags, + unsigned RuntimeVersion) { + DIBuilder *D = unwrap(Dref); + DICompileUnit CU = D->createCompileUnit(Lang, File, Dir, Producer, Optimized, + Flags, RuntimeVersion); + return wrap(CU); +} + +LLVMValueRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef Dref, const char *File, + const char *Dir) { + DIBuilder *D = unwrap(Dref); + DIFile F = D->createFile(File, Dir); + return wrap(F); +} + +LLVMValueRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Dref, + LLVMValueRef Scope, + LLVMValueRef File, unsigned Line, + unsigned Column) { + DIBuilder *D = unwrap(Dref); + DILexicalBlock LB = D->createLexicalBlock( + unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Column); + return wrap(LB); +} + +LLVMValueRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Dref, + LLVMValueRef Scope, + LLVMValueRef File, + unsigned Discriminator) { + DIBuilder *D = unwrap(Dref); + DILexicalBlockFile LBF = D->createLexicalBlockFile( + unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Discriminator); + return wrap(LBF); +} + +LLVMValueRef LLVMDIBuilderCreateFunction( + LLVMDIBuilderRef Dref, LLVMValueRef Scope, const char *Name, + const char *LinkageName, LLVMValueRef File, unsigned Line, + LLVMValueRef CompositeType, int IsLocalToUnit, int IsDefinition, + unsigned ScopeLine, unsigned Flags, int IsOptimized, LLVMValueRef Func) { + DIBuilder *D = unwrap(Dref); + DISubprogram SP = D->createFunction( + unwrapDI<DIDescriptor>(Scope), Name, LinkageName, unwrapDI<DIFile>(File), + Line, unwrapDI<DICompositeType>(CompositeType), IsLocalToUnit, + IsDefinition, ScopeLine, Flags, IsOptimized, unwrap<Function>(Func)); + return wrap(SP); +} + +LLVMValueRef LLVMDIBuilderCreateLocalVariable( + LLVMDIBuilderRef Dref, unsigned Tag, LLVMValueRef Scope, const char *Name, + LLVMValueRef File, unsigned Line, LLVMValueRef Ty, int AlwaysPreserve, + unsigned Flags, unsigned ArgNo) { + DIBuilder *D = unwrap(Dref); + DIVariable V = D->createLocalVariable( + Tag, unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line, + unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo); + return wrap(V); +} + +LLVMValueRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref, + const char *Name, uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding) { + DIBuilder *D = unwrap(Dref); + DIBasicType T = D->createBasicType(Name, SizeInBits, AlignInBits, Encoding); + return wrap(T); +} + +LLVMValueRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef Dref, + LLVMValueRef PointeeType, + uint64_t SizeInBits, + uint64_t AlignInBits, + const char *Name) { + DIBuilder *D = unwrap(Dref); + DIDerivedType T = D->createPointerType(unwrapDI<DIType>(PointeeType), + SizeInBits, AlignInBits, Name); + return wrap(T); +} + +LLVMValueRef LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Dref, + LLVMValueRef File, + LLVMValueRef ParameterTypes) { + DIBuilder *D = unwrap(Dref); + DICompositeType CT = D->createSubroutineType( + unwrapDI<DIFile>(File), unwrapDI<DITypeArray>(ParameterTypes)); + return wrap(CT); +} + +LLVMValueRef LLVMDIBuilderCreateStructType( + LLVMDIBuilderRef Dref, LLVMValueRef Scope, const char *Name, + LLVMValueRef File, unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Flags, LLVMValueRef DerivedFrom, LLVMValueRef ElementTypes) { + DIBuilder *D = unwrap(Dref); + DICompositeType CT = D->createStructType( + unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line, + SizeInBits, AlignInBits, Flags, unwrapDI<DIType>(DerivedFrom), + unwrapDI<DIArray>(ElementTypes)); + return wrap(CT); +} + +LLVMValueRef LLVMDIBuilderCreateMemberType( + LLVMDIBuilderRef Dref, LLVMValueRef Scope, const char *Name, + LLVMValueRef File, unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, LLVMValueRef Ty) { + DIBuilder *D = unwrap(Dref); + DIDerivedType DT = D->createMemberType( + unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line, + SizeInBits, AlignInBits, OffsetInBits, Flags, unwrapDI<DIType>(Ty)); + return wrap(DT); +} + +LLVMValueRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Dref, + uint64_t SizeInBits, + uint64_t AlignInBits, + LLVMValueRef ElementType, + LLVMValueRef Subscripts) { + DIBuilder *D = unwrap(Dref); + DICompositeType CT = + D->createArrayType(SizeInBits, AlignInBits, unwrapDI<DIType>(ElementType), + unwrapDI<DIArray>(Subscripts)); + return wrap(CT); +} + +LLVMValueRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, LLVMValueRef Ty, + const char *Name, LLVMValueRef File, + unsigned Line, LLVMValueRef Context) { + DIBuilder *D = unwrap(Dref); + DIDerivedType DT = + D->createTypedef(unwrapDI<DIType>(Ty), Name, unwrapDI<DIFile>(File), Line, + unwrapDI<DIDescriptor>(Context)); + return wrap(DT); +} + +LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Dref, int64_t Lo, + int64_t Count) { + DIBuilder *D = unwrap(Dref); + DISubrange S = D->getOrCreateSubrange(Lo, Count); + return wrap(S); +} + +LLVMValueRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Dref, + LLVMValueRef *Data, size_t Length) { + DIBuilder *D = unwrap(Dref); + Value **DataValue = unwrap(Data); + ArrayRef<Value *> Elements(DataValue, Length); + DIArray A = D->getOrCreateArray(Elements); + return wrap(A); +} + +LLVMValueRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Dref, + LLVMValueRef *Data, + size_t Length) { + DIBuilder *D = unwrap(Dref); + Value **DataValue = unwrap(Data); + ArrayRef<Value *> Elements(DataValue, Length); + DITypeArray A = D->getOrCreateTypeArray(Elements); + return wrap(A); +} + +LLVMValueRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, int64_t *Addr, + size_t Length) { + DIBuilder *D = unwrap(Dref); + DIExpression Expr = D->createExpression(ArrayRef<int64_t>(Addr, Length)); + return wrap(Expr); +} + +LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref, + LLVMValueRef Storage, + LLVMValueRef VarInfo, + LLVMValueRef Expr, + LLVMBasicBlockRef Block) { + DIBuilder *D = unwrap(Dref); + Instruction *Instr = + D->insertDeclare(unwrap(Storage), unwrapDI<DIVariable>(VarInfo), + unwrapDI<DIExpression>(Expr), unwrap(Block)); + return wrap(Instr); +} diff --git a/bindings/go/llvm/DIBuilderBindings.h b/bindings/go/llvm/DIBuilderBindings.h new file mode 100644 index 0000000..e6fe02a --- /dev/null +++ b/bindings/go/llvm/DIBuilderBindings.h @@ -0,0 +1,123 @@ +//===- DIBuilderBindings.h - Bindings for DIBuilder -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines C bindings for the DIBuilder class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_DIBUILDERBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_DIBUILDERBINDINGS_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// FIXME: These bindings shouldn't be Go-specific and should eventually move to +// a (somewhat) less stable collection of C APIs for use in creating bindings of +// LLVM in other languages. + +typedef struct LLVMOpaqueDIBuilder *LLVMDIBuilderRef; + +LLVMDIBuilderRef LLVMNewDIBuilder(LLVMModuleRef m); + +void LLVMDIBuilderDestroy(LLVMDIBuilderRef d); +void LLVMDIBuilderFinalize(LLVMDIBuilderRef d); + +LLVMValueRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef D, + unsigned Language, const char *File, + const char *Dir, + const char *Producer, int Optimized, + const char *Flags, + unsigned RuntimeVersion); + +LLVMValueRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef D, const char *File, + const char *Dir); + +LLVMValueRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef D, + LLVMValueRef Scope, + LLVMValueRef File, unsigned Line, + unsigned Column); + +LLVMValueRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef D, + LLVMValueRef Scope, + LLVMValueRef File, + unsigned Discriminator); + +LLVMValueRef LLVMDIBuilderCreateFunction( + LLVMDIBuilderRef D, LLVMValueRef Scope, const char *Name, + const char *LinkageName, LLVMValueRef File, unsigned Line, + LLVMValueRef CompositeType, int IsLocalToUnit, int IsDefinition, + unsigned ScopeLine, unsigned Flags, int IsOptimized, LLVMValueRef Function); + +LLVMValueRef LLVMDIBuilderCreateLocalVariable( + LLVMDIBuilderRef D, unsigned Tag, LLVMValueRef Scope, const char *Name, + LLVMValueRef File, unsigned Line, LLVMValueRef Ty, int AlwaysPreserve, + unsigned Flags, unsigned ArgNo); + +LLVMValueRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef D, const char *Name, + uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding); + +LLVMValueRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef D, + LLVMValueRef PointeeType, + uint64_t SizeInBits, + uint64_t AlignInBits, + const char *Name); + +LLVMValueRef LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef D, + LLVMValueRef File, + LLVMValueRef ParameterTypes); + +LLVMValueRef LLVMDIBuilderCreateStructType( + LLVMDIBuilderRef D, LLVMValueRef Scope, const char *Name, LLVMValueRef File, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, + LLVMValueRef DerivedFrom, LLVMValueRef ElementTypes); + +LLVMValueRef LLVMDIBuilderCreateMemberType( + LLVMDIBuilderRef D, LLVMValueRef Scope, const char *Name, LLVMValueRef File, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, LLVMValueRef Ty); + +LLVMValueRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef D, + uint64_t SizeInBits, + uint64_t AlignInBits, + LLVMValueRef ElementType, + LLVMValueRef Subscripts); + +LLVMValueRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef D, LLVMValueRef Ty, + const char *Name, LLVMValueRef File, + unsigned Line, LLVMValueRef Context); + +LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef D, int64_t Lo, + int64_t Count); + +LLVMValueRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef D, + LLVMValueRef *Data, size_t Length); + +LLVMValueRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef D, + LLVMValueRef *Data, + size_t Length); + +LLVMValueRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, int64_t *Addr, + size_t Length); + +LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef D, + LLVMValueRef Storage, + LLVMValueRef VarInfo, + LLVMValueRef Expr, + LLVMBasicBlockRef Block); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/bindings/go/llvm/IRBindings.cpp b/bindings/go/llvm/IRBindings.cpp new file mode 100644 index 0000000..67a54a2 --- /dev/null +++ b/bindings/go/llvm/IRBindings.cpp @@ -0,0 +1,47 @@ +//===- IRBindings.cpp - Additional bindings for ir ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines additional C bindings for the ir component. +// +//===----------------------------------------------------------------------===// + +#include "IRBindings.h" + +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Function.h" + +using namespace llvm; + +void LLVMAddFunctionAttr2(LLVMValueRef Fn, uint64_t PA) { + Function *Func = unwrap<Function>(Fn); + const AttributeSet PAL = Func->getAttributes(); + AttrBuilder B(PA); + const AttributeSet PALnew = + PAL.addAttributes(Func->getContext(), AttributeSet::FunctionIndex, + AttributeSet::get(Func->getContext(), + AttributeSet::FunctionIndex, B)); + Func->setAttributes(PALnew); +} + +uint64_t LLVMGetFunctionAttr2(LLVMValueRef Fn) { + Function *Func = unwrap<Function>(Fn); + const AttributeSet PAL = Func->getAttributes(); + return PAL.Raw(AttributeSet::FunctionIndex); +} + +void LLVMRemoveFunctionAttr2(LLVMValueRef Fn, uint64_t PA) { + Function *Func = unwrap<Function>(Fn); + const AttributeSet PAL = Func->getAttributes(); + AttrBuilder B(PA); + const AttributeSet PALnew = + PAL.removeAttributes(Func->getContext(), AttributeSet::FunctionIndex, + AttributeSet::get(Func->getContext(), + AttributeSet::FunctionIndex, B)); + Func->setAttributes(PALnew); +} diff --git a/bindings/go/llvm/IRBindings.h b/bindings/go/llvm/IRBindings.h new file mode 100644 index 0000000..cc63e4e --- /dev/null +++ b/bindings/go/llvm/IRBindings.h @@ -0,0 +1,37 @@ +//===- IRBindings.h - Additional bindings for IR ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines additional C bindings for the IR component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_IRBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_IRBINDINGS_H + +#include "llvm-c/Core.h" +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// These functions duplicate the LLVM*FunctionAttr functions in the stable C +// API. We cannot use the existing functions because they take 32-bit attribute +// values, and the Go bindings expose all of the LLVM attributes, some of which +// have values >= 1<<32. + +void LLVMAddFunctionAttr2(LLVMValueRef Fn, uint64_t PA); +uint64_t LLVMGetFunctionAttr2(LLVMValueRef Fn); +void LLVMRemoveFunctionAttr2(LLVMValueRef Fn, uint64_t PA); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bindings/go/llvm/InstrumentationBindings.cpp b/bindings/go/llvm/InstrumentationBindings.cpp new file mode 100644 index 0000000..b604abb --- /dev/null +++ b/bindings/go/llvm/InstrumentationBindings.cpp @@ -0,0 +1,42 @@ +//===- InstrumentationBindings.cpp - instrumentation bindings -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines C bindings for the instrumentation component. +// +//===----------------------------------------------------------------------===// + +#include "InstrumentationBindings.h" + +#include "llvm-c/Core.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Transforms/Instrumentation.h" + +using namespace llvm; + +void LLVMAddAddressSanitizerFunctionPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createAddressSanitizerFunctionPass()); +} + +void LLVMAddAddressSanitizerModulePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createAddressSanitizerModulePass()); +} + +void LLVMAddThreadSanitizerPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createThreadSanitizerPass()); +} + +void LLVMAddMemorySanitizerPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createMemorySanitizerPass()); +} + +void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, + const char *ABIListFile) { + unwrap(PM)->add(createDataFlowSanitizerPass(ABIListFile)); +} diff --git a/bindings/go/llvm/InstrumentationBindings.h b/bindings/go/llvm/InstrumentationBindings.h new file mode 100644 index 0000000..e8dbd59 --- /dev/null +++ b/bindings/go/llvm/InstrumentationBindings.h @@ -0,0 +1,38 @@ +//===- InstrumentationBindings.h - instrumentation bindings -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines C bindings for the Transforms/Instrumentation component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_INSTRUMENTATIONBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_INSTRUMENTATIONBINDINGS_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// FIXME: These bindings shouldn't be Go-specific and should eventually move to +// a (somewhat) less stable collection of C APIs for use in creating bindings of +// LLVM in other languages. + +void LLVMAddAddressSanitizerFunctionPass(LLVMPassManagerRef PM); +void LLVMAddAddressSanitizerModulePass(LLVMPassManagerRef PM); +void LLVMAddThreadSanitizerPass(LLVMPassManagerRef PM); +void LLVMAddMemorySanitizerPass(LLVMPassManagerRef PM); +void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, + const char *ABIListFile); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bindings/go/llvm/SupportBindings.cpp b/bindings/go/llvm/SupportBindings.cpp new file mode 100644 index 0000000..df5f865 --- /dev/null +++ b/bindings/go/llvm/SupportBindings.cpp @@ -0,0 +1,27 @@ +//===- SupportBindings.cpp - Additional bindings for support --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines additional C bindings for the support component. +// +//===----------------------------------------------------------------------===// + +#include "SupportBindings.h" + +#include "llvm/Support/DynamicLibrary.h" +#include <stdlib.h> +#include <string.h> + +void LLVMLoadLibraryPermanently2(const char *Filename, char **ErrMsg) { + std::string ErrMsgStr; + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename, &ErrMsgStr)) { + *ErrMsg = static_cast<char *>(malloc(ErrMsgStr.size() + 1)); + memcpy(static_cast<void *>(*ErrMsg), + static_cast<const void *>(ErrMsgStr.c_str()), ErrMsgStr.size() + 1); + } +} diff --git a/bindings/go/llvm/SupportBindings.h b/bindings/go/llvm/SupportBindings.h new file mode 100644 index 0000000..efcd667 --- /dev/null +++ b/bindings/go/llvm/SupportBindings.h @@ -0,0 +1,30 @@ +//===- SupportBindings.h - Additional bindings for Support ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines additional C bindings for the Support component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_SUPPORTBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_SUPPORTBINDINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +// This function duplicates the LLVMLoadLibraryPermanently function in the +// stable C API and adds an extra ErrMsg parameter to retrieve the error +// message. +void LLVMLoadLibraryPermanently2(const char *Filename, char **ErrMsg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bindings/go/llvm/analysis.go b/bindings/go/llvm/analysis.go new file mode 100644 index 0000000..7b0d8e3 --- /dev/null +++ b/bindings/go/llvm/analysis.go @@ -0,0 +1,68 @@ +//===- analysis.go - Bindings for analysis --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the analysis component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Analysis.h" // If you are getting an error here read bindings/go/README.txt +#include <stdlib.h> +*/ +import "C" +import "errors" + +type VerifierFailureAction C.LLVMVerifierFailureAction + +const ( + // verifier will print to stderr and abort() + AbortProcessAction VerifierFailureAction = C.LLVMAbortProcessAction + // verifier will print to stderr and return 1 + PrintMessageAction VerifierFailureAction = C.LLVMPrintMessageAction + // verifier will just return 1 + ReturnStatusAction VerifierFailureAction = C.LLVMReturnStatusAction +) + +// Verifies that a module is valid, taking the specified action if not. +// Optionally returns a human-readable description of any invalid constructs. +func VerifyModule(m Module, a VerifierFailureAction) error { + var cmsg *C.char + broken := C.LLVMVerifyModule(m.C, C.LLVMVerifierFailureAction(a), &cmsg) + + // C++'s verifyModule means isModuleBroken, so it returns false if + // there are no errors + if broken != 0 { + err := errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + return err + } + return nil +} + +var verifyFunctionError = errors.New("Function is broken") + +// Verifies that a single function is valid, taking the specified action. +// Useful for debugging. +func VerifyFunction(f Value, a VerifierFailureAction) error { + broken := C.LLVMVerifyFunction(f.C, C.LLVMVerifierFailureAction(a)) + + // C++'s verifyFunction means isFunctionBroken, so it returns false if + // there are no errors + if broken != 0 { + return verifyFunctionError + } + return nil +} + +// Open up a ghostview window that displays the CFG of the current function. +// Useful for debugging. +func ViewFunctionCFG(f Value) { C.LLVMViewFunctionCFG(f.C) } +func ViewFunctionCFGOnly(f Value) { C.LLVMViewFunctionCFGOnly(f.C) } diff --git a/bindings/go/llvm/bitreader.go b/bindings/go/llvm/bitreader.go new file mode 100644 index 0000000..98112a9 --- /dev/null +++ b/bindings/go/llvm/bitreader.go @@ -0,0 +1,50 @@ +//===- bitreader.go - Bindings for bitreader ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the bitreader component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/BitReader.h" +#include <stdlib.h> +*/ +import "C" + +import ( + "errors" + "unsafe" +) + +// ParseBitcodeFile parses the LLVM IR (bitcode) in the file with the +// specified name, and returns a new LLVM module. +func ParseBitcodeFile(name string) (Module, error) { + var buf C.LLVMMemoryBufferRef + var errmsg *C.char + var cfilename *C.char = C.CString(name) + defer C.free(unsafe.Pointer(cfilename)) + result := C.LLVMCreateMemoryBufferWithContentsOfFile(cfilename, &buf, &errmsg) + if result != 0 { + err := errors.New(C.GoString(errmsg)) + C.free(unsafe.Pointer(errmsg)) + return Module{}, err + } + defer C.LLVMDisposeMemoryBuffer(buf) + + var m Module + if C.LLVMParseBitcode(buf, &m.C, &errmsg) == 0 { + return m, nil + } + + err := errors.New(C.GoString(errmsg)) + C.free(unsafe.Pointer(errmsg)) + return Module{}, err +} diff --git a/bindings/go/llvm/bitwriter.go b/bindings/go/llvm/bitwriter.go new file mode 100644 index 0000000..e03699c --- /dev/null +++ b/bindings/go/llvm/bitwriter.go @@ -0,0 +1,39 @@ +//===- bitwriter.go - Bindings for bitwriter ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the bitwriter component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/BitWriter.h" +#include <stdlib.h> +*/ +import "C" +import "os" +import "errors" + +var writeBitcodeToFileErr = errors.New("Failed to write bitcode to file") + +func WriteBitcodeToFile(m Module, file *os.File) error { + fail := C.LLVMWriteBitcodeToFD(m.C, C.int(file.Fd()), C.int(0), C.int(0)) + if fail != 0 { + return writeBitcodeToFileErr + } + return nil +} + +func WriteBitcodeToMemoryBuffer(m Module) MemoryBuffer { + mb := C.LLVMWriteBitcodeToMemoryBuffer(m.C) + return MemoryBuffer{mb} +} + +// TODO(nsf): Figure out way how to make it work with io.Writer diff --git a/bindings/go/llvm/dibuilder.go b/bindings/go/llvm/dibuilder.go new file mode 100644 index 0000000..1d07e98 --- /dev/null +++ b/bindings/go/llvm/dibuilder.go @@ -0,0 +1,492 @@ +//===- dibuilder.go - Bindings for DIBuilder ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the DIBuilder class. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "DIBuilderBindings.h" +#include <stdlib.h> +*/ +import "C" + +import ( + "debug/dwarf" + "unsafe" +) + +type DwarfTag uint32 + +const ( + DW_TAG_lexical_block DwarfTag = 0x0b + DW_TAG_compile_unit DwarfTag = 0x11 + DW_TAG_variable DwarfTag = 0x34 + DW_TAG_base_type DwarfTag = 0x24 + DW_TAG_pointer_type DwarfTag = 0x0F + DW_TAG_structure_type DwarfTag = 0x13 + DW_TAG_subroutine_type DwarfTag = 0x15 + DW_TAG_file_type DwarfTag = 0x29 + DW_TAG_subprogram DwarfTag = 0x2E + DW_TAG_auto_variable DwarfTag = 0x100 + DW_TAG_arg_variable DwarfTag = 0x101 +) + +const ( + FlagPrivate = 1 << iota + FlagProtected + FlagFwdDecl + FlagAppleBlock + FlagBlockByrefStruct + FlagVirtual + FlagArtificial + FlagExplicit + FlagPrototyped + FlagObjcClassComplete + FlagObjectPointer + FlagVector + FlagStaticMember + FlagIndirectVariable +) + +type DwarfLang uint32 + +const ( + // http://dwarfstd.org/ShowIssue.php?issue=101014.1&type=open + DW_LANG_Go DwarfLang = 0x0016 +) + +type DwarfTypeEncoding uint32 + +const ( + DW_ATE_address DwarfTypeEncoding = 0x01 + DW_ATE_boolean DwarfTypeEncoding = 0x02 + DW_ATE_complex_float DwarfTypeEncoding = 0x03 + DW_ATE_float DwarfTypeEncoding = 0x04 + DW_ATE_signed DwarfTypeEncoding = 0x05 + DW_ATE_signed_char DwarfTypeEncoding = 0x06 + DW_ATE_unsigned DwarfTypeEncoding = 0x07 + DW_ATE_unsigned_char DwarfTypeEncoding = 0x08 + DW_ATE_imaginary_float DwarfTypeEncoding = 0x09 + DW_ATE_packed_decimal DwarfTypeEncoding = 0x0a + DW_ATE_numeric_string DwarfTypeEncoding = 0x0b + DW_ATE_edited DwarfTypeEncoding = 0x0c + DW_ATE_signed_fixed DwarfTypeEncoding = 0x0d + DW_ATE_unsigned_fixed DwarfTypeEncoding = 0x0e + DW_ATE_decimal_float DwarfTypeEncoding = 0x0f + DW_ATE_UTF DwarfTypeEncoding = 0x10 + DW_ATE_lo_user DwarfTypeEncoding = 0x80 + DW_ATE_hi_user DwarfTypeEncoding = 0xff +) + +// DIBuilder is a wrapper for the LLVM DIBuilder class. +type DIBuilder struct { + ref C.LLVMDIBuilderRef + m Module +} + +// NewDIBuilder creates a new DIBuilder, associated with the given module. +func NewDIBuilder(m Module) *DIBuilder { + d := C.LLVMNewDIBuilder(m.C) + return &DIBuilder{ref: d, m: m} +} + +// Destroy destroys the DIBuilder. +func (d *DIBuilder) Destroy() { + C.LLVMDIBuilderDestroy(d.ref) +} + +// FInalize finalizes the debug information generated by the DIBuilder. +func (d *DIBuilder) Finalize() { + C.LLVMDIBuilderFinalize(d.ref) +} + +// DICompileUnit holds the values for creating compile unit debug metadata. +type DICompileUnit struct { + Language DwarfLang + File string + Dir string + Producer string + Optimized bool + Flags string + RuntimeVersion int +} + +// CreateCompileUnit creates compile unit debug metadata. +func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Value { + file := C.CString(cu.File) + defer C.free(unsafe.Pointer(file)) + dir := C.CString(cu.Dir) + defer C.free(unsafe.Pointer(dir)) + producer := C.CString(cu.Producer) + defer C.free(unsafe.Pointer(producer)) + flags := C.CString(cu.Flags) + defer C.free(unsafe.Pointer(flags)) + result := C.LLVMDIBuilderCreateCompileUnit( + d.ref, + C.unsigned(cu.Language), + file, dir, + producer, + boolToCInt(cu.Optimized), + flags, + C.unsigned(cu.RuntimeVersion), + ) + return Value{C: result} +} + +// CreateCompileUnit creates file debug metadata. +func (d *DIBuilder) CreateFile(filename, dir string) Value { + cfilename := C.CString(filename) + defer C.free(unsafe.Pointer(cfilename)) + cdir := C.CString(dir) + defer C.free(unsafe.Pointer(cdir)) + result := C.LLVMDIBuilderCreateFile(d.ref, cfilename, cdir) + return Value{C: result} +} + +// DILexicalBlock holds the values for creating lexical block debug metadata. +type DILexicalBlock struct { + File Value + Line int + Column int +} + +// CreateCompileUnit creates lexical block debug metadata. +func (d *DIBuilder) CreateLexicalBlock(diScope Value, b DILexicalBlock) Value { + result := C.LLVMDIBuilderCreateLexicalBlock( + d.ref, + diScope.C, + b.File.C, + C.unsigned(b.Line), + C.unsigned(b.Column), + ) + return Value{C: result} +} + +func (d *DIBuilder) CreateLexicalBlockFile(diScope Value, diFile Value, discriminator int) Value { + result := C.LLVMDIBuilderCreateLexicalBlockFile(d.ref, diScope.C, diFile.C, + C.unsigned(discriminator)) + return Value{C: result} +} + +// DIFunction holds the values for creating function debug metadata. +type DIFunction struct { + Name string + LinkageName string + File Value + Line int + Type Value + LocalToUnit bool + IsDefinition bool + ScopeLine int + Flags int + Optimized bool + Function Value +} + +// CreateCompileUnit creates function debug metadata. +func (d *DIBuilder) CreateFunction(diScope Value, f DIFunction) Value { + name := C.CString(f.Name) + defer C.free(unsafe.Pointer(name)) + linkageName := C.CString(f.LinkageName) + defer C.free(unsafe.Pointer(linkageName)) + result := C.LLVMDIBuilderCreateFunction( + d.ref, + diScope.C, + name, + linkageName, + f.File.C, + C.unsigned(f.Line), + f.Type.C, + boolToCInt(f.LocalToUnit), + boolToCInt(f.IsDefinition), + C.unsigned(f.ScopeLine), + C.unsigned(f.Flags), + boolToCInt(f.Optimized), + f.Function.C, + ) + return Value{C: result} +} + +// DILocalVariable holds the values for creating local variable debug metadata. +type DILocalVariable struct { + Tag dwarf.Tag + Name string + File Value + Line int + Type Value + AlwaysPreserve bool + Flags int + + // ArgNo is the 1-based index of the argument in the function's + // parameter list if it is an argument, or 0 otherwise. + ArgNo int +} + +// CreateLocalVariable creates local variable debug metadata. +func (d *DIBuilder) CreateLocalVariable(scope Value, v DILocalVariable) Value { + name := C.CString(v.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateLocalVariable( + d.ref, + C.unsigned(v.Tag), + scope.C, + name, + v.File.C, + C.unsigned(v.Line), + v.Type.C, + boolToCInt(v.AlwaysPreserve), + C.unsigned(v.Flags), + C.unsigned(v.ArgNo), + ) + return Value{C: result} +} + +// DIBasicType holds the values for creating basic type debug metadata. +type DIBasicType struct { + Name string + SizeInBits uint64 + AlignInBits uint64 + Encoding DwarfTypeEncoding +} + +// CreateBasicType creates basic type debug metadata. +func (d *DIBuilder) CreateBasicType(t DIBasicType) Value { + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateBasicType( + d.ref, + name, + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + C.unsigned(t.Encoding), + ) + return Value{C: result} +} + +// DIPointerType holds the values for creating pointer type debug metadata. +type DIPointerType struct { + Pointee Value + SizeInBits uint64 + AlignInBits uint64 // optional + Name string // optional +} + +// CreateBasicType creates basic type debug metadata. +func (d *DIBuilder) CreatePointerType(t DIPointerType) Value { + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreatePointerType( + d.ref, + t.Pointee.C, + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + name, + ) + return Value{C: result} +} + +// DISubroutineType holds the values for creating subroutine type debug metadata. +type DISubroutineType struct { + // File is the file in which the subroutine type is defined. + File Value + + // Parameters contains the subroutine parameter types, + // including the return type at the 0th index. + Parameters []Value +} + +// CreateSubroutineType creates subroutine type debug metadata. +func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Value { + params := d.getOrCreateTypeArray(t.Parameters) + result := C.LLVMDIBuilderCreateSubroutineType(d.ref, t.File.C, params.C) + return Value{C: result} +} + +// DIStructType holds the values for creating struct type debug metadata. +type DIStructType struct { + Name string + File Value + Line int + SizeInBits uint64 + AlignInBits uint64 + Flags int + DerivedFrom Value + Elements []Value +} + +// CreateStructType creates struct type debug metadata. +func (d *DIBuilder) CreateStructType(scope Value, t DIStructType) Value { + elements := d.getOrCreateArray(t.Elements) + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateStructType( + d.ref, + scope.C, + name, + t.File.C, + C.unsigned(t.Line), + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + C.unsigned(t.Flags), + t.DerivedFrom.C, + elements.C, + ) + return Value{C: result} +} + +// DIMemberType holds the values for creating member type debug metadata. +type DIMemberType struct { + Name string + File Value + Line int + SizeInBits uint64 + AlignInBits uint64 + OffsetInBits uint64 + Flags int + Type Value +} + +// CreateMemberType creates struct type debug metadata. +func (d *DIBuilder) CreateMemberType(scope Value, t DIMemberType) Value { + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateMemberType( + d.ref, + scope.C, + name, + t.File.C, + C.unsigned(t.Line), + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + C.uint64_t(t.OffsetInBits), + C.unsigned(t.Flags), + t.Type.C, + ) + return Value{C: result} +} + +// DISubrange describes an integer value range. +type DISubrange struct { + Lo int64 + Count int64 +} + +// DIArrayType holds the values for creating array type debug metadata. +type DIArrayType struct { + SizeInBits uint64 + AlignInBits uint64 + ElementType Value + Subscripts []DISubrange +} + +// CreateArrayType creates struct type debug metadata. +func (d *DIBuilder) CreateArrayType(t DIArrayType) Value { + subscriptsSlice := make([]Value, len(t.Subscripts)) + for i, s := range t.Subscripts { + subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count) + } + subscripts := d.getOrCreateArray(subscriptsSlice) + result := C.LLVMDIBuilderCreateArrayType( + d.ref, + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + t.ElementType.C, + subscripts.C, + ) + return Value{C: result} +} + +// DITypedef holds the values for creating typedef type debug metadata. +type DITypedef struct { + Type Value + Name string + File Value + Line int + Context Value +} + +// CreateTypedef creates typedef type debug metadata. +func (d *DIBuilder) CreateTypedef(t DITypedef) Value { + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateTypedef( + d.ref, + t.Type.C, + name, + t.File.C, + C.unsigned(t.Line), + t.Context.C, + ) + return Value{C: result} +} + +// getOrCreateSubrange gets a metadata node for the specified subrange, +// creating if required. +func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Value { + result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count)) + return Value{C: result} +} + +// getOrCreateArray gets a metadata node containing the specified values, +// creating if required. +func (d *DIBuilder) getOrCreateArray(values []Value) Value { + if len(values) == 0 { + return Value{} + } + var data *C.LLVMValueRef + length := len(values) + if length > 0 { + data = &values[0].C + } + result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length)) + return Value{C: result} +} + +// getOrCreateTypeArray gets a metadata node for a type array containing the +// specified values, creating if required. +func (d *DIBuilder) getOrCreateTypeArray(values []Value) Value { + if len(values) == 0 { + return Value{} + } + var data *C.LLVMValueRef + length := len(values) + if length > 0 { + data = &values[0].C + } + result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length)) + return Value{C: result} +} + +// CreateExpression creates a new descriptor for the specified +// variable which has a complex address expression for its address. +func (d *DIBuilder) CreateExpression(addr []int64) Value { + var data *C.int64_t + if len(addr) > 0 { + data = (*C.int64_t)(unsafe.Pointer(&addr[0])) + } + result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr))) + return Value{C: result} +} + +// InsertDeclareAtEnd inserts a call to llvm.dbg.declare at the end of the +// specified basic block for the given value and associated debug metadata. +func (d *DIBuilder) InsertDeclareAtEnd(v, diVarInfo, expr Value, bb BasicBlock) Value { + result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, bb.C) + return Value{C: result} +} + +func boolToCInt(v bool) C.int { + if v { + return 1 + } + return 0 +} diff --git a/bindings/go/llvm/executionengine.go b/bindings/go/llvm/executionengine.go new file mode 100644 index 0000000..26b7524 --- /dev/null +++ b/bindings/go/llvm/executionengine.go @@ -0,0 +1,163 @@ +//===- executionengine.go - Bindings for executionengine ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the executionengine component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/ExecutionEngine.h" +#include <stdlib.h> +*/ +import "C" +import "unsafe" +import "errors" + +func LinkInMCJIT() { C.LLVMLinkInMCJIT() } +func LinkInInterpreter() { C.LLVMLinkInInterpreter() } + +type GenericValue struct { + C C.LLVMGenericValueRef +} +type ExecutionEngine struct { + C C.LLVMExecutionEngineRef +} +type MCJITCompilerOptions struct { + OptLevel uint + CodeModel CodeModel + NoFramePointerElim bool + EnableFastISel bool +} + +// helpers +func llvmGenericValueRefPtr(t *GenericValue) *C.LLVMGenericValueRef { + return (*C.LLVMGenericValueRef)(unsafe.Pointer(t)) +} + +//------------------------------------------------------------------------- +// llvm.GenericValue +//------------------------------------------------------------------------- + +func NewGenericValueFromInt(t Type, n uint64, signed bool) (g GenericValue) { + g.C = C.LLVMCreateGenericValueOfInt(t.C, C.ulonglong(n), boolToLLVMBool(signed)) + return +} +func NewGenericValueFromPointer(p unsafe.Pointer) (g GenericValue) { + g.C = C.LLVMCreateGenericValueOfPointer(p) + return +} +func NewGenericValueFromFloat(t Type, n float64) (g GenericValue) { + g.C = C.LLVMCreateGenericValueOfFloat(t.C, C.double(n)) + return +} +func (g GenericValue) IntWidth() int { return int(C.LLVMGenericValueIntWidth(g.C)) } +func (g GenericValue) Int(signed bool) uint64 { + return uint64(C.LLVMGenericValueToInt(g.C, boolToLLVMBool(signed))) +} +func (g GenericValue) Float(t Type) float64 { + return float64(C.LLVMGenericValueToFloat(t.C, g.C)) +} +func (g GenericValue) Pointer() unsafe.Pointer { + return C.LLVMGenericValueToPointer(g.C) +} +func (g GenericValue) Dispose() { C.LLVMDisposeGenericValue(g.C) } + +//------------------------------------------------------------------------- +// llvm.ExecutionEngine +//------------------------------------------------------------------------- + +func NewExecutionEngine(m Module) (ee ExecutionEngine, err error) { + var cmsg *C.char + fail := C.LLVMCreateExecutionEngineForModule(&ee.C, m.C, &cmsg) + if fail != 0 { + ee.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func NewInterpreter(m Module) (ee ExecutionEngine, err error) { + var cmsg *C.char + fail := C.LLVMCreateInterpreterForModule(&ee.C, m.C, &cmsg) + if fail != 0 { + ee.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func NewMCJITCompiler(m Module, options MCJITCompilerOptions) (ee ExecutionEngine, err error) { + var cmsg *C.char + copts := C.struct_LLVMMCJITCompilerOptions{ + OptLevel: C.unsigned(options.OptLevel), + CodeModel: C.LLVMCodeModel(options.CodeModel), + NoFramePointerElim: boolToLLVMBool(options.NoFramePointerElim), + EnableFastISel: boolToLLVMBool(options.EnableFastISel), + } + fail := C.LLVMCreateMCJITCompilerForModule(&ee.C, m.C, &copts, C.size_t(unsafe.Sizeof(copts)), &cmsg) + if fail != 0 { + ee.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func (ee ExecutionEngine) Dispose() { C.LLVMDisposeExecutionEngine(ee.C) } +func (ee ExecutionEngine) RunStaticConstructors() { C.LLVMRunStaticConstructors(ee.C) } +func (ee ExecutionEngine) RunStaticDestructors() { C.LLVMRunStaticDestructors(ee.C) } + +func (ee ExecutionEngine) RunFunction(f Value, args []GenericValue) (g GenericValue) { + nargs := len(args) + var argptr *GenericValue + if nargs > 0 { + argptr = &args[0] + } + g.C = C.LLVMRunFunction(ee.C, f.C, + C.unsigned(nargs), llvmGenericValueRefPtr(argptr)) + return +} + +func (ee ExecutionEngine) FreeMachineCodeForFunction(f Value) { + C.LLVMFreeMachineCodeForFunction(ee.C, f.C) +} +func (ee ExecutionEngine) AddModule(m Module) { C.LLVMAddModule(ee.C, m.C) } + +func (ee ExecutionEngine) RemoveModule(m Module) { + var modtmp C.LLVMModuleRef + C.LLVMRemoveModule(ee.C, m.C, &modtmp, nil) +} + +func (ee ExecutionEngine) FindFunction(name string) (f Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMFindFunction(ee.C, cname, &f.C) + return +} + +func (ee ExecutionEngine) RecompileAndRelinkFunction(f Value) unsafe.Pointer { + return C.LLVMRecompileAndRelinkFunction(ee.C, f.C) +} + +func (ee ExecutionEngine) TargetData() (td TargetData) { + td.C = C.LLVMGetExecutionEngineTargetData(ee.C) + return +} + +func (ee ExecutionEngine) AddGlobalMapping(global Value, addr unsafe.Pointer) { + C.LLVMAddGlobalMapping(ee.C, global.C, addr) +} + +func (ee ExecutionEngine) PointerToGlobal(global Value) unsafe.Pointer { + return C.LLVMGetPointerToGlobal(ee.C, global.C) +} diff --git a/bindings/go/llvm/executionengine_test.go b/bindings/go/llvm/executionengine_test.go new file mode 100644 index 0000000..1a3fd45 --- /dev/null +++ b/bindings/go/llvm/executionengine_test.go @@ -0,0 +1,93 @@ +//===- executionengine_test.go - Tests for executionengine ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests bindings for the executionengine component. +// +//===----------------------------------------------------------------------===// + +package llvm + +import ( + "testing" +) + +func TestFactorial(t *testing.T) { + LinkInMCJIT() + InitializeNativeTarget() + InitializeNativeAsmPrinter() + + mod := NewModule("fac_module") + + fac_args := []Type{Int32Type()} + fac_type := FunctionType(Int32Type(), fac_args, false) + fac := AddFunction(mod, "fac", fac_type) + fac.SetFunctionCallConv(CCallConv) + n := fac.Param(0) + + entry := AddBasicBlock(fac, "entry") + iftrue := AddBasicBlock(fac, "iftrue") + iffalse := AddBasicBlock(fac, "iffalse") + end := AddBasicBlock(fac, "end") + + builder := NewBuilder() + defer builder.Dispose() + + builder.SetInsertPointAtEnd(entry) + If := builder.CreateICmp(IntEQ, n, ConstInt(Int32Type(), 0, false), "cmptmp") + builder.CreateCondBr(If, iftrue, iffalse) + + builder.SetInsertPointAtEnd(iftrue) + res_iftrue := ConstInt(Int32Type(), 1, false) + builder.CreateBr(end) + + builder.SetInsertPointAtEnd(iffalse) + n_minus := builder.CreateSub(n, ConstInt(Int32Type(), 1, false), "subtmp") + call_fac_args := []Value{n_minus} + call_fac := builder.CreateCall(fac, call_fac_args, "calltmp") + res_iffalse := builder.CreateMul(n, call_fac, "multmp") + builder.CreateBr(end) + + builder.SetInsertPointAtEnd(end) + res := builder.CreatePHI(Int32Type(), "result") + phi_vals := []Value{res_iftrue, res_iffalse} + phi_blocks := []BasicBlock{iftrue, iffalse} + res.AddIncoming(phi_vals, phi_blocks) + builder.CreateRet(res) + + err := VerifyModule(mod, ReturnStatusAction) + if err != nil { + t.Errorf("Error verifying module: %s", err) + return + } + + engine, err := NewMCJITCompiler(mod, MCJITCompilerOptions{OptLevel: 2}) + if err != nil { + t.Errorf("Error creating JIT: %s", err) + return + } + defer engine.Dispose() + + pass := NewPassManager() + defer pass.Dispose() + + pass.Add(engine.TargetData()) + pass.AddConstantPropagationPass() + pass.AddInstructionCombiningPass() + pass.AddPromoteMemoryToRegisterPass() + pass.AddGVNPass() + pass.AddCFGSimplificationPass() + pass.Run(mod) + + exec_args := []GenericValue{NewGenericValueFromInt(Int32Type(), 10, false)} + exec_res := engine.RunFunction(fac, exec_args) + var fac10 uint64 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 + if exec_res.Int(false) != fac10 { + t.Errorf("Expected %d, got %d", fac10, exec_res.Int(false)) + } +} diff --git a/bindings/go/llvm/ir.go b/bindings/go/llvm/ir.go new file mode 100644 index 0000000..7834f5c --- /dev/null +++ b/bindings/go/llvm/ir.go @@ -0,0 +1,1824 @@ +//===- ir.go - Bindings for ir --------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the ir component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Core.h" +#include "IRBindings.h" +#include <stdlib.h> +*/ +import "C" +import "unsafe" +import "errors" + +type ( + // We use these weird structs here because *Ref types are pointers and + // Go's spec says that a pointer cannot be used as a receiver base type. + Context struct { + C C.LLVMContextRef + } + Module struct { + C C.LLVMModuleRef + } + Type struct { + C C.LLVMTypeRef + } + Value struct { + C C.LLVMValueRef + } + BasicBlock struct { + C C.LLVMBasicBlockRef + } + Builder struct { + C C.LLVMBuilderRef + } + ModuleProvider struct { + C C.LLVMModuleProviderRef + } + MemoryBuffer struct { + C C.LLVMMemoryBufferRef + } + PassManager struct { + C C.LLVMPassManagerRef + } + Use struct { + C C.LLVMUseRef + } + Attribute uint64 + Opcode C.LLVMOpcode + TypeKind C.LLVMTypeKind + Linkage C.LLVMLinkage + Visibility C.LLVMVisibility + CallConv C.LLVMCallConv + IntPredicate C.LLVMIntPredicate + FloatPredicate C.LLVMRealPredicate + LandingPadClause C.LLVMLandingPadClauseTy +) + +func (c Context) IsNil() bool { return c.C == nil } +func (c Module) IsNil() bool { return c.C == nil } +func (c Type) IsNil() bool { return c.C == nil } +func (c Value) IsNil() bool { return c.C == nil } +func (c BasicBlock) IsNil() bool { return c.C == nil } +func (c Builder) IsNil() bool { return c.C == nil } +func (c ModuleProvider) IsNil() bool { return c.C == nil } +func (c MemoryBuffer) IsNil() bool { return c.C == nil } +func (c PassManager) IsNil() bool { return c.C == nil } +func (c Use) IsNil() bool { return c.C == nil } + +// helpers +func llvmTypeRefPtr(t *Type) *C.LLVMTypeRef { return (*C.LLVMTypeRef)(unsafe.Pointer(t)) } +func llvmValueRefPtr(t *Value) *C.LLVMValueRef { return (*C.LLVMValueRef)(unsafe.Pointer(t)) } +func llvmBasicBlockRefPtr(t *BasicBlock) *C.LLVMBasicBlockRef { + return (*C.LLVMBasicBlockRef)(unsafe.Pointer(t)) +} +func boolToLLVMBool(b bool) C.LLVMBool { + if b { + return C.LLVMBool(1) + } + return C.LLVMBool(0) +} + +func llvmValueRefs(values []Value) (*C.LLVMValueRef, C.unsigned) { + var pt *C.LLVMValueRef + ptlen := C.unsigned(len(values)) + if ptlen > 0 { + pt = llvmValueRefPtr(&values[0]) + } + return pt, ptlen +} + +//------------------------------------------------------------------------- +// llvm.Attribute +//------------------------------------------------------------------------- + +const ( + NoneAttribute Attribute = 0 + ZExtAttribute Attribute = C.LLVMZExtAttribute + SExtAttribute Attribute = C.LLVMSExtAttribute + NoReturnAttribute Attribute = C.LLVMNoReturnAttribute + InRegAttribute Attribute = C.LLVMInRegAttribute + StructRetAttribute Attribute = C.LLVMStructRetAttribute + NoUnwindAttribute Attribute = C.LLVMNoUnwindAttribute + NoAliasAttribute Attribute = C.LLVMNoAliasAttribute + ByValAttribute Attribute = C.LLVMByValAttribute + NestAttribute Attribute = C.LLVMNestAttribute + ReadNoneAttribute Attribute = C.LLVMReadNoneAttribute + ReadOnlyAttribute Attribute = C.LLVMReadOnlyAttribute + NoInlineAttribute Attribute = C.LLVMNoInlineAttribute + AlwaysInlineAttribute Attribute = C.LLVMAlwaysInlineAttribute + OptimizeForSizeAttribute Attribute = C.LLVMOptimizeForSizeAttribute + StackProtectAttribute Attribute = C.LLVMStackProtectAttribute + StackProtectReqAttribute Attribute = C.LLVMStackProtectReqAttribute + Alignment Attribute = C.LLVMAlignment + NoCaptureAttribute Attribute = C.LLVMNoCaptureAttribute + NoRedZoneAttribute Attribute = C.LLVMNoRedZoneAttribute + NoImplicitFloatAttribute Attribute = C.LLVMNoImplicitFloatAttribute + NakedAttribute Attribute = C.LLVMNakedAttribute + InlineHintAttribute Attribute = C.LLVMInlineHintAttribute + StackAlignment Attribute = C.LLVMStackAlignment + ReturnsTwiceAttribute Attribute = C.LLVMReturnsTwice + UWTableAttribute Attribute = C.LLVMUWTable + NonLazyBindAttribute Attribute = 1 << 31 + SanitizeAddressAttribute Attribute = 1 << 32 + MinSizeAttribute Attribute = 1 << 33 + NoDuplicateAttribute Attribute = 1 << 34 + StackProtectStrongAttribute Attribute = 1 << 35 + SanitizeThreadAttribute Attribute = 1 << 36 + SanitizeMemoryAttribute Attribute = 1 << 37 + NoBuiltinAttribute Attribute = 1 << 38 + ReturnedAttribute Attribute = 1 << 39 + ColdAttribute Attribute = 1 << 40 + BuiltinAttribute Attribute = 1 << 41 + OptimizeNoneAttribute Attribute = 1 << 42 + InAllocaAttribute Attribute = 1 << 43 + NonNullAttribute Attribute = 1 << 44 + JumpTableAttribute Attribute = 1 << 45 +) + +//------------------------------------------------------------------------- +// llvm.Opcode +//------------------------------------------------------------------------- + +const ( + Ret Opcode = C.LLVMRet + Br Opcode = C.LLVMBr + Switch Opcode = C.LLVMSwitch + IndirectBr Opcode = C.LLVMIndirectBr + Invoke Opcode = C.LLVMInvoke + Unreachable Opcode = C.LLVMUnreachable + + // Standard Binary Operators + Add Opcode = C.LLVMAdd + FAdd Opcode = C.LLVMFAdd + Sub Opcode = C.LLVMSub + FSub Opcode = C.LLVMFSub + Mul Opcode = C.LLVMMul + FMul Opcode = C.LLVMFMul + UDiv Opcode = C.LLVMUDiv + SDiv Opcode = C.LLVMSDiv + FDiv Opcode = C.LLVMFDiv + URem Opcode = C.LLVMURem + SRem Opcode = C.LLVMSRem + FRem Opcode = C.LLVMFRem + + // Logical Operators + Shl Opcode = C.LLVMShl + LShr Opcode = C.LLVMLShr + AShr Opcode = C.LLVMAShr + And Opcode = C.LLVMAnd + Or Opcode = C.LLVMOr + Xor Opcode = C.LLVMXor + + // Memory Operators + Alloca Opcode = C.LLVMAlloca + Load Opcode = C.LLVMLoad + Store Opcode = C.LLVMStore + GetElementPtr Opcode = C.LLVMGetElementPtr + + // Cast Operators + Trunc Opcode = C.LLVMTrunc + ZExt Opcode = C.LLVMZExt + SExt Opcode = C.LLVMSExt + FPToUI Opcode = C.LLVMFPToUI + FPToSI Opcode = C.LLVMFPToSI + UIToFP Opcode = C.LLVMUIToFP + SIToFP Opcode = C.LLVMSIToFP + FPTrunc Opcode = C.LLVMFPTrunc + FPExt Opcode = C.LLVMFPExt + PtrToInt Opcode = C.LLVMPtrToInt + IntToPtr Opcode = C.LLVMIntToPtr + BitCast Opcode = C.LLVMBitCast + + // Other Operators + ICmp Opcode = C.LLVMICmp + FCmp Opcode = C.LLVMFCmp + PHI Opcode = C.LLVMPHI + Call Opcode = C.LLVMCall + Select Opcode = C.LLVMSelect + // UserOp1 + // UserOp2 + VAArg Opcode = C.LLVMVAArg + ExtractElement Opcode = C.LLVMExtractElement + InsertElement Opcode = C.LLVMInsertElement + ShuffleVector Opcode = C.LLVMShuffleVector + ExtractValue Opcode = C.LLVMExtractValue + InsertValue Opcode = C.LLVMInsertValue +) + +//------------------------------------------------------------------------- +// llvm.TypeKind +//------------------------------------------------------------------------- + +const ( + VoidTypeKind TypeKind = C.LLVMVoidTypeKind + FloatTypeKind TypeKind = C.LLVMFloatTypeKind + DoubleTypeKind TypeKind = C.LLVMDoubleTypeKind + X86_FP80TypeKind TypeKind = C.LLVMX86_FP80TypeKind + FP128TypeKind TypeKind = C.LLVMFP128TypeKind + PPC_FP128TypeKind TypeKind = C.LLVMPPC_FP128TypeKind + LabelTypeKind TypeKind = C.LLVMLabelTypeKind + IntegerTypeKind TypeKind = C.LLVMIntegerTypeKind + FunctionTypeKind TypeKind = C.LLVMFunctionTypeKind + StructTypeKind TypeKind = C.LLVMStructTypeKind + ArrayTypeKind TypeKind = C.LLVMArrayTypeKind + PointerTypeKind TypeKind = C.LLVMPointerTypeKind + VectorTypeKind TypeKind = C.LLVMVectorTypeKind + MetadataTypeKind TypeKind = C.LLVMMetadataTypeKind +) + +//------------------------------------------------------------------------- +// llvm.Linkage +//------------------------------------------------------------------------- + +const ( + ExternalLinkage Linkage = C.LLVMExternalLinkage + AvailableExternallyLinkage Linkage = C.LLVMAvailableExternallyLinkage + LinkOnceAnyLinkage Linkage = C.LLVMLinkOnceAnyLinkage + LinkOnceODRLinkage Linkage = C.LLVMLinkOnceODRLinkage + WeakAnyLinkage Linkage = C.LLVMWeakAnyLinkage + WeakODRLinkage Linkage = C.LLVMWeakODRLinkage + AppendingLinkage Linkage = C.LLVMAppendingLinkage + InternalLinkage Linkage = C.LLVMInternalLinkage + PrivateLinkage Linkage = C.LLVMPrivateLinkage + ExternalWeakLinkage Linkage = C.LLVMExternalWeakLinkage + CommonLinkage Linkage = C.LLVMCommonLinkage +) + +//------------------------------------------------------------------------- +// llvm.Visibility +//------------------------------------------------------------------------- + +const ( + DefaultVisibility Visibility = C.LLVMDefaultVisibility + HiddenVisibility Visibility = C.LLVMHiddenVisibility + ProtectedVisibility Visibility = C.LLVMProtectedVisibility +) + +//------------------------------------------------------------------------- +// llvm.CallConv +//------------------------------------------------------------------------- + +const ( + CCallConv CallConv = C.LLVMCCallConv + FastCallConv CallConv = C.LLVMFastCallConv + ColdCallConv CallConv = C.LLVMColdCallConv + X86StdcallCallConv CallConv = C.LLVMX86StdcallCallConv + X86FastcallCallConv CallConv = C.LLVMX86FastcallCallConv +) + +//------------------------------------------------------------------------- +// llvm.IntPredicate +//------------------------------------------------------------------------- + +const ( + IntEQ IntPredicate = C.LLVMIntEQ + IntNE IntPredicate = C.LLVMIntNE + IntUGT IntPredicate = C.LLVMIntUGT + IntUGE IntPredicate = C.LLVMIntUGE + IntULT IntPredicate = C.LLVMIntULT + IntULE IntPredicate = C.LLVMIntULE + IntSGT IntPredicate = C.LLVMIntSGT + IntSGE IntPredicate = C.LLVMIntSGE + IntSLT IntPredicate = C.LLVMIntSLT + IntSLE IntPredicate = C.LLVMIntSLE +) + +//------------------------------------------------------------------------- +// llvm.FloatPredicate +//------------------------------------------------------------------------- + +const ( + FloatPredicateFalse FloatPredicate = C.LLVMRealPredicateFalse + FloatOEQ FloatPredicate = C.LLVMRealOEQ + FloatOGT FloatPredicate = C.LLVMRealOGT + FloatOGE FloatPredicate = C.LLVMRealOGE + FloatOLT FloatPredicate = C.LLVMRealOLT + FloatOLE FloatPredicate = C.LLVMRealOLE + FloatONE FloatPredicate = C.LLVMRealONE + FloatORD FloatPredicate = C.LLVMRealORD + FloatUNO FloatPredicate = C.LLVMRealUNO + FloatUEQ FloatPredicate = C.LLVMRealUEQ + FloatUGT FloatPredicate = C.LLVMRealUGT + FloatUGE FloatPredicate = C.LLVMRealUGE + FloatULT FloatPredicate = C.LLVMRealULT + FloatULE FloatPredicate = C.LLVMRealULE + FloatUNE FloatPredicate = C.LLVMRealUNE + FloatPredicateTrue FloatPredicate = C.LLVMRealPredicateTrue +) + +//------------------------------------------------------------------------- +// llvm.LandingPadClause +//------------------------------------------------------------------------- + +const ( + LandingPadCatch LandingPadClause = C.LLVMLandingPadCatch + LandingPadFilter LandingPadClause = C.LLVMLandingPadFilter +) + +//------------------------------------------------------------------------- +// llvm.Context +//------------------------------------------------------------------------- + +func NewContext() Context { return Context{C.LLVMContextCreate()} } +func GlobalContext() Context { return Context{C.LLVMGetGlobalContext()} } +func (c Context) Dispose() { C.LLVMContextDispose(c.C) } + +func (c Context) MDKindID(name string) (id int) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + id = int(C.LLVMGetMDKindIDInContext(c.C, cname, C.unsigned(len(name)))) + return +} + +func MDKindID(name string) (id int) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + id = int(C.LLVMGetMDKindID(cname, C.unsigned(len(name)))) + return +} + +//------------------------------------------------------------------------- +// llvm.Module +//------------------------------------------------------------------------- + +// Create and destroy modules. +// See llvm::Module::Module. +func NewModule(name string) (m Module) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + m.C = C.LLVMModuleCreateWithName(cname) + return +} + +func (c Context) NewModule(name string) (m Module) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + m.C = C.LLVMModuleCreateWithNameInContext(cname, c.C) + return +} + +// See llvm::Module::~Module +func (m Module) Dispose() { C.LLVMDisposeModule(m.C) } + +// Data layout. See Module::getDataLayout. +func (m Module) DataLayout() string { + clayout := C.LLVMGetDataLayout(m.C) + return C.GoString(clayout) +} + +func (m Module) SetDataLayout(layout string) { + clayout := C.CString(layout) + defer C.free(unsafe.Pointer(clayout)) + C.LLVMSetDataLayout(m.C, clayout) +} + +// Target triple. See Module::getTargetTriple. +func (m Module) Target() string { + ctarget := C.LLVMGetTarget(m.C) + return C.GoString(ctarget) +} +func (m Module) SetTarget(target string) { + ctarget := C.CString(target) + defer C.free(unsafe.Pointer(ctarget)) + C.LLVMSetTarget(m.C, ctarget) +} + +func (m Module) GetTypeByName(name string) (t Type) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + t.C = C.LLVMGetTypeByName(m.C, cname) + return +} + +// See Module::dump. +func (m Module) Dump() { + C.LLVMDumpModule(m.C) +} + +func (m Module) String() string { + cir := C.LLVMPrintModuleToString(m.C) + defer C.free(unsafe.Pointer(cir)) + ir := C.GoString(cir) + return ir +} + +// See Module::setModuleInlineAsm. +func (m Module) SetInlineAsm(asm string) { + casm := C.CString(asm) + defer C.free(unsafe.Pointer(casm)) + C.LLVMSetModuleInlineAsm(m.C, casm) +} + +func (m Module) AddNamedMetadataOperand(name string, operand Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMAddNamedMetadataOperand(m.C, cname, operand.C) +} + +func (m Module) Context() (c Context) { + c.C = C.LLVMGetModuleContext(m.C) + return +} + +//------------------------------------------------------------------------- +// llvm.Type +//------------------------------------------------------------------------- + +// LLVM types conform to the following hierarchy: +// +// types: +// integer type +// real type +// function type +// sequence types: +// array type +// pointer type +// vector type +// void type +// label type +// opaque type + +// See llvm::LLVMTypeKind::getTypeID. +func (t Type) TypeKind() TypeKind { return TypeKind(C.LLVMGetTypeKind(t.C)) } + +// See llvm::LLVMType::getContext. +func (t Type) Context() (c Context) { + c.C = C.LLVMGetTypeContext(t.C) + return +} + +// Operations on integer types +func (c Context) Int1Type() (t Type) { t.C = C.LLVMInt1TypeInContext(c.C); return } +func (c Context) Int8Type() (t Type) { t.C = C.LLVMInt8TypeInContext(c.C); return } +func (c Context) Int16Type() (t Type) { t.C = C.LLVMInt16TypeInContext(c.C); return } +func (c Context) Int32Type() (t Type) { t.C = C.LLVMInt32TypeInContext(c.C); return } +func (c Context) Int64Type() (t Type) { t.C = C.LLVMInt64TypeInContext(c.C); return } +func (c Context) IntType(numbits int) (t Type) { + t.C = C.LLVMIntTypeInContext(c.C, C.unsigned(numbits)) + return +} + +func Int1Type() (t Type) { t.C = C.LLVMInt1Type(); return } +func Int8Type() (t Type) { t.C = C.LLVMInt8Type(); return } +func Int16Type() (t Type) { t.C = C.LLVMInt16Type(); return } +func Int32Type() (t Type) { t.C = C.LLVMInt32Type(); return } +func Int64Type() (t Type) { t.C = C.LLVMInt64Type(); return } + +func IntType(numbits int) (t Type) { + t.C = C.LLVMIntType(C.unsigned(numbits)) + return +} + +func (t Type) IntTypeWidth() int { + return int(C.LLVMGetIntTypeWidth(t.C)) +} + +// Operations on real types +func (c Context) FloatType() (t Type) { t.C = C.LLVMFloatTypeInContext(c.C); return } +func (c Context) DoubleType() (t Type) { t.C = C.LLVMDoubleTypeInContext(c.C); return } +func (c Context) X86FP80Type() (t Type) { t.C = C.LLVMX86FP80TypeInContext(c.C); return } +func (c Context) FP128Type() (t Type) { t.C = C.LLVMFP128TypeInContext(c.C); return } +func (c Context) PPCFP128Type() (t Type) { t.C = C.LLVMPPCFP128TypeInContext(c.C); return } + +func FloatType() (t Type) { t.C = C.LLVMFloatType(); return } +func DoubleType() (t Type) { t.C = C.LLVMDoubleType(); return } +func X86FP80Type() (t Type) { t.C = C.LLVMX86FP80Type(); return } +func FP128Type() (t Type) { t.C = C.LLVMFP128Type(); return } +func PPCFP128Type() (t Type) { t.C = C.LLVMPPCFP128Type(); return } + +// Operations on function types +func FunctionType(returnType Type, paramTypes []Type, isVarArg bool) (t Type) { + var pt *C.LLVMTypeRef + var ptlen C.unsigned + if len(paramTypes) > 0 { + pt = llvmTypeRefPtr(¶mTypes[0]) + ptlen = C.unsigned(len(paramTypes)) + } + t.C = C.LLVMFunctionType(returnType.C, + pt, + ptlen, + boolToLLVMBool(isVarArg)) + return +} + +func (t Type) IsFunctionVarArg() bool { return C.LLVMIsFunctionVarArg(t.C) != 0 } +func (t Type) ReturnType() (rt Type) { rt.C = C.LLVMGetReturnType(t.C); return } +func (t Type) ParamTypesCount() int { return int(C.LLVMCountParamTypes(t.C)) } +func (t Type) ParamTypes() []Type { + count := t.ParamTypesCount() + if count > 0 { + out := make([]Type, count) + C.LLVMGetParamTypes(t.C, llvmTypeRefPtr(&out[0])) + return out + } + return nil +} + +// Operations on struct types +func (c Context) StructType(elementTypes []Type, packed bool) (t Type) { + var pt *C.LLVMTypeRef + var ptlen C.unsigned + if len(elementTypes) > 0 { + pt = llvmTypeRefPtr(&elementTypes[0]) + ptlen = C.unsigned(len(elementTypes)) + } + t.C = C.LLVMStructTypeInContext(c.C, + pt, + ptlen, + boolToLLVMBool(packed)) + return +} + +func StructType(elementTypes []Type, packed bool) (t Type) { + var pt *C.LLVMTypeRef + var ptlen C.unsigned + if len(elementTypes) > 0 { + pt = llvmTypeRefPtr(&elementTypes[0]) + ptlen = C.unsigned(len(elementTypes)) + } + t.C = C.LLVMStructType(pt, ptlen, boolToLLVMBool(packed)) + return +} + +func (c Context) StructCreateNamed(name string) (t Type) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + t.C = C.LLVMStructCreateNamed(c.C, cname) + return +} + +func (t Type) StructName() string { + return C.GoString(C.LLVMGetStructName(t.C)) +} + +func (t Type) StructSetBody(elementTypes []Type, packed bool) { + var pt *C.LLVMTypeRef + var ptlen C.unsigned + if len(elementTypes) > 0 { + pt = llvmTypeRefPtr(&elementTypes[0]) + ptlen = C.unsigned(len(elementTypes)) + } + C.LLVMStructSetBody(t.C, pt, ptlen, boolToLLVMBool(packed)) +} + +func (t Type) IsStructPacked() bool { return C.LLVMIsPackedStruct(t.C) != 0 } +func (t Type) StructElementTypesCount() int { return int(C.LLVMCountStructElementTypes(t.C)) } +func (t Type) StructElementTypes() []Type { + out := make([]Type, t.StructElementTypesCount()) + if len(out) > 0 { + C.LLVMGetStructElementTypes(t.C, llvmTypeRefPtr(&out[0])) + } + return out +} + +// Operations on array, pointer, and vector types (sequence types) +func ArrayType(elementType Type, elementCount int) (t Type) { + t.C = C.LLVMArrayType(elementType.C, C.unsigned(elementCount)) + return +} +func PointerType(elementType Type, addressSpace int) (t Type) { + t.C = C.LLVMPointerType(elementType.C, C.unsigned(addressSpace)) + return +} +func VectorType(elementType Type, elementCount int) (t Type) { + t.C = C.LLVMVectorType(elementType.C, C.unsigned(elementCount)) + return +} + +func (t Type) ElementType() (rt Type) { rt.C = C.LLVMGetElementType(t.C); return } +func (t Type) ArrayLength() int { return int(C.LLVMGetArrayLength(t.C)) } +func (t Type) PointerAddressSpace() int { return int(C.LLVMGetPointerAddressSpace(t.C)) } +func (t Type) VectorSize() int { return int(C.LLVMGetVectorSize(t.C)) } + +// Operations on other types +func (c Context) VoidType() (t Type) { t.C = C.LLVMVoidTypeInContext(c.C); return } +func (c Context) LabelType() (t Type) { t.C = C.LLVMLabelTypeInContext(c.C); return } + +func VoidType() (t Type) { t.C = C.LLVMVoidType(); return } +func LabelType() (t Type) { t.C = C.LLVMLabelType(); return } + +//------------------------------------------------------------------------- +// llvm.Value +//------------------------------------------------------------------------- + +// Operations on all values +func (v Value) Type() (t Type) { t.C = C.LLVMTypeOf(v.C); return } +func (v Value) Name() string { return C.GoString(C.LLVMGetValueName(v.C)) } +func (v Value) SetName(name string) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMSetValueName(v.C, cname) +} +func (v Value) Dump() { C.LLVMDumpValue(v.C) } +func (v Value) ReplaceAllUsesWith(nv Value) { C.LLVMReplaceAllUsesWith(v.C, nv.C) } +func (v Value) HasMetadata() bool { return C.LLVMHasMetadata(v.C) != 0 } +func (v Value) Metadata(kind int) (rv Value) { + rv.C = C.LLVMGetMetadata(v.C, C.unsigned(kind)) + return +} +func (v Value) SetMetadata(kind int, node Value) { + C.LLVMSetMetadata(v.C, C.unsigned(kind), node.C) +} + +// Conversion functions. +// Return the input value if it is an instance of the specified class, otherwise NULL. +// See llvm::dyn_cast_or_null<>. +func (v Value) IsAArgument() (rv Value) { rv.C = C.LLVMIsAArgument(v.C); return } +func (v Value) IsABasicBlock() (rv Value) { rv.C = C.LLVMIsABasicBlock(v.C); return } +func (v Value) IsAInlineAsm() (rv Value) { rv.C = C.LLVMIsAInlineAsm(v.C); return } +func (v Value) IsAUser() (rv Value) { rv.C = C.LLVMIsAUser(v.C); return } +func (v Value) IsAConstant() (rv Value) { rv.C = C.LLVMIsAConstant(v.C); return } +func (v Value) IsAConstantAggregateZero() (rv Value) { + rv.C = C.LLVMIsAConstantAggregateZero(v.C) + return +} +func (v Value) IsAConstantArray() (rv Value) { rv.C = C.LLVMIsAConstantArray(v.C); return } +func (v Value) IsAConstantExpr() (rv Value) { rv.C = C.LLVMIsAConstantExpr(v.C); return } +func (v Value) IsAConstantFP() (rv Value) { rv.C = C.LLVMIsAConstantFP(v.C); return } +func (v Value) IsAConstantInt() (rv Value) { rv.C = C.LLVMIsAConstantInt(v.C); return } +func (v Value) IsAConstantPointerNull() (rv Value) { rv.C = C.LLVMIsAConstantPointerNull(v.C); return } +func (v Value) IsAConstantStruct() (rv Value) { rv.C = C.LLVMIsAConstantStruct(v.C); return } +func (v Value) IsAConstantVector() (rv Value) { rv.C = C.LLVMIsAConstantVector(v.C); return } +func (v Value) IsAGlobalValue() (rv Value) { rv.C = C.LLVMIsAGlobalValue(v.C); return } +func (v Value) IsAFunction() (rv Value) { rv.C = C.LLVMIsAFunction(v.C); return } +func (v Value) IsAGlobalAlias() (rv Value) { rv.C = C.LLVMIsAGlobalAlias(v.C); return } +func (v Value) IsAGlobalVariable() (rv Value) { rv.C = C.LLVMIsAGlobalVariable(v.C); return } +func (v Value) IsAUndefValue() (rv Value) { rv.C = C.LLVMIsAUndefValue(v.C); return } +func (v Value) IsAInstruction() (rv Value) { rv.C = C.LLVMIsAInstruction(v.C); return } +func (v Value) IsABinaryOperator() (rv Value) { rv.C = C.LLVMIsABinaryOperator(v.C); return } +func (v Value) IsACallInst() (rv Value) { rv.C = C.LLVMIsACallInst(v.C); return } +func (v Value) IsAIntrinsicInst() (rv Value) { rv.C = C.LLVMIsAIntrinsicInst(v.C); return } +func (v Value) IsADbgInfoIntrinsic() (rv Value) { rv.C = C.LLVMIsADbgInfoIntrinsic(v.C); return } +func (v Value) IsADbgDeclareInst() (rv Value) { rv.C = C.LLVMIsADbgDeclareInst(v.C); return } +func (v Value) IsAMemIntrinsic() (rv Value) { rv.C = C.LLVMIsAMemIntrinsic(v.C); return } +func (v Value) IsAMemCpyInst() (rv Value) { rv.C = C.LLVMIsAMemCpyInst(v.C); return } +func (v Value) IsAMemMoveInst() (rv Value) { rv.C = C.LLVMIsAMemMoveInst(v.C); return } +func (v Value) IsAMemSetInst() (rv Value) { rv.C = C.LLVMIsAMemSetInst(v.C); return } +func (v Value) IsACmpInst() (rv Value) { rv.C = C.LLVMIsACmpInst(v.C); return } +func (v Value) IsAFCmpInst() (rv Value) { rv.C = C.LLVMIsAFCmpInst(v.C); return } +func (v Value) IsAICmpInst() (rv Value) { rv.C = C.LLVMIsAICmpInst(v.C); return } +func (v Value) IsAExtractElementInst() (rv Value) { rv.C = C.LLVMIsAExtractElementInst(v.C); return } +func (v Value) IsAGetElementPtrInst() (rv Value) { rv.C = C.LLVMIsAGetElementPtrInst(v.C); return } +func (v Value) IsAInsertElementInst() (rv Value) { rv.C = C.LLVMIsAInsertElementInst(v.C); return } +func (v Value) IsAInsertValueInst() (rv Value) { rv.C = C.LLVMIsAInsertValueInst(v.C); return } +func (v Value) IsAPHINode() (rv Value) { rv.C = C.LLVMIsAPHINode(v.C); return } +func (v Value) IsASelectInst() (rv Value) { rv.C = C.LLVMIsASelectInst(v.C); return } +func (v Value) IsAShuffleVectorInst() (rv Value) { rv.C = C.LLVMIsAShuffleVectorInst(v.C); return } +func (v Value) IsAStoreInst() (rv Value) { rv.C = C.LLVMIsAStoreInst(v.C); return } +func (v Value) IsATerminatorInst() (rv Value) { rv.C = C.LLVMIsATerminatorInst(v.C); return } +func (v Value) IsABranchInst() (rv Value) { rv.C = C.LLVMIsABranchInst(v.C); return } +func (v Value) IsAInvokeInst() (rv Value) { rv.C = C.LLVMIsAInvokeInst(v.C); return } +func (v Value) IsAReturnInst() (rv Value) { rv.C = C.LLVMIsAReturnInst(v.C); return } +func (v Value) IsASwitchInst() (rv Value) { rv.C = C.LLVMIsASwitchInst(v.C); return } +func (v Value) IsAUnreachableInst() (rv Value) { rv.C = C.LLVMIsAUnreachableInst(v.C); return } +func (v Value) IsAUnaryInstruction() (rv Value) { rv.C = C.LLVMIsAUnaryInstruction(v.C); return } +func (v Value) IsAAllocaInst() (rv Value) { rv.C = C.LLVMIsAAllocaInst(v.C); return } +func (v Value) IsACastInst() (rv Value) { rv.C = C.LLVMIsACastInst(v.C); return } +func (v Value) IsABitCastInst() (rv Value) { rv.C = C.LLVMIsABitCastInst(v.C); return } +func (v Value) IsAFPExtInst() (rv Value) { rv.C = C.LLVMIsAFPExtInst(v.C); return } +func (v Value) IsAFPToSIInst() (rv Value) { rv.C = C.LLVMIsAFPToSIInst(v.C); return } +func (v Value) IsAFPToUIInst() (rv Value) { rv.C = C.LLVMIsAFPToUIInst(v.C); return } +func (v Value) IsAFPTruncInst() (rv Value) { rv.C = C.LLVMIsAFPTruncInst(v.C); return } +func (v Value) IsAIntToPtrInst() (rv Value) { rv.C = C.LLVMIsAIntToPtrInst(v.C); return } +func (v Value) IsAPtrToIntInst() (rv Value) { rv.C = C.LLVMIsAPtrToIntInst(v.C); return } +func (v Value) IsASExtInst() (rv Value) { rv.C = C.LLVMIsASExtInst(v.C); return } +func (v Value) IsASIToFPInst() (rv Value) { rv.C = C.LLVMIsASIToFPInst(v.C); return } +func (v Value) IsATruncInst() (rv Value) { rv.C = C.LLVMIsATruncInst(v.C); return } +func (v Value) IsAUIToFPInst() (rv Value) { rv.C = C.LLVMIsAUIToFPInst(v.C); return } +func (v Value) IsAZExtInst() (rv Value) { rv.C = C.LLVMIsAZExtInst(v.C); return } +func (v Value) IsAExtractValueInst() (rv Value) { rv.C = C.LLVMIsAExtractValueInst(v.C); return } +func (v Value) IsALoadInst() (rv Value) { rv.C = C.LLVMIsALoadInst(v.C); return } +func (v Value) IsAVAArgInst() (rv Value) { rv.C = C.LLVMIsAVAArgInst(v.C); return } + +// Operations on Uses +func (v Value) FirstUse() (u Use) { u.C = C.LLVMGetFirstUse(v.C); return } +func (u Use) NextUse() (ru Use) { ru.C = C.LLVMGetNextUse(u.C); return } +func (u Use) User() (v Value) { v.C = C.LLVMGetUser(u.C); return } +func (u Use) UsedValue() (v Value) { v.C = C.LLVMGetUsedValue(u.C); return } + +// Operations on Users +func (v Value) Operand(i int) (rv Value) { rv.C = C.LLVMGetOperand(v.C, C.unsigned(i)); return } +func (v Value) SetOperand(i int, op Value) { C.LLVMSetOperand(v.C, C.unsigned(i), op.C) } +func (v Value) OperandsCount() int { return int(C.LLVMGetNumOperands(v.C)) } + +// Operations on constants of any type +func ConstNull(t Type) (v Value) { v.C = C.LLVMConstNull(t.C); return } +func ConstAllOnes(t Type) (v Value) { v.C = C.LLVMConstAllOnes(t.C); return } +func Undef(t Type) (v Value) { v.C = C.LLVMGetUndef(t.C); return } +func (v Value) IsConstant() bool { return C.LLVMIsConstant(v.C) != 0 } +func (v Value) IsNull() bool { return C.LLVMIsNull(v.C) != 0 } +func (v Value) IsUndef() bool { return C.LLVMIsUndef(v.C) != 0 } +func ConstPointerNull(t Type) (v Value) { v.C = C.LLVMConstPointerNull(t.C); return } + +// Operations on metadata +func (c Context) MDString(str string) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMMDStringInContext(c.C, cstr, C.unsigned(len(str))) + return +} +func MDString(str string) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMMDString(cstr, C.unsigned(len(str))) + return +} +func (c Context) MDNode(vals []Value) (v Value) { + ptr, nvals := llvmValueRefs(vals) + v.C = C.LLVMMDNodeInContext(c.C, ptr, nvals) + return +} +func MDNode(vals []Value) (v Value) { + ptr, nvals := llvmValueRefs(vals) + v.C = C.LLVMMDNode(ptr, nvals) + return +} + +// Operations on scalar constants +func ConstInt(t Type, n uint64, signExtend bool) (v Value) { + v.C = C.LLVMConstInt(t.C, + C.ulonglong(n), + boolToLLVMBool(signExtend)) + return +} +func ConstIntFromString(t Type, str string, radix int) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMConstIntOfString(t.C, cstr, C.uint8_t(radix)) + return +} +func ConstFloat(t Type, n float64) (v Value) { + v.C = C.LLVMConstReal(t.C, C.double(n)) + return +} +func ConstFloatFromString(t Type, str string) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMConstRealOfString(t.C, cstr) + return +} + +func (v Value) ZExtValue() uint64 { return uint64(C.LLVMConstIntGetZExtValue(v.C)) } +func (v Value) SExtValue() int64 { return int64(C.LLVMConstIntGetSExtValue(v.C)) } + +// Operations on composite constants +func (c Context) ConstString(str string, addnull bool) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMConstStringInContext(c.C, cstr, + C.unsigned(len(str)), boolToLLVMBool(!addnull)) + return +} +func (c Context) ConstStruct(constVals []Value, packed bool) (v Value) { + ptr, nvals := llvmValueRefs(constVals) + v.C = C.LLVMConstStructInContext(c.C, ptr, nvals, + boolToLLVMBool(packed)) + return +} +func ConstNamedStruct(t Type, constVals []Value) (v Value) { + ptr, nvals := llvmValueRefs(constVals) + v.C = C.LLVMConstNamedStruct(t.C, ptr, nvals) + return +} +func ConstString(str string, addnull bool) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMConstString(cstr, + C.unsigned(len(str)), boolToLLVMBool(!addnull)) + return +} +func ConstArray(t Type, constVals []Value) (v Value) { + ptr, nvals := llvmValueRefs(constVals) + v.C = C.LLVMConstArray(t.C, ptr, nvals) + return +} +func ConstStruct(constVals []Value, packed bool) (v Value) { + ptr, nvals := llvmValueRefs(constVals) + v.C = C.LLVMConstStruct(ptr, nvals, boolToLLVMBool(packed)) + return +} +func ConstVector(scalarConstVals []Value, packed bool) (v Value) { + ptr, nvals := llvmValueRefs(scalarConstVals) + v.C = C.LLVMConstVector(ptr, nvals) + return +} + +// Constant expressions +func (v Value) Opcode() Opcode { return Opcode(C.LLVMGetConstOpcode(v.C)) } +func (v Value) InstructionOpcode() Opcode { return Opcode(C.LLVMGetInstructionOpcode(v.C)) } +func AlignOf(t Type) (v Value) { v.C = C.LLVMAlignOf(t.C); return } +func SizeOf(t Type) (v Value) { v.C = C.LLVMSizeOf(t.C); return } +func ConstNeg(v Value) (rv Value) { rv.C = C.LLVMConstNeg(v.C); return } +func ConstNSWNeg(v Value) (rv Value) { rv.C = C.LLVMConstNSWNeg(v.C); return } +func ConstNUWNeg(v Value) (rv Value) { rv.C = C.LLVMConstNUWNeg(v.C); return } +func ConstFNeg(v Value) (rv Value) { rv.C = C.LLVMConstFNeg(v.C); return } +func ConstNot(v Value) (rv Value) { rv.C = C.LLVMConstNot(v.C); return } +func ConstAdd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstAdd(lhs.C, rhs.C); return } +func ConstNSWAdd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNSWAdd(lhs.C, rhs.C); return } +func ConstNUWAdd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNUWAdd(lhs.C, rhs.C); return } +func ConstFAdd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFAdd(lhs.C, rhs.C); return } +func ConstSub(lhs, rhs Value) (v Value) { v.C = C.LLVMConstSub(lhs.C, rhs.C); return } +func ConstNSWSub(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNSWSub(lhs.C, rhs.C); return } +func ConstNUWSub(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNUWSub(lhs.C, rhs.C); return } +func ConstFSub(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFSub(lhs.C, rhs.C); return } +func ConstMul(lhs, rhs Value) (v Value) { v.C = C.LLVMConstMul(lhs.C, rhs.C); return } +func ConstNSWMul(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNSWMul(lhs.C, rhs.C); return } +func ConstNUWMul(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNUWMul(lhs.C, rhs.C); return } +func ConstFMul(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFMul(lhs.C, rhs.C); return } +func ConstUDiv(lhs, rhs Value) (v Value) { v.C = C.LLVMConstUDiv(lhs.C, rhs.C); return } +func ConstSDiv(lhs, rhs Value) (v Value) { v.C = C.LLVMConstSDiv(lhs.C, rhs.C); return } +func ConstExactSDiv(lhs, rhs Value) (v Value) { v.C = C.LLVMConstExactSDiv(lhs.C, rhs.C); return } +func ConstFDiv(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFDiv(lhs.C, rhs.C); return } +func ConstURem(lhs, rhs Value) (v Value) { v.C = C.LLVMConstURem(lhs.C, rhs.C); return } +func ConstSRem(lhs, rhs Value) (v Value) { v.C = C.LLVMConstSRem(lhs.C, rhs.C); return } +func ConstFRem(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFRem(lhs.C, rhs.C); return } +func ConstAnd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstAnd(lhs.C, rhs.C); return } +func ConstOr(lhs, rhs Value) (v Value) { v.C = C.LLVMConstOr(lhs.C, rhs.C); return } +func ConstXor(lhs, rhs Value) (v Value) { v.C = C.LLVMConstXor(lhs.C, rhs.C); return } + +func ConstICmp(pred IntPredicate, lhs, rhs Value) (v Value) { + v.C = C.LLVMConstICmp(C.LLVMIntPredicate(pred), lhs.C, rhs.C) + return +} +func ConstFCmp(pred FloatPredicate, lhs, rhs Value) (v Value) { + v.C = C.LLVMConstFCmp(C.LLVMRealPredicate(pred), lhs.C, rhs.C) + return +} + +func ConstShl(lhs, rhs Value) (v Value) { v.C = C.LLVMConstShl(lhs.C, rhs.C); return } +func ConstLShr(lhs, rhs Value) (v Value) { v.C = C.LLVMConstLShr(lhs.C, rhs.C); return } +func ConstAShr(lhs, rhs Value) (v Value) { v.C = C.LLVMConstAShr(lhs.C, rhs.C); return } + +func ConstGEP(v Value, indices []Value) (rv Value) { + ptr, nvals := llvmValueRefs(indices) + rv.C = C.LLVMConstGEP(v.C, ptr, nvals) + return +} +func ConstInBoundsGEP(v Value, indices []Value) (rv Value) { + ptr, nvals := llvmValueRefs(indices) + rv.C = C.LLVMConstInBoundsGEP(v.C, ptr, nvals) + return +} +func ConstTrunc(v Value, t Type) (rv Value) { rv.C = C.LLVMConstTrunc(v.C, t.C); return } +func ConstSExt(v Value, t Type) (rv Value) { rv.C = C.LLVMConstSExt(v.C, t.C); return } +func ConstZExt(v Value, t Type) (rv Value) { rv.C = C.LLVMConstZExt(v.C, t.C); return } +func ConstFPTrunc(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPTrunc(v.C, t.C); return } +func ConstFPExt(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPExt(v.C, t.C); return } +func ConstUIToFP(v Value, t Type) (rv Value) { rv.C = C.LLVMConstUIToFP(v.C, t.C); return } +func ConstSIToFP(v Value, t Type) (rv Value) { rv.C = C.LLVMConstSIToFP(v.C, t.C); return } +func ConstFPToUI(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPToUI(v.C, t.C); return } +func ConstFPToSI(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPToSI(v.C, t.C); return } +func ConstPtrToInt(v Value, t Type) (rv Value) { rv.C = C.LLVMConstPtrToInt(v.C, t.C); return } +func ConstIntToPtr(v Value, t Type) (rv Value) { rv.C = C.LLVMConstIntToPtr(v.C, t.C); return } +func ConstBitCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstBitCast(v.C, t.C); return } +func ConstZExtOrBitCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstZExtOrBitCast(v.C, t.C); return } +func ConstSExtOrBitCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstSExtOrBitCast(v.C, t.C); return } +func ConstTruncOrBitCast(v Value, t Type) (rv Value) { + rv.C = C.LLVMConstTruncOrBitCast(v.C, t.C) + return +} +func ConstPointerCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstPointerCast(v.C, t.C); return } +func ConstIntCast(v Value, t Type, signed bool) (rv Value) { + rv.C = C.LLVMConstIntCast(v.C, t.C, boolToLLVMBool(signed)) + return +} +func ConstFPCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPCast(v.C, t.C); return } +func ConstSelect(cond, iftrue, iffalse Value) (rv Value) { + rv.C = C.LLVMConstSelect(cond.C, iftrue.C, iffalse.C) + return +} +func ConstExtractElement(vec, i Value) (rv Value) { + rv.C = C.LLVMConstExtractElement(vec.C, i.C) + return +} +func ConstInsertElement(vec, elem, i Value) (rv Value) { + rv.C = C.LLVMConstInsertElement(vec.C, elem.C, i.C) + return +} +func ConstShuffleVector(veca, vecb, mask Value) (rv Value) { + rv.C = C.LLVMConstShuffleVector(veca.C, vecb.C, mask.C) + return +} + +//TODO +//LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList, +// unsigned NumIdx); + +func ConstExtractValue(agg Value, indices []uint32) (rv Value) { + n := len(indices) + if n == 0 { + panic("one or more indices are required") + } + ptr := (*C.unsigned)(&indices[0]) + rv.C = C.LLVMConstExtractValue(agg.C, ptr, C.unsigned(n)) + return +} + +func ConstInsertValue(agg, val Value, indices []uint32) (rv Value) { + n := len(indices) + if n == 0 { + panic("one or more indices are required") + } + ptr := (*C.unsigned)(&indices[0]) + rv.C = C.LLVMConstInsertValue(agg.C, val.C, ptr, C.unsigned(n)) + return +} + +func BlockAddress(f Value, bb BasicBlock) (v Value) { + v.C = C.LLVMBlockAddress(f.C, bb.C) + return +} + +// Operations on global variables, functions, and aliases (globals) +func (v Value) GlobalParent() (m Module) { m.C = C.LLVMGetGlobalParent(v.C); return } +func (v Value) IsDeclaration() bool { return C.LLVMIsDeclaration(v.C) != 0 } +func (v Value) Linkage() Linkage { return Linkage(C.LLVMGetLinkage(v.C)) } +func (v Value) SetLinkage(l Linkage) { C.LLVMSetLinkage(v.C, C.LLVMLinkage(l)) } +func (v Value) Section() string { return C.GoString(C.LLVMGetSection(v.C)) } +func (v Value) SetSection(str string) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + C.LLVMSetSection(v.C, cstr) +} +func (v Value) Visibility() Visibility { return Visibility(C.LLVMGetVisibility(v.C)) } +func (v Value) SetVisibility(vi Visibility) { C.LLVMSetVisibility(v.C, C.LLVMVisibility(vi)) } +func (v Value) Alignment() int { return int(C.LLVMGetAlignment(v.C)) } +func (v Value) SetAlignment(a int) { C.LLVMSetAlignment(v.C, C.unsigned(a)) } +func (v Value) SetUnnamedAddr(ua bool) { C.LLVMSetUnnamedAddr(v.C, boolToLLVMBool(ua)) } + +// Operations on global variables +func AddGlobal(m Module, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMAddGlobal(m.C, t.C, cname) + return +} +func AddGlobalInAddressSpace(m Module, t Type, name string, addressSpace int) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMAddGlobalInAddressSpace(m.C, t.C, cname, C.unsigned(addressSpace)) + return +} +func (m Module) NamedGlobal(name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMGetNamedGlobal(m.C, cname) + return +} + +func (m Module) FirstGlobal() (v Value) { v.C = C.LLVMGetFirstGlobal(m.C); return } +func (m Module) LastGlobal() (v Value) { v.C = C.LLVMGetLastGlobal(m.C); return } +func NextGlobal(v Value) (rv Value) { rv.C = C.LLVMGetNextGlobal(v.C); return } +func PrevGlobal(v Value) (rv Value) { rv.C = C.LLVMGetPreviousGlobal(v.C); return } +func (v Value) EraseFromParentAsGlobal() { C.LLVMDeleteGlobal(v.C) } +func (v Value) Initializer() (rv Value) { rv.C = C.LLVMGetInitializer(v.C); return } +func (v Value) SetInitializer(cv Value) { C.LLVMSetInitializer(v.C, cv.C) } +func (v Value) IsThreadLocal() bool { return C.LLVMIsThreadLocal(v.C) != 0 } +func (v Value) SetThreadLocal(tl bool) { C.LLVMSetThreadLocal(v.C, boolToLLVMBool(tl)) } +func (v Value) IsGlobalConstant() bool { return C.LLVMIsGlobalConstant(v.C) != 0 } +func (v Value) SetGlobalConstant(gc bool) { C.LLVMSetGlobalConstant(v.C, boolToLLVMBool(gc)) } + +// Operations on aliases +func AddAlias(m Module, t Type, aliasee Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMAddAlias(m.C, t.C, aliasee.C, cname) + return +} + +// Operations on functions +func AddFunction(m Module, name string, ft Type) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMAddFunction(m.C, cname, ft.C) + return +} + +func (m Module) NamedFunction(name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMGetNamedFunction(m.C, cname) + return +} + +func (m Module) FirstFunction() (v Value) { v.C = C.LLVMGetFirstFunction(m.C); return } +func (m Module) LastFunction() (v Value) { v.C = C.LLVMGetLastFunction(m.C); return } +func NextFunction(v Value) (rv Value) { rv.C = C.LLVMGetNextFunction(v.C); return } +func PrevFunction(v Value) (rv Value) { rv.C = C.LLVMGetPreviousFunction(v.C); return } +func (v Value) EraseFromParentAsFunction() { C.LLVMDeleteFunction(v.C) } +func (v Value) IntrinsicID() int { return int(C.LLVMGetIntrinsicID(v.C)) } +func (v Value) FunctionCallConv() CallConv { + return CallConv(C.LLVMCallConv(C.LLVMGetFunctionCallConv(v.C))) +} +func (v Value) SetFunctionCallConv(cc CallConv) { C.LLVMSetFunctionCallConv(v.C, C.unsigned(cc)) } +func (v Value) GC() string { return C.GoString(C.LLVMGetGC(v.C)) } +func (v Value) SetGC(name string) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMSetGC(v.C, cname) +} +func (v Value) AddFunctionAttr(a Attribute) { C.LLVMAddFunctionAttr2(v.C, C.uint64_t(a)) } +func (v Value) FunctionAttr() Attribute { return Attribute(C.LLVMGetFunctionAttr2(v.C)) } +func (v Value) RemoveFunctionAttr(a Attribute) { C.LLVMRemoveFunctionAttr2(v.C, C.uint64_t(a)) } +func (v Value) AddTargetDependentFunctionAttr(attr, value string) { + cattr := C.CString(attr) + defer C.free(unsafe.Pointer(cattr)) + cvalue := C.CString(value) + defer C.free(unsafe.Pointer(cvalue)) + C.LLVMAddTargetDependentFunctionAttr(v.C, cattr, cvalue) +} + +// Operations on parameters +func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) } +func (v Value) Params() []Value { + out := make([]Value, v.ParamsCount()) + if len(out) > 0 { + C.LLVMGetParams(v.C, llvmValueRefPtr(&out[0])) + } + return out +} +func (v Value) Param(i int) (rv Value) { rv.C = C.LLVMGetParam(v.C, C.unsigned(i)); return } +func (v Value) ParamParent() (rv Value) { rv.C = C.LLVMGetParamParent(v.C); return } +func (v Value) FirstParam() (rv Value) { rv.C = C.LLVMGetFirstParam(v.C); return } +func (v Value) LastParam() (rv Value) { rv.C = C.LLVMGetLastParam(v.C); return } +func NextParam(v Value) (rv Value) { rv.C = C.LLVMGetNextParam(v.C); return } +func PrevParam(v Value) (rv Value) { rv.C = C.LLVMGetPreviousParam(v.C); return } +func (v Value) AddAttribute(a Attribute) { + if a >= 1<<32 { + panic("attribute value currently unsupported") + } + C.LLVMAddAttribute(v.C, C.LLVMAttribute(a)) +} +func (v Value) RemoveAttribute(a Attribute) { + if a >= 1<<32 { + panic("attribute value currently unsupported") + } + C.LLVMRemoveAttribute(v.C, C.LLVMAttribute(a)) +} +func (v Value) Attribute() Attribute { return Attribute(C.LLVMGetAttribute(v.C)) } +func (v Value) SetParamAlignment(align int) { C.LLVMSetParamAlignment(v.C, C.unsigned(align)) } + +// Operations on basic blocks +func (bb BasicBlock) AsValue() (v Value) { v.C = C.LLVMBasicBlockAsValue(bb.C); return } +func (v Value) IsBasicBlock() bool { return C.LLVMValueIsBasicBlock(v.C) != 0 } +func (v Value) AsBasicBlock() (bb BasicBlock) { bb.C = C.LLVMValueAsBasicBlock(v.C); return } +func (bb BasicBlock) Parent() (v Value) { v.C = C.LLVMGetBasicBlockParent(bb.C); return } +func (v Value) BasicBlocksCount() int { return int(C.LLVMCountBasicBlocks(v.C)) } +func (v Value) BasicBlocks() []BasicBlock { + out := make([]BasicBlock, v.BasicBlocksCount()) + C.LLVMGetBasicBlocks(v.C, llvmBasicBlockRefPtr(&out[0])) + return out +} +func (v Value) FirstBasicBlock() (bb BasicBlock) { bb.C = C.LLVMGetFirstBasicBlock(v.C); return } +func (v Value) LastBasicBlock() (bb BasicBlock) { bb.C = C.LLVMGetLastBasicBlock(v.C); return } +func NextBasicBlock(bb BasicBlock) (rbb BasicBlock) { rbb.C = C.LLVMGetNextBasicBlock(bb.C); return } +func PrevBasicBlock(bb BasicBlock) (rbb BasicBlock) { rbb.C = C.LLVMGetPreviousBasicBlock(bb.C); return } +func (v Value) EntryBasicBlock() (bb BasicBlock) { bb.C = C.LLVMGetEntryBasicBlock(v.C); return } +func (c Context) AddBasicBlock(f Value, name string) (bb BasicBlock) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + bb.C = C.LLVMAppendBasicBlockInContext(c.C, f.C, cname) + return +} +func (c Context) InsertBasicBlock(ref BasicBlock, name string) (bb BasicBlock) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + bb.C = C.LLVMInsertBasicBlockInContext(c.C, ref.C, cname) + return +} +func AddBasicBlock(f Value, name string) (bb BasicBlock) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + bb.C = C.LLVMAppendBasicBlock(f.C, cname) + return +} +func InsertBasicBlock(ref BasicBlock, name string) (bb BasicBlock) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + bb.C = C.LLVMInsertBasicBlock(ref.C, cname) + return +} +func (bb BasicBlock) EraseFromParent() { C.LLVMDeleteBasicBlock(bb.C) } +func (bb BasicBlock) MoveBefore(pos BasicBlock) { C.LLVMMoveBasicBlockBefore(bb.C, pos.C) } +func (bb BasicBlock) MoveAfter(pos BasicBlock) { C.LLVMMoveBasicBlockAfter(bb.C, pos.C) } + +// Operations on instructions +func (v Value) InstructionParent() (bb BasicBlock) { bb.C = C.LLVMGetInstructionParent(v.C); return } +func (bb BasicBlock) FirstInstruction() (v Value) { v.C = C.LLVMGetFirstInstruction(bb.C); return } +func (bb BasicBlock) LastInstruction() (v Value) { v.C = C.LLVMGetLastInstruction(bb.C); return } +func NextInstruction(v Value) (rv Value) { rv.C = C.LLVMGetNextInstruction(v.C); return } +func PrevInstruction(v Value) (rv Value) { rv.C = C.LLVMGetPreviousInstruction(v.C); return } + +// Operations on call sites +func (v Value) SetInstructionCallConv(cc CallConv) { + C.LLVMSetInstructionCallConv(v.C, C.unsigned(cc)) +} +func (v Value) InstructionCallConv() CallConv { + return CallConv(C.LLVMCallConv(C.LLVMGetInstructionCallConv(v.C))) +} +func (v Value) AddInstrAttribute(i int, a Attribute) { + if a >= 1<<32 { + panic("attribute value currently unsupported") + } + C.LLVMAddInstrAttribute(v.C, C.unsigned(i), C.LLVMAttribute(a)) +} +func (v Value) RemoveInstrAttribute(i int, a Attribute) { + if a >= 1<<32 { + panic("attribute value currently unsupported") + } + C.LLVMRemoveInstrAttribute(v.C, C.unsigned(i), C.LLVMAttribute(a)) +} +func (v Value) SetInstrParamAlignment(i int, align int) { + C.LLVMSetInstrParamAlignment(v.C, C.unsigned(i), C.unsigned(align)) +} + +// Operations on call instructions (only) +func (v Value) IsTailCall() bool { return C.LLVMIsTailCall(v.C) != 0 } +func (v Value) SetTailCall(is bool) { C.LLVMSetTailCall(v.C, boolToLLVMBool(is)) } + +// Operations on phi nodes +func (v Value) AddIncoming(vals []Value, blocks []BasicBlock) { + ptr, nvals := llvmValueRefs(vals) + C.LLVMAddIncoming(v.C, ptr, llvmBasicBlockRefPtr(&blocks[0]), nvals) +} +func (v Value) IncomingCount() int { return int(C.LLVMCountIncoming(v.C)) } +func (v Value) IncomingValue(i int) (rv Value) { + rv.C = C.LLVMGetIncomingValue(v.C, C.unsigned(i)) + return +} +func (v Value) IncomingBlock(i int) (bb BasicBlock) { + bb.C = C.LLVMGetIncomingBlock(v.C, C.unsigned(i)) + return +} + +//------------------------------------------------------------------------- +// llvm.Builder +//------------------------------------------------------------------------- + +// An instruction builder represents a point within a basic block, and is the +// exclusive means of building instructions using the C interface. + +func (c Context) NewBuilder() (b Builder) { b.C = C.LLVMCreateBuilderInContext(c.C); return } +func NewBuilder() (b Builder) { b.C = C.LLVMCreateBuilder(); return } +func (b Builder) SetInsertPoint(block BasicBlock, instr Value) { + C.LLVMPositionBuilder(b.C, block.C, instr.C) +} +func (b Builder) SetInsertPointBefore(instr Value) { C.LLVMPositionBuilderBefore(b.C, instr.C) } +func (b Builder) SetInsertPointAtEnd(block BasicBlock) { C.LLVMPositionBuilderAtEnd(b.C, block.C) } +func (b Builder) GetInsertBlock() (bb BasicBlock) { bb.C = C.LLVMGetInsertBlock(b.C); return } +func (b Builder) ClearInsertionPoint() { C.LLVMClearInsertionPosition(b.C) } +func (b Builder) Insert(instr Value) { C.LLVMInsertIntoBuilder(b.C, instr.C) } +func (b Builder) InsertWithName(instr Value, name string) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMInsertIntoBuilderWithName(b.C, instr.C, cname) +} +func (b Builder) Dispose() { C.LLVMDisposeBuilder(b.C) } + +// Metadata +func (b Builder) SetCurrentDebugLocation(v Value) { C.LLVMSetCurrentDebugLocation(b.C, v.C) } +func (b Builder) CurrentDebugLocation() (v Value) { v.C = C.LLVMGetCurrentDebugLocation(b.C); return } +func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) } +func (b Builder) InsertDeclare(module Module, storage Value, md Value) Value { + f := module.NamedFunction("llvm.dbg.declare") + if f.IsNil() { + ftyp := FunctionType(VoidType(), []Type{storage.Type(), md.Type()}, false) + f = AddFunction(module, "llvm.dbg.declare", ftyp) + } + return b.CreateCall(f, []Value{storage, md}, "") +} + +// Terminators +func (b Builder) CreateRetVoid() (rv Value) { rv.C = C.LLVMBuildRetVoid(b.C); return } +func (b Builder) CreateRet(v Value) (rv Value) { rv.C = C.LLVMBuildRet(b.C, v.C); return } +func (b Builder) CreateAggregateRet(vs []Value) (rv Value) { + ptr, nvals := llvmValueRefs(vs) + rv.C = C.LLVMBuildAggregateRet(b.C, ptr, nvals) + return +} +func (b Builder) CreateBr(bb BasicBlock) (rv Value) { rv.C = C.LLVMBuildBr(b.C, bb.C); return } +func (b Builder) CreateCondBr(ifv Value, thenb, elseb BasicBlock) (rv Value) { + rv.C = C.LLVMBuildCondBr(b.C, ifv.C, thenb.C, elseb.C) + return +} +func (b Builder) CreateSwitch(v Value, elseb BasicBlock, numCases int) (rv Value) { + rv.C = C.LLVMBuildSwitch(b.C, v.C, elseb.C, C.unsigned(numCases)) + return +} +func (b Builder) CreateIndirectBr(addr Value, numDests int) (rv Value) { + rv.C = C.LLVMBuildIndirectBr(b.C, addr.C, C.unsigned(numDests)) + return +} +func (b Builder) CreateInvoke(fn Value, args []Value, then, catch BasicBlock, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(args) + rv.C = C.LLVMBuildInvoke(b.C, fn.C, ptr, nvals, then.C, catch.C, cname) + return +} +func (b Builder) CreateUnreachable() (rv Value) { rv.C = C.LLVMBuildUnreachable(b.C); return } + +// Add a case to the switch instruction +func (v Value) AddCase(on Value, dest BasicBlock) { C.LLVMAddCase(v.C, on.C, dest.C) } + +// Add a destination to the indirectbr instruction +func (v Value) AddDest(dest BasicBlock) { C.LLVMAddDestination(v.C, dest.C) } + +// Arithmetic +func (b Builder) CreateAdd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildAdd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNSWAdd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNSWAdd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNUWAdd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNUWAdd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFAdd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFAdd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateSub(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSub(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNSWSub(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNSWSub(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNUWSub(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNUWSub(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFSub(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + v.C = C.LLVMBuildFSub(b.C, lhs.C, rhs.C, cname) + C.free(unsafe.Pointer(cname)) + return +} +func (b Builder) CreateMul(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildMul(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNSWMul(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNSWMul(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNUWMul(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNUWMul(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFMul(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFMul(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateUDiv(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildUDiv(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateSDiv(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSDiv(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateExactSDiv(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildExactSDiv(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFDiv(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFDiv(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateURem(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildURem(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateSRem(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSRem(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFRem(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFRem(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateShl(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildShl(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateLShr(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildLShr(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateAShr(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildAShr(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateAnd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildAnd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateOr(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildOr(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateXor(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildXor(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateBinOp(op Opcode, lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildBinOp(b.C, C.LLVMOpcode(op), lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNeg(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildNeg(b.C, v.C, cname) + return +} +func (b Builder) CreateNSWNeg(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildNSWNeg(b.C, v.C, cname) + return +} +func (b Builder) CreateNUWNeg(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildNUWNeg(b.C, v.C, cname) + return +} +func (b Builder) CreateFNeg(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildFNeg(b.C, v.C, cname) + return +} +func (b Builder) CreateNot(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildNot(b.C, v.C, cname) + return +} + +// Memory + +func (b Builder) CreateMalloc(t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildMalloc(b.C, t.C, cname) + return +} +func (b Builder) CreateArrayMalloc(t Type, val Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildArrayMalloc(b.C, t.C, val.C, cname) + return +} +func (b Builder) CreateAlloca(t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildAlloca(b.C, t.C, cname) + return +} +func (b Builder) CreateArrayAlloca(t Type, val Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildArrayAlloca(b.C, t.C, val.C, cname) + return +} +func (b Builder) CreateFree(p Value) (v Value) { + v.C = C.LLVMBuildFree(b.C, p.C) + return +} +func (b Builder) CreateLoad(p Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildLoad(b.C, p.C, cname) + return +} +func (b Builder) CreateStore(val Value, p Value) (v Value) { + v.C = C.LLVMBuildStore(b.C, val.C, p.C) + return +} +func (b Builder) CreateGEP(p Value, indices []Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(indices) + v.C = C.LLVMBuildGEP(b.C, p.C, ptr, nvals, cname) + return +} +func (b Builder) CreateInBoundsGEP(p Value, indices []Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(indices) + v.C = C.LLVMBuildInBoundsGEP(b.C, p.C, ptr, nvals, cname) + return +} +func (b Builder) CreateStructGEP(p Value, i int, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildStructGEP(b.C, p.C, C.unsigned(i), cname) + return +} +func (b Builder) CreateGlobalString(str, name string) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildGlobalString(b.C, cstr, cname) + return +} +func (b Builder) CreateGlobalStringPtr(str, name string) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildGlobalStringPtr(b.C, cstr, cname) + return +} + +// Casts +func (b Builder) CreateTrunc(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildTrunc(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateZExt(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildZExt(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateSExt(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSExt(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPToUI(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPToUI(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPToSI(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPToSI(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateUIToFP(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildUIToFP(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateSIToFP(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSIToFP(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPTrunc(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPTrunc(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPExt(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPExt(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreatePtrToInt(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildPtrToInt(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateIntToPtr(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildIntToPtr(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateBitCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildBitCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateZExtOrBitCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildZExtOrBitCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateSExtOrBitCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSExtOrBitCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateTruncOrBitCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildTruncOrBitCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateCast(val Value, op Opcode, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildCast(b.C, C.LLVMOpcode(op), val.C, t.C, cname) + return +} // +func (b Builder) CreatePointerCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildPointerCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateIntCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildIntCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPCast(b.C, val.C, t.C, cname) + return +} + +// Comparisons +func (b Builder) CreateICmp(pred IntPredicate, lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildICmp(b.C, C.LLVMIntPredicate(pred), lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFCmp(pred FloatPredicate, lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFCmp(b.C, C.LLVMRealPredicate(pred), lhs.C, rhs.C, cname) + return +} + +// Miscellaneous instructions +func (b Builder) CreatePHI(t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildPhi(b.C, t.C, cname) + return +} +func (b Builder) CreateCall(fn Value, args []Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(args) + v.C = C.LLVMBuildCall(b.C, fn.C, ptr, nvals, cname) + return +} + +func (b Builder) CreateSelect(ifv, thenv, elsev Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSelect(b.C, ifv.C, thenv.C, elsev.C, cname) + return +} + +func (b Builder) CreateVAArg(list Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildVAArg(b.C, list.C, t.C, cname) + return +} +func (b Builder) CreateExtractElement(vec, i Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildExtractElement(b.C, vec.C, i.C, cname) + return +} +func (b Builder) CreateInsertElement(vec, elt, i Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildInsertElement(b.C, vec.C, elt.C, i.C, cname) + return +} +func (b Builder) CreateShuffleVector(v1, v2, mask Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildShuffleVector(b.C, v1.C, v2.C, mask.C, cname) + return +} +func (b Builder) CreateExtractValue(agg Value, i int, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildExtractValue(b.C, agg.C, C.unsigned(i), cname) + return +} +func (b Builder) CreateInsertValue(agg, elt Value, i int, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildInsertValue(b.C, agg.C, elt.C, C.unsigned(i), cname) + return +} + +func (b Builder) CreateIsNull(val Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildIsNull(b.C, val.C, cname) + return +} +func (b Builder) CreateIsNotNull(val Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildIsNotNull(b.C, val.C, cname) + return +} +func (b Builder) CreatePtrDiff(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildPtrDiff(b.C, lhs.C, rhs.C, cname) + return +} + +func (b Builder) CreateLandingPad(t Type, personality Value, nclauses int, name string) (l Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + l.C = C.LLVMBuildLandingPad(b.C, t.C, personality.C, C.unsigned(nclauses), cname) + return l +} + +func (l Value) AddClause(v Value) { + C.LLVMAddClause(l.C, v.C) +} + +func (l Value) SetCleanup(cleanup bool) { + C.LLVMSetCleanup(l.C, boolToLLVMBool(cleanup)) +} + +func (b Builder) CreateResume(ex Value) (v Value) { + v.C = C.LLVMBuildResume(b.C, ex.C) + return +} + +//------------------------------------------------------------------------- +// llvm.ModuleProvider +//------------------------------------------------------------------------- + +// Changes the type of M so it can be passed to FunctionPassManagers and the +// JIT. They take ModuleProviders for historical reasons. +func NewModuleProviderForModule(m Module) (mp ModuleProvider) { + mp.C = C.LLVMCreateModuleProviderForExistingModule(m.C) + return +} + +// Destroys the module M. +func (mp ModuleProvider) Dispose() { C.LLVMDisposeModuleProvider(mp.C) } + +//------------------------------------------------------------------------- +// llvm.MemoryBuffer +//------------------------------------------------------------------------- + +func NewMemoryBufferFromFile(path string) (b MemoryBuffer, err error) { + var cmsg *C.char + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + fail := C.LLVMCreateMemoryBufferWithContentsOfFile(cpath, &b.C, &cmsg) + if fail != 0 { + b.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func NewMemoryBufferFromStdin() (b MemoryBuffer, err error) { + var cmsg *C.char + fail := C.LLVMCreateMemoryBufferWithSTDIN(&b.C, &cmsg) + if fail != 0 { + b.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func (b MemoryBuffer) Bytes() []byte { + cstart := C.LLVMGetBufferStart(b.C) + csize := C.LLVMGetBufferSize(b.C) + return C.GoBytes(unsafe.Pointer(cstart), C.int(csize)) +} + +func (b MemoryBuffer) Dispose() { C.LLVMDisposeMemoryBuffer(b.C) } + +//------------------------------------------------------------------------- +// llvm.PassManager +//------------------------------------------------------------------------- + +// Constructs a new whole-module pass pipeline. This type of pipeline is +// suitable for link-time optimization and whole-module transformations. +// See llvm::PassManager::PassManager. +func NewPassManager() (pm PassManager) { pm.C = C.LLVMCreatePassManager(); return } + +// Constructs a new function-by-function pass pipeline over the module +// provider. It does not take ownership of the module provider. This type of +// pipeline is suitable for code generation and JIT compilation tasks. +// See llvm::FunctionPassManager::FunctionPassManager. +func NewFunctionPassManagerForModule(m Module) (pm PassManager) { + pm.C = C.LLVMCreateFunctionPassManagerForModule(m.C) + return +} + +// Initializes, executes on the provided module, and finalizes all of the +// passes scheduled in the pass manager. Returns 1 if any of the passes +// modified the module, 0 otherwise. See llvm::PassManager::run(Module&). +func (pm PassManager) Run(m Module) bool { return C.LLVMRunPassManager(pm.C, m.C) != 0 } + +// Initializes all of the function passes scheduled in the function pass +// manager. Returns 1 if any of the passes modified the module, 0 otherwise. +// See llvm::FunctionPassManager::doInitialization. +func (pm PassManager) InitializeFunc() bool { return C.LLVMInitializeFunctionPassManager(pm.C) != 0 } + +// Executes all of the function passes scheduled in the function pass manager +// on the provided function. Returns 1 if any of the passes modified the +// function, false otherwise. +// See llvm::FunctionPassManager::run(Function&). +func (pm PassManager) RunFunc(f Value) bool { return C.LLVMRunFunctionPassManager(pm.C, f.C) != 0 } + +// Finalizes all of the function passes scheduled in in the function pass +// manager. Returns 1 if any of the passes modified the module, 0 otherwise. +// See llvm::FunctionPassManager::doFinalization. +func (pm PassManager) FinalizeFunc() bool { return C.LLVMFinalizeFunctionPassManager(pm.C) != 0 } + +// Frees the memory of a pass pipeline. For function pipelines, does not free +// the module provider. +// See llvm::PassManagerBase::~PassManagerBase. +func (pm PassManager) Dispose() { C.LLVMDisposePassManager(pm.C) } diff --git a/bindings/go/llvm/ir_test.go b/bindings/go/llvm/ir_test.go new file mode 100644 index 0000000..981c94a --- /dev/null +++ b/bindings/go/llvm/ir_test.go @@ -0,0 +1,95 @@ +//===- ir_test.go - Tests for ir ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests bindings for the ir component. +// +//===----------------------------------------------------------------------===// + +package llvm + +import ( + "strings" + "testing" +) + +func testAttribute(t *testing.T, attr Attribute, name string) { + mod := NewModule("") + defer mod.Dispose() + + ftyp := FunctionType(VoidType(), nil, false) + fn := AddFunction(mod, "foo", ftyp) + + fn.AddFunctionAttr(attr) + newattr := fn.FunctionAttr() + if attr != newattr { + t.Errorf("got attribute mask %d, want %d", newattr, attr) + } + + text := mod.String() + if !strings.Contains(text, " "+name+" ") { + t.Errorf("expected attribute '%s', got:\n%s", name, text) + } + + fn.RemoveFunctionAttr(attr) + newattr = fn.FunctionAttr() + if newattr != 0 { + t.Errorf("got attribute mask %d, want 0", newattr) + } +} + +func TestAttributes(t *testing.T) { + // Tests that our attribute constants haven't drifted from LLVM's. + attrTests := []struct { + attr Attribute + name string + }{ + {SanitizeAddressAttribute, "sanitize_address"}, + {AlwaysInlineAttribute, "alwaysinline"}, + {BuiltinAttribute, "builtin"}, + {ByValAttribute, "byval"}, + {InAllocaAttribute, "inalloca"}, + {InlineHintAttribute, "inlinehint"}, + {InRegAttribute, "inreg"}, + {JumpTableAttribute, "jumptable"}, + {MinSizeAttribute, "minsize"}, + {NakedAttribute, "naked"}, + {NestAttribute, "nest"}, + {NoAliasAttribute, "noalias"}, + {NoBuiltinAttribute, "nobuiltin"}, + {NoCaptureAttribute, "nocapture"}, + {NoDuplicateAttribute, "noduplicate"}, + {NoImplicitFloatAttribute, "noimplicitfloat"}, + {NoInlineAttribute, "noinline"}, + {NonLazyBindAttribute, "nonlazybind"}, + {NonNullAttribute, "nonnull"}, + {NoRedZoneAttribute, "noredzone"}, + {NoReturnAttribute, "noreturn"}, + {NoUnwindAttribute, "nounwind"}, + {OptimizeNoneAttribute, "optnone"}, + {OptimizeForSizeAttribute, "optsize"}, + {ReadNoneAttribute, "readnone"}, + {ReadOnlyAttribute, "readonly"}, + {ReturnedAttribute, "returned"}, + {ReturnsTwiceAttribute, "returns_twice"}, + {SExtAttribute, "signext"}, + {StackProtectAttribute, "ssp"}, + {StackProtectReqAttribute, "sspreq"}, + {StackProtectStrongAttribute, "sspstrong"}, + {StructRetAttribute, "sret"}, + {SanitizeThreadAttribute, "sanitize_thread"}, + {SanitizeMemoryAttribute, "sanitize_memory"}, + {UWTableAttribute, "uwtable"}, + {ZExtAttribute, "zeroext"}, + {ColdAttribute, "cold"}, + } + + for _, a := range attrTests { + testAttribute(t, a.attr, a.name) + } +} diff --git a/bindings/go/llvm/linker.go b/bindings/go/llvm/linker.go new file mode 100644 index 0000000..31e9ad2 --- /dev/null +++ b/bindings/go/llvm/linker.go @@ -0,0 +1,39 @@ +//===- linker.go - Bindings for linker ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the linker component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Linker.h" +#include <stdlib.h> +*/ +import "C" +import "errors" + +type LinkerMode C.LLVMLinkerMode + +const ( + LinkerDestroySource = C.LLVMLinkerDestroySource + LinkerPreserveSource = C.LLVMLinkerPreserveSource +) + +func LinkModules(Dest, Src Module, Mode LinkerMode) error { + var cmsg *C.char + failed := C.LLVMLinkModules(Dest.C, Src.C, C.LLVMLinkerMode(Mode), &cmsg) + if failed != 0 { + err := errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + return err + } + return nil +} diff --git a/bindings/go/llvm/llvm_config.go.in b/bindings/go/llvm/llvm_config.go.in new file mode 100644 index 0000000..41854fa --- /dev/null +++ b/bindings/go/llvm/llvm_config.go.in @@ -0,0 +1,12 @@ +// +build !byollvm + +package llvm + +/* +#cgo CXXFLAGS: -std=c++11 +#cgo CPPFLAGS: @LLVM_CFLAGS@ +#cgo LDFLAGS: @LLVM_LDFLAGS@ +*/ +import "C" + +type (run_build_sh int) diff --git a/bindings/go/llvm/llvm_dep.go b/bindings/go/llvm/llvm_dep.go new file mode 100644 index 0000000..39b4675 --- /dev/null +++ b/bindings/go/llvm/llvm_dep.go @@ -0,0 +1,19 @@ +//===- llvm_dep.go - creates LLVM dependency ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file ensures that the LLVM libraries are built before using the +// bindings. +// +//===----------------------------------------------------------------------===// + +// +build !byollvm + +package llvm + +var _ run_build_sh diff --git a/bindings/go/llvm/string.go b/bindings/go/llvm/string.go new file mode 100644 index 0000000..bfe869d --- /dev/null +++ b/bindings/go/llvm/string.go @@ -0,0 +1,105 @@ +//===- string.go - Stringer implementation for Type -----------------------===// +// +// 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 Stringer interface for the Type type. +// +//===----------------------------------------------------------------------===// + +package llvm + +import "fmt" + +func (t TypeKind) String() string { + switch t { + case VoidTypeKind: + return "VoidTypeKind" + case FloatTypeKind: + return "FloatTypeKind" + case DoubleTypeKind: + return "DoubleTypeKind" + case X86_FP80TypeKind: + return "X86_FP80TypeKind" + case FP128TypeKind: + return "FP128TypeKind" + case PPC_FP128TypeKind: + return "PPC_FP128TypeKind" + case LabelTypeKind: + return "LabelTypeKind" + case IntegerTypeKind: + return "IntegerTypeKind" + case FunctionTypeKind: + return "FunctionTypeKind" + case StructTypeKind: + return "StructTypeKind" + case ArrayTypeKind: + return "ArrayTypeKind" + case PointerTypeKind: + return "PointerTypeKind" + case VectorTypeKind: + return "VectorTypeKind" + case MetadataTypeKind: + return "MetadataTypeKind" + } + panic("unreachable") +} + +func (t Type) String() string { + ts := typeStringer{s: make(map[Type]string)} + return ts.typeString(t) +} + +type typeStringer struct { + s map[Type]string +} + +func (ts *typeStringer) typeString(t Type) string { + if s, ok := ts.s[t]; ok { + return s + } + + k := t.TypeKind() + s := k.String() + s = s[:len(s)-len("Kind")] + + switch k { + case ArrayTypeKind: + s += fmt.Sprintf("(%v[%v])", ts.typeString(t.ElementType()), t.ArrayLength()) + case PointerTypeKind: + s += fmt.Sprintf("(%v)", ts.typeString(t.ElementType())) + case FunctionTypeKind: + params := t.ParamTypes() + s += "(" + if len(params) > 0 { + s += fmt.Sprintf("%v", ts.typeString(params[0])) + for i := 1; i < len(params); i++ { + s += fmt.Sprintf(", %v", ts.typeString(params[i])) + } + } + s += fmt.Sprintf("):%v", ts.typeString(t.ReturnType())) + case StructTypeKind: + if name := t.StructName(); name != "" { + ts.s[t] = "%" + name + s = fmt.Sprintf("%%%s: %s", name, s) + } + etypes := t.StructElementTypes() + s += "(" + if n := len(etypes); n > 0 { + s += ts.typeString(etypes[0]) + for i := 1; i < n; i++ { + s += fmt.Sprintf(", %v", ts.typeString(etypes[i])) + } + } + s += ")" + case IntegerTypeKind: + s += fmt.Sprintf("(%d bits)", t.IntTypeWidth()) + } + + ts.s[t] = s + return s +} diff --git a/bindings/go/llvm/string_test.go b/bindings/go/llvm/string_test.go new file mode 100644 index 0000000..3008f3e --- /dev/null +++ b/bindings/go/llvm/string_test.go @@ -0,0 +1,28 @@ +//===- string_test.go - test Stringer implementation for Type -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests the Stringer interface for the Type type. +// +//===----------------------------------------------------------------------===// + +package llvm + +import ( + "testing" +) + +func TestStringRecursiveType(t *testing.T) { + ctx := NewContext() + defer ctx.Dispose() + s := ctx.StructCreateNamed("recursive") + s.StructSetBody([]Type{s, s}, false) + if str := s.String(); str != "%recursive: StructType(%recursive, %recursive)" { + t.Errorf("incorrect string result %q", str) + } +} diff --git a/bindings/go/llvm/support.go b/bindings/go/llvm/support.go new file mode 100644 index 0000000..6f20086 --- /dev/null +++ b/bindings/go/llvm/support.go @@ -0,0 +1,54 @@ +//===- support.go - Bindings for support ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the support component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Support.h" +#include "SupportBindings.h" +#include <stdlib.h> +*/ +import "C" + +import ( + "errors" + "unsafe" +) + +// Loads a dynamic library such that it may be used as an LLVM plugin. +// See llvm::sys::DynamicLibrary::LoadLibraryPermanently. +func LoadLibraryPermanently(lib string) error { + var errstr *C.char + libstr := C.CString(lib) + defer C.free(unsafe.Pointer(libstr)) + C.LLVMLoadLibraryPermanently2(libstr, &errstr) + if errstr != nil { + err := errors.New(C.GoString(errstr)) + C.free(unsafe.Pointer(errstr)) + return err + } + return nil +} + +// Parse the given arguments using the LLVM command line parser. +// See llvm::cl::ParseCommandLineOptions. +func ParseCommandLineOptions(args []string, overview string) { + argstrs := make([]*C.char, len(args)) + for i, arg := range args { + argstrs[i] = C.CString(arg) + defer C.free(unsafe.Pointer(argstrs[i])) + } + overviewstr := C.CString(overview) + defer C.free(unsafe.Pointer(overviewstr)) + C.LLVMParseCommandLineOptions(C.int(len(args)), &argstrs[0], overviewstr) +} diff --git a/bindings/go/llvm/target.go b/bindings/go/llvm/target.go new file mode 100644 index 0000000..bd1d0f3 --- /dev/null +++ b/bindings/go/llvm/target.go @@ -0,0 +1,300 @@ +//===- target.go - Bindings for target ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the target component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Target.h" +#include "llvm-c/TargetMachine.h" +#include <stdlib.h> +*/ +import "C" +import "unsafe" +import "errors" + +type ( + TargetData struct { + C C.LLVMTargetDataRef + } + Target struct { + C C.LLVMTargetRef + } + TargetMachine struct { + C C.LLVMTargetMachineRef + } + ByteOrdering C.enum_LLVMByteOrdering + RelocMode C.LLVMRelocMode + CodeGenOptLevel C.LLVMCodeGenOptLevel + CodeGenFileType C.LLVMCodeGenFileType + CodeModel C.LLVMCodeModel +) + +const ( + BigEndian ByteOrdering = C.LLVMBigEndian + LittleEndian ByteOrdering = C.LLVMLittleEndian +) + +const ( + RelocDefault RelocMode = C.LLVMRelocDefault + RelocStatic RelocMode = C.LLVMRelocStatic + RelocPIC RelocMode = C.LLVMRelocPIC + RelocDynamicNoPic RelocMode = C.LLVMRelocDynamicNoPic +) + +const ( + CodeGenLevelNone CodeGenOptLevel = C.LLVMCodeGenLevelNone + CodeGenLevelLess CodeGenOptLevel = C.LLVMCodeGenLevelLess + CodeGenLevelDefault CodeGenOptLevel = C.LLVMCodeGenLevelDefault + CodeGenLevelAggressive CodeGenOptLevel = C.LLVMCodeGenLevelAggressive +) + +const ( + CodeModelDefault CodeModel = C.LLVMCodeModelDefault + CodeModelJITDefault CodeModel = C.LLVMCodeModelJITDefault + CodeModelSmall CodeModel = C.LLVMCodeModelSmall + CodeModelKernel CodeModel = C.LLVMCodeModelKernel + CodeModelMedium CodeModel = C.LLVMCodeModelMedium + CodeModelLarge CodeModel = C.LLVMCodeModelLarge +) + +const ( + AssemblyFile CodeGenFileType = C.LLVMAssemblyFile + ObjectFile CodeGenFileType = C.LLVMObjectFile +) + +// InitializeAllTargetInfos - The main program should call this function if it +// wants access to all available targets that LLVM is configured to support. +func InitializeAllTargetInfos() { C.LLVMInitializeAllTargetInfos() } + +// InitializeAllTargets - The main program should call this function if it wants +// to link in all available targets that LLVM is configured to support. +func InitializeAllTargets() { C.LLVMInitializeAllTargets() } + +func InitializeAllTargetMCs() { C.LLVMInitializeAllTargetMCs() } + +func InitializeAllAsmParsers() { C.LLVMInitializeAllAsmParsers() } + +func InitializeAllAsmPrinters() { C.LLVMInitializeAllAsmPrinters() } + +var initializeNativeTargetError = errors.New("Failed to initialize native target") + +// InitializeNativeTarget - The main program should call this function to +// initialize the native target corresponding to the host. This is useful +// for JIT applications to ensure that the target gets linked in correctly. +func InitializeNativeTarget() error { + fail := C.LLVMInitializeNativeTarget() + if fail != 0 { + return initializeNativeTargetError + } + return nil +} + +func InitializeNativeAsmPrinter() error { + fail := C.LLVMInitializeNativeAsmPrinter() + if fail != 0 { + return initializeNativeTargetError + } + return nil +} + +//------------------------------------------------------------------------- +// llvm.TargetData +//------------------------------------------------------------------------- + +// Creates target data from a target layout string. +// See the constructor llvm::TargetData::TargetData. +func NewTargetData(rep string) (td TargetData) { + crep := C.CString(rep) + defer C.free(unsafe.Pointer(crep)) + td.C = C.LLVMCreateTargetData(crep) + return +} + +// Adds target data information to a pass manager. This does not take ownership +// of the target data. +// See the method llvm::PassManagerBase::add. +func (pm PassManager) Add(td TargetData) { + C.LLVMAddTargetData(td.C, pm.C) +} + +// Converts target data to a target layout string. The string must be disposed +// with LLVMDisposeMessage. +// See the constructor llvm::TargetData::TargetData. +func (td TargetData) String() (s string) { + cmsg := C.LLVMCopyStringRepOfTargetData(td.C) + s = C.GoString(cmsg) + C.LLVMDisposeMessage(cmsg) + return +} + +// Returns the byte order of a target, either BigEndian or LittleEndian. +// See the method llvm::TargetData::isLittleEndian. +func (td TargetData) ByteOrder() ByteOrdering { return ByteOrdering(C.LLVMByteOrder(td.C)) } + +// Returns the pointer size in bytes for a target. +// See the method llvm::TargetData::getPointerSize. +func (td TargetData) PointerSize() int { return int(C.LLVMPointerSize(td.C)) } + +// Returns the integer type that is the same size as a pointer on a target. +// See the method llvm::TargetData::getIntPtrType. +func (td TargetData) IntPtrType() (t Type) { t.C = C.LLVMIntPtrType(td.C); return } + +// Computes the size of a type in bytes for a target. +// See the method llvm::TargetData::getTypeSizeInBits. +func (td TargetData) TypeSizeInBits(t Type) uint64 { + return uint64(C.LLVMSizeOfTypeInBits(td.C, t.C)) +} + +// Computes the storage size of a type in bytes for a target. +// See the method llvm::TargetData::getTypeStoreSize. +func (td TargetData) TypeStoreSize(t Type) uint64 { + return uint64(C.LLVMStoreSizeOfType(td.C, t.C)) +} + +// Computes the ABI size of a type in bytes for a target. +// See the method llvm::TargetData::getTypeAllocSize. +func (td TargetData) TypeAllocSize(t Type) uint64 { + return uint64(C.LLVMABISizeOfType(td.C, t.C)) +} + +// Computes the ABI alignment of a type in bytes for a target. +// See the method llvm::TargetData::getABITypeAlignment. +func (td TargetData) ABITypeAlignment(t Type) int { + return int(C.LLVMABIAlignmentOfType(td.C, t.C)) +} + +// Computes the call frame alignment of a type in bytes for a target. +// See the method llvm::TargetData::getCallFrameTypeAlignment. +func (td TargetData) CallFrameTypeAlignment(t Type) int { + return int(C.LLVMCallFrameAlignmentOfType(td.C, t.C)) +} + +// Computes the preferred alignment of a type in bytes for a target. +// See the method llvm::TargetData::getPrefTypeAlignment. +func (td TargetData) PrefTypeAlignment(t Type) int { + return int(C.LLVMPreferredAlignmentOfType(td.C, t.C)) +} + +// Computes the preferred alignment of a global variable in bytes for a target. +// See the method llvm::TargetData::getPreferredAlignment. +func (td TargetData) PreferredAlignment(g Value) int { + return int(C.LLVMPreferredAlignmentOfGlobal(td.C, g.C)) +} + +// Computes the structure element that contains the byte offset for a target. +// See the method llvm::StructLayout::getElementContainingOffset. +func (td TargetData) ElementContainingOffset(t Type, offset uint64) int { + return int(C.LLVMElementAtOffset(td.C, t.C, C.ulonglong(offset))) +} + +// Computes the byte offset of the indexed struct element for a target. +// See the method llvm::StructLayout::getElementOffset. +func (td TargetData) ElementOffset(t Type, element int) uint64 { + return uint64(C.LLVMOffsetOfElement(td.C, t.C, C.unsigned(element))) +} + +// Deallocates a TargetData. +// See the destructor llvm::TargetData::~TargetData. +func (td TargetData) Dispose() { C.LLVMDisposeTargetData(td.C) } + +//------------------------------------------------------------------------- +// llvm.Target +//------------------------------------------------------------------------- + +func FirstTarget() Target { + return Target{C.LLVMGetFirstTarget()} +} + +func (t Target) NextTarget() Target { + return Target{C.LLVMGetNextTarget(t.C)} +} + +func GetTargetFromTriple(triple string) (t Target, err error) { + var errstr *C.char + ctriple := C.CString(triple) + defer C.free(unsafe.Pointer(ctriple)) + fail := C.LLVMGetTargetFromTriple(ctriple, &t.C, &errstr) + if fail != 0 { + err = errors.New(C.GoString(errstr)) + C.free(unsafe.Pointer(errstr)) + } + return +} + +func (t Target) Name() string { + return C.GoString(C.LLVMGetTargetName(t.C)) +} + +func (t Target) Description() string { + return C.GoString(C.LLVMGetTargetDescription(t.C)) +} + +//------------------------------------------------------------------------- +// llvm.TargetMachine +//------------------------------------------------------------------------- + +// CreateTargetMachine creates a new TargetMachine. +func (t Target) CreateTargetMachine(Triple string, CPU string, Features string, + Level CodeGenOptLevel, Reloc RelocMode, + CodeModel CodeModel) (tm TargetMachine) { + cTriple := C.CString(Triple) + defer C.free(unsafe.Pointer(cTriple)) + cCPU := C.CString(CPU) + defer C.free(unsafe.Pointer(cCPU)) + cFeatures := C.CString(Features) + defer C.free(unsafe.Pointer(cFeatures)) + tm.C = C.LLVMCreateTargetMachine(t.C, cTriple, cCPU, cFeatures, + C.LLVMCodeGenOptLevel(Level), + C.LLVMRelocMode(Reloc), + C.LLVMCodeModel(CodeModel)) + return +} + +// Triple returns the triple describing the machine (arch-vendor-os). +func (tm TargetMachine) Triple() string { + cstr := C.LLVMGetTargetMachineTriple(tm.C) + return C.GoString(cstr) +} + +// TargetData returns the TargetData for the machine. +func (tm TargetMachine) TargetData() TargetData { + return TargetData{C.LLVMGetTargetMachineData(tm.C)} +} + +func (tm TargetMachine) EmitToMemoryBuffer(m Module, ft CodeGenFileType) (MemoryBuffer, error) { + var errstr *C.char + var mb MemoryBuffer + fail := C.LLVMTargetMachineEmitToMemoryBuffer(tm.C, m.C, C.LLVMCodeGenFileType(ft), &errstr, &mb.C) + if fail != 0 { + err := errors.New(C.GoString(errstr)) + C.free(unsafe.Pointer(errstr)) + return MemoryBuffer{}, err + } + return mb, nil +} + +func (tm TargetMachine) AddAnalysisPasses(pm PassManager) { + C.LLVMAddAnalysisPasses(tm.C, pm.C) +} + +// Dispose releases resources related to the TargetMachine. +func (tm TargetMachine) Dispose() { + C.LLVMDisposeTargetMachine(tm.C) +} + +func DefaultTargetTriple() (triple string) { + cTriple := C.LLVMGetDefaultTargetTriple() + defer C.free(unsafe.Pointer(cTriple)) + triple = C.GoString(cTriple) + return +} diff --git a/bindings/go/llvm/transforms_instrumentation.go b/bindings/go/llvm/transforms_instrumentation.go new file mode 100644 index 0000000..9b191b2 --- /dev/null +++ b/bindings/go/llvm/transforms_instrumentation.go @@ -0,0 +1,43 @@ +//===- transforms_instrumentation.go - Bindings for instrumentation -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the instrumentation component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "InstrumentationBindings.h" +#include <stdlib.h> +*/ +import "C" +import "unsafe" + +func (pm PassManager) AddAddressSanitizerFunctionPass() { + C.LLVMAddAddressSanitizerFunctionPass(pm.C) +} + +func (pm PassManager) AddAddressSanitizerModulePass() { + C.LLVMAddAddressSanitizerModulePass(pm.C) +} + +func (pm PassManager) AddThreadSanitizerPass() { + C.LLVMAddThreadSanitizerPass(pm.C) +} + +func (pm PassManager) AddMemorySanitizerPass() { + C.LLVMAddMemorySanitizerPass(pm.C) +} + +func (pm PassManager) AddDataFlowSanitizerPass(abilist string) { + cabilist := C.CString(abilist) + defer C.free(unsafe.Pointer(cabilist)) + C.LLVMAddDataFlowSanitizerPass(pm.C, cabilist) +} diff --git a/bindings/go/llvm/transforms_ipo.go b/bindings/go/llvm/transforms_ipo.go new file mode 100644 index 0000000..12d972b --- /dev/null +++ b/bindings/go/llvm/transforms_ipo.go @@ -0,0 +1,42 @@ +//===- transforms_ipo.go - Bindings for ipo -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the ipo component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Transforms/IPO.h" +*/ +import "C" + +// helpers +func boolToUnsigned(b bool) C.unsigned { + if b { + return 1 + } + return 0 +} + +func (pm PassManager) AddArgumentPromotionPass() { C.LLVMAddArgumentPromotionPass(pm.C) } +func (pm PassManager) AddConstantMergePass() { C.LLVMAddConstantMergePass(pm.C) } +func (pm PassManager) AddDeadArgEliminationPass() { C.LLVMAddDeadArgEliminationPass(pm.C) } +func (pm PassManager) AddFunctionAttrsPass() { C.LLVMAddFunctionAttrsPass(pm.C) } +func (pm PassManager) AddFunctionInliningPass() { C.LLVMAddFunctionInliningPass(pm.C) } +func (pm PassManager) AddGlobalDCEPass() { C.LLVMAddGlobalDCEPass(pm.C) } +func (pm PassManager) AddGlobalOptimizerPass() { C.LLVMAddGlobalOptimizerPass(pm.C) } +func (pm PassManager) AddIPConstantPropagationPass() { C.LLVMAddIPConstantPropagationPass(pm.C) } +func (pm PassManager) AddPruneEHPass() { C.LLVMAddPruneEHPass(pm.C) } +func (pm PassManager) AddIPSCCPPass() { C.LLVMAddIPSCCPPass(pm.C) } +func (pm PassManager) AddInternalizePass(allButMain bool) { + C.LLVMAddInternalizePass(pm.C, boolToUnsigned(allButMain)) +} +func (pm PassManager) AddStripDeadPrototypesPass() { C.LLVMAddStripDeadPrototypesPass(pm.C) } diff --git a/bindings/go/llvm/transforms_pmbuilder.go b/bindings/go/llvm/transforms_pmbuilder.go new file mode 100644 index 0000000..3d79d6e --- /dev/null +++ b/bindings/go/llvm/transforms_pmbuilder.go @@ -0,0 +1,48 @@ +//===- transforms_pmbuilder.go - Bindings for PassManagerBuilder ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the PassManagerBuilder class. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Transforms/PassManagerBuilder.h" +*/ +import "C" + +type PassManagerBuilder struct { + C C.LLVMPassManagerBuilderRef +} + +func NewPassManagerBuilder() (pmb PassManagerBuilder) { + pmb.C = C.LLVMPassManagerBuilderCreate() + return +} + +func (pmb PassManagerBuilder) SetOptLevel(level int) { + C.LLVMPassManagerBuilderSetOptLevel(pmb.C, C.uint(level)) +} + +func (pmb PassManagerBuilder) SetSizeLevel(level int) { + C.LLVMPassManagerBuilderSetSizeLevel(pmb.C, C.uint(level)) +} + +func (pmb PassManagerBuilder) Populate(pm PassManager) { + C.LLVMPassManagerBuilderPopulateModulePassManager(pmb.C, pm.C) +} + +func (pmb PassManagerBuilder) PopulateFunc(pm PassManager) { + C.LLVMPassManagerBuilderPopulateFunctionPassManager(pmb.C, pm.C) +} + +func (pmb PassManagerBuilder) Dispose() { + C.LLVMPassManagerBuilderDispose(pmb.C) +} diff --git a/bindings/go/llvm/transforms_scalar.go b/bindings/go/llvm/transforms_scalar.go new file mode 100644 index 0000000..6492a85 --- /dev/null +++ b/bindings/go/llvm/transforms_scalar.go @@ -0,0 +1,45 @@ +//===- transforms_scalar.go - Bindings for scalaropts ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the scalaropts component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Transforms/Scalar.h" +*/ +import "C" + +func (pm PassManager) AddAggressiveDCEPass() { C.LLVMAddAggressiveDCEPass(pm.C) } +func (pm PassManager) AddCFGSimplificationPass() { C.LLVMAddCFGSimplificationPass(pm.C) } +func (pm PassManager) AddDeadStoreEliminationPass() { C.LLVMAddDeadStoreEliminationPass(pm.C) } +func (pm PassManager) AddGVNPass() { C.LLVMAddGVNPass(pm.C) } +func (pm PassManager) AddIndVarSimplifyPass() { C.LLVMAddIndVarSimplifyPass(pm.C) } +func (pm PassManager) AddInstructionCombiningPass() { C.LLVMAddInstructionCombiningPass(pm.C) } +func (pm PassManager) AddJumpThreadingPass() { C.LLVMAddJumpThreadingPass(pm.C) } +func (pm PassManager) AddLICMPass() { C.LLVMAddLICMPass(pm.C) } +func (pm PassManager) AddLoopDeletionPass() { C.LLVMAddLoopDeletionPass(pm.C) } +func (pm PassManager) AddLoopRotatePass() { C.LLVMAddLoopRotatePass(pm.C) } +func (pm PassManager) AddLoopUnrollPass() { C.LLVMAddLoopUnrollPass(pm.C) } +func (pm PassManager) AddLoopUnswitchPass() { C.LLVMAddLoopUnswitchPass(pm.C) } +func (pm PassManager) AddMemCpyOptPass() { C.LLVMAddMemCpyOptPass(pm.C) } +func (pm PassManager) AddPromoteMemoryToRegisterPass() { C.LLVMAddPromoteMemoryToRegisterPass(pm.C) } +func (pm PassManager) AddReassociatePass() { C.LLVMAddReassociatePass(pm.C) } +func (pm PassManager) AddSCCPPass() { C.LLVMAddSCCPPass(pm.C) } +func (pm PassManager) AddScalarReplAggregatesPass() { C.LLVMAddScalarReplAggregatesPass(pm.C) } +func (pm PassManager) AddScalarReplAggregatesPassWithThreshold(threshold int) { + C.LLVMAddScalarReplAggregatesPassWithThreshold(pm.C, C.int(threshold)) +} +func (pm PassManager) AddSimplifyLibCallsPass() { C.LLVMAddSimplifyLibCallsPass(pm.C) } +func (pm PassManager) AddTailCallEliminationPass() { C.LLVMAddTailCallEliminationPass(pm.C) } +func (pm PassManager) AddConstantPropagationPass() { C.LLVMAddConstantPropagationPass(pm.C) } +func (pm PassManager) AddDemoteMemoryToRegisterPass() { C.LLVMAddDemoteMemoryToRegisterPass(pm.C) } +func (pm PassManager) AddVerifierPass() { C.LLVMAddVerifierPass(pm.C) } diff --git a/bindings/go/llvm/version.go b/bindings/go/llvm/version.go new file mode 100644 index 0000000..d0623be --- /dev/null +++ b/bindings/go/llvm/version.go @@ -0,0 +1,21 @@ +//===- version.go - LLVM version info -------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines LLVM version information. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm/Config/llvm-config.h" +*/ +import "C" + +const Version = C.LLVM_VERSION_STRING diff --git a/bindings/ocaml/Makefile b/bindings/ocaml/Makefile index b0e1f09..2005367 100644 --- a/bindings/ocaml/Makefile +++ b/bindings/ocaml/Makefile @@ -1,10 +1,10 @@ ##===- bindings/ocaml/Makefile -----------------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../.. diff --git a/bindings/ocaml/Makefile.ocaml b/bindings/ocaml/Makefile.ocaml index 1b964ee..5e00cf5 100644 --- a/bindings/ocaml/Makefile.ocaml +++ b/bindings/ocaml/Makefile.ocaml @@ -1,27 +1,30 @@ ##===- bindings/ocaml/Makefile.ocaml -----------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## -# +# # An OCaml library is a unique project type in the context of LLVM, so rules are # here rather than in Makefile.rules. -# +# # Reference materials on installing OCaml libraries: -# +# # https://fedoraproject.org/wiki/Packaging/OCaml # http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt -# +# ##===----------------------------------------------------------------------===## include $(LEVEL)/Makefile.config +# We have our own rules for building static libraries. +NO_BUILD_ARCHIVE = 1 + # CFLAGS needs to be set before Makefile.rules is included. -CXX.Flags += -I"$(shell $(OCAMLC) -where)" -C.Flags += -I"$(shell $(OCAMLC) -where)" +CXX.Flags += -I"$(shell $(OCAMLFIND) c -where)" +C.Flags += -I"$(shell $(OCAMLFIND) c -where)" ifeq ($(ENABLE_SHARED),1) LINK_COMPONENTS := all @@ -50,64 +53,55 @@ endif # from toplevels. ifneq ($(ObjectsO),) ifeq ($(ENABLE_SHARED),1) -OCAMLSTUBS := 1 +OCAMLSTUBS := 1 +OCAMLSTUBFLAGS := $(patsubst %,-cclib %, $(LLVMLibsOptions) -l$(LIBRARYNAME)) +endif +endif + +# Avoid the need for LD_LIBRARY_PATH +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +ifneq ($(HOST_OS),Darwin) +OCAMLRPATH := $(RPATH) -Wl,'$$ORIGIN/../../lib' endif endif # Tools -OCAMLCFLAGS += -I $(ObjDir) -I $(OcamlDir) +OCAMLCFLAGS += -I $(OcamlDir) $(addprefix -package ,$(FindlibPackages)) + ifndef IS_CLEANING_TARGET ifneq ($(ObjectsO),) OCAMLAFLAGS += $(patsubst %,-cclib %, \ $(filter-out -L$(LibDir),-l$(LIBRARYNAME) \ $(shell $(LLVM_CONFIG) --ldflags)) \ - $(UsedLibs)) + $(UsedLibs) $(ExtraLibs)) else OCAMLAFLAGS += $(patsubst %,-cclib %, \ $(filter-out -L$(LibDir),$(shell $(LLVM_CONFIG) --ldflags)) \ - $(UsedLibs)) + $(UsedLibs) $(ExtraLibs)) endif endif - -# -g was introduced in 3.10.0. -#ifneq ($(ENABLE_OPTIMIZED),1) -# OCAMLDEBUGFLAG := -g -#endif - -Compile.CMI := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) -Compile.CMO := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) -Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) -ifdef OCAMLSTUBS -# Avoid the need for LD_LIBRARY_PATH -ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) -ifneq ($(HOST_OS),Darwin) -OCAMLRPATH := $(RPATH) -Wl,'$(SharedLibDir)' -endif -endif +ifneq ($(DEBUG_SYMBOLS),1) + OCAMLDEBUGFLAG := -g endif -ifdef OCAMLSTUBS -Archive.CMA := $(strip $(OCAMLC) -a -dllib -l$(LIBRARYNAME) $(OCAMLDEBUGFLAG) \ - -o) -else -Archive.CMA := $(strip $(OCAMLC) -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ - -o) -endif +Compile.CMI := $(strip $(OCAMLFIND) c -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Compile.CMO := $(strip $(OCAMLFIND) c -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Compile.CMX := $(strip $(OCAMLFIND) opt -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) ifdef OCAMLSTUBS -Archive.CMXA := $(strip $(OCAMLOPT) -a $(patsubst %,-cclib %, \ - $(LLVMLibsOptions) -l$(LIBRARYNAME) \ - -L$(SharedLibDir) $(OCAMLRPATH)) \ - $(OCAMLDEBUGFLAG) -o) +# -dllib is engaged with ocamlc builds, $(OCAMLSTUBFLAGS) in ocamlc -custom builds. +Archive.CMA := $(strip $(OCAMLFIND) c -a -dllib -l$(LIBRARYNAME) $(OCAMLSTUBFLAGS) \ + $(OCAMLDEBUGFLAG) -o) else -Archive.CMXA := $(strip $(OCAMLOPT) -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o) +Archive.CMA := $(strip $(OCAMLFIND) c -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ + -o) endif -ifdef OCAMLOPT -Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamlLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o) +ifdef OCAMLSTUBS +Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLSTUBFLAGS) $(OCAMLDEBUGFLAG) -o) else -Archive.EXE := $(strip $(OCAMLC) -cc $(CXX) $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG:%=%.cma) -o) +Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o) endif # Source files @@ -191,7 +185,7 @@ $(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi) ifdef LIBRARYNAME $(ObjDir)/$(LIBRARYNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ $(OcamlDir)/.dir $(ObjDir)/.dir - $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ + $(Verb) $(OCAMLFIND) dep $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ -include $(ObjDir)/$(LIBRARYNAME).ocamldep endif @@ -199,7 +193,7 @@ endif ifdef TOOLNAME $(ObjDir)/$(TOOLNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ $(OcamlDir)/.dir $(ObjDir)/.dir - $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ + $(Verb) $(OCAMLFIND) dep $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ -include $(ObjDir)/$(TOOLNAME).ocamldep endif @@ -225,7 +219,7 @@ install-a:: $(LibraryA) $(Echo) "Installing $(BuildMode) $(DestA)" $(Verb) $(MKDIR) $(PROJ_libocamldir) $(Verb) $(INSTALL) $(LibraryA) $(DestA) - $(Verb) + $(Verb) uninstall-a:: $(Echo) "Uninstalling $(DestA)" @@ -368,8 +362,8 @@ endif ##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===## # The ocamlopt compiler is supported on a set of targets disjoint from LLVM's. -# If unavailable, 'configure' will not define OCAMLOPT in Makefile.config. -ifdef OCAMLOPT +# If unavailable, 'configure' will set HAVE_OCAMLOPT to 0 in Makefile.config. +ifeq ($(HAVE_OCAMLOPT),1) $(OcamlDir)/%.cmx: $(ObjDir)/%.cmx $(Verb) $(CP) -f $< $@ @@ -419,31 +413,11 @@ uninstall-cmxa:: endif endif -##===- Build executables --------------------------------------------------===## - -ifdef TOOLNAME -all-local:: $(OutputEXE) -clean-local:: clean-exe - -$(OutputEXE): $(ToolEXE) $(OcamlDir)/.dir - $(Verb) $(CP) -f $< $@ - -ifndef OCAMLOPT -$(ToolEXE): $(ObjectsCMO) $(OcamlDir)/.dir - $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" - $(Verb) $(Archive.EXE) $@ $(ObjectsCMO) -else -$(ToolEXE): $(ObjectsCMX) $(OcamlDir)/.dir - $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" - $(Verb) $(Archive.EXE) $@ $(ObjectsCMX) -endif -endif - ##===- Generate documentation ---------------------------------------------===## $(ObjDir)/$(LIBRARYNAME).odoc: $(ObjectsCMI) $(Echo) "Documenting $(notdir $@)" - $(Verb) $(OCAMLDOC) -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) + $(Verb) $(OCAMLFIND) doc -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) ocamldoc: $(ObjDir)/$(LIBRARYNAME).odoc @@ -454,15 +428,17 @@ printcamlvars:: $(Echo) "LLVM_CONFIG : " '$(LLVM_CONFIG)' $(Echo) "OCAMLCFLAGS : " '$(OCAMLCFLAGS)' $(Echo) "OCAMLAFLAGS : " '$(OCAMLAFLAGS)' - $(Echo) "OCAMLC : " '$(OCAMLC)' - $(Echo) "OCAMLOPT : " '$(OCAMLOPT)' - $(Echo) "OCAMLDEP : " '$(OCAMLDEP)' + $(Echo) "OCAMLRPATH : " '$(OCAMLRPATH)' + $(Echo) "OCAMLSTUBS : " '$(OCAMLSTUBS)' + $(Echo) "OCAMLSTUBFLAGS : " '$(OCAMLSTUBFLAGS)' + $(Echo) "OCAMLFIND : " '$(OCAMLFIND)' $(Echo) "Compile.CMI : " '$(Compile.CMI)' $(Echo) "Compile.CMO : " '$(Compile.CMO)' $(Echo) "Archive.CMA : " '$(Archive.CMA)' $(Echo) "Compile.CMX : " '$(Compile.CMX)' $(Echo) "Archive.CMXA : " '$(Archive.CMXA)' $(Echo) "CAML_LIBDIR : " '$(CAML_LIBDIR)' + $(Echo) "LibraryA : " '$(LibraryA)' $(Echo) "LibraryCMA : " '$(LibraryCMA)' $(Echo) "LibraryCMXA : " '$(LibraryCMXA)' $(Echo) "SharedLib : " '$(SharedLib)' @@ -482,6 +458,7 @@ printcamlvars:: $(Echo) "DestSharedLib: " '$(DestSharedLib)' $(Echo) "UsedLibs : " '$(UsedLibs)' $(Echo) "UsedLibNames : " '$(UsedLibNames)' + $(Echo) "ExtraLibs : " '$(ExtraLibs)' .PHONY: printcamlvars build-cmis \ clean-a clean-cmis clean-cma clean-cmxa \ diff --git a/bindings/ocaml/all_backends/Makefile b/bindings/ocaml/all_backends/Makefile index a5ff290..f7c8cdb 100644 --- a/bindings/ocaml/all_backends/Makefile +++ b/bindings/ocaml/all_backends/Makefile @@ -1,4 +1,4 @@ -##===- bindings/ocaml/all_backends/Makefile ----------------------*- Makefile -*-===## +##===- bindings/ocaml/all_backends/Makefile ----------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## # -# This is the makefile for the Objective Caml Llvm_backends interface. +# This is the makefile for the Objective Caml Llvm_all_backends interface. # ##===----------------------------------------------------------------------===## diff --git a/bindings/ocaml/analysis/Makefile b/bindings/ocaml/analysis/Makefile index cbfcb24..daff061 100644 --- a/bindings/ocaml/analysis/Makefile +++ b/bindings/ocaml/analysis/Makefile @@ -1,14 +1,14 @@ ##===- bindings/ocaml/analysis/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_analysis interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. diff --git a/bindings/ocaml/analysis/analysis_ocaml.c b/bindings/ocaml/analysis/analysis_ocaml.c index 91be2d3..44e3197 100644 --- a/bindings/ocaml/analysis/analysis_ocaml.c +++ b/bindings/ocaml/analysis/analysis_ocaml.c @@ -20,15 +20,14 @@ #include "caml/mlvalues.h" #include "caml/memory.h" - /* Llvm.llmodule -> string option */ CAMLprim value llvm_verify_module(LLVMModuleRef M) { CAMLparam0(); CAMLlocal2(String, Option); - + char *Message; int Result = LLVMVerifyModule(M, LLVMReturnStatusAction, &Message); - + if (0 == Result) { Option = Val_int(0); } else { @@ -36,9 +35,9 @@ CAMLprim value llvm_verify_module(LLVMModuleRef M) { String = copy_string(Message); Store_field(Option, 0, String); } - + LLVMDisposeMessage(Message); - + CAMLreturn(Option); } diff --git a/bindings/ocaml/analysis/llvm_analysis.ml b/bindings/ocaml/analysis/llvm_analysis.ml index 21088ab..8c11a63 100644 --- a/bindings/ocaml/analysis/llvm_analysis.ml +++ b/bindings/ocaml/analysis/llvm_analysis.ml @@ -1,4 +1,4 @@ -(*===-- llvm_analysis.ml - LLVM OCaml Interface -----------------*- C++ -*-===* +(*===-- llvm_analysis.ml - LLVM OCaml Interface ---------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * diff --git a/bindings/ocaml/analysis/llvm_analysis.mli b/bindings/ocaml/analysis/llvm_analysis.mli index 1a0af02..03197cd 100644 --- a/bindings/ocaml/analysis/llvm_analysis.mli +++ b/bindings/ocaml/analysis/llvm_analysis.mli @@ -1,4 +1,4 @@ -(*===-- llvm_analysis.mli - LLVM OCaml Interface ----------------*- C++ -*-===* +(*===-- llvm_analysis.mli - LLVM OCaml Interface --------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * diff --git a/bindings/ocaml/backends/META.llvm_backend.in b/bindings/ocaml/backends/META.llvm_backend.in index 0d4a6d6..6c1e8c4 100644 --- a/bindings/ocaml/backends/META.llvm_backend.in +++ b/bindings/ocaml/backends/META.llvm_backend.in @@ -5,4 +5,3 @@ requires = "llvm" archive(byte) = "llvm_@TARGET@.cma" archive(native) = "llvm_@TARGET@.cmxa" directory = "." -linkopts = "-ccopt -lstdc++"
\ No newline at end of file diff --git a/bindings/ocaml/backends/backend_ocaml.c b/bindings/ocaml/backends/backend_ocaml.c index 2d4ba85..3e1a438 100644 --- a/bindings/ocaml/backends/backend_ocaml.c +++ b/bindings/ocaml/backends/backend_ocaml.c @@ -19,10 +19,11 @@ #include "caml/alloc.h" #include "caml/memory.h" -// TODO: Figure out how to call these only for targets which support them. -// LLVMInitialize ## target ## AsmPrinter(); -// LLVMInitialize ## target ## AsmParser(); -// LLVMInitialize ## target ## Disassembler(); +/* TODO: Figure out how to call these only for targets which support them. + * LLVMInitialize ## target ## AsmPrinter(); + * LLVMInitialize ## target ## AsmParser(); + * LLVMInitialize ## target ## Disassembler(); + */ #define INITIALIZER1(target) \ CAMLprim value llvm_initialize_ ## target(value Unit) { \ diff --git a/bindings/ocaml/bitreader/Makefile b/bindings/ocaml/bitreader/Makefile index a1c7de8..dad4e1d 100644 --- a/bindings/ocaml/bitreader/Makefile +++ b/bindings/ocaml/bitreader/Makefile @@ -1,14 +1,14 @@ ##===- bindings/ocaml/bitreader/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_bitreader interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. diff --git a/bindings/ocaml/bitreader/bitreader_ocaml.c b/bindings/ocaml/bitreader/bitreader_ocaml.c index 0264e73..15ebd5f 100644 --- a/bindings/ocaml/bitreader/bitreader_ocaml.c +++ b/bindings/ocaml/bitreader/bitreader_ocaml.c @@ -16,58 +16,28 @@ #include "caml/alloc.h" #include "caml/fail.h" #include "caml/memory.h" +#include "caml/callback.h" - -/* Can't use the recommended caml_named_value mechanism for backwards - compatibility reasons. This is largely equivalent. */ -static value llvm_bitreader_error_exn; - -CAMLprim value llvm_register_bitreader_exns(value Error) { - llvm_bitreader_error_exn = Field(Error, 0); - register_global_root(&llvm_bitreader_error_exn); - return Val_unit; -} - -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif -} - - -/*===-- Modules -----------------------------------------------------------===*/ +void llvm_raise(value Prototype, char *Message); /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ -CAMLprim value llvm_get_module(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { - CAMLparam0(); - CAMLlocal2(Variant, MessageVal); - char *Message; - +CAMLprim LLVMModuleRef llvm_get_module(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { LLVMModuleRef M; + char *Message; + if (LLVMGetBitcodeModuleInContext(C, MemBuf, &M, &Message)) - llvm_raise(llvm_bitreader_error_exn, Message); - - CAMLreturn((value) M); + llvm_raise(*caml_named_value("Llvm_bitreader.Error"), Message); + + return M; } /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ -CAMLprim value llvm_parse_bitcode(LLVMContextRef C, - LLVMMemoryBufferRef MemBuf) { - CAMLparam0(); - CAMLlocal2(Variant, MessageVal); +CAMLprim LLVMModuleRef llvm_parse_bitcode(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { LLVMModuleRef M; char *Message; - + if (LLVMParseBitcodeInContext(C, MemBuf, &M, &Message)) - llvm_raise(llvm_bitreader_error_exn, Message); - - CAMLreturn((value) M); + llvm_raise(*caml_named_value("Llvm_bitreader.Error"), Message); + + return M; } diff --git a/bindings/ocaml/bitreader/llvm_bitreader.ml b/bindings/ocaml/bitreader/llvm_bitreader.ml index 865208c..b26efdd 100644 --- a/bindings/ocaml/bitreader/llvm_bitreader.ml +++ b/bindings/ocaml/bitreader/llvm_bitreader.ml @@ -1,4 +1,4 @@ -(*===-- llvm_bitreader.ml - LLVM OCaml Interface ----------------*- C++ -*-===* +(*===-- llvm_bitreader.ml - LLVM OCaml Interface --------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -7,14 +7,13 @@ * *===----------------------------------------------------------------------===*) - exception Error of string -external register_exns : exn -> unit = "llvm_register_bitreader_exns" -let _ = register_exns (Error "") - -external get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule - = "llvm_get_module" +let () = Callback.register_exception "Llvm_bitreader.Error" (Error "") -external parse_bitcode : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule - = "llvm_parse_bitcode" +external get_module + : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_get_module" +external parse_bitcode + : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_parse_bitcode" diff --git a/bindings/ocaml/bitreader/llvm_bitreader.mli b/bindings/ocaml/bitreader/llvm_bitreader.mli index ff377b9..4351343 100644 --- a/bindings/ocaml/bitreader/llvm_bitreader.mli +++ b/bindings/ocaml/bitreader/llvm_bitreader.mli @@ -1,4 +1,4 @@ -(*===-- llvm_bitreader.mli - LLVM OCaml Interface ---------------*- C++ -*-===* +(*===-- llvm_bitreader.mli - LLVM OCaml Interface -------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -20,7 +20,6 @@ exception Error of string encountered. See the function [llvm::getBitcodeModule]. *) val get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule - (** [parse_bitcode context mb] parses the bitcode for a new module [m] from the memory buffer [mb] in the context [context]. Returns [m] if successful, or raises [Error msg] otherwise, where [msg] is a description of the error diff --git a/bindings/ocaml/bitwriter/Makefile b/bindings/ocaml/bitwriter/Makefile index cec0a59..9f0b2c8 100644 --- a/bindings/ocaml/bitwriter/Makefile +++ b/bindings/ocaml/bitwriter/Makefile @@ -1,14 +1,14 @@ ##===- bindings/ocaml/bitwriter/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_bitwriter interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. diff --git a/bindings/ocaml/bitwriter/bitwriter_ocaml.c b/bindings/ocaml/bitwriter/bitwriter_ocaml.c index a47f700..04fd619 100644 --- a/bindings/ocaml/bitwriter/bitwriter_ocaml.c +++ b/bindings/ocaml/bitwriter/bitwriter_ocaml.c @@ -21,25 +21,28 @@ #include "caml/mlvalues.h" #include "caml/memory.h" -/*===-- Modules -----------------------------------------------------------===*/ - /* Llvm.llmodule -> string -> bool */ -CAMLprim value llvm_write_bitcode_file(value M, value Path) { - int res = LLVMWriteBitcodeToFile((LLVMModuleRef) M, String_val(Path)); - return Val_bool(res == 0); +CAMLprim value llvm_write_bitcode_file(LLVMModuleRef M, value Path) { + int Result = LLVMWriteBitcodeToFile(M, String_val(Path)); + return Val_bool(Result == 0); } /* ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool */ -CAMLprim value llvm_write_bitcode_to_fd(value U, value M, value FD) { +CAMLprim value llvm_write_bitcode_to_fd(value U, LLVMModuleRef M, value FD) { int Unbuffered; - int res; + int Result; if (U == Val_int(0)) { Unbuffered = 0; } else { - Unbuffered = Bool_val(Field(U,0)); + Unbuffered = Bool_val(Field(U, 0)); } - res = LLVMWriteBitcodeToFD((LLVMModuleRef) M, Int_val(FD), 0, Unbuffered); - return Val_bool(res == 0); + Result = LLVMWriteBitcodeToFD(M, Int_val(FD), 0, Unbuffered); + return Val_bool(Result == 0); +} + +/* Llvm.llmodule -> Llvm.llmemorybuffer */ +CAMLprim LLVMMemoryBufferRef llvm_write_bitcode_to_memory_buffer(LLVMModuleRef M) { + return LLVMWriteBitcodeToMemoryBuffer(M); } diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.ml b/bindings/ocaml/bitwriter/llvm_bitwriter.ml index fac8553..fca6efa 100644 --- a/bindings/ocaml/bitwriter/llvm_bitwriter.ml +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.ml @@ -1,4 +1,4 @@ -(*===-- llvm_bitwriter.ml - LLVM OCaml Interface ----------------*- C++ -*-===* +(*===-- llvm_bitwriter.ml - LLVM OCaml Interface --------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -12,14 +12,17 @@ * *===----------------------------------------------------------------------===*) +external write_bitcode_file + : Llvm.llmodule -> string -> bool + = "llvm_write_bitcode_file" -(* Writes the bitcode for module the given path. Returns true if successful. *) -external write_bitcode_file : Llvm.llmodule -> string -> bool - = "llvm_write_bitcode_file" +external write_bitcode_to_fd + : ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" -external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule - -> Unix.file_descr -> bool - = "llvm_write_bitcode_to_fd" +external write_bitcode_to_memory_buffer + : Llvm.llmodule -> Llvm.llmemorybuffer + = "llvm_write_bitcode_to_memory_buffer" let output_bitcode ?unbuffered channel m = write_bitcode_to_fd ?unbuffered m (Unix.descr_of_out_channel channel) diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.mli b/bindings/ocaml/bitwriter/llvm_bitwriter.mli index bb3e3b8..3d0f780 100644 --- a/bindings/ocaml/bitwriter/llvm_bitwriter.mli +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.mli @@ -1,4 +1,4 @@ -(*===-- llvm_bitwriter.mli - LLVM OCaml Interface ---------------*- C++ -*-===* +(*===-- llvm_bitwriter.mli - LLVM OCaml Interface -------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -14,15 +14,22 @@ (** [write_bitcode_file m path] writes the bitcode for module [m] to the file at [path]. Returns [true] if successful, [false] otherwise. *) -external write_bitcode_file : Llvm.llmodule -> string -> bool - = "llvm_write_bitcode_file" +external write_bitcode_file + : Llvm.llmodule -> string -> bool + = "llvm_write_bitcode_file" (** [write_bitcode_to_fd ~unbuffered fd m] writes the bitcode for module [m] to the channel [c]. If [unbuffered] is [true], after every write the fd will be flushed. Returns [true] if successful, [false] otherwise. *) -external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule - -> Unix.file_descr -> bool - = "llvm_write_bitcode_to_fd" +external write_bitcode_to_fd + : ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" + +(** [write_bitcode_to_memory_buffer m] returns a memory buffer containing + the bitcode for module [m]. *) +external write_bitcode_to_memory_buffer + : Llvm.llmodule -> Llvm.llmemorybuffer + = "llvm_write_bitcode_to_memory_buffer" (** [output_bitcode ~unbuffered c m] writes the bitcode for module [m] to the channel [c]. If [unbuffered] is [true], after every write the fd diff --git a/bindings/ocaml/executionengine/Makefile b/bindings/ocaml/executionengine/Makefile index 5fa3f22..8b5d28f 100644 --- a/bindings/ocaml/executionengine/Makefile +++ b/bindings/ocaml/executionengine/Makefile @@ -1,19 +1,20 @@ -##===- bindings/ocaml/executionengine/Makefile --------------*- Makefile -*-===## -# +##===- bindings/ocaml/executionengine/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_executionengine interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. LIBRARYNAME := llvm_executionengine -UsedComponents := executionengine jit interpreter native +UsedComponents := executionengine mcjit native UsedOcamlInterfaces := llvm llvm_target +FindlibPackages := ctypes include ../Makefile.ocaml diff --git a/bindings/ocaml/executionengine/executionengine_ocaml.c b/bindings/ocaml/executionengine/executionengine_ocaml.c index 4b44a91..0557efc 100644 --- a/bindings/ocaml/executionengine/executionengine_ocaml.c +++ b/bindings/ocaml/executionengine/executionengine_ocaml.c @@ -15,189 +15,48 @@ |* *| \*===----------------------------------------------------------------------===*/ +#include <string.h> +#include <assert.h> #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Target.h" #include "caml/alloc.h" #include "caml/custom.h" #include "caml/fail.h" #include "caml/memory.h" -#include <string.h> -#include <assert.h> +#include "caml/callback.h" -/* Force the LLVM interpreter and JIT to be linked in. */ -void llvm_initialize(void) { - LLVMLinkInInterpreter(); - LLVMLinkInJIT(); -} +void llvm_raise(value Prototype, char *Message); /* unit -> bool */ -CAMLprim value llvm_initialize_native_target(value Unit) { - return Val_bool(LLVMInitializeNativeTarget()); -} - -/* Can't use the recommended caml_named_value mechanism for backwards - compatibility reasons. This is largely equivalent. */ -static value llvm_ee_error_exn; - -CAMLprim value llvm_register_ee_exns(value Error) { - llvm_ee_error_exn = Field(Error, 0); - register_global_root(&llvm_ee_error_exn); - return Val_unit; -} +CAMLprim value llvm_ee_initialize(value Unit) { + LLVMLinkInMCJIT(); -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif + return Val_bool(!LLVMInitializeNativeTarget() && + !LLVMInitializeNativeAsmParser() && + !LLVMInitializeNativeAsmPrinter()); } - -/*--... Operations on generic values .......................................--*/ - -#define Genericvalue_val(v) (*(LLVMGenericValueRef *)(Data_custom_val(v))) - -static void llvm_finalize_generic_value(value GenVal) { - LLVMDisposeGenericValue(Genericvalue_val(GenVal)); -} - -static struct custom_operations generic_value_ops = { - (char *) "LLVMGenericValue", - llvm_finalize_generic_value, - custom_compare_default, - custom_hash_default, - custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif -}; - -static value alloc_generic_value(LLVMGenericValueRef Ref) { - value Val = alloc_custom(&generic_value_ops, sizeof(LLVMGenericValueRef), 0, 1); - Genericvalue_val(Val) = Ref; - return Val; -} - -/* Llvm.lltype -> float -> t */ -CAMLprim value llvm_genericvalue_of_float(LLVMTypeRef Ty, value N) { - CAMLparam1(N); - CAMLreturn(alloc_generic_value( - LLVMCreateGenericValueOfFloat(Ty, Double_val(N)))); -} - -/* 'a -> t */ -CAMLprim value llvm_genericvalue_of_pointer(value V) { - CAMLparam1(V); - CAMLreturn(alloc_generic_value(LLVMCreateGenericValueOfPointer(Op_val(V)))); -} - -/* Llvm.lltype -> int -> t */ -CAMLprim value llvm_genericvalue_of_int(LLVMTypeRef Ty, value Int) { - return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty, Int_val(Int), 1)); -} - -/* Llvm.lltype -> int32 -> t */ -CAMLprim value llvm_genericvalue_of_int32(LLVMTypeRef Ty, value Int32) { - CAMLparam1(Int32); - CAMLreturn(alloc_generic_value( - LLVMCreateGenericValueOfInt(Ty, Int32_val(Int32), 1))); -} - -/* Llvm.lltype -> nativeint -> t */ -CAMLprim value llvm_genericvalue_of_nativeint(LLVMTypeRef Ty, value NatInt) { - CAMLparam1(NatInt); - CAMLreturn(alloc_generic_value( - LLVMCreateGenericValueOfInt(Ty, Nativeint_val(NatInt), 1))); -} - -/* Llvm.lltype -> int64 -> t */ -CAMLprim value llvm_genericvalue_of_int64(LLVMTypeRef Ty, value Int64) { - CAMLparam1(Int64); - CAMLreturn(alloc_generic_value( - LLVMCreateGenericValueOfInt(Ty, Int64_val(Int64), 1))); -} - -/* Llvm.lltype -> t -> float */ -CAMLprim value llvm_genericvalue_as_float(LLVMTypeRef Ty, value GenVal) { - CAMLparam1(GenVal); - CAMLreturn(copy_double( - LLVMGenericValueToFloat(Ty, Genericvalue_val(GenVal)))); -} - -/* t -> 'a */ -CAMLprim value llvm_genericvalue_as_pointer(value GenVal) { - return Val_op(LLVMGenericValueToPointer(Genericvalue_val(GenVal))); -} - -/* t -> int */ -CAMLprim value llvm_genericvalue_as_int(value GenVal) { - assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value) - && "Generic value too wide to treat as an int!"); - return Val_int(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1)); -} - -/* t -> int32 */ -CAMLprim value llvm_genericvalue_as_int32(value GenVal) { - CAMLparam1(GenVal); - assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 32 - && "Generic value too wide to treat as an int32!"); - CAMLreturn(copy_int32(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1))); -} - -/* t -> int64 */ -CAMLprim value llvm_genericvalue_as_int64(value GenVal) { - CAMLparam1(GenVal); - assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 64 - && "Generic value too wide to treat as an int64!"); - CAMLreturn(copy_int64(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1))); -} - -/* t -> nativeint */ -CAMLprim value llvm_genericvalue_as_nativeint(value GenVal) { - CAMLparam1(GenVal); - assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value) - && "Generic value too wide to treat as a nativeint!"); - CAMLreturn(copy_nativeint(LLVMGenericValueToInt(Genericvalue_val(GenVal),1))); -} - - -/*--... Operations on execution engines ....................................--*/ - -/* llmodule -> ExecutionEngine.t */ -CAMLprim LLVMExecutionEngineRef llvm_ee_create(LLVMModuleRef M) { - LLVMExecutionEngineRef Interp; - char *Error; - if (LLVMCreateExecutionEngineForModule(&Interp, M, &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return Interp; -} - -/* llmodule -> ExecutionEngine.t */ -CAMLprim LLVMExecutionEngineRef -llvm_ee_create_interpreter(LLVMModuleRef M) { - LLVMExecutionEngineRef Interp; +/* llmodule -> llcompileroption -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef llvm_ee_create(value OptRecordOpt, LLVMModuleRef M) { + value OptRecord; + LLVMExecutionEngineRef MCJIT; char *Error; - if (LLVMCreateInterpreterForModule(&Interp, M, &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return Interp; -} + struct LLVMMCJITCompilerOptions Options; + + LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options)); + if (OptRecordOpt != Val_int(0)) { + OptRecord = Field(OptRecordOpt, 0); + Options.OptLevel = Int_val(Field(OptRecord, 0)); + Options.CodeModel = Int_val(Field(OptRecord, 1)); + Options.NoFramePointerElim = Int_val(Field(OptRecord, 2)); + Options.EnableFastISel = Int_val(Field(OptRecord, 3)); + Options.MCJMM = NULL; + } -/* llmodule -> int -> ExecutionEngine.t */ -CAMLprim LLVMExecutionEngineRef -llvm_ee_create_jit(LLVMModuleRef M, value OptLevel) { - LLVMExecutionEngineRef JIT; - char *Error; - if (LLVMCreateJITCompilerForModule(&JIT, M, Int_val(OptLevel), &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return JIT; + if (LLVMCreateMCJITCompilerForModule(&MCJIT, M, &Options, + sizeof(Options), &Error)) + llvm_raise(*caml_named_value("Llvm_executionengine.Error"), Error); + return MCJIT; } /* ExecutionEngine.t -> unit */ @@ -213,43 +72,12 @@ CAMLprim value llvm_ee_add_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { } /* llmodule -> ExecutionEngine.t -> llmodule */ -CAMLprim LLVMModuleRef llvm_ee_remove_module(LLVMModuleRef M, - LLVMExecutionEngineRef EE) { +CAMLprim value llvm_ee_remove_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { LLVMModuleRef RemovedModule; char *Error; if (LLVMRemoveModule(EE, M, &RemovedModule, &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return RemovedModule; -} - -/* string -> ExecutionEngine.t -> llvalue option */ -CAMLprim value llvm_ee_find_function(value Name, LLVMExecutionEngineRef EE) { - CAMLparam1(Name); - CAMLlocal1(Option); - LLVMValueRef Found; - if (LLVMFindFunction(EE, String_val(Name), &Found)) - CAMLreturn(Val_unit); - Option = alloc(1, 0); - Field(Option, 0) = Val_op(Found); - CAMLreturn(Option); -} - -/* llvalue -> GenericValue.t array -> ExecutionEngine.t -> GenericValue.t */ -CAMLprim value llvm_ee_run_function(LLVMValueRef F, value Args, - LLVMExecutionEngineRef EE) { - unsigned NumArgs; - LLVMGenericValueRef Result, *GVArgs; - unsigned I; - - NumArgs = Wosize_val(Args); - GVArgs = (LLVMGenericValueRef*) malloc(NumArgs * sizeof(LLVMGenericValueRef)); - for (I = 0; I != NumArgs; ++I) - GVArgs[I] = Genericvalue_val(Field(Args, I)); - - Result = LLVMRunFunction(EE, F, NumArgs, GVArgs); - - free(GVArgs); - return alloc_generic_value(Result); + llvm_raise(*caml_named_value("Llvm_executionengine.Error"), Error); + return Val_unit; } /* ExecutionEngine.t -> unit */ @@ -264,78 +92,31 @@ CAMLprim value llvm_ee_run_static_dtors(LLVMExecutionEngineRef EE) { return Val_unit; } -/* llvalue -> string array -> (string * string) array -> ExecutionEngine.t -> - int */ -CAMLprim value llvm_ee_run_function_as_main(LLVMValueRef F, - value Args, value Env, - LLVMExecutionEngineRef EE) { - CAMLparam2(Args, Env); - int I, NumArgs, NumEnv, EnvSize, Result; - const char **CArgs, **CEnv; - char *CEnvBuf, *Pos; - - NumArgs = Wosize_val(Args); - NumEnv = Wosize_val(Env); - - /* Build the environment. */ - CArgs = (const char **) malloc(NumArgs * sizeof(char*)); - for (I = 0; I != NumArgs; ++I) - CArgs[I] = String_val(Field(Args, I)); - - /* Compute the size of the environment string buffer. */ - for (I = 0, EnvSize = 0; I != NumEnv; ++I) { - EnvSize += strlen(String_val(Field(Field(Env, I), 0))) + 1; - EnvSize += strlen(String_val(Field(Field(Env, I), 1))) + 1; - } - - /* Build the environment. */ - CEnv = (const char **) malloc((NumEnv + 1) * sizeof(char*)); - CEnvBuf = (char*) malloc(EnvSize); - Pos = CEnvBuf; - for (I = 0; I != NumEnv; ++I) { - char *Name = String_val(Field(Field(Env, I), 0)), - *Value = String_val(Field(Field(Env, I), 1)); - int NameLen = strlen(Name), - ValueLen = strlen(Value); - - CEnv[I] = Pos; - memcpy(Pos, Name, NameLen); - Pos += NameLen; - *Pos++ = '='; - memcpy(Pos, Value, ValueLen); - Pos += ValueLen; - *Pos++ = '\0'; - } - CEnv[NumEnv] = NULL; - - Result = LLVMRunFunctionAsMain(EE, F, NumArgs, CArgs, CEnv); - - free(CArgs); - free(CEnv); - free(CEnvBuf); - - CAMLreturn(Val_int(Result)); -} - -/* llvalue -> ExecutionEngine.t -> unit */ -CAMLprim value llvm_ee_free_machine_code(LLVMValueRef F, - LLVMExecutionEngineRef EE) { - LLVMFreeMachineCodeForFunction(EE, F); - return Val_unit; -} - extern value llvm_alloc_data_layout(LLVMTargetDataRef TargetData); /* ExecutionEngine.t -> Llvm_target.DataLayout.t */ CAMLprim value llvm_ee_get_data_layout(LLVMExecutionEngineRef EE) { value DataLayout; LLVMTargetDataRef OrigDataLayout; - OrigDataLayout = LLVMGetExecutionEngineTargetData(EE); - char* TargetDataCStr; + + OrigDataLayout = LLVMGetExecutionEngineTargetData(EE); TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); LLVMDisposeMessage(TargetDataCStr); return DataLayout; } + +/* Llvm.llvalue -> int64 -> llexecutionengine -> unit */ +CAMLprim value llvm_ee_add_global_mapping(LLVMValueRef Global, value Ptr, + LLVMExecutionEngineRef EE) { + LLVMAddGlobalMapping(EE, Global, (void*) (Int64_val(Ptr))); + return Val_unit; +} + +/* Llvm.llvalue -> llexecutionengine -> int64 */ +CAMLprim value llvm_ee_get_pointer_to_global(LLVMValueRef Global, + LLVMExecutionEngineRef EE) { + return caml_copy_int64((int64_t) LLVMGetPointerToGlobal(EE, Global)); +} diff --git a/bindings/ocaml/executionengine/llvm_executionengine.ml b/bindings/ocaml/executionengine/llvm_executionengine.ml index a738df7..c0ff330 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.ml +++ b/bindings/ocaml/executionengine/llvm_executionengine.ml @@ -1,4 +1,4 @@ -(*===-- llvm_executionengine.ml - LLVM OCaml Interface ----------*- C++ -*-===* +(*===-- llvm_executionengine.ml - LLVM OCaml Interface --------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -7,105 +7,54 @@ * *===----------------------------------------------------------------------===*) - exception Error of string -external register_exns: exn -> unit - = "llvm_register_ee_exns" - - -module GenericValue = struct - type t - - external of_float: Llvm.lltype -> float -> t - = "llvm_genericvalue_of_float" - external of_pointer: 'a -> t - = "llvm_genericvalue_of_pointer" - external of_int32: Llvm.lltype -> int32 -> t - = "llvm_genericvalue_of_int32" - external of_int: Llvm.lltype -> int -> t - = "llvm_genericvalue_of_int" - external of_nativeint: Llvm.lltype -> nativeint -> t - = "llvm_genericvalue_of_nativeint" - external of_int64: Llvm.lltype -> int64 -> t - = "llvm_genericvalue_of_int64" - - external as_float: Llvm.lltype -> t -> float - = "llvm_genericvalue_as_float" - external as_pointer: t -> 'a - = "llvm_genericvalue_as_pointer" - external as_int32: t -> int32 - = "llvm_genericvalue_as_int32" - external as_int: t -> int - = "llvm_genericvalue_as_int" - external as_nativeint: t -> nativeint - = "llvm_genericvalue_as_nativeint" - external as_int64: t -> int64 - = "llvm_genericvalue_as_int64" -end - - -module ExecutionEngine = struct - type t - - (* FIXME: Ocaml is not running this setup code unless we use 'val' in the - interface, which causes the emission of a stub for each function; - using 'external' in the module allows direct calls into - ocaml_executionengine.c. This is hardly fatal, but it is unnecessary - overhead on top of the two stubs that are already invoked for each - call into LLVM. *) - let _ = register_exns (Error "") - - external create: Llvm.llmodule -> t - = "llvm_ee_create" - external create_interpreter: Llvm.llmodule -> t - = "llvm_ee_create_interpreter" - external create_jit: Llvm.llmodule -> int -> t - = "llvm_ee_create_jit" - external dispose: t -> unit - = "llvm_ee_dispose" - external add_module: Llvm.llmodule -> t -> unit - = "llvm_ee_add_module" - external remove_module: Llvm.llmodule -> t -> Llvm.llmodule - = "llvm_ee_remove_module" - external find_function: string -> t -> Llvm.llvalue option - = "llvm_ee_find_function" - external run_function: Llvm.llvalue -> GenericValue.t array -> t -> - GenericValue.t - = "llvm_ee_run_function" - external run_static_ctors: t -> unit - = "llvm_ee_run_static_ctors" - external run_static_dtors: t -> unit - = "llvm_ee_run_static_dtors" - external run_function_as_main: Llvm.llvalue -> string array -> - (string * string) array -> t -> int - = "llvm_ee_run_function_as_main" - external free_machine_code: Llvm.llvalue -> t -> unit - = "llvm_ee_free_machine_code" - - external data_layout : t -> Llvm_target.DataLayout.t - = "llvm_ee_get_data_layout" - - (* The following are not bound. Patches are welcome. - - add_global_mapping: llvalue -> llgenericvalue -> t -> unit - clear_all_global_mappings: t -> unit - update_global_mapping: llvalue -> llgenericvalue -> t -> unit - get_pointer_to_global_if_available: llvalue -> t -> llgenericvalue - get_pointer_to_global: llvalue -> t -> llgenericvalue - get_pointer_to_function: llvalue -> t -> llgenericvalue - get_pointer_to_function_or_stub: llvalue -> t -> llgenericvalue - get_global_value_at_address: llgenericvalue -> t -> llvalue option - store_value_to_memory: llgenericvalue -> llgenericvalue -> lltype -> unit - initialize_memory: llvalue -> llgenericvalue -> t -> unit - recompile_and_relink_function: llvalue -> t -> llgenericvalue - get_or_emit_global_variable: llvalue -> t -> llgenericvalue - disable_lazy_compilation: t -> unit - lazy_compilation_enabled: t -> bool - install_lazy_function_creator: (string -> llgenericvalue) -> t -> unit - - *) -end - -external initialize_native_target : unit -> bool - = "llvm_initialize_native_target" +let () = Callback.register_exception "Llvm_executionengine.Error" (Error "") + +external initialize : unit -> bool + = "llvm_ee_initialize" + +type llexecutionengine + +type llcompileroptions = { + opt_level: int; + code_model: Llvm_target.CodeModel.t; + no_framepointer_elim: bool; + enable_fast_isel: bool; +} + +let default_compiler_options = { + opt_level = 0; + code_model = Llvm_target.CodeModel.JITDefault; + no_framepointer_elim = false; + enable_fast_isel = false } + +external create : ?options:llcompileroptions -> Llvm.llmodule -> llexecutionengine + = "llvm_ee_create" +external dispose : llexecutionengine -> unit + = "llvm_ee_dispose" +external add_module : Llvm.llmodule -> llexecutionengine -> unit + = "llvm_ee_add_module" +external remove_module : Llvm.llmodule -> llexecutionengine -> unit + = "llvm_ee_remove_module" +external run_static_ctors : llexecutionengine -> unit + = "llvm_ee_run_static_ctors" +external run_static_dtors : llexecutionengine -> unit + = "llvm_ee_run_static_dtors" +external data_layout : llexecutionengine -> Llvm_target.DataLayout.t + = "llvm_ee_get_data_layout" +external add_global_mapping_ : Llvm.llvalue -> int64 -> llexecutionengine -> unit + = "llvm_ee_add_global_mapping" +external get_pointer_to_global_ : Llvm.llvalue -> llexecutionengine -> int64 + = "llvm_ee_get_pointer_to_global" + +let add_global_mapping llval ptr ee = + add_global_mapping_ llval (Ctypes.raw_address_of_ptr (Ctypes.to_voidp ptr)) ee + +let get_pointer_to_global llval typ ee = + Ctypes.coerce (let open Ctypes in ptr void) typ + (Ctypes.ptr_of_raw_address (get_pointer_to_global_ llval ee)) + +(* The following are not bound. Patches are welcome. +target_machine : llexecutionengine -> Llvm_target.TargetMachine.t + *) diff --git a/bindings/ocaml/executionengine/llvm_executionengine.mli b/bindings/ocaml/executionengine/llvm_executionengine.mli index 74a6062..b07151d 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.mli +++ b/bindings/ocaml/executionengine/llvm_executionengine.mli @@ -1,4 +1,4 @@ -(*===-- llvm_executionengine.mli - LLVM OCaml Interface ---------*- C++ -*-===* +(*===-- llvm_executionengine.mli - LLVM OCaml Interface -------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -10,147 +10,75 @@ (** JIT Interpreter. This interface provides an OCaml API for LLVM execution engine (JIT/ - interpreter), the classes in the ExecutionEngine library. *) + interpreter), the classes in the [ExecutionEngine] library. *) exception Error of string -module GenericValue: sig - (** [GenericValue.t] is a boxed union type used to portably pass arguments to - and receive values from the execution engine. It supports only a limited - selection of types; for more complex argument types, it is necessary to - generate a stub function by hand or to pass parameters by reference. - See the struct [llvm::GenericValue]. *) - type t - - (** [of_float fpty n] boxes the float [n] in a float-valued generic value - according to the floating point type [fpty]. See the fields - [llvm::GenericValue::DoubleVal] and [llvm::GenericValue::FloatVal]. *) - val of_float : Llvm.lltype -> float -> t - - (** [of_pointer v] boxes the pointer value [v] in a generic value. See the - field [llvm::GenericValue::PointerVal]. *) - val of_pointer : 'a -> t - - (** [of_int32 n w] boxes the int32 [i] in a generic value with the bitwidth - [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int32 : Llvm.lltype -> int32 -> t - - (** [of_int n w] boxes the int [i] in a generic value with the bitwidth - [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int : Llvm.lltype -> int -> t - - (** [of_natint n w] boxes the native int [i] in a generic value with the - bitwidth [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_nativeint : Llvm.lltype -> nativeint -> t - - (** [of_int64 n w] boxes the int64 [i] in a generic value with the bitwidth - [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int64 : Llvm.lltype -> int64 -> t - - (** [as_float fpty gv] unboxes the floating point-valued generic value [gv] of - floating point type [fpty]. See the fields [llvm::GenericValue::DoubleVal] - and [llvm::GenericValue::FloatVal]. *) - val as_float : Llvm.lltype -> t -> float - - (** [as_pointer gv] unboxes the pointer-valued generic value [gv]. See the - field [llvm::GenericValue::PointerVal]. *) - val as_pointer : t -> 'a - - (** [as_int32 gv] unboxes the integer-valued generic value [gv] as an [int32]. - Is invalid if [gv] has a bitwidth greater than 32 bits. See the field - [llvm::GenericValue::IntVal]. *) - val as_int32 : t -> int32 - - (** [as_int gv] unboxes the integer-valued generic value [gv] as an [int]. - Is invalid if [gv] has a bitwidth greater than the host bit width (but the - most significant bit may be lost). See the field - [llvm::GenericValue::IntVal]. *) - val as_int : t -> int - - (** [as_natint gv] unboxes the integer-valued generic value [gv] as a - [nativeint]. Is invalid if [gv] has a bitwidth greater than - [nativeint]. See the field [llvm::GenericValue::IntVal]. *) - val as_nativeint : t -> nativeint - - (** [as_int64 gv] returns the integer-valued generic value [gv] as an [int64]. - Is invalid if [gv] has a bitwidth greater than [int64]. See the field - [llvm::GenericValue::IntVal]. *) - val as_int64 : t -> int64 -end - - -module ExecutionEngine: sig - (** An execution engine is either a JIT compiler or an interpreter, capable of - directly loading an LLVM module and executing its functions without first - invoking a static compiler and generating a native executable. *) - type t - - (** [create m] creates a new execution engine, taking ownership of the - module [m] if successful. Creates a JIT if possible, else falls back to an - interpreter. Raises [Error msg] if an error occurrs. The execution engine - is not garbage collected and must be destroyed with [dispose ee]. - See the function [llvm::EngineBuilder::create]. *) - val create : Llvm.llmodule -> t - - (** [create_interpreter m] creates a new interpreter, taking ownership of the - module [m] if successful. Raises [Error msg] if an error occurrs. The - execution engine is not garbage collected and must be destroyed with - [dispose ee]. - See the function [llvm::EngineBuilder::create]. *) - val create_interpreter : Llvm.llmodule -> t - - (** [create_jit m optlevel] creates a new JIT (just-in-time compiler), taking - ownership of the module [m] if successful with the desired optimization - level [optlevel]. Raises [Error msg] if an error occurrs. The execution - engine is not garbage collected and must be destroyed with [dispose ee]. - See the function [llvm::EngineBuilder::create]. *) - val create_jit : Llvm.llmodule -> int -> t - - (** [dispose ee] releases the memory used by the execution engine and must be - invoked to avoid memory leaks. *) - val dispose : t -> unit - - (** [add_module m ee] adds the module [m] to the execution engine [ee]. *) - val add_module : Llvm.llmodule -> t -> unit - - (** [remove_module m ee] removes the module [m] from the execution engine - [ee], disposing of [m] and the module referenced by [mp]. Raises - [Error msg] if an error occurs. *) - val remove_module : Llvm.llmodule -> t -> Llvm.llmodule - - (** [find_function n ee] finds the function named [n] defined in any of the - modules owned by the execution engine [ee]. Returns [None] if the function - is not found and [Some f] otherwise. *) - val find_function : string -> t -> Llvm.llvalue option - - (** [run_function f args ee] synchronously executes the function [f] with the - arguments [args], which must be compatible with the parameter types. *) - val run_function : Llvm.llvalue -> GenericValue.t array -> t -> - GenericValue.t - - (** [run_static_ctors ee] executes the static constructors of each module in - the execution engine [ee]. *) - val run_static_ctors : t -> unit - - (** [run_static_dtors ee] executes the static destructors of each module in - the execution engine [ee]. *) - val run_static_dtors : t -> unit - - (** [run_function_as_main f args env ee] executes the function [f] as a main - function, passing it [argv] and [argc] according to the string array - [args], and [envp] as specified by the array [env]. Returns the integer - return value of the function. *) - val run_function_as_main : Llvm.llvalue -> string array -> - (string * string) array -> t -> int - - (** [free_machine_code f ee] releases the memory in the execution engine [ee] - used to store the machine code for the function [f]. *) - val free_machine_code : Llvm.llvalue -> t -> unit - - (** [data_layout ee] is the data layout of the execution engine [ee]. *) - val data_layout : t -> Llvm_target.DataLayout.t -end - -(** [initialize_native_target ()] initializes the native target corresponding - to the host. Returns [true] if initialization is {b not} done. *) -val initialize_native_target : unit -> bool +(** [initialize ()] initializes the backend corresponding to the host. + Returns [true] if initialization is successful; [false] indicates + that there is no such backend or it is unable to emit object code + via MCJIT. *) +val initialize : unit -> bool + +(** An execution engine is either a JIT compiler or an interpreter, capable of + directly loading an LLVM module and executing its functions without first + invoking a static compiler and generating a native executable. *) +type llexecutionengine + +(** MCJIT compiler options. See [llvm::TargetOptions]. *) +type llcompileroptions = { + opt_level: int; + code_model: Llvm_target.CodeModel.t; + no_framepointer_elim: bool; + enable_fast_isel: bool; +} + +(** Default MCJIT compiler options: + [{ opt_level = 0; code_model = CodeModel.JIT_default; + no_framepointer_elim = false; enable_fast_isel = false }] *) +val default_compiler_options : llcompileroptions + +(** [create m optlevel] creates a new MCJIT just-in-time compiler, taking + ownership of the module [m] if successful with the desired optimization + level [optlevel]. Raises [Error msg] if an error occurrs. The execution + engine is not garbage collected and must be destroyed with [dispose ee]. + + Run {!initialize} before using this function. + + See the function [llvm::EngineBuilder::create]. *) +val create : ?options:llcompileroptions -> Llvm.llmodule -> llexecutionengine + +(** [dispose ee] releases the memory used by the execution engine and must be + invoked to avoid memory leaks. *) +val dispose : llexecutionengine -> unit + +(** [add_module m ee] adds the module [m] to the execution engine [ee]. *) +val add_module : Llvm.llmodule -> llexecutionengine -> unit + +(** [remove_module m ee] removes the module [m] from the execution engine + [ee]. Raises [Error msg] if an error occurs. *) +val remove_module : Llvm.llmodule -> llexecutionengine -> unit + +(** [run_static_ctors ee] executes the static constructors of each module in + the execution engine [ee]. *) +val run_static_ctors : llexecutionengine -> unit + +(** [run_static_dtors ee] executes the static destructors of each module in + the execution engine [ee]. *) +val run_static_dtors : llexecutionengine -> unit + +(** [data_layout ee] is the data layout of the execution engine [ee]. *) +val data_layout : llexecutionengine -> Llvm_target.DataLayout.t + +(** [add_global_mapping gv ptr ee] tells the execution engine [ee] that + the global [gv] is at the specified location [ptr], which must outlive + [gv] and [ee]. + All uses of [gv] in the compiled code will refer to [ptr]. *) +val add_global_mapping : Llvm.llvalue -> 'a Ctypes.ptr -> llexecutionengine -> unit + +(** [get_pointer_to_global gv typ ee] returns the value of the global + variable [gv] in the execution engine [ee] as type [typ], which may + be a pointer type (e.g. [int ptr typ]) for global variables or + a function (e.g. [(int -> int) typ]) type for functions, and which + will be live as long as [gv] and [ee] are. *) +val get_pointer_to_global : Llvm.llvalue -> 'a Ctypes.typ -> llexecutionengine -> 'a diff --git a/bindings/ocaml/irreader/irreader_ocaml.c b/bindings/ocaml/irreader/irreader_ocaml.c index 30c10c7..ce593db 100644 --- a/bindings/ocaml/irreader/irreader_ocaml.c +++ b/bindings/ocaml/irreader/irreader_ocaml.c @@ -16,33 +16,9 @@ #include "caml/alloc.h" #include "caml/fail.h" #include "caml/memory.h" +#include "caml/callback.h" -/* Can't use the recommended caml_named_value mechanism for backwards - compatibility reasons. This is largely equivalent. */ -static value llvm_irreader_error_exn; - -CAMLprim value llvm_register_irreader_exns(value Error) { - llvm_irreader_error_exn = Field(Error, 0); - register_global_root(&llvm_irreader_error_exn); - return Val_unit; -} - -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif -} - - -/*===-- Modules -----------------------------------------------------------===*/ +void llvm_raise(value Prototype, char *Message); /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ CAMLprim value llvm_parse_ir(LLVMContextRef C, @@ -53,7 +29,7 @@ CAMLprim value llvm_parse_ir(LLVMContextRef C, char *Message; if (LLVMParseIRInContext(C, MemBuf, &M, &Message)) - llvm_raise(llvm_irreader_error_exn, Message); + llvm_raise(*caml_named_value("Llvm_irreader.Error"), Message); CAMLreturn((value) M); } diff --git a/bindings/ocaml/irreader/llvm_irreader.ml b/bindings/ocaml/irreader/llvm_irreader.ml index 455b1fa..f757d62 100644 --- a/bindings/ocaml/irreader/llvm_irreader.ml +++ b/bindings/ocaml/irreader/llvm_irreader.ml @@ -10,8 +10,7 @@ exception Error of string -external register_exns : exn -> unit = "llvm_register_irreader_exns" -let _ = register_exns (Error "") +let _ = Callback.register_exception "Llvm_irreader.Error" (Error "") external parse_ir : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule = "llvm_parse_ir" diff --git a/bindings/ocaml/linker/linker_ocaml.c b/bindings/ocaml/linker/linker_ocaml.c index 2491e3b..ed37777 100644 --- a/bindings/ocaml/linker/linker_ocaml.c +++ b/bindings/ocaml/linker/linker_ocaml.c @@ -1,4 +1,4 @@ -/*===-- linker_ocaml.c - LLVM Ocaml Glue ------------------------*- C++ -*-===*\ +/*===-- linker_ocaml.c - LLVM OCaml Glue ------------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -19,36 +19,16 @@ #include "caml/alloc.h" #include "caml/memory.h" #include "caml/fail.h" +#include "caml/callback.h" -static value llvm_linker_error_exn; +void llvm_raise(value Prototype, char *Message); -CAMLprim value llvm_register_linker_exns(value Error) { - llvm_linker_error_exn = Field(Error, 0); - register_global_root(&llvm_linker_error_exn); - return Val_unit; -} - -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif -} - -/* llmodule -> llmodule -> Mode.t -> unit - raises Error msg on error */ +/* llmodule -> llmodule -> Mode.t -> unit */ CAMLprim value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src, value Mode) { char* Message; if (LLVMLinkModules(Dst, Src, Int_val(Mode), &Message)) - llvm_raise(llvm_linker_error_exn, Message); + llvm_raise(*caml_named_value("Llvm_linker.Error"), Message); return Val_unit; } diff --git a/bindings/ocaml/linker/llvm_linker.ml b/bindings/ocaml/linker/llvm_linker.ml index 2b73e2e..5854d70 100644 --- a/bindings/ocaml/linker/llvm_linker.ml +++ b/bindings/ocaml/linker/llvm_linker.ml @@ -9,8 +9,7 @@ exception Error of string -external register_exns : exn -> unit = "llvm_register_linker_exns" -let _ = register_exns (Error "") +let () = Callback.register_exception "Llvm_linker.Error" (Error "") module Mode = struct type t = @@ -19,4 +18,4 @@ module Mode = struct end external link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit - = "llvm_link_modules"
\ No newline at end of file + = "llvm_link_modules" diff --git a/bindings/ocaml/llvm/META.llvm.in b/bindings/ocaml/llvm/META.llvm.in index edb84e0..f9808c7 100644 --- a/bindings/ocaml/llvm/META.llvm.in +++ b/bindings/ocaml/llvm/META.llvm.in @@ -4,7 +4,6 @@ description = "LLVM OCaml bindings" archive(byte) = "llvm.cma" archive(native) = "llvm.cmxa" directory = "." -linkopts = "-ccopt -lstdc++" package "analysis" ( requires = "llvm" @@ -31,7 +30,7 @@ package "bitwriter" ( ) package "executionengine" ( - requires = "llvm,llvm.target" + requires = "llvm,llvm.target,ctypes.foreign" version = "@PACKAGE_VERSION@" description = "JIT and Interpreter for LLVM" archive(byte) = "llvm_executionengine.cma" diff --git a/bindings/ocaml/llvm/Makefile b/bindings/ocaml/llvm/Makefile index 850f564..fb682c7 100644 --- a/bindings/ocaml/llvm/Makefile +++ b/bindings/ocaml/llvm/Makefile @@ -1,20 +1,21 @@ ##===- bindings/ocaml/llvm/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 interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. LIBRARYNAME := llvm -UsedComponents := core +UsedComponents := core transformutils UsedOcamlLibs := llvm +ExtraLibs := -lstdc++ include ../Makefile.ocaml diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index 39875a5..0df4d40 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -1,4 +1,4 @@ -(*===-- llvm/llvm.ml - LLVM Ocaml Interface --------------------------------===* +(*===-- llvm/llvm.ml - LLVM OCaml Interface -------------------------------===* * * The LLVM Compiler Infrastructure * @@ -66,6 +66,13 @@ module Visibility = struct | Protected end +module DLLStorageClass = struct + type t = + | Default + | DLLImport + | DLLExport +end + module CallConv = struct let c = 0 let fast = 8 @@ -278,8 +285,7 @@ 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" @@ -287,6 +293,8 @@ external reset_fatal_error_handler : unit -> unit = "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 @@ -305,6 +313,7 @@ external mdkind_id : llcontext -> string -> llmdkind = "llvm_mdkind_id" (*===-- Modules -----------------------------------------------------------===*) external create_module : llcontext -> string -> llmodule = "llvm_create_module" external dispose_module : llmodule -> unit = "llvm_dispose_module" +external clone_module : llmodule -> llmodule = "LLVMCloneModule" external target_triple: llmodule -> string = "llvm_target_triple" external set_target_triple: string -> llmodule -> unit @@ -428,6 +437,7 @@ let fold_right_uses f v init = (*--... 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" @@ -465,6 +475,8 @@ external int64_of_const : llvalue -> Int64.t option 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" @@ -479,6 +491,8 @@ external const_named_struct : lltype -> 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 string_of_const : llvalue -> string option = "llvm_string_of_const" +external const_element : llvalue -> int -> llvalue = "llvm_const_element" (*--... Constant expressions ...............................................--*) external align_of : lltype -> llvalue = "LLVMAlignOf" @@ -569,6 +583,8 @@ 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" @@ -952,6 +968,8 @@ external instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos 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 @@ -1019,6 +1037,63 @@ external set_tail_call : bool -> llvalue -> unit = "llvm_set_tail_call" 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" diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index f5f5b53..e5e90c3 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -105,6 +105,15 @@ module Visibility : sig | Protected end +(** The DLL storage class of a global value, accessed with {!dll_storage_class} and + {!set_dll_storage_class}. See [llvm::GlobalValue::DLLStorageClassTypes]. *) +module DLLStorageClass : sig + type t = + | Default + | DLLImport + | DLLExport +end + (** The following calling convention values may be accessed with {!function_call_conv} and {!set_function_call_conv}. Calling conventions are open-ended. *) @@ -157,16 +166,16 @@ end See the [llvm::ICmpInst::Predicate] enumeration. *) module Icmp : sig type t = - | Eq (* Equal *) - | Ne (* Not equal *) - | Ugt (* Unsigned greater than *) - | Uge (* Unsigned greater or equal *) - | Ult (* Unsigned less than *) - | Ule (* Unsigned less or equal *) - | Sgt (* Signed greater than *) - | Sge (* Signed greater or equal *) - | Slt (* Signed less than *) - | Sle (* Signed less or equal *) + | Eq (** Equal *) + | Ne (** Not equal *) + | Ugt (** Unsigned greater than *) + | Uge (** Unsigned greater or equal *) + | Ult (** Unsigned less than *) + | Ule (** Unsigned less or equal *) + | Sgt (** Signed greater than *) + | Sge (** Signed greater or equal *) + | Slt (** Signed less than *) + | Sle (** Signed less or equal *) end (** The predicate for a floating-point comparison ([fcmp]) instruction. @@ -175,38 +184,38 @@ end See the [llvm::FCmpInst::Predicate] enumeration. *) module Fcmp : sig type t = - | False (* Always false *) - | Oeq (* Ordered and equal *) - | Ogt (* Ordered and greater than *) - | Oge (* Ordered and greater or equal *) - | Olt (* Ordered and less than *) - | Ole (* Ordered and less or equal *) - | One (* Ordered and not equal *) - | Ord (* Ordered (no operand is NaN) *) - | Uno (* Unordered (one operand at least is NaN) *) - | Ueq (* Unordered and equal *) - | Ugt (* Unordered and greater than *) - | Uge (* Unordered and greater or equal *) - | Ult (* Unordered and less than *) - | Ule (* Unordered and less or equal *) - | Une (* Unordered and not equal *) - | True (* Always true *) + | False (** Always false *) + | Oeq (** Ordered and equal *) + | Ogt (** Ordered and greater than *) + | Oge (** Ordered and greater or equal *) + | Olt (** Ordered and less than *) + | Ole (** Ordered and less or equal *) + | One (** Ordered and not equal *) + | Ord (** Ordered (no operand is NaN) *) + | Uno (** Unordered (one operand at least is NaN) *) + | Ueq (** Unordered and equal *) + | Ugt (** Unordered and greater than *) + | Uge (** Unordered and greater or equal *) + | Ult (** Unordered and less than *) + | Ule (** Unordered and less or equal *) + | Une (** Unordered and not equal *) + | True (** Always true *) end (** The opcodes for LLVM instructions and constant expressions. *) module Opcode : sig type t = - | Invalid (* not an instruction *) - (* Terminator Instructions *) - | Ret + | Invalid (** Not an instruction *) + + | Ret (** Terminator Instructions *) | Br | Switch | IndirectBr | Invoke | Invalid2 | Unreachable - (* Standard Binary Operators *) - | Add + + | Add (** Standard Binary Operators *) | FAdd | Sub | FSub @@ -218,20 +227,20 @@ module Opcode : sig | URem | SRem | FRem - (* Logical Operators *) - | Shl + + | Shl (** Logical Operators *) | LShr | AShr | And | Or | Xor - (* Memory Operators *) - | Alloca + + | Alloca (** Memory Operators *) | Load | Store | GetElementPtr - (* Cast Operators *) - | Trunc + + | Trunc (** Cast Operators *) | ZExt | SExt | FPToUI @@ -243,8 +252,8 @@ module Opcode : sig | PtrToInt | IntToPtr | BitCast - (* Other Operators *) - | ICmp + + | ICmp (** Other Operators *) | FCmp | PHI | Call @@ -291,7 +300,7 @@ module AtomicOrdering : sig | NotAtomic | Unordered | Monotonic - | Invalid (* removed due to API changes *) + | Invalid (** removed due to API changes *) | Acquire | Release | AcqiureRelease @@ -381,6 +390,14 @@ val install_fatal_error_handler : (string -> unit) -> unit (** [reset_fatal_error_handler ()] resets LLVM's fatal error handler. *) val reset_fatal_error_handler : unit -> unit +(** [parse_command_line_options ?overview args] parses [args] using + the LLVM command line parser. Note that the only stable thing about this + function is its signature; you cannot rely on any particular set of command + line arguments being interpreted the same way across LLVM versions. + + See the function [llvm::cl::ParseCommandLineOptions()]. *) +val parse_command_line_options : ?overview:string -> string array -> unit + (** {6 Contexts} *) (** [create_context ()] creates a context for storing the "global" state in @@ -414,6 +431,9 @@ val create_module : llcontext -> string -> llmodule [llvm::Module::~Module]. *) val dispose_module : llmodule -> unit +(** [clone_module m] returns an exact copy of module [m]. *) +val clone_module : llmodule -> llmodule + (** [target_triple m] is the target specifier for the module [m], something like [i686-apple-darwin8]. See the method [llvm::Module::getTargetTriple]. *) val target_triple: llmodule -> string @@ -651,7 +671,7 @@ val x86_mmx_type : llcontext -> lltype val type_by_name : llmodule -> string -> lltype option -(* {6 Values} *) +(** {6 Values} *) (** [type_of v] returns the type of the value [v]. See the method [llvm::Value::getType]. *) @@ -682,7 +702,7 @@ val string_of_llvalue : llvalue -> string val replace_all_uses_with : llvalue -> llvalue -> unit -(* {6 Uses} *) +(** {6 Uses} *) (** [use_begin v] returns the first position in the use list for the value [v]. [use_begin] and [use_succ] can e used to iterate over the use list in order. @@ -714,12 +734,17 @@ val fold_left_uses : ('a -> lluse -> 'a) -> 'a -> llvalue -> 'a val fold_right_uses : (lluse -> 'a -> 'a) -> llvalue -> 'a -> 'a -(* {6 Users} *) +(** {6 Users} *) (** [operand v i] returns the operand at index [i] for the value [v]. See the method [llvm::User::getOperand]. *) val operand : llvalue -> int -> llvalue +(** [operand_use v i] returns the use of the operand at index [i] for the value [v]. See the + method [llvm::User::getOperandUse]. *) +val operand_use : llvalue -> int -> lluse + + (** [set_operand v i o] sets the operand of the value [v] at the index [i] to the value [o]. See the method [llvm::User::setOperand]. *) @@ -837,15 +862,19 @@ val const_int_of_string : lltype -> string -> int -> llvalue value [n]. See the method [llvm::ConstantFP::get]. *) val const_float : lltype -> float -> llvalue +(** [float_of_const c] returns the float value of the [c] constant float. + None is returned if this is not an float constant. + See the method [llvm::ConstantFP::getDoubleValue].*) +val float_of_const : llvalue -> float option + (** [const_float_of_string ty s] returns the floating point constant of type [ty] and value [n]. See the method [llvm::ConstantFP::get]. *) val const_float_of_string : lltype -> string -> llvalue - (** {7 Operations on composite constants} *) (** [const_string c s] returns the constant [i8] array with the values of the - characters in the string [s] in the context [c]. The array is not + characters in the string [s] in the context [c]. The array is not null-terminated (but see {!const_stringz}). This value can in turn be used as the initializer for a global variable. See the method [llvm::ConstantArray::get]. *) @@ -887,6 +916,14 @@ val const_packed_struct : llcontext -> llvalue array -> llvalue values [elts]. See the method [llvm::ConstantVector::get]. *) val const_vector : llvalue array -> llvalue +(** [string_of_const c] returns [Some str] if [c] is a string constant, + or [None] if this is not a string constant. *) +val string_of_const : llvalue -> string option + +(** [const_element c] returns a constant for a specified index's element. + See the method ConstantDataSequential::getElementAsConstant. *) +val const_element : llvalue -> int -> llvalue + (** {7 Constant expressions} *) @@ -1234,6 +1271,14 @@ val visibility : llvalue -> Visibility.t [v]. See the method [llvm::GlobalValue::setVisibility]. *) val set_visibility : Visibility.t -> llvalue -> unit +(** [dll_storage_class g] returns the DLL storage class of the global value [g]. + See the method [llvm::GlobalValue::getDLLStorageClass]. *) +val dll_storage_class : llvalue -> DLLStorageClass.t + +(** [set_dll_storage_class v g] sets the DLL storage class of the global value [g] to + [v]. See the method [llvm::GlobalValue::setDLLStorageClass]. *) +val set_dll_storage_class : DLLStorageClass.t -> llvalue -> unit + (** [alignment g] returns the required alignment of the global value [g]. See the method [llvm::GlobalValue::getAlignment]. *) val alignment : llvalue -> int @@ -1687,6 +1732,15 @@ val instr_opcode : llvalue -> Opcode.t instruction [i]. *) val icmp_predicate : llvalue -> Icmp.t option +(** [fcmp_predicate i] returns the [fcmp.t] corresponding to an [fcmp] + instruction [i]. *) +val fcmp_predicate : llvalue -> Fcmp.t option + +(** [inst_clone i] returns a copy of instruction [i], + The instruction has no parent, and no name. + See the method [llvm::Instruction::clone]. *) +val instr_clone : llvalue -> llvalue + (** {7 Operations on call sites} *) @@ -1741,6 +1795,52 @@ val is_volatile : llvalue -> bool [llvm::StoreInst::setVolatile]. *) val set_volatile : bool -> llvalue -> unit +(** {7 Operations on terminators} *) + +(** [is_terminator v] returns true if the instruction [v] is a terminator. *) +val is_terminator : llvalue -> bool + +(** [successor v i] returns the successor at index [i] for the value [v]. + See the method [llvm::TerminatorInst::getSuccessor]. *) +val successor : llvalue -> int -> llbasicblock + +(** [set_successor v i o] sets the successor of the value [v] at the index [i] to + the value [o]. + See the method [llvm::TerminatorInst::setSuccessor]. *) +val set_successor : llvalue -> int -> llbasicblock -> unit + +(** [num_successors v] returns the number of successors for the value [v]. + See the method [llvm::TerminatorInst::getNumSuccessors]. *) +val num_successors : llvalue -> int + +(** [successors v] returns the successors of [v]. *) +val successors : llvalue -> llbasicblock array + +(** [iter_successors f v] applies function f to each successor [v] in order. Tail recursive. *) +val iter_successors : (llbasicblock -> unit) -> llvalue -> unit + +(** [fold_successors f v init] is [f (... (f init vN) ...) v1] where [v1,...,vN] are the successors of [v]. Tail recursive. *) +val fold_successors : (llbasicblock -> 'a -> 'a) -> llvalue -> 'a -> 'a + +(** {7 Operations on branches} *) + +(** [is_conditional v] returns true if the branch instruction [v] is conditional. + See the method [llvm::BranchInst::isConditional]. *) +val is_conditional : llvalue -> bool + +(** [condition v] return the condition of the branch instruction [v]. + See the method [llvm::BranchInst::getCondition]. *) +val condition : llvalue -> llvalue + +(** [set_condition v c] sets the condition of the branch instruction [v] to the value [c]. + See the method [llvm::BranchInst::setCondition]. *) +val set_condition : llvalue -> llvalue -> unit + +(** [get_branch c] returns a description of the branch instruction [c]. *) +val get_branch : llvalue -> + [ `Conditional of llvalue * llbasicblock * llbasicblock + | `Unconditional of llbasicblock ] + option (** {7 Operations on phi nodes} *) @@ -2402,7 +2502,7 @@ module MemoryBuffer : sig path [p]. If the file could not be read, then [IoError msg] is raised. *) val of_file : string -> llmemorybuffer - + (** [of_stdin ()] is the memory buffer containing the contents of standard input. If standard input is empty, then [IoError msg] is raised. *) val of_stdin : unit -> llmemorybuffer @@ -2413,7 +2513,7 @@ module MemoryBuffer : sig (** [as_string mb] is the string containing the contents of memory buffer [mb]. *) val as_string : llmemorybuffer -> string - + (** Disposes of a memory buffer. *) val dispose : llmemorybuffer -> unit end @@ -2425,13 +2525,13 @@ module PassManager : sig (** *) type 'a t type any = [ `Module | `Function ] - + (** [PassManager.create ()] constructs a new whole-module pass pipeline. This type of pipeline is suitable for link-time optimization and whole-module transformations. See the constructor of [llvm::PassManager]. *) val create : unit -> [ `Module ] t - + (** [PassManager.create_function m] constructs a new function-by-function pass pipeline over the module [m]. It does not take ownership of [m]. This type of pipeline is suitable for code generation and JIT compilation @@ -2450,19 +2550,19 @@ module PassManager : sig the module, [false] otherwise. See the [llvm::FunctionPassManager::doInitialization] method. *) val initialize : [ `Function ] t -> bool - + (** [run_function f fpm] executes all of the function passes scheduled in the function pass manager [fpm] over the function [f]. Returns [true] if any of the passes modified [f], [false] otherwise. See the [llvm::FunctionPassManager::run] method. *) val run_function : llvalue -> [ `Function ] t -> bool - + (** [finalize fpm] finalizes all of the function passes scheduled in in the function pass manager [fpm]. Returns [true] if any of the passes modified the module, [false] otherwise. See the [llvm::FunctionPassManager::doFinalization] method. *) val finalize : [ `Function ] t -> bool - + (** Frees the memory of a pass pipeline. For function pipelines, does not free the module. See the destructor of [llvm::BasePassManager]. *) diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index d5ebdcd..63c235d 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -15,46 +15,33 @@ |* *| \*===----------------------------------------------------------------------===*/ +#include <assert.h> +#include <stdlib.h> +#include <string.h> #include "llvm-c/Core.h" #include "caml/alloc.h" #include "caml/custom.h" #include "caml/memory.h" #include "caml/fail.h" #include "caml/callback.h" -#include <assert.h> -#include <stdlib.h> -#include <string.h> - - -/* Can't use the recommended caml_named_value mechanism for backwards - compatibility reasons. This is largely equivalent. */ -static value llvm_ioerror_exn; -CAMLprim value llvm_register_core_exns(value IoError) { - llvm_ioerror_exn = Field(IoError, 0); - register_global_root(&llvm_ioerror_exn); +value llvm_string_of_message(char* Message) { + value String = caml_copy_string(Message); + LLVMDisposeMessage(Message); - return Val_unit; + return String; } -static void llvm_raise(value Prototype, char *Message) { +void llvm_raise(value Prototype, char *Message) { CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif + caml_raise_with_arg(Prototype, llvm_string_of_message(Message)); + CAMLnoreturn; } static value llvm_fatal_error_handler; static void llvm_fatal_error_trampoline(const char *Reason) { - callback(llvm_fatal_error_handler, copy_string(Reason)); + callback(llvm_fatal_error_handler, caml_copy_string(Reason)); } CAMLprim value llvm_install_fatal_error_handler(value Handler) { @@ -75,6 +62,17 @@ CAMLprim value llvm_enable_pretty_stacktrace(value Unit) { return Val_unit; } +CAMLprim value llvm_parse_command_line_options(value Overview, value Args) { + char *COverview; + if (Overview == Val_int(0)) { + COverview = NULL; + } else { + COverview = String_val(Field(Overview, 0)); + } + LLVMParseCommandLineOptions(Wosize_val(Args), (const char* const*) Op_val(Args), COverview); + return Val_unit; +} + static value alloc_variant(int tag, void *Value) { value Iter = alloc_small(1, tag); Field(Iter, 0) = Val_op(Value); @@ -157,7 +155,7 @@ CAMLprim value llvm_dispose_module(LLVMModuleRef M) { /* llmodule -> string */ CAMLprim value llvm_target_triple(LLVMModuleRef M) { - return copy_string(LLVMGetTarget(M)); + return caml_copy_string(LLVMGetTarget(M)); } /* string -> llmodule -> unit */ @@ -168,7 +166,7 @@ CAMLprim value llvm_set_target_triple(value Trip, LLVMModuleRef M) { /* llmodule -> string */ CAMLprim value llvm_data_layout(LLVMModuleRef M) { - return copy_string(LLVMGetDataLayout(M)); + return caml_copy_string(LLVMGetDataLayout(M)); } /* string -> llmodule -> unit */ @@ -186,22 +184,24 @@ CAMLprim value llvm_dump_module(LLVMModuleRef M) { /* string -> llmodule -> unit */ CAMLprim value llvm_print_module(value Filename, LLVMModuleRef M) { char* Message; - if(LLVMPrintModuleToFile(M, String_val(Filename), &Message)) { - llvm_raise(llvm_ioerror_exn, Message); - } + + if(LLVMPrintModuleToFile(M, String_val(Filename), &Message)) + llvm_raise(*caml_named_value("Llvm.IoError"), Message); return Val_unit; } /* llmodule -> string */ CAMLprim value llvm_string_of_llmodule(LLVMModuleRef M) { + CAMLparam0(); + CAMLlocal1(ModuleStr); char* ModuleCStr; - ModuleCStr = LLVMPrintModuleToString(M); - value ModuleStr = caml_copy_string(ModuleCStr); + ModuleCStr = LLVMPrintModuleToString(M); + ModuleStr = caml_copy_string(ModuleCStr); LLVMDisposeMessage(ModuleCStr); - return ModuleStr; + CAMLreturn(ModuleStr); } /* llmodule -> string -> unit */ @@ -234,13 +234,15 @@ CAMLprim value llvm_dump_type(LLVMTypeRef Val) { /* lltype -> string */ CAMLprim value llvm_string_of_lltype(LLVMTypeRef M) { + CAMLparam0(); + CAMLlocal1(TypeStr); char* TypeCStr; - TypeCStr = LLVMPrintTypeToString(M); - value TypeStr = caml_copy_string(TypeCStr); + TypeCStr = LLVMPrintTypeToString(M); + TypeStr = caml_copy_string(TypeCStr); LLVMDisposeMessage(TypeCStr); - return TypeStr; + CAMLreturn(TypeStr); } /*--... Operations on integer types ........................................--*/ @@ -537,7 +539,7 @@ CAMLprim value llvm_classify_value(LLVMValueRef Val) { /* llvalue -> string */ CAMLprim value llvm_value_name(LLVMValueRef Val) { - return copy_string(LLVMGetValueName(Val)); + return caml_copy_string(LLVMGetValueName(Val)); } /* string -> llvalue -> unit */ @@ -554,13 +556,15 @@ CAMLprim value llvm_dump_value(LLVMValueRef Val) { /* llvalue -> string */ CAMLprim value llvm_string_of_llvalue(LLVMValueRef M) { + CAMLparam0(); + CAMLlocal1(ValueStr); char* ValueCStr; - ValueCStr = LLVMPrintValueToString(M); - value ValueStr = caml_copy_string(ValueCStr); + ValueCStr = LLVMPrintValueToString(M); + ValueStr = caml_copy_string(ValueCStr); LLVMDisposeMessage(ValueCStr); - return ValueStr; + CAMLreturn(ValueStr); } /* llvalue -> llvalue -> unit */ @@ -577,6 +581,11 @@ CAMLprim LLVMValueRef llvm_operand(LLVMValueRef V, value I) { return LLVMGetOperand(V, Int_val(I)); } +/* llvalue -> int -> lluse */ +CAMLprim LLVMUseRef llvm_operand_use(LLVMValueRef V, value I) { + return LLVMGetOperandUse(V, Int_val(I)); +} + /* llvalue -> int -> llvalue -> unit */ CAMLprim value llvm_set_operand(LLVMValueRef U, value I, LLVMValueRef V) { LLVMSetOperand(U, Int_val(I), V); @@ -695,7 +704,7 @@ CAMLprim value llvm_append_namedmd(LLVMModuleRef M, value Name, LLVMValueRef Val /* lltype -> int -> llvalue */ CAMLprim LLVMValueRef llvm_const_int(LLVMTypeRef IntTy, value N) { - return LLVMConstInt(IntTy, (long long) Int_val(N), 1); + return LLVMConstInt(IntTy, (long long) Long_val(N), 1); } /* lltype -> Int64.t -> bool -> llvalue */ @@ -729,6 +738,28 @@ CAMLprim LLVMValueRef llvm_const_float(LLVMTypeRef RealTy, value N) { return LLVMConstReal(RealTy, Double_val(N)); } + +/* llvalue -> float */ +CAMLprim value llvm_float_of_const(LLVMValueRef Const) +{ + CAMLparam0(); + CAMLlocal1(Option); + LLVMBool LosesInfo; + double Result; + + if (LLVMIsAConstantFP(Const)) { + Result = LLVMConstRealGetDouble(Const, &LosesInfo); + if (LosesInfo) + CAMLreturn(Val_int(0)); + + Option = alloc(1, 0); + Field(Option, 0) = caml_copy_double(Result); + CAMLreturn(Option); + } + + CAMLreturn(Val_int(0)); +} + /* lltype -> string -> llvalue */ CAMLprim LLVMValueRef llvm_const_float_of_string(LLVMTypeRef RealTy, value S) { return LLVMConstRealOfStringAndSize(RealTy, String_val(S), @@ -782,6 +813,31 @@ CAMLprim LLVMValueRef llvm_const_vector(value ElementVals) { Wosize_val(ElementVals)); } +/* llvalue -> string option */ +CAMLprim value llvm_string_of_const(LLVMValueRef Const) { + const char *S; + size_t Len; + CAMLparam0(); + CAMLlocal2(Option, Str); + + if(LLVMIsAConstantDataSequential(Const) && LLVMIsConstantString(Const)) { + S = LLVMGetAsString(Const, &Len); + Str = caml_alloc_string(Len); + memcpy(String_val(Str), S, Len); + + Option = alloc(1, 0); + Field(Option, 0) = Str; + CAMLreturn(Option); + } else { + CAMLreturn(Val_int(0)); + } +} + +/* llvalue -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_const_element(LLVMValueRef Const, value N) { + return LLVMGetElementAsConstant(Const, Int_val(N)); +} + /*--... Constant expressions ...............................................--*/ /* Icmp.t -> llvalue -> llvalue -> llvalue */ @@ -881,7 +937,7 @@ CAMLprim value llvm_set_linkage(value Linkage, LLVMValueRef Global) { /* llvalue -> string */ CAMLprim value llvm_section(LLVMValueRef Global) { - return copy_string(LLVMGetSection(Global)); + return caml_copy_string(LLVMGetSection(Global)); } /* string -> llvalue -> unit */ @@ -901,6 +957,17 @@ CAMLprim value llvm_set_visibility(value Viz, LLVMValueRef Global) { return Val_unit; } +/* llvalue -> DLLStorageClass.t */ +CAMLprim value llvm_dll_storage_class(LLVMValueRef Global) { + return Val_int(LLVMGetDLLStorageClass(Global)); +} + +/* DLLStorageClass.t -> llvalue -> unit */ +CAMLprim value llvm_set_dll_storage_class(value Viz, LLVMValueRef Global) { + LLVMSetDLLStorageClass(Global, Int_val(Viz)); + return Val_unit; +} + /* llvalue -> int */ CAMLprim value llvm_alignment(LLVMValueRef Global) { return Val_int(LLVMGetAlignment(Global)); @@ -1151,10 +1218,10 @@ CAMLprim value llvm_gc(LLVMValueRef Fn) { const char *GC; CAMLparam0(); CAMLlocal2(Name, Option); - + if ((GC = LLVMGetGC(Fn))) { - Name = copy_string(GC); - + Name = caml_copy_string(GC); + Option = alloc(1, 0); Field(Option, 0) = Name; CAMLreturn(Option); @@ -1328,6 +1395,25 @@ CAMLprim value llvm_instr_icmp_predicate(LLVMValueRef Val) { CAMLreturn(Val_int(0)); } +/* llvalue -> FCmp.t option */ +CAMLprim value llvm_instr_fcmp_predicate(LLVMValueRef Val) { + CAMLparam0(); + int x = LLVMGetFCmpPredicate(Val); + if (x) { + value Option = alloc(1, 0); + Field(Option, 0) = Val_int(x - LLVMRealPredicateFalse); + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llvalue -> llvalue */ +CAMLprim LLVMValueRef llvm_instr_clone(LLVMValueRef Inst) { + if (!LLVMIsAInstruction(Inst)) + failwith("Not an instruction"); + return LLVMInstructionClone(Inst); +} + /*--... Operations on call sites ...........................................--*/ @@ -1386,6 +1472,43 @@ CAMLprim value llvm_set_volatile(value IsVolatile, return Val_unit; } + +/*--.. Operations on terminators ...........................................--*/ + +/* llvalue -> int -> llbasicblock */ +CAMLprim LLVMBasicBlockRef llvm_successor(LLVMValueRef V, value I) { + return LLVMGetSuccessor(V, Int_val(I)); +} + +/* llvalue -> int -> llvalue -> unit */ +CAMLprim value llvm_set_successor(LLVMValueRef U, value I, LLVMBasicBlockRef B) { + LLVMSetSuccessor(U, Int_val(I), B); + return Val_unit; +} + +/* llvalue -> int */ +CAMLprim value llvm_num_successors(LLVMValueRef V) { + return Val_int(LLVMGetNumSuccessors(V)); +} + +/*--.. Operations on branch ................................................--*/ + +/* llvalue -> llvalue */ +CAMLprim LLVMValueRef llvm_condition(LLVMValueRef V) { + return LLVMGetCondition(V); +} + +/* llvalue -> llvalue -> unit */ +CAMLprim value llvm_set_condition(LLVMValueRef B, LLVMValueRef C) { + LLVMSetCondition(B, C); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_conditional(LLVMValueRef V) { + return Val_bool(LLVMIsConditional(V)); +} + /*--... Operations on phi nodes ............................................--*/ /* (llvalue * llbasicblock) -> llvalue -> unit */ @@ -1402,20 +1525,20 @@ CAMLprim value llvm_incoming(LLVMValueRef PhiNode) { unsigned I; CAMLparam0(); CAMLlocal3(Hd, Tl, Tmp); - + /* Build a tuple list of them. */ Tl = Val_int(0); for (I = LLVMCountIncoming(PhiNode); I != 0; ) { Hd = alloc(2, 0); Store_field(Hd, 0, (value) LLVMGetIncomingValue(PhiNode, --I)); Store_field(Hd, 1, (value) LLVMGetIncomingBlock(PhiNode, I)); - + Tmp = alloc(2, 0); Store_field(Tmp, 0, Hd); Store_field(Tmp, 1, Tl); Tl = Tmp; } - + CAMLreturn(Tl); } @@ -1434,15 +1557,13 @@ static void llvm_finalize_builder(value B) { } static struct custom_operations builder_ops = { - (char *) "LLVMIRBuilder", + (char *) "Llvm.llbuilder", llvm_finalize_builder, custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif + custom_deserialize_default, + custom_compare_ext_default }; static value alloc_builder(LLVMBuilderRef B) { @@ -1472,7 +1593,7 @@ CAMLprim value llvm_position_builder(value Pos, value B) { CAMLprim LLVMBasicBlockRef llvm_insertion_block(value B) { LLVMBasicBlockRef InsertBlock = LLVMGetInsertBlock(Builder_val(B)); if (!InsertBlock) - raise_not_found(); + caml_raise_not_found(); return InsertBlock; } @@ -2048,9 +2169,9 @@ CAMLprim LLVMValueRef llvm_build_fcmp(value Pred, CAMLprim LLVMValueRef llvm_build_phi(value Incoming, value Name, value B) { value Hd, Tl; LLVMValueRef FirstValue, PhiNode; - + assert(Incoming != Val_int(0) && "Empty list passed to Llvm.build_phi!"); - + Hd = Field(Incoming, 0); FirstValue = (LLVMValueRef) Field(Hd, 0); PhiNode = LLVMBuildPhi(Builder_val(B), LLVMTypeOf(FirstValue), @@ -2061,7 +2182,7 @@ CAMLprim LLVMValueRef llvm_build_phi(value Incoming, value Name, value B) { LLVMAddIncoming(PhiNode, (LLVMValueRef*) &Field(Hd, 0), (LLVMBasicBlockRef*) &Field(Hd, 1), 1); } - + return PhiNode; } @@ -2097,7 +2218,7 @@ CAMLprim LLVMValueRef llvm_build_insertelement(LLVMValueRef Vec, LLVMValueRef Element, LLVMValueRef Idx, value Name, value B) { - return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx, + return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx, String_val(Name)); } @@ -2149,11 +2270,11 @@ CAMLprim value llvm_memorybuffer_of_file(value Path) { CAMLparam1(Path); char *Message; LLVMMemoryBufferRef MemBuf; - + if (LLVMCreateMemoryBufferWithContentsOfFile(String_val(Path), &MemBuf, &Message)) - llvm_raise(llvm_ioerror_exn, Message); - + llvm_raise(*caml_named_value("Llvm.IoError"), Message); + CAMLreturn((value) MemBuf); } @@ -2162,22 +2283,23 @@ CAMLprim value llvm_memorybuffer_of_file(value Path) { CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_stdin(value Unit) { char *Message; LLVMMemoryBufferRef MemBuf; - + if (LLVMCreateMemoryBufferWithSTDIN(&MemBuf, &Message)) - llvm_raise(llvm_ioerror_exn, Message); - + llvm_raise(*caml_named_value("Llvm.IoError"), Message); + return MemBuf; } /* ?name:string -> string -> llmemorybuffer */ CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_string(value Name, value String) { + LLVMMemoryBufferRef MemBuf; const char *NameCStr; + if(Name == Val_int(0)) NameCStr = ""; else NameCStr = String_val(Field(Name, 0)); - LLVMMemoryBufferRef MemBuf; MemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy( String_val(String), caml_string_length(String), NameCStr); diff --git a/bindings/ocaml/target/llvm_target.ml b/bindings/ocaml/target/llvm_target.ml index 974bd49..bd7388e 100644 --- a/bindings/ocaml/target/llvm_target.ml +++ b/bindings/ocaml/target/llvm_target.ml @@ -47,8 +47,7 @@ end exception Error of string -external register_exns : exn -> unit = "llvm_register_target_exns" -let _ = register_exns (Error "") +let () = Callback.register_exception "Llvm_target.Error" (Error "") module DataLayout = struct type t @@ -127,6 +126,8 @@ module TargetMachine = struct = "llvm_targetmachine_features" external data_layout : t -> DataLayout.t = "llvm_targetmachine_data_layout" + external add_analysis_passes : [< Llvm.PassManager.any ] Llvm.PassManager.t -> t -> unit + = "llvm_targetmachine_add_analysis_passes" external set_verbose_asm : bool -> t -> unit = "llvm_targetmachine_set_verbose_asm" external emit_to_file : Llvm.llmodule -> CodeGenFileType.t -> string -> diff --git a/bindings/ocaml/target/llvm_target.mli b/bindings/ocaml/target/llvm_target.mli index 4f5e717..676bc61 100644 --- a/bindings/ocaml/target/llvm_target.mli +++ b/bindings/ocaml/target/llvm_target.mli @@ -67,7 +67,7 @@ module DataLayout : sig See the method [llvm::DataLayout::getStringRepresentation]. *) val as_string : t -> string - (** [add_to_pass_manager dl pm] adds the target data [dl] to + (** [add_to_pass_manager pm dl] adds the data layout [dl] to the pass manager [pm]. See the method [llvm::PassManagerBase::add]. *) val add_to_pass_manager : [<Llvm.PassManager.any] Llvm.PassManager.t -> @@ -207,6 +207,10 @@ module TargetMachine : sig (** Returns the data layout of this target machine. *) val data_layout : t -> DataLayout.t + (** Adds the target-specific analysis passes to the pass manager. + See [llvm::TargetMachine::addAnalysisPasses]. *) + val add_analysis_passes : [< Llvm.PassManager.any ] Llvm.PassManager.t -> t -> unit + (** Sets the assembly verbosity of this target machine. See [llvm::TargetMachine::setAsmVerbosity]. *) val set_verbose_asm : bool -> t -> unit diff --git a/bindings/ocaml/target/target_ocaml.c b/bindings/ocaml/target/target_ocaml.c index 74e8185..8f77cb4 100644 --- a/bindings/ocaml/target/target_ocaml.c +++ b/bindings/ocaml/target/target_ocaml.c @@ -21,37 +21,10 @@ #include "caml/fail.h" #include "caml/memory.h" #include "caml/custom.h" +#include "caml/callback.h" -/*===---- Exceptions ------------------------------------------------------===*/ - -static value llvm_target_error_exn; - -CAMLprim value llvm_register_target_exns(value Error) { - llvm_target_error_exn = Field(Error, 0); - register_global_root(&llvm_target_error_exn); - return Val_unit; -} - -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif -} - -static value llvm_string_of_message(char* Message) { - value String = caml_copy_string(Message); - LLVMDisposeMessage(Message); - - return String; -} +void llvm_raise(value Prototype, char *Message); +value llvm_string_of_message(char* Message); /*===---- Data Layout -----------------------------------------------------===*/ @@ -62,15 +35,13 @@ static void llvm_finalize_data_layout(value DataLayout) { } static struct custom_operations llvm_data_layout_ops = { - (char *) "LLVMDataLayout", + (char *) "Llvm_target.DataLayout.t", llvm_finalize_data_layout, custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif + custom_deserialize_default, + custom_compare_ext_default }; value llvm_alloc_data_layout(LLVMTargetDataRef DataLayout) { @@ -219,7 +190,7 @@ CAMLprim LLVMTargetRef llvm_target_by_triple(value Triple) { char *Error; if(LLVMGetTargetFromTriple(String_val(Triple), &T, &Error)) - llvm_raise(llvm_target_error_exn, Error); + llvm_raise(*caml_named_value("Llvm_target.Error"), Error); return T; } @@ -258,15 +229,13 @@ static void llvm_finalize_target_machine(value Machine) { } static struct custom_operations llvm_target_machine_ops = { - (char *) "LLVMTargetMachine", + (char *) "Llvm_target.TargetMachine.t", llvm_finalize_target_machine, custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif + custom_deserialize_default, + custom_compare_ext_default }; static value llvm_alloc_targetmachine(LLVMTargetMachineRef Machine) { @@ -337,6 +306,7 @@ CAMLprim value llvm_targetmachine_features(value Machine) { CAMLprim value llvm_targetmachine_data_layout(value Machine) { CAMLparam1(Machine); CAMLlocal1(DataLayout); + char *TargetDataCStr; /* LLVMGetTargetMachineData returns a pointer owned by the TargetMachine, so it is impossible to wrap it with llvm_alloc_target_data, which assumes @@ -344,7 +314,6 @@ CAMLprim value llvm_targetmachine_data_layout(value Machine) { LLVMTargetDataRef OrigDataLayout; OrigDataLayout = LLVMGetTargetMachineData(TargetMachine_val(Machine)); - char* TargetDataCStr; TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); LLVMDisposeMessage(TargetDataCStr); @@ -361,12 +330,12 @@ CAMLprim value llvm_targetmachine_set_verbose_asm(value Verb, value Machine) { /* Llvm.llmodule -> CodeGenFileType.t -> string -> TargetMachine.t -> unit */ CAMLprim value llvm_targetmachine_emit_to_file(LLVMModuleRef Module, value FileType, value FileName, value Machine) { - char* ErrorMessage; + char *ErrorMessage; if(LLVMTargetMachineEmitToFile(TargetMachine_val(Machine), Module, String_val(FileName), Int_val(FileType), &ErrorMessage)) { - llvm_raise(llvm_target_error_exn, ErrorMessage); + llvm_raise(*caml_named_value("Llvm_target.Error"), ErrorMessage); } return Val_unit; @@ -377,14 +346,21 @@ CAMLprim value llvm_targetmachine_emit_to_file(LLVMModuleRef Module, CAMLprim LLVMMemoryBufferRef llvm_targetmachine_emit_to_memory_buffer( LLVMModuleRef Module, value FileType, value Machine) { - char* ErrorMessage; + char *ErrorMessage; LLVMMemoryBufferRef Buffer; if(LLVMTargetMachineEmitToMemoryBuffer(TargetMachine_val(Machine), Module, Int_val(FileType), &ErrorMessage, &Buffer)) { - llvm_raise(llvm_target_error_exn, ErrorMessage); + llvm_raise(*caml_named_value("Llvm_target.Error"), ErrorMessage); } return Buffer; } + +/* TargetMachine.t -> Llvm.PassManager.t -> unit */ +CAMLprim value llvm_targetmachine_add_analysis_passes(LLVMPassManagerRef PM, + value Machine) { + LLVMAddAnalysisPasses(TargetMachine_val(Machine), PM); + return Val_unit; +} diff --git a/bindings/ocaml/transforms/Makefile b/bindings/ocaml/transforms/Makefile index 92c8396..f3637a6 100644 --- a/bindings/ocaml/transforms/Makefile +++ b/bindings/ocaml/transforms/Makefile @@ -8,7 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL := ../../.. -DIRS = scalar ipo vectorize passmgr_builder +DIRS = scalar_opts ipo vectorize passmgr_builder ocamldoc: $(Verb) for i in $(DIRS) ; do \ diff --git a/bindings/ocaml/transforms/ipo/Makefile b/bindings/ocaml/transforms/ipo/Makefile index ed67a7c..f54bc4e 100644 --- a/bindings/ocaml/transforms/ipo/Makefile +++ b/bindings/ocaml/transforms/ipo/Makefile @@ -1,4 +1,4 @@ -##===- bindings/ocaml/transforms/scalar/Makefile -----------*- Makefile -*-===## +##===- bindings/ocaml/transforms/ipo/Makefile --------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## # -# This is the makefile for the Objective Caml Llvm_scalar_opts interface. +# This is the makefile for the Objective Caml Llvm_ipo interface. # ##===----------------------------------------------------------------------===## diff --git a/bindings/ocaml/transforms/ipo/ipo_ocaml.c b/bindings/ocaml/transforms/ipo/ipo_ocaml.c index 4ad8afb..9d8fb1e 100644 --- a/bindings/ocaml/transforms/ipo/ipo_ocaml.c +++ b/bindings/ocaml/transforms/ipo/ipo_ocaml.c @@ -56,12 +56,6 @@ CAMLprim value llvm_add_always_inliner(LLVMPassManagerRef PM) { } /* [`Module] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_always_inliner_pass(LLVMPassManagerRef PM) { - LLVMAddAlwaysInlinerPass(PM); - return Val_unit; -} - -/* [`Module] Llvm.PassManager.t -> unit */ CAMLprim value llvm_add_global_dce(LLVMPassManagerRef PM) { LLVMAddGlobalDCEPass(PM); return Val_unit; @@ -74,7 +68,7 @@ CAMLprim value llvm_add_global_optimizer(LLVMPassManagerRef PM) { } /* [`Module] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_ipc_propagation(LLVMPassManagerRef PM) { +CAMLprim value llvm_add_ip_constant_propagation(LLVMPassManagerRef PM) { LLVMAddIPConstantPropagationPass(PM); return Val_unit; } @@ -91,7 +85,7 @@ CAMLprim value llvm_add_ipsccp(LLVMPassManagerRef PM) { return Val_unit; } -/* [`Module] Llvm.PassManager.t -> bool -> unit */ +/* [`Module] Llvm.PassManager.t -> all_but_main:bool -> unit */ CAMLprim value llvm_add_internalize(LLVMPassManagerRef PM, value AllButMain) { LLVMAddInternalizePass(PM, Bool_val(AllButMain)); return Val_unit; diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.ml b/bindings/ocaml/transforms/ipo/llvm_ipo.ml index 93f564a..1af7d67 100644 --- a/bindings/ocaml/transforms/ipo/llvm_ipo.ml +++ b/bindings/ocaml/transforms/ipo/llvm_ipo.ml @@ -7,31 +7,45 @@ * *===----------------------------------------------------------------------===*) -external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_argument_promotion" -external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_constant_merge" -external add_dead_arg_elimination : - [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination" -external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_function_attrs" -external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_function_inlining" -external add_always_inliner : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_always_inliner" -external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_global_dce" -external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_global_optimizer" -external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_ipc_propagation" -external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_prune_eh" -external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_ipsccp" -external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit = - "llvm_add_internalize" -external add_strip_dead_prototypes : - [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes" -external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_strip_symbols" +external add_argument_promotion + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_argument_promotion" +external add_constant_merge + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_constant_merge" +external add_dead_arg_elimination + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_dead_arg_elimination" +external add_function_attrs + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_function_attrs" +external add_function_inlining + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_function_inlining" +external add_always_inliner + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_always_inliner" +external add_global_dce + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_global_dce" +external add_global_optimizer + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_global_optimizer" +external add_ipc_propagation + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_ip_constant_propagation" +external add_prune_eh + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_prune_eh" +external add_ipsccp + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_ipsccp" +external add_internalize + : [ `Module ] Llvm.PassManager.t -> all_but_main:bool -> unit + = "llvm_add_internalize" +external add_strip_dead_prototypes + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_strip_dead_prototypes" +external add_strip_symbols + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_strip_symbols" diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.mli b/bindings/ocaml/transforms/ipo/llvm_ipo.mli index 1944c30..09a4860 100644 --- a/bindings/ocaml/transforms/ipo/llvm_ipo.mli +++ b/bindings/ocaml/transforms/ipo/llvm_ipo.mli @@ -12,58 +12,72 @@ This interface provides an OCaml API for LLVM interprocedural optimizations, the classes in the [LLVMIPO] library. *) -(** See llvm::createAddArgumentPromotionPass *) -external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_argument_promotion" - -(** See llvm::createConstantMergePass function. *) -external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_constant_merge" - -(** See llvm::createDeadArgEliminationPass function. *) -external add_dead_arg_elimination : - [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination" - -(** See llvm::createFunctionAttrsPass function. *) -external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_function_attrs" - -(** See llvm::createFunctionInliningPass function. *) -external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_function_inlining" - -(** See llvm::createAlwaysInlinerPass function. *) -external add_always_inliner : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_always_inliner" - -(** See llvm::createGlobalDCEPass function. *) -external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_global_dce" - -(** See llvm::createGlobalOptimizerPass function. *) -external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_global_optimizer" - -(** See llvm::createIPConstantPropagationPass function. *) -external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_ipc_propagation" - -(** See llvm::createPruneEHPass function. *) -external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_prune_eh" - -(** See llvm::createIPSCCPPass function. *) -external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_ipsccp" - -(** See llvm::createInternalizePass function. *) -external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit = - "llvm_add_internalize" - -(** See llvm::createStripDeadPrototypesPass function. *) -external add_strip_dead_prototypes : - [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes" - -(** See llvm::createStripSymbolsPass function. *) -external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_strip_symbols" +(** See the [llvm::createAddArgumentPromotionPass] function. *) +external add_argument_promotion + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_argument_promotion" + +(** See the [llvm::createConstantMergePass] function. *) +external add_constant_merge + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_constant_merge" + +(** See the [llvm::createDeadArgEliminationPass] function. *) +external add_dead_arg_elimination + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_dead_arg_elimination" + +(** See the [llvm::createFunctionAttrsPass] function. *) +external add_function_attrs + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_function_attrs" + +(** See the [llvm::createFunctionInliningPass] function. *) +external add_function_inlining + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_function_inlining" + +(** See the [llvm::createAlwaysInlinerPass] function. *) +external add_always_inliner + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_always_inliner" + +(** See the [llvm::createGlobalDCEPass] function. *) +external add_global_dce + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_global_dce" + +(** See the [llvm::createGlobalOptimizerPass] function. *) +external add_global_optimizer + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_global_optimizer" + +(** See the [llvm::createIPConstantPropagationPass] function. *) +external add_ipc_propagation + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_ip_constant_propagation" + +(** See the [llvm::createPruneEHPass] function. *) +external add_prune_eh + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_prune_eh" + +(** See the [llvm::createIPSCCPPass] function. *) +external add_ipsccp + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_ipsccp" + +(** See the [llvm::createInternalizePass] function. *) +external add_internalize + : [ `Module ] Llvm.PassManager.t -> all_but_main:bool -> unit + = "llvm_add_internalize" + +(** See the [llvm::createStripDeadPrototypesPass] function. *) +external add_strip_dead_prototypes + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_strip_dead_prototypes" + +(** See the [llvm::createStripSymbolsPass] function. *) +external add_strip_symbols + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_strip_symbols" diff --git a/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli index 66b0981..ce162b1 100644 --- a/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli +++ b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli @@ -14,41 +14,41 @@ type t -(** See [llvm::PassManagerBuilder]. *) +(** See the [llvm::PassManagerBuilder] function. *) external create : unit -> t = "llvm_pmbuilder_create" -(** See [llvm::PassManagerBuilder::OptLevel]. *) +(** See the [llvm::PassManagerBuilder::OptLevel] function. *) external set_opt_level : int -> t -> unit = "llvm_pmbuilder_set_opt_level" -(** See [llvm::PassManagerBuilder::SizeLevel]. *) +(** See the [llvm::PassManagerBuilder::SizeLevel] function. *) external set_size_level : int -> t -> unit = "llvm_pmbuilder_set_size_level" -(** See [llvm::PassManagerBuilder::DisableUnitAtATime]. *) +(** See the [llvm::PassManagerBuilder::DisableUnitAtATime] function. *) external set_disable_unit_at_a_time : bool -> t -> unit = "llvm_pmbuilder_set_disable_unit_at_a_time" -(** See [llvm::PassManagerBuilder::DisableUnrollLoops]. *) +(** See the [llvm::PassManagerBuilder::DisableUnrollLoops] function. *) external set_disable_unroll_loops : bool -> t -> unit = "llvm_pmbuilder_set_disable_unroll_loops" -(** See [llvm::PassManagerBuilder::Inliner]. *) +(** See the [llvm::PassManagerBuilder::Inliner] function. *) external use_inliner_with_threshold : int -> t -> unit = "llvm_pmbuilder_use_inliner_with_threshold" -(** See [llvm::PassManagerBuilder::populateFunctionPassManager]. *) +(** See the [llvm::PassManagerBuilder::populateFunctionPassManager] function. *) external populate_function_pass_manager : [ `Function ] Llvm.PassManager.t -> t -> unit = "llvm_pmbuilder_populate_function_pass_manager" -(** See [llvm::PassManagerBuilder::populateModulePassManager]. *) +(** See the [llvm::PassManagerBuilder::populateModulePassManager] function. *) external populate_module_pass_manager : [ `Module ] Llvm.PassManager.t -> t -> unit = "llvm_pmbuilder_populate_module_pass_manager" -(** See [llvm::PassManagerBuilder::populateLTOPassManager]. *) +(** See the [llvm::PassManagerBuilder::populateLTOPassManager] function. *) external populate_lto_pass_manager : [ `Module ] Llvm.PassManager.t -> internalize:bool -> run_inliner:bool -> t -> unit - = "llvm_pmbuilder_populate_lto_pass_manager"
\ No newline at end of file + = "llvm_pmbuilder_populate_lto_pass_manager" diff --git a/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c b/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c index a707856..a43863c 100644 --- a/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c +++ b/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c @@ -27,15 +27,13 @@ static void llvm_finalize_pmbuilder(value PMB) { } static struct custom_operations pmbuilder_ops = { - (char *) "LLVMPassManagerBuilder", + (char *) "Llvm_passmgr_builder.t", llvm_finalize_pmbuilder, custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif + custom_deserialize_default, + custom_compare_ext_default }; static value alloc_pmbuilder(LLVMPassManagerBuilderRef Ref) { diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml deleted file mode 100644 index 958939d..0000000 --- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml +++ /dev/null @@ -1,114 +0,0 @@ -(*===-- llvm_scalar_opts.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. - * - *===----------------------------------------------------------------------===*) - -external add_constant_propagation : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_constant_propagation" -external add_sccp : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_sccp" -external add_dead_store_elimination : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_dead_store_elimination" -external add_aggressive_dce : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_aggressive_dce" -external -add_scalar_repl_aggregation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_scalar_repl_aggregation" - -external -add_scalar_repl_aggregation_ssa : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_scalar_repl_aggregation_ssa" - -external -add_scalar_repl_aggregation_with_threshold : int -> [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_scalar_repl_aggregation_with_threshold" -external add_ind_var_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_ind_var_simplification" -external -add_instruction_combination : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_instruction_combination" -external add_licm : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_licm" -external add_loop_unswitch : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_unswitch" -external add_loop_unroll : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_unroll" -external add_loop_rotation : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_rotation" -external -add_memory_to_register_promotion : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_memory_to_register_promotion" -external -add_memory_to_register_demotion : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_memory_to_register_demotion" -external add_reassociation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_reassociation" -external add_jump_threading : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_jump_threading" -external add_cfg_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_cfg_simplification" -external -add_tail_call_elimination : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_tail_call_elimination" -external add_gvn : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_gvn" -external add_memcpy_opt : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_memcpy_opt" -external add_loop_deletion : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_deletion" - -external add_loop_idiom : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_idiom" - -external -add_lib_call_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_lib_call_simplification" - -external -add_verifier : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_verifier" - -external -add_correlated_value_propagation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_correlated_value_propagation" - -external -add_early_cse : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_early_cse" - -external -add_lower_expect_intrinsic : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_lower_expect_intrinsic" - -external -add_type_based_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_type_based_alias_analysis" - -external -add_basic_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_basic_alias_analysis" - -external -add_partially_inline_lib_calls : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_partially_inline_lib_calls" diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli deleted file mode 100644 index ab6fa4a..0000000 --- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli +++ /dev/null @@ -1,168 +0,0 @@ -(*===-- llvm_scalar_opts.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. - * - *===----------------------------------------------------------------------===*) - -(** Scalar Transforms. - - This interface provides an OCaml API for LLVM scalar transforms, the - classes in the [LLVMScalarOpts] library. *) - -(** See the [llvm::createConstantPropagationPass] function. *) -external add_constant_propagation : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_constant_propagation" - -(** See the [llvm::createSCCPPass] function. *) -external add_sccp : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_sccp" - -(** See [llvm::createDeadStoreEliminationPass] function. *) -external add_dead_store_elimination : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_dead_store_elimination" - -(** See The [llvm::createAggressiveDCEPass] function. *) -external add_aggressive_dce : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_aggressive_dce" - -(** See the [llvm::createScalarReplAggregatesPass] function. *) -external -add_scalar_repl_aggregation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_scalar_repl_aggregation" - -(** See the [llvm::createScalarReplAggregatesPassSSA] function. *) -external -add_scalar_repl_aggregation_ssa : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_scalar_repl_aggregation_ssa" - -(** See the [llvm::createScalarReplAggregatesWithThreshold] function. *) -external -add_scalar_repl_aggregation_with_threshold : int -> [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_scalar_repl_aggregation_with_threshold" - -(** See the [llvm::createIndVarSimplifyPass] function. *) -external add_ind_var_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_ind_var_simplification" - -(** See the [llvm::createInstructionCombiningPass] function. *) -external -add_instruction_combination : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_instruction_combination" - -(** See the [llvm::createLICMPass] function. *) -external add_licm : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_licm" - -(** See the [llvm::createLoopUnswitchPass] function. *) -external add_loop_unswitch : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_unswitch" - -(** See the [llvm::createLoopUnrollPass] function. *) -external add_loop_unroll : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_unroll" - -(** See the [llvm::createLoopRotatePass] function. *) -external add_loop_rotation : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_rotation" - -(** See the [llvm::createPromoteMemoryToRegisterPass] function. *) -external -add_memory_to_register_promotion : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_memory_to_register_promotion" - -(** See the [llvm::createDemoteMemoryToRegisterPass] function. *) -external -add_memory_to_register_demotion : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_memory_to_register_demotion" - -(** See the [llvm::createReassociatePass] function. *) -external add_reassociation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_reassociation" - -(** See the [llvm::createJumpThreadingPass] function. *) -external add_jump_threading : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_jump_threading" - -(** See the [llvm::createCFGSimplificationPass] function. *) -external add_cfg_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_cfg_simplification" - -(** See the [llvm::createTailCallEliminationPass] function. *) -external -add_tail_call_elimination : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_tail_call_elimination" - -(** See the [llvm::createGVNPass] function. *) -external add_gvn : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_gvn" - -(** See the [llvm::createMemCpyOptPass] function. *) -external add_memcpy_opt : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_memcpy_opt" - -(** See the [llvm::createLoopDeletionPass] function. *) -external add_loop_deletion : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_deletion" - -external add_loop_idiom : [<Llvm.PassManager.any] Llvm.PassManager.t - -> unit - = "llvm_add_loop_idiom" - -(** See the [llvm::createSimplifyLibCallsPass] function. *) -external -add_lib_call_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_lib_call_simplification" - -(** See the [llvm::createVerifierPass] function. *) -external -add_verifier : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_verifier" - -(** See the [llvm::createCorrelatedValuePropagationPass] function. *) -external -add_correlated_value_propagation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_correlated_value_propagation" - -(** See the [llvm::createEarlyCSE] function. *) -external -add_early_cse : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_early_cse" - -(** See the [llvm::createLowerExpectIntrinsicPass] function. *) -external -add_lower_expect_intrinsic : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_lower_expect_intrinsic" - -(** See the [llvm::createTypeBasedAliasAnalysisPass] function. *) -external -add_type_based_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_type_based_alias_analysis" - -(** See the [llvm::createBasicAliasAnalysisPass] function. *) -external -add_basic_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_basic_alias_analysis" - -(** See the [llvm::createPartiallyInlineLibCallsPass] function. *) -external -add_partially_inline_lib_calls : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_partially_inline_lib_calls" diff --git a/bindings/ocaml/transforms/scalar/Makefile b/bindings/ocaml/transforms/scalar_opts/Makefile index 6e250f6..63d86a6 100644 --- a/bindings/ocaml/transforms/scalar/Makefile +++ b/bindings/ocaml/transforms/scalar_opts/Makefile @@ -1,4 +1,4 @@ -##===- bindings/ocaml/transforms/scalar/Makefile -----------*- Makefile -*-===## +##===- bindings/ocaml/transforms/scalar_opts/Makefile ------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # diff --git a/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.ml b/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.ml new file mode 100644 index 0000000..b90d0ae --- /dev/null +++ b/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.ml @@ -0,0 +1,120 @@ +(*===-- llvm_scalar_opts.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. + * + *===----------------------------------------------------------------------===*) + +external add_aggressive_dce + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_aggressive_dce" +external add_alignment_from_assumptions + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_alignment_from_assumptions" +external add_cfg_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_cfg_simplification" +external add_dead_store_elimination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_dead_store_elimination" +external add_scalarizer + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalarizer" +external add_merged_load_store_motion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_merged_load_store_motion" +external add_gvn + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_gvn" +external add_ind_var_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_ind_var_simplify" +external add_instruction_combination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_instruction_combining" +external add_jump_threading + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_jump_threading" +external add_licm + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_licm" +external add_loop_deletion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_deletion" +external add_loop_idiom + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_idiom" +external add_loop_rotation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_rotate" +external add_loop_reroll + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_reroll" +external add_loop_unroll + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_unroll" +external add_loop_unswitch + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_unswitch" +external add_memcpy_opt + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_memcpy_opt" +external add_partially_inline_lib_calls + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_partially_inline_lib_calls" +external add_lower_switch + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_switch" +external add_memory_to_register_promotion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_promote_memory_to_register" +external add_reassociation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_reassociation" +external add_sccp + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_sccp" +external add_scalar_repl_aggregation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates" +external add_scalar_repl_aggregation_ssa + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates_ssa" +external add_scalar_repl_aggregation_with_threshold + : int -> [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates_with_threshold" +external add_lib_call_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_simplify_lib_calls" +external add_tail_call_elimination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_tail_call_elimination" +external add_constant_propagation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_constant_propagation" +external add_memory_to_register_demotion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_demote_memory_to_register" +external add_verifier + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_verifier" +external add_correlated_value_propagation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_correlated_value_propagation" +external add_early_cse + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_early_cse" +external add_lower_expect_intrinsic + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_expect_intrinsic" +external add_type_based_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_type_based_alias_analysis" +external add_scoped_no_alias_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scoped_no_alias_aa" +external add_basic_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_basic_alias_analysis" diff --git a/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli b/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli new file mode 100644 index 0000000..b4cefed --- /dev/null +++ b/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli @@ -0,0 +1,198 @@ +(*===-- llvm_scalar_opts.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. + * + *===----------------------------------------------------------------------===*) + +(** Scalar Transforms. + + This interface provides an OCaml API for LLVM scalar transforms, the + classes in the [LLVMScalarOpts] library. *) + +(** See the [llvm::createAggressiveDCEPass] function. *) +external add_aggressive_dce + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_aggressive_dce" + +(** See the [llvm::createAlignmentFromAssumptionsPass] function. *) +external add_alignment_from_assumptions + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_alignment_from_assumptions" + +(** See the [llvm::createCFGSimplificationPass] function. *) +external add_cfg_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_cfg_simplification" + +(** See [llvm::createDeadStoreEliminationPass] function. *) +external add_dead_store_elimination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_dead_store_elimination" + +(** See [llvm::createScalarizerPass] function. *) +external add_scalarizer + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalarizer" + +(** See [llvm::createMergedLoadStoreMotionPass] function. *) +external add_merged_load_store_motion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_merged_load_store_motion" + +(** See the [llvm::createGVNPass] function. *) +external add_gvn + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_gvn" + +(** See the [llvm::createIndVarSimplifyPass] function. *) +external add_ind_var_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_ind_var_simplify" + +(** See the [llvm::createInstructionCombiningPass] function. *) +external add_instruction_combination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_instruction_combining" + +(** See the [llvm::createJumpThreadingPass] function. *) +external add_jump_threading + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_jump_threading" + +(** See the [llvm::createLICMPass] function. *) +external add_licm + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_licm" + +(** See the [llvm::createLoopDeletionPass] function. *) +external add_loop_deletion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_deletion" + +(** See the [llvm::createLoopIdiomPass] function. *) +external add_loop_idiom + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_idiom" + +(** See the [llvm::createLoopRotatePass] function. *) +external add_loop_rotation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_rotate" + +(** See the [llvm::createLoopRerollPass] function. *) +external add_loop_reroll + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_reroll" + +(** See the [llvm::createLoopUnrollPass] function. *) +external add_loop_unroll + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_unroll" + +(** See the [llvm::createLoopUnswitchPass] function. *) +external add_loop_unswitch + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_unswitch" + +(** See the [llvm::createMemCpyOptPass] function. *) +external add_memcpy_opt + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_memcpy_opt" + +(** See the [llvm::createPartiallyInlineLibCallsPass] function. *) +external add_partially_inline_lib_calls + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_partially_inline_lib_calls" + +(** See the [llvm::createLowerSwitchPass] function. *) +external add_lower_switch + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_switch" + +(** See the [llvm::createPromoteMemoryToRegisterPass] function. *) +external add_memory_to_register_promotion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_promote_memory_to_register" + +(** See the [llvm::createReassociatePass] function. *) +external add_reassociation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_reassociation" + +(** See the [llvm::createSCCPPass] function. *) +external add_sccp + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_sccp" + +(** See the [llvm::createScalarReplAggregatesPass] function. *) +external add_scalar_repl_aggregation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates" + +(** See the [llvm::createScalarReplAggregatesPassSSA] function. *) +external add_scalar_repl_aggregation_ssa + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates_ssa" + +(** See the [llvm::createScalarReplAggregatesWithThreshold] function. *) +external add_scalar_repl_aggregation_with_threshold + : int -> [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates_with_threshold" + +(** See the [llvm::createSimplifyLibCallsPass] function. *) +external add_lib_call_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_simplify_lib_calls" + +(** See the [llvm::createTailCallEliminationPass] function. *) +external add_tail_call_elimination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_tail_call_elimination" + +(** See the [llvm::createConstantPropagationPass] function. *) +external add_constant_propagation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_constant_propagation" + +(** See the [llvm::createDemoteMemoryToRegisterPass] function. *) +external add_memory_to_register_demotion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_demote_memory_to_register" + +(** See the [llvm::createVerifierPass] function. *) +external add_verifier + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_verifier" + +(** See the [llvm::createCorrelatedValuePropagationPass] function. *) +external add_correlated_value_propagation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_correlated_value_propagation" + +(** See the [llvm::createEarlyCSE] function. *) +external add_early_cse + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_early_cse" + +(** See the [llvm::createLowerExpectIntrinsicPass] function. *) +external add_lower_expect_intrinsic + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_expect_intrinsic" + +(** See the [llvm::createTypeBasedAliasAnalysisPass] function. *) +external add_type_based_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_type_based_alias_analysis" + +(** See the [llvm::createScopedNoAliasAAPass] function. *) +external add_scoped_no_alias_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scoped_no_alias_aa" + +(** See the [llvm::createBasicAliasAnalysisPass] function. *) +external add_basic_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_basic_alias_analysis" diff --git a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c b/bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c index 0a71bd7..bae4e31 100644 --- a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c +++ b/bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c @@ -20,69 +20,92 @@ #include "caml/misc.h" /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_constant_propagation(LLVMPassManagerRef PM) { - LLVMAddConstantPropagationPass(PM); +CAMLprim value llvm_add_aggressive_dce(LLVMPassManagerRef PM) { + LLVMAddAggressiveDCEPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_sccp(LLVMPassManagerRef PM) { - LLVMAddSCCPPass(PM); +CAMLprim value llvm_add_alignment_from_assumptions(LLVMPassManagerRef PM) { + LLVMAddAlignmentFromAssumptionsPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_dead_store_elimination(LLVMPassManagerRef PM) { - LLVMAddDeadStoreEliminationPass(PM); +CAMLprim value llvm_add_cfg_simplification(LLVMPassManagerRef PM) { + LLVMAddCFGSimplificationPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_aggressive_dce(LLVMPassManagerRef PM) { - LLVMAddAggressiveDCEPass(PM); +CAMLprim value llvm_add_dead_store_elimination(LLVMPassManagerRef PM) { + LLVMAddDeadStoreEliminationPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_scalar_repl_aggregation(LLVMPassManagerRef PM) { - LLVMAddScalarReplAggregatesPass(PM); +CAMLprim value llvm_add_scalarizer(LLVMPassManagerRef PM) { + LLVMAddScalarizerPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_scalar_repl_aggregation_ssa(LLVMPassManagerRef PM) { - LLVMAddScalarReplAggregatesPassSSA(PM); +CAMLprim value llvm_add_merged_load_store_motion(LLVMPassManagerRef PM) { + LLVMAddMergedLoadStoreMotionPass(PM); return Val_unit; } -/* [<Llvm.PassManager.any] Llvm.PassManager.t -> int -> unit */ -CAMLprim value llvm_add_scalar_repl_aggregation_with_threshold(value threshold, - LLVMPassManagerRef PM) { - LLVMAddScalarReplAggregatesPassWithThreshold(PM, Int_val(threshold)); +/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_gvn(LLVMPassManagerRef PM) { + LLVMAddGVNPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_ind_var_simplification(LLVMPassManagerRef PM) { +CAMLprim value llvm_add_ind_var_simplify(LLVMPassManagerRef PM) { LLVMAddIndVarSimplifyPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_instruction_combination(LLVMPassManagerRef PM) { +CAMLprim value llvm_add_instruction_combining(LLVMPassManagerRef PM) { LLVMAddInstructionCombiningPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_jump_threading(LLVMPassManagerRef PM) { + LLVMAddJumpThreadingPass(PM); + return Val_unit; +} + +/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ CAMLprim value llvm_add_licm(LLVMPassManagerRef PM) { LLVMAddLICMPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) { - LLVMAddLoopUnswitchPass(PM); +CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) { + LLVMAddLoopDeletionPass(PM); + return Val_unit; +} + +/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_loop_idiom(LLVMPassManagerRef PM) { + LLVMAddLoopIdiomPass(PM); + return Val_unit; +} + +/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_loop_rotate(LLVMPassManagerRef PM) { + LLVMAddLoopRotatePass(PM); + return Val_unit; +} + +/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_loop_reroll(LLVMPassManagerRef PM) { + LLVMAddLoopRerollPass(PM); return Val_unit; } @@ -93,20 +116,32 @@ CAMLprim value llvm_add_loop_unroll(LLVMPassManagerRef PM) { } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_loop_rotation(LLVMPassManagerRef PM) { - LLVMAddLoopRotatePass(PM); +CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) { + LLVMAddLoopUnswitchPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_memory_to_register_promotion(LLVMPassManagerRef PM) { - LLVMAddPromoteMemoryToRegisterPass(PM); +CAMLprim value llvm_add_memcpy_opt(LLVMPassManagerRef PM) { + LLVMAddMemCpyOptPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_memory_to_register_demotion(LLVMPassManagerRef PM) { - LLVMAddDemoteMemoryToRegisterPass(PM); +CAMLprim value llvm_add_partially_inline_lib_calls(LLVMPassManagerRef PM) { + LLVMAddPartiallyInlineLibCallsPass(PM); + return Val_unit; +} + +/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_lower_switch(LLVMPassManagerRef PM) { + LLVMAddLowerSwitchPass(PM); + return Val_unit; +} + +/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_promote_memory_to_register(LLVMPassManagerRef PM) { + LLVMAddPromoteMemoryToRegisterPass(PM); return Val_unit; } @@ -117,50 +152,51 @@ CAMLprim value llvm_add_reassociation(LLVMPassManagerRef PM) { } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_jump_threading(LLVMPassManagerRef PM) { - LLVMAddJumpThreadingPass(PM); +CAMLprim value llvm_add_sccp(LLVMPassManagerRef PM) { + LLVMAddSCCPPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_cfg_simplification(LLVMPassManagerRef PM) { - LLVMAddCFGSimplificationPass(PM); +CAMLprim value llvm_add_scalar_repl_aggregates(LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_tail_call_elimination(LLVMPassManagerRef PM) { - LLVMAddTailCallEliminationPass(PM); +CAMLprim value llvm_add_scalar_repl_aggregates_ssa(LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPassSSA(PM); return Val_unit; } -/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_gvn(LLVMPassManagerRef PM) { - LLVMAddGVNPass(PM); +/* int -> [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_scalar_repl_aggregates_with_threshold(value threshold, + LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPassWithThreshold(PM, Int_val(threshold)); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_memcpy_opt(LLVMPassManagerRef PM) { - LLVMAddMemCpyOptPass(PM); +CAMLprim value llvm_add_simplify_lib_calls(LLVMPassManagerRef PM) { + LLVMAddSimplifyLibCallsPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) { - LLVMAddLoopDeletionPass(PM); +CAMLprim value llvm_add_tail_call_elimination(LLVMPassManagerRef PM) { + LLVMAddTailCallEliminationPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_loop_idiom(LLVMPassManagerRef PM) { - LLVMAddLoopIdiomPass(PM); +CAMLprim value llvm_add_constant_propagation(LLVMPassManagerRef PM) { + LLVMAddConstantPropagationPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_lib_call_simplification(LLVMPassManagerRef PM) { - LLVMAddSimplifyLibCallsPass(PM); +CAMLprim value llvm_add_demote_memory_to_register(LLVMPassManagerRef PM) { + LLVMAddDemoteMemoryToRegisterPass(PM); return Val_unit; } @@ -195,13 +231,13 @@ CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) { } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_basic_alias_analysis(LLVMPassManagerRef PM) { - LLVMAddBasicAliasAnalysisPass(PM); +CAMLprim value llvm_add_scoped_no_alias_aa(LLVMPassManagerRef PM) { + LLVMAddScopedNoAliasAAPass(PM); return Val_unit; } /* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_partially_inline_lib_calls(LLVMPassManagerRef PM) { - LLVMAddPartiallyInlineLibCallsPass(PM); +CAMLprim value llvm_add_basic_alias_analysis(LLVMPassManagerRef PM) { + LLVMAddBasicAliasAnalysisPass(PM); return Val_unit; } diff --git a/bindings/ocaml/transforms/vectorize/Makefile b/bindings/ocaml/transforms/vectorize/Makefile index 5a854d1..64ac5c3 100644 --- a/bindings/ocaml/transforms/vectorize/Makefile +++ b/bindings/ocaml/transforms/vectorize/Makefile @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## # -# This is the makefile for the Objective Caml Llvm_vectorize_opts interface. +# This is the makefile for the Objective Caml Llvm_vectorize interface. # ##===----------------------------------------------------------------------===## diff --git a/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml b/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml index 4fc53c6..88831da 100644 --- a/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml +++ b/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml @@ -7,9 +7,12 @@ * *===----------------------------------------------------------------------===*) -external add_bb_vectorize : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_bb_vectorize" -external add_loop_vectorize : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_loop_vectorize" -external add_slp_vectorize : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_slp_vectorize" +external add_bb_vectorize + : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit + = "llvm_add_bb_vectorize" +external add_loop_vectorize + : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit + = "llvm_add_loop_vectorize" +external add_slp_vectorize + : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit + = "llvm_add_slp_vectorize" diff --git a/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli b/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli index 0253039..23a68a2 100644 --- a/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli +++ b/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli @@ -13,13 +13,16 @@ classes in the [LLVMVectorize] library. *) (** See the [llvm::createBBVectorizePass] function. *) -external add_bb_vectorize : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_bb_vectorize" +external add_bb_vectorize + : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit + = "llvm_add_bb_vectorize" (** See the [llvm::createLoopVectorizePass] function. *) -external add_loop_vectorize : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_loop_vectorize" +external add_loop_vectorize + : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit + = "llvm_add_loop_vectorize" -(** See [llvm::createSLPVectorizerPass] function. *) -external add_slp_vectorize : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit - = "llvm_add_slp_vectorize" +(** See the [llvm::createSLPVectorizerPass] function. *) +external add_slp_vectorize + : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit + = "llvm_add_slp_vectorize" |