Initial version of Go bindings.

This code is based on the existing LLVM Go bindings project hosted at:
https://github.com/go-llvm/llvm

Note that all contributors to the gollvm project have agreed to relicense
their changes under the LLVM license and submit them to the LLVM project.

Differential Revision: http://reviews.llvm.org/D5684

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219976 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Peter Collingbourne 2014-10-16 22:48:02 +00:00
parent 86b3d8eb43
commit 798ace2e58
45 changed files with 4426 additions and 6 deletions

6
.gitignore vendored
View File

@ -49,3 +49,9 @@ tools/lld
tools/polly
# Sphinx build tree, if building in-source dir.
docs/_build
#==============================================================================#
# Files created in tree by the Go bindings.
#==============================================================================#
bindings/go/llvm/llvm_config.go
bindings/go/llvm/workdir

View File

@ -202,6 +202,7 @@ DOT := @DOT@
DOXYGEN := @DOXYGEN@
GROFF := @GROFF@
GZIPBIN := @GZIPBIN@
GO := @GO@
OCAMLC := @OCAMLC@
OCAMLOPT := @OCAMLOPT@
OCAMLDEP := @OCAMLDEP@

View File

@ -1287,6 +1287,7 @@ AC_PATH_PROG(GROFF, [groff])
AC_PATH_PROG(GZIPBIN, [gzip])
AC_PATH_PROG(PDFROFF, [pdfroff])
AC_PATH_PROG(ZIP, [zip])
AC_PATH_PROG(GO, [go])
AC_PATH_PROGS(OCAMLC, [ocamlc])
AC_PATH_PROGS(OCAMLOPT, [ocamlopt])
AC_PATH_PROGS(OCAMLDEP, [ocamldep])
@ -1867,6 +1868,11 @@ if test "$BINDINGS_TO_BUILD" = auto ; then
if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then
BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD"
fi
if test "x$GO" != x ; then
if $GO run ${srcdir}/bindings/go/conftest.go ; then
BINDINGS_TO_BUILD="go $BINDINGS_TO_BUILD"
fi
fi
fi
AC_SUBST(BINDINGS_TO_BUILD,$BINDINGS_TO_BUILD)
@ -1901,6 +1907,19 @@ for a_binding in $BINDINGS_TO_BUILD ; do
fi
fi
;;
go)
if test "x$GO" = x ; then
AC_MSG_WARN([--enable-bindings=go specified, but go not found. Try configure GO=/path/to/go])
binding_prereqs_failed=1
else
if $GO run ${srcdir}/bindings/go/conftest.go ; then
:
else
AC_MSG_WARN([--enable-bindings=go specified, but need at least Go 1.2. Try configure GO=/path/to/go])
binding_prereqs_failed=1
fi
fi
;;
esac
done
if test "$binding_prereqs_failed" = 1 ; then

View File

@ -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

53
bindings/go/README.txt Normal file
View File

@ -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

67
bindings/go/build.sh Executable file
View File

@ -0,0 +1,67 @@
#!/bin/sh -xe
llvm_components="\
all-targets \
analysis \
asmparser \
asmprinter \
bitreader \
bitwriter \
codegen \
core \
debuginfo \
executionengine \
instrumentation \
interpreter \
ipo \
irreader \
linker \
mc \
mcjit \
objcarcopts \
option \
profiledata \
scalaropts \
support \
target \
"
if [ "$1" == "--print-components" ] ; then
echo $llvm_components
exit 0
fi
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"
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_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_version="$($llvm_config --version)"
llvm_cflags="$($llvm_config --cppflags)"
llvm_ldflags="$($llvm_config --ldflags) $($llvm_config --libs $llvm_components) $($llvm_config --system-libs)"
if [ $(uname) != "Darwin" ]; then
# OS X doesn't like -rpath with cgo. See:
# https://code.google.com/p/go/issues/detail?id=7293
llvm_ldflags="-Wl,-rpath,$($llvm_config --libdir) $llvm_ldflags"
fi
sed -e "s#@LLVM_CFLAGS@#$llvm_cflags#g; s#@LLVM_LDFLAGS@#$llvm_ldflags#g" $gollvmdir/llvm_config.go.in > \
$gollvmdir/llvm_config.go
printf "package llvm\n\nconst Version = \"%s\"\n" "$llvm_version" > $gollvmdir/version.go

16
bindings/go/conftest.go Normal file
View File

@ -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)
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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) }

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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)
}

View File

@ -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))
}
}

1823
bindings/go/llvm/ir.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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)

View File

@ -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

105
bindings/go/llvm/string.go Normal file
View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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)
}

300
bindings/go/llvm/target.go Normal file
View File

@ -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
}

View File

@ -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)
}

View File

@ -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) }

View File

@ -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)
}

View File

@ -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) }

View File

@ -0,0 +1,3 @@
package llvm
const Version = "3.6.0svn"

View File

@ -491,3 +491,18 @@ if (LLVM_ENABLE_SPHINX)
else()
message(STATUS "Sphinx disabled.")
endif()
set(LLVM_BINDINGS "")
find_program(GO_EXECUTABLE NAMES go DOC "go executable")
if(GO_EXECUTABLE STREQUAL "GO_EXECUTABLE-NOTFOUND")
message(STATUS "Go bindings disabled.")
else()
execute_process(COMMAND ${GO_EXECUTABLE} run ${CMAKE_SOURCE_DIR}/bindings/go/conftest.go
RESULT_VARIABLE GO_CONFTEST)
if(GO_CONFTEST STREQUAL "0")
set(LLVM_BINDINGS "${LLVM_BINDINGS} go")
message(STATUS "Go bindings enabled.")
else()
message(STATUS "Go bindings disabled, need at least Go 1.2.")
endif()
endif()

View File

@ -651,6 +651,9 @@ function(configure_lit_site_cfg input output)
set(HOST_OS ${CMAKE_SYSTEM_NAME})
set(HOST_ARCH ${CMAKE_SYSTEM_PROCESSOR})
set(HOST_CC "${CMAKE_C_COMPILER}")
set(HOST_CXX "${CMAKE_CXX_COMPILER}")
configure_file(${input} ${output} @ONLY)
endfunction()

64
configure vendored
View File

@ -752,6 +752,7 @@ GROFF
GZIPBIN
PDFROFF
ZIP
GO
OCAMLC
OCAMLOPT
OCAMLDEP
@ -6871,6 +6872,46 @@ echo "${ECHO_T}no" >&6; }
fi
# Extract the first word of "go", so it can be a program name with args.
set dummy go; ac_word=$2
{ echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
if test "${ac_cv_path_GO+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
case $GO in
[\\/]* | ?:[\\/]*)
ac_cv_path_GO="$GO" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_GO="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
GO=$ac_cv_path_GO
if test -n "$GO"; then
{ echo "$as_me:$LINENO: result: $GO" >&5
echo "${ECHO_T}$GO" >&6; }
else
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
fi
for ac_prog in ocamlc
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
@ -18613,6 +18654,11 @@ if test "$BINDINGS_TO_BUILD" = auto ; then
if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then
BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD"
fi
if test "x$GO" != x ; then
if $GO run ${srcdir}/bindings/go/conftest.go ; then
BINDINGS_TO_BUILD="go $BINDINGS_TO_BUILD"
fi
fi
fi
BINDINGS_TO_BUILD=$BINDINGS_TO_BUILD
@ -18652,6 +18698,21 @@ echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found
fi
fi
;;
go)
if test "x$GO" = x ; then
{ echo "$as_me:$LINENO: WARNING: --enable-bindings=go specified, but go not found. Try configure GO=/path/to/go" >&5
echo "$as_me: WARNING: --enable-bindings=go specified, but go not found. Try configure GO=/path/to/go" >&2;}
binding_prereqs_failed=1
else
if $GO run ${srcdir}/bindings/go/conftest.go ; then
:
else
{ echo "$as_me:$LINENO: WARNING: --enable-bindings=go specified, but need at least Go 1.2. Try configure GO=/path/to/go" >&5
echo "$as_me: WARNING: --enable-bindings=go specified, but need at least Go 1.2. Try configure GO=/path/to/go" >&2;}
binding_prereqs_failed=1
fi
fi
;;
esac
done
if test "$binding_prereqs_failed" = 1 ; then
@ -19679,6 +19740,7 @@ GROFF!$GROFF$ac_delim
GZIPBIN!$GZIPBIN$ac_delim
PDFROFF!$PDFROFF$ac_delim
ZIP!$ZIP$ac_delim
GO!$GO$ac_delim
OCAMLC!$OCAMLC$ac_delim
OCAMLOPT!$OCAMLOPT$ac_delim
OCAMLDEP!$OCAMLDEP$ac_delim
@ -19724,7 +19786,7 @@ LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 96; then
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5

8
test/Bindings/Go/go.test Normal file
View File

@ -0,0 +1,8 @@
; RUN: cd %S/../../../bindings/go/llvm && \
; RUN: env CGO_CPPFLAGS="$(llvm-config --cppflags)" \
; RUN: CGO_CXXFLAGS=-std=c++11 \
; RUN: CGO_LDFLAGS="$(llvm-config --ldflags --libs --system-libs \
; RUN: $(../build.sh --print-components))" \
; RUN: %go test -tags byollvm .
; REQUIRES: shell

View File

@ -0,0 +1,33 @@
import distutils.spawn
import os
import pipes
import shlex
if not 'go' in config.root.llvm_bindings:
config.unsupported = True
# Resolve certain symlinks in the first word of compiler.
#
# This is a Go-specific hack. cgo and other Go tools check $CC and $CXX for the
# substring 'clang' to determine if the compiler is Clang. This won't work if
# $CC is cc and cc is a symlink pointing to clang, as it is on Darwin.
def fixup_compiler_path(compiler):
args = shlex.split(compiler)
path = distutils.spawn.find_executable(args[0])
try:
if path.endswith('/cc') and os.readlink(path) == 'clang':
args[0] = path[:len(path)-2] + 'clang'
except OSError:
skip
try:
if path.endswith('/c++') and os.readlink(path) == 'clang++':
args[0] = path[:len(path)-3] + 'clang++'
except OSError:
skip
return ' '.join([pipes.quote(arg) for arg in args])
config.environment['CC'] = fixup_compiler_path(config.host_cc)
config.environment['CXX'] = fixup_compiler_path(config.host_cxx)

View File

@ -1,5 +1,4 @@
config.suffixes = ['.ml']
bindings = set([s.strip() for s in config.root.llvm_bindings.split(',')])
if not 'ocaml' in bindings:
if not 'ocaml' in config.root.llvm_bindings:
config.unsupported = True

View File

@ -133,6 +133,9 @@ lit.site.cfg: FORCE
@$(ECHOPATH) s=@EXEEXT@=$(EXEEXT)=g >> lit.tmp
@$(ECHOPATH) s=@PYTHON_EXECUTABLE@=$(PYTHON)=g >> lit.tmp
@$(ECHOPATH) s=@OCAMLOPT@=$(OCAMLOPT) -cc $(subst *,'\\\"',*$(subst =,"\\=",$(CXX_FOR_OCAMLOPT))*) -cclib -L$(LibDir) -I $(LibDir)/ocaml=g >> lit.tmp
@$(ECHOPATH) s=@GO_EXECUTABLE@=$(GO)=g >> lit.tmp
@$(ECHOPATH) s!@HOST_CC@!$(CC)!g >> lit.tmp
@$(ECHOPATH) s!@HOST_CXX@!$(CXX)!g >> lit.tmp
@$(ECHOPATH) s=@ENABLE_SHARED@=$(ENABLE_SHARED)=g >> lit.tmp
@$(ECHOPATH) s=@ENABLE_ASSERTIONS@=$(ENABLE_ASSERTIONS)=g >> lit.tmp
@$(ECHOPATH) s=@TARGETS_TO_BUILD@=$(TARGETS_TO_BUILD)=g >> lit.tmp

View File

@ -168,6 +168,7 @@ config.substitutions.append( ('%llc_dwarf', llc_dwarf) )
# Add site-specific substitutions.
config.substitutions.append( ('%ocamlopt', config.ocamlopt_executable) )
config.substitutions.append( ('%go', config.go_executable) )
config.substitutions.append( ('%llvmshlibdir', config.llvm_shlib_dir) )
config.substitutions.append( ('%shlibext', config.llvm_shlib_ext) )
config.substitutions.append( ('%exeext', config.llvm_exe_ext) )

View File

@ -13,12 +13,15 @@ config.llvm_exe_ext = "@EXEEXT@"
config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
config.python_executable = "@PYTHON_EXECUTABLE@"
config.ocamlopt_executable = "@OCAMLOPT@"
config.go_executable = "@GO_EXECUTABLE@"
config.enable_shared = @ENABLE_SHARED@
config.enable_assertions = @ENABLE_ASSERTIONS@
config.targets_to_build = "@TARGETS_TO_BUILD@"
config.llvm_bindings = "@LLVM_BINDINGS@"
config.llvm_bindings = "@LLVM_BINDINGS@".split(' ')
config.host_os = "@HOST_OS@"
config.host_arch = "@HOST_ARCH@"
config.host_cc = "@HOST_CC@"
config.host_cxx = "@HOST_CXX@"
config.llvm_use_intel_jitevents = "@LLVM_USE_INTEL_JITEVENTS@"
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
config.have_zlib = "@HAVE_LIBZ@"

View File

@ -91,7 +91,7 @@ def getLocalConfig(ts, path_in_suite, litConfig, cache):
# Otherwise, copy the current config and load the local configuration
# file into it.
config = copy.copy(parent)
config = copy.deepcopy(parent)
if litConfig.debug:
litConfig.note('loading local config %r' % cfgpath)
config.load_from_path(cfgpath, litConfig)