mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 05:40:09 +00:00
[Bindings] Remove go bindings
Remove the unmaintained Go bindings per https://discourse.llvm.org/t/rfc-remove-the-go-bindings/65725. The tinygo project provides maintained Go bindings at https://github.com/tinygo-org/go-llvm. Differential Revision: https://reviews.llvm.org/D135436
This commit is contained in:
parent
36b13eb8bb
commit
bc839b4b4e
6
llvm/.gitignore
vendored
6
llvm/.gitignore
vendored
@ -50,12 +50,6 @@ docs/_build
|
||||
.vscode
|
||||
.vs
|
||||
|
||||
#==============================================================================#
|
||||
# Files created in tree by the Go bindings.
|
||||
#==============================================================================#
|
||||
bindings/go/llvm/llvm_config.go
|
||||
bindings/go/llvm/workdir
|
||||
|
||||
#==============================================================================#
|
||||
# File extensions to be ignored anywhere in the tree.
|
||||
# Placed at the end to override any previous ! patterns.
|
||||
|
@ -1,61 +0,0 @@
|
||||
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++14
|
||||
$ export CGO_LDFLAGS="`/path/to/llvm-build/bin/llvm-config --ldflags --libs --system-libs all`"
|
||||
$ go build -tags byollvm
|
||||
|
||||
If you see a compilation error while compiling your code with Go 1.9.4 or later as follows,
|
||||
|
||||
go build llvm.org/llvm/bindings/go/llvm: invalid flag in #cgo LDFLAGS: -Wl,-headerpad_max_install_names
|
||||
|
||||
you need to setup $CGO_LDFLAGS_ALLOW to allow a compiler to specify some linker options:
|
||||
|
||||
$ export CGO_LDFLAGS_ALLOW='-Wl,(-search_paths_first|-headerpad_max_install_names)'
|
@ -1,28 +0,0 @@
|
||||
#!/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
|
@ -1,16 +0,0 @@
|
||||
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)
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
//===- IRBindings.cpp - Additional bindings for ir ------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines additional C bindings for the ir component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IRBindings.h"
|
||||
#include "llvm/IR/Attributes.h"
|
||||
#include "llvm/IR/DebugLoc.h"
|
||||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
LLVMMetadataRef LLVMConstantAsMetadata(LLVMValueRef C) {
|
||||
return wrap(ConstantAsMetadata::get(unwrap<Constant>(C)));
|
||||
}
|
||||
|
||||
LLVMMetadataRef LLVMMDString2(LLVMContextRef C, const char *Str, unsigned SLen) {
|
||||
return wrap(MDString::get(*unwrap(C), StringRef(Str, SLen)));
|
||||
}
|
||||
|
||||
LLVMMetadataRef LLVMMDNode2(LLVMContextRef C, LLVMMetadataRef *MDs,
|
||||
unsigned Count) {
|
||||
return wrap(
|
||||
MDNode::get(*unwrap(C), ArrayRef<Metadata *>(unwrap(MDs), Count)));
|
||||
}
|
||||
|
||||
void LLVMAddNamedMetadataOperand2(LLVMModuleRef M, const char *name,
|
||||
LLVMMetadataRef Val) {
|
||||
NamedMDNode *N = unwrap(M)->getOrInsertNamedMetadata(name);
|
||||
if (!N)
|
||||
return;
|
||||
if (!Val)
|
||||
return;
|
||||
N->addOperand(unwrap<MDNode>(Val));
|
||||
}
|
||||
|
||||
void LLVMSetMetadata2(LLVMValueRef Inst, unsigned KindID, LLVMMetadataRef MD) {
|
||||
MDNode *N = MD ? unwrap<MDNode>(MD) : nullptr;
|
||||
unwrap<Instruction>(Inst)->setMetadata(KindID, N);
|
||||
}
|
||||
|
||||
void LLVMGoSetCurrentDebugLocation(LLVMBuilderRef Bref, unsigned Line,
|
||||
unsigned Col, LLVMMetadataRef Scope,
|
||||
LLVMMetadataRef InlinedAt) {
|
||||
if (!Scope)
|
||||
unwrap(Bref)->SetCurrentDebugLocation(DebugLoc());
|
||||
else
|
||||
unwrap(Bref)->SetCurrentDebugLocation(DILocation::get(
|
||||
unwrap<MDNode>(Scope)->getContext(), Line, Col, unwrap<MDNode>(Scope),
|
||||
InlinedAt ? unwrap<MDNode>(InlinedAt) : nullptr));
|
||||
}
|
||||
|
||||
LLVMDebugLocMetadata LLVMGoGetCurrentDebugLocation(LLVMBuilderRef Bref) {
|
||||
const auto& Loc = unwrap(Bref)->getCurrentDebugLocation();
|
||||
const auto* InlinedAt = Loc.getInlinedAt();
|
||||
const LLVMDebugLocMetadata md{
|
||||
Loc.getLine(),
|
||||
Loc.getCol(),
|
||||
wrap(Loc.getScope()),
|
||||
InlinedAt == nullptr ? nullptr : wrap(InlinedAt->getRawInlinedAt()),
|
||||
};
|
||||
return md;
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
//===- IRBindings.h - Additional bindings for IR ----------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 "llvm-c/DebugInfo.h"
|
||||
#ifdef __cplusplus
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/Support/CBindingWrapping.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct LLVMDebugLocMetadata{
|
||||
unsigned Line;
|
||||
unsigned Col;
|
||||
LLVMMetadataRef Scope;
|
||||
LLVMMetadataRef InlinedAt;
|
||||
};
|
||||
|
||||
LLVMMetadataRef LLVMConstantAsMetadata(LLVMValueRef Val);
|
||||
|
||||
LLVMMetadataRef LLVMMDString2(LLVMContextRef C, const char *Str, unsigned SLen);
|
||||
LLVMMetadataRef LLVMMDNode2(LLVMContextRef C, LLVMMetadataRef *MDs,
|
||||
unsigned Count);
|
||||
|
||||
void LLVMAddNamedMetadataOperand2(LLVMModuleRef M, const char *name,
|
||||
LLVMMetadataRef Val);
|
||||
void LLVMSetMetadata2(LLVMValueRef Inst, unsigned KindID, LLVMMetadataRef MD);
|
||||
|
||||
void LLVMGoSetCurrentDebugLocation(LLVMBuilderRef Bref, unsigned Line,
|
||||
unsigned Col, LLVMMetadataRef Scope,
|
||||
LLVMMetadataRef InlinedAt);
|
||||
|
||||
struct LLVMDebugLocMetadata LLVMGoGetCurrentDebugLocation(LLVMBuilderRef Bref);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,30 +0,0 @@
|
||||
//===- InstrumentationBindings.cpp - instrumentation bindings -------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines C bindings for the instrumentation component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InstrumentationBindings.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM,
|
||||
int ABIListFilesNum,
|
||||
const char **ABIListFiles) {
|
||||
std::vector<std::string> ABIListFilesVec;
|
||||
for (int i = 0; i != ABIListFilesNum; ++i) {
|
||||
ABIListFilesVec.push_back(ABIListFiles[i]);
|
||||
}
|
||||
unwrap(PM)->add(createDataFlowSanitizerLegacyPassPass(ABIListFilesVec));
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
//===- InstrumentationBindings.h - instrumentation bindings -----*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, int ABIListFilesNum,
|
||||
const char **ABIListFiles);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,25 +0,0 @@
|
||||
//===- SupportBindings.cpp - Additional bindings for support --------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
//===- SupportBindings.h - Additional bindings for Support ------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
@ -1,68 +0,0 @@
|
||||
//===- analysis.go - Bindings for analysis --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 "llvm-c/Core.h"
|
||||
#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) }
|
@ -1,50 +0,0 @@
|
||||
//===- bitreader.go - Bindings for bitreader ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines bindings for the bitreader component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#include "llvm-c/BitReader.h"
|
||||
#include "llvm-c/Core.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.LLVMParseBitcode2(buf, &m.C) == 0 {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
err := errors.New(C.GoString(errmsg))
|
||||
C.free(unsafe.Pointer(errmsg))
|
||||
return Module{}, err
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
//===- bitwriter.go - Bindings for bitwriter ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
@ -1,711 +0,0 @@
|
||||
//===- dibuilder.go - Bindings for DIBuilder ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines bindings for the DIBuilder class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#include "IRBindings.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
|
||||
FlagReserved
|
||||
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.LLVMCreateDIBuilder(m.C)
|
||||
return &DIBuilder{ref: d, m: m}
|
||||
}
|
||||
|
||||
// Destroy destroys the DIBuilder.
|
||||
func (d *DIBuilder) Destroy() {
|
||||
C.LLVMDisposeDIBuilder(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
|
||||
SysRoot string
|
||||
SDK string
|
||||
}
|
||||
|
||||
// CreateCompileUnit creates compile unit debug metadata.
|
||||
func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata {
|
||||
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))
|
||||
sysroot := C.CString(cu.SysRoot)
|
||||
defer C.free(unsafe.Pointer(sysroot))
|
||||
sdk := C.CString(cu.SDK)
|
||||
defer C.free(unsafe.Pointer(sdk))
|
||||
result := C.LLVMDIBuilderCreateCompileUnit(
|
||||
d.ref,
|
||||
C.LLVMDWARFSourceLanguage(cu.Language),
|
||||
C.LLVMDIBuilderCreateFile(d.ref, file, C.size_t(len(cu.File)), dir, C.size_t(len(cu.Dir))),
|
||||
producer, C.size_t(len(cu.Producer)),
|
||||
C.LLVMBool(boolToCInt(cu.Optimized)),
|
||||
flags, C.size_t(len(cu.Flags)),
|
||||
C.unsigned(cu.RuntimeVersion),
|
||||
/*SplitName=*/ nil, 0,
|
||||
C.LLVMDWARFEmissionFull,
|
||||
/*DWOId=*/ 0,
|
||||
/*SplitDebugInlining*/ C.LLVMBool(boolToCInt(true)),
|
||||
/*DebugInfoForProfiling*/ C.LLVMBool(boolToCInt(false)),
|
||||
sysroot, C.size_t(len(cu.SysRoot)),
|
||||
sdk, C.size_t(len(cu.SDK)),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// CreateFile creates file debug metadata.
|
||||
func (d *DIBuilder) CreateFile(filename, dir string) Metadata {
|
||||
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, C.size_t(len(filename)),
|
||||
cdir, C.size_t(len(dir)))
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DILexicalBlock holds the values for creating lexical block debug metadata.
|
||||
type DILexicalBlock struct {
|
||||
File Metadata
|
||||
Line int
|
||||
Column int
|
||||
}
|
||||
|
||||
// CreateLexicalBlock creates lexical block debug metadata.
|
||||
func (d *DIBuilder) CreateLexicalBlock(diScope Metadata, b DILexicalBlock) Metadata {
|
||||
result := C.LLVMDIBuilderCreateLexicalBlock(
|
||||
d.ref,
|
||||
diScope.C,
|
||||
b.File.C,
|
||||
C.unsigned(b.Line),
|
||||
C.unsigned(b.Column),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
func (d *DIBuilder) CreateLexicalBlockFile(diScope Metadata, diFile Metadata, discriminator int) Metadata {
|
||||
result := C.LLVMDIBuilderCreateLexicalBlockFile(d.ref, diScope.C, diFile.C,
|
||||
C.unsigned(discriminator))
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DIFunction holds the values for creating function debug metadata.
|
||||
type DIFunction struct {
|
||||
Name string
|
||||
LinkageName string
|
||||
File Metadata
|
||||
Line int
|
||||
Type Metadata
|
||||
LocalToUnit bool
|
||||
IsDefinition bool
|
||||
ScopeLine int
|
||||
Flags int
|
||||
Optimized bool
|
||||
}
|
||||
|
||||
// CreateFunction creates function debug metadata.
|
||||
func (d *DIBuilder) CreateFunction(diScope Metadata, f DIFunction) Metadata {
|
||||
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, C.size_t(len(f.Name)),
|
||||
linkageName, C.size_t(len(f.LinkageName)),
|
||||
f.File.C,
|
||||
C.unsigned(f.Line),
|
||||
f.Type.C,
|
||||
C.LLVMBool(boolToCInt(f.LocalToUnit)),
|
||||
C.LLVMBool(boolToCInt(f.IsDefinition)),
|
||||
C.unsigned(f.ScopeLine),
|
||||
C.LLVMDIFlags(f.Flags),
|
||||
C.LLVMBool(boolToCInt(f.Optimized)),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DIAutoVariable holds the values for creating auto variable debug metadata.
|
||||
type DIAutoVariable struct {
|
||||
Name string
|
||||
File Metadata
|
||||
Line int
|
||||
Type Metadata
|
||||
AlwaysPreserve bool
|
||||
Flags int
|
||||
AlignInBits uint32
|
||||
}
|
||||
|
||||
// CreateAutoVariable creates local variable debug metadata.
|
||||
func (d *DIBuilder) CreateAutoVariable(scope Metadata, v DIAutoVariable) Metadata {
|
||||
name := C.CString(v.Name)
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
result := C.LLVMDIBuilderCreateAutoVariable(
|
||||
d.ref,
|
||||
scope.C,
|
||||
name, C.size_t(len(v.Name)),
|
||||
v.File.C,
|
||||
C.unsigned(v.Line),
|
||||
v.Type.C,
|
||||
C.LLVMBool(boolToCInt(v.AlwaysPreserve)),
|
||||
C.LLVMDIFlags(v.Flags),
|
||||
C.uint32_t(v.AlignInBits),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DIParameterVariable holds the values for creating parameter variable debug metadata.
|
||||
type DIParameterVariable struct {
|
||||
Name string
|
||||
File Metadata
|
||||
Line int
|
||||
Type Metadata
|
||||
AlwaysPreserve bool
|
||||
Flags int
|
||||
|
||||
// ArgNo is the 1-based index of the argument in the function's
|
||||
// parameter list.
|
||||
ArgNo int
|
||||
}
|
||||
|
||||
// CreateParameterVariable creates parameter variable debug metadata.
|
||||
func (d *DIBuilder) CreateParameterVariable(scope Metadata, v DIParameterVariable) Metadata {
|
||||
name := C.CString(v.Name)
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
result := C.LLVMDIBuilderCreateParameterVariable(
|
||||
d.ref,
|
||||
scope.C,
|
||||
name, C.size_t(len(v.Name)),
|
||||
C.unsigned(v.ArgNo),
|
||||
v.File.C,
|
||||
C.unsigned(v.Line),
|
||||
v.Type.C,
|
||||
C.LLVMBool(boolToCInt(v.AlwaysPreserve)),
|
||||
C.LLVMDIFlags(v.Flags),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DIBasicType holds the values for creating basic type debug metadata.
|
||||
type DIBasicType struct {
|
||||
Name string
|
||||
SizeInBits uint64
|
||||
Encoding DwarfTypeEncoding
|
||||
}
|
||||
|
||||
// CreateBasicType creates basic type debug metadata.
|
||||
func (d *DIBuilder) CreateBasicType(t DIBasicType) Metadata {
|
||||
name := C.CString(t.Name)
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
result := C.LLVMDIBuilderCreateBasicType(
|
||||
d.ref,
|
||||
name,
|
||||
C.size_t(len(t.Name)),
|
||||
C.uint64_t(t.SizeInBits),
|
||||
C.LLVMDWARFTypeEncoding(t.Encoding),
|
||||
C.LLVMDIFlags(0),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DIPointerType holds the values for creating pointer type debug metadata.
|
||||
type DIPointerType struct {
|
||||
Pointee Metadata
|
||||
SizeInBits uint64
|
||||
AlignInBits uint32 // optional
|
||||
AddressSpace uint32
|
||||
Name string // optional
|
||||
}
|
||||
|
||||
// CreatePointerType creates a type that represents a pointer to another type.
|
||||
func (d *DIBuilder) CreatePointerType(t DIPointerType) Metadata {
|
||||
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.uint32_t(t.AlignInBits),
|
||||
C.unsigned(t.AddressSpace),
|
||||
name,
|
||||
C.size_t(len(t.Name)),
|
||||
)
|
||||
return Metadata{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 Metadata
|
||||
|
||||
// Parameters contains the subroutine parameter types,
|
||||
// including the return type at the 0th index.
|
||||
Parameters []Metadata
|
||||
|
||||
Flags int
|
||||
}
|
||||
|
||||
// CreateSubroutineType creates subroutine type debug metadata.
|
||||
func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Metadata {
|
||||
params, length := llvmMetadataRefs(t.Parameters)
|
||||
result := C.LLVMDIBuilderCreateSubroutineType(
|
||||
d.ref,
|
||||
t.File.C,
|
||||
params,
|
||||
length,
|
||||
C.LLVMDIFlags(t.Flags),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DIStructType holds the values for creating struct type debug metadata.
|
||||
type DIStructType struct {
|
||||
Name string
|
||||
File Metadata
|
||||
Line int
|
||||
SizeInBits uint64
|
||||
AlignInBits uint32
|
||||
Flags int
|
||||
DerivedFrom Metadata
|
||||
Elements []Metadata
|
||||
VTableHolder Metadata // optional
|
||||
UniqueID string
|
||||
}
|
||||
|
||||
// CreateStructType creates struct type debug metadata.
|
||||
func (d *DIBuilder) CreateStructType(scope Metadata, t DIStructType) Metadata {
|
||||
elements, length := llvmMetadataRefs(t.Elements)
|
||||
name := C.CString(t.Name)
|
||||
uniqueID := C.CString(t.UniqueID)
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
defer C.free(unsafe.Pointer(uniqueID))
|
||||
result := C.LLVMDIBuilderCreateStructType(
|
||||
d.ref,
|
||||
scope.C,
|
||||
name,
|
||||
C.size_t(len(t.Name)),
|
||||
t.File.C,
|
||||
C.unsigned(t.Line),
|
||||
C.uint64_t(t.SizeInBits),
|
||||
C.uint32_t(t.AlignInBits),
|
||||
C.LLVMDIFlags(t.Flags),
|
||||
t.DerivedFrom.C,
|
||||
elements,
|
||||
length,
|
||||
C.unsigned(0), // Optional Objective-C runtime version.
|
||||
t.VTableHolder.C,
|
||||
uniqueID,
|
||||
C.size_t(len(t.UniqueID)),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DIReplaceableCompositeType holds the values for creating replaceable
|
||||
// composite type debug metadata.
|
||||
type DIReplaceableCompositeType struct {
|
||||
Tag dwarf.Tag
|
||||
Name string
|
||||
File Metadata
|
||||
Line int
|
||||
RuntimeLang int
|
||||
SizeInBits uint64
|
||||
AlignInBits uint32
|
||||
Flags int
|
||||
UniqueID string
|
||||
}
|
||||
|
||||
// CreateReplaceableCompositeType creates replaceable composite type debug metadata.
|
||||
func (d *DIBuilder) CreateReplaceableCompositeType(scope Metadata, t DIReplaceableCompositeType) Metadata {
|
||||
name := C.CString(t.Name)
|
||||
uniqueID := C.CString(t.UniqueID)
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
defer C.free(unsafe.Pointer(uniqueID))
|
||||
result := C.LLVMDIBuilderCreateReplaceableCompositeType(
|
||||
d.ref,
|
||||
C.unsigned(t.Tag),
|
||||
name,
|
||||
C.size_t(len(t.Name)),
|
||||
scope.C,
|
||||
t.File.C,
|
||||
C.unsigned(t.Line),
|
||||
C.unsigned(t.RuntimeLang),
|
||||
C.uint64_t(t.SizeInBits),
|
||||
C.uint32_t(t.AlignInBits),
|
||||
C.LLVMDIFlags(t.Flags),
|
||||
uniqueID,
|
||||
C.size_t(len(t.UniqueID)),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DIMemberType holds the values for creating member type debug metadata.
|
||||
type DIMemberType struct {
|
||||
Name string
|
||||
File Metadata
|
||||
Line int
|
||||
SizeInBits uint64
|
||||
AlignInBits uint32
|
||||
OffsetInBits uint64
|
||||
Flags int
|
||||
Type Metadata
|
||||
}
|
||||
|
||||
// CreateMemberType creates struct type debug metadata.
|
||||
func (d *DIBuilder) CreateMemberType(scope Metadata, t DIMemberType) Metadata {
|
||||
name := C.CString(t.Name)
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
result := C.LLVMDIBuilderCreateMemberType(
|
||||
d.ref,
|
||||
scope.C,
|
||||
name,
|
||||
C.size_t(len(t.Name)),
|
||||
t.File.C,
|
||||
C.unsigned(t.Line),
|
||||
C.uint64_t(t.SizeInBits),
|
||||
C.uint32_t(t.AlignInBits),
|
||||
C.uint64_t(t.OffsetInBits),
|
||||
C.LLVMDIFlags(t.Flags),
|
||||
t.Type.C,
|
||||
)
|
||||
return Metadata{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 uint32
|
||||
ElementType Metadata
|
||||
Subscripts []DISubrange
|
||||
}
|
||||
|
||||
// CreateArrayType creates struct type debug metadata.
|
||||
func (d *DIBuilder) CreateArrayType(t DIArrayType) Metadata {
|
||||
subscriptsSlice := make([]Metadata, len(t.Subscripts))
|
||||
for i, s := range t.Subscripts {
|
||||
subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count)
|
||||
}
|
||||
subscripts, length := llvmMetadataRefs(subscriptsSlice)
|
||||
result := C.LLVMDIBuilderCreateArrayType(
|
||||
d.ref,
|
||||
C.uint64_t(t.SizeInBits),
|
||||
C.uint32_t(t.AlignInBits),
|
||||
t.ElementType.C,
|
||||
subscripts,
|
||||
length,
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// DITypedef holds the values for creating typedef type debug metadata.
|
||||
type DITypedef struct {
|
||||
Type Metadata
|
||||
Name string
|
||||
File Metadata
|
||||
Line int
|
||||
Context Metadata
|
||||
AlignInBits uint32
|
||||
}
|
||||
|
||||
// CreateTypedef creates typedef type debug metadata.
|
||||
func (d *DIBuilder) CreateTypedef(t DITypedef) Metadata {
|
||||
name := C.CString(t.Name)
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
result := C.LLVMDIBuilderCreateTypedef(
|
||||
d.ref,
|
||||
t.Type.C,
|
||||
name,
|
||||
C.size_t(len(t.Name)),
|
||||
t.File.C,
|
||||
C.unsigned(t.Line),
|
||||
t.Context.C,
|
||||
C.uint32_t(t.AlignInBits),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// getOrCreateSubrange gets a metadata node for the specified subrange,
|
||||
// creating if required.
|
||||
func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Metadata {
|
||||
result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count))
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// getOrCreateArray gets a metadata node containing the specified values,
|
||||
// creating if required.
|
||||
func (d *DIBuilder) getOrCreateArray(values []Metadata) Metadata {
|
||||
if len(values) == 0 {
|
||||
return Metadata{}
|
||||
}
|
||||
data, length := llvmMetadataRefs(values)
|
||||
result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length))
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
// getOrCreateTypeArray gets a metadata node for a type array containing the
|
||||
// specified values, creating if required.
|
||||
func (d *DIBuilder) getOrCreateTypeArray(values []Metadata) Metadata {
|
||||
if len(values) == 0 {
|
||||
return Metadata{}
|
||||
}
|
||||
data, length := llvmMetadataRefs(values)
|
||||
result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length))
|
||||
return Metadata{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 []uint64) Metadata {
|
||||
var data *C.uint64_t
|
||||
if len(addr) > 0 {
|
||||
data = (*C.uint64_t)(unsafe.Pointer(&addr[0]))
|
||||
}
|
||||
result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr)))
|
||||
return Metadata{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 Value, diVarInfo, expr Metadata, l DebugLoc, bb BasicBlock) Value {
|
||||
loc := C.LLVMDIBuilderCreateDebugLocation(
|
||||
d.m.Context().C, C.uint(l.Line), C.uint(l.Col), l.Scope.C, l.InlinedAt.C)
|
||||
result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, loc, bb.C)
|
||||
return Value{C: result}
|
||||
}
|
||||
|
||||
// InsertValueAtEnd inserts a call to llvm.dbg.value at the end of the
|
||||
// specified basic block for the given value and associated debug metadata.
|
||||
func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, l DebugLoc, bb BasicBlock) Value {
|
||||
loc := C.LLVMDIBuilderCreateDebugLocation(
|
||||
d.m.Context().C, C.uint(l.Line), C.uint(l.Col), l.Scope.C, l.InlinedAt.C)
|
||||
result := C.LLVMDIBuilderInsertDbgValueAtEnd(d.ref, v.C, diVarInfo.C, expr.C, loc, bb.C)
|
||||
return Value{C: result}
|
||||
}
|
||||
|
||||
func (v Value) SetSubprogram(sp Metadata) {
|
||||
C.LLVMSetSubprogram(v.C, sp.C)
|
||||
}
|
||||
|
||||
func (v Value) Subprogram() (md Metadata) {
|
||||
md.C = C.LLVMGetSubprogram(v.C)
|
||||
return
|
||||
}
|
||||
|
||||
func boolToCInt(v bool) C.int {
|
||||
if v {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// llvm.Metadata
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
func (c Context) TemporaryMDNode(mds []Metadata) (md Metadata) {
|
||||
ptr, nvals := llvmMetadataRefs(mds)
|
||||
md.C = C.LLVMTemporaryMDNode(c.C, ptr, C.size_t(nvals))
|
||||
return
|
||||
}
|
||||
|
||||
func (md Metadata) ReplaceAllUsesWith(new Metadata) {
|
||||
C.LLVMMetadataReplaceAllUsesWith(md.C, new.C)
|
||||
}
|
||||
|
||||
type MetadataKind C.LLVMMetadataKind
|
||||
|
||||
const (
|
||||
MDStringMetadataKind = C.LLVMMDStringMetadataKind
|
||||
ConstantAsMetadataMetadataKind = C.LLVMConstantAsMetadataMetadataKind
|
||||
LocalAsMetadataMetadataKind = C.LLVMLocalAsMetadataMetadataKind
|
||||
DistinctMDOperandPlaceholderMetadataKind = C.LLVMDistinctMDOperandPlaceholderMetadataKind
|
||||
MDTupleMetadataKind = C.LLVMMDTupleMetadataKind
|
||||
DILocationMetadataKind = C.LLVMDILocationMetadataKind
|
||||
DIExpressionMetadataKind = C.LLVMDIExpressionMetadataKind
|
||||
DIGlobalVariableExpressionMetadataKind = C.LLVMDIGlobalVariableExpressionMetadataKind
|
||||
GenericDINodeMetadataKind = C.LLVMGenericDINodeMetadataKind
|
||||
DISubrangeMetadataKind = C.LLVMDISubrangeMetadataKind
|
||||
DIEnumeratorMetadataKind = C.LLVMDIEnumeratorMetadataKind
|
||||
DIBasicTypeMetadataKind = C.LLVMDIBasicTypeMetadataKind
|
||||
DIDerivedTypeMetadataKind = C.LLVMDIDerivedTypeMetadataKind
|
||||
DICompositeTypeMetadataKind = C.LLVMDICompositeTypeMetadataKind
|
||||
DISubroutineTypeMetadataKind = C.LLVMDISubroutineTypeMetadataKind
|
||||
DIFileMetadataKind = C.LLVMDIFileMetadataKind
|
||||
DICompileUnitMetadataKind = C.LLVMDICompileUnitMetadataKind
|
||||
DISubprogramMetadataKind = C.LLVMDISubprogramMetadataKind
|
||||
DILexicalBlockMetadataKind = C.LLVMDILexicalBlockMetadataKind
|
||||
DILexicalBlockFileMetadataKind = C.LLVMDILexicalBlockFileMetadataKind
|
||||
DINamespaceMetadataKind = C.LLVMDINamespaceMetadataKind
|
||||
DIModuleMetadataKind = C.LLVMDIModuleMetadataKind
|
||||
DITemplateTypeParameterMetadataKind = C.LLVMDITemplateTypeParameterMetadataKind
|
||||
DITemplateValueParameterMetadataKind = C.LLVMDITemplateValueParameterMetadataKind
|
||||
DIGlobalVariableMetadataKind = C.LLVMDIGlobalVariableMetadataKind
|
||||
DILocalVariableMetadataKind = C.LLVMDILocalVariableMetadataKind
|
||||
DILabelMetadataKind = C.LLVMDILabelMetadataKind
|
||||
DIObjCPropertyMetadataKind = C.LLVMDIObjCPropertyMetadataKind
|
||||
DIImportedEntityMetadataKind = C.LLVMDIImportedEntityMetadataKind
|
||||
DIMacroMetadataKind = C.LLVMDIMacroMetadataKind
|
||||
DIMacroFileMetadataKind = C.LLVMDIMacroFileMetadataKind
|
||||
DICommonBlockMetadataKind = C.LLVMDICommonBlockMetadataKind
|
||||
)
|
||||
|
||||
// Kind returns the metadata kind.
|
||||
func (md Metadata) Kind() MetadataKind {
|
||||
return MetadataKind(C.LLVMGetMetadataKind(md.C))
|
||||
}
|
||||
|
||||
// FileDirectory returns the directory of a DIFile metadata node.
|
||||
func (md Metadata) FileDirectory() string {
|
||||
var length C.unsigned
|
||||
ptr := C.LLVMDIFileGetDirectory(md.C, &length)
|
||||
return string(((*[1 << 20]byte)(unsafe.Pointer(ptr)))[:length:length])
|
||||
}
|
||||
|
||||
// FileFilename returns the filename of a DIFile metadata node.
|
||||
func (md Metadata) FileFilename() string {
|
||||
var length C.unsigned
|
||||
ptr := C.LLVMDIFileGetFilename(md.C, &length)
|
||||
return string(((*[1 << 20]byte)(unsafe.Pointer(ptr)))[:length:length])
|
||||
}
|
||||
|
||||
// FileSource returns the source of a DIFile metadata node.
|
||||
func (md Metadata) FileSource() string {
|
||||
var length C.unsigned
|
||||
ptr := C.LLVMDIFileGetSource(md.C, &length)
|
||||
return string(((*[1 << 20]byte)(unsafe.Pointer(ptr)))[:length:length])
|
||||
}
|
||||
|
||||
// LocationLine returns the line number of a DILocation.
|
||||
func (md Metadata) LocationLine() uint {
|
||||
return uint(C.LLVMDILocationGetLine(md.C))
|
||||
}
|
||||
|
||||
// LocationColumn returns the column (offset from the start of the line) of a
|
||||
// DILocation.
|
||||
func (md Metadata) LocationColumn() uint {
|
||||
return uint(C.LLVMDILocationGetColumn(md.C))
|
||||
}
|
||||
|
||||
// LocationScope returns the local scope associated with this debug location.
|
||||
func (md Metadata) LocationScope() Metadata {
|
||||
return Metadata{C.LLVMDILocationGetScope(md.C)}
|
||||
}
|
||||
|
||||
// LocationInlinedAt return the "inline at" location associated with this debug
|
||||
// location.
|
||||
func (md Metadata) LocationInlinedAt() Metadata {
|
||||
return Metadata{C.LLVMDILocationGetInlinedAt(md.C)}
|
||||
}
|
||||
|
||||
// ScopeFile returns the file (DIFile) of a given scope.
|
||||
func (md Metadata) ScopeFile() Metadata {
|
||||
return Metadata{C.LLVMDIScopeGetFile(md.C)}
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
//===- executionengine.go - Bindings for executionengine ------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines bindings for the executionengine component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#include "llvm-c/Core.h"
|
||||
#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 {
|
||||
C C.struct_LLVMMCJITCompilerOptions
|
||||
}
|
||||
|
||||
func (options *MCJITCompilerOptions) SetMCJITOptimizationLevel(level uint) {
|
||||
options.C.OptLevel = C.uint(level)
|
||||
}
|
||||
|
||||
func (options *MCJITCompilerOptions) SetMCJITNoFramePointerElim(nfp bool) {
|
||||
options.C.NoFramePointerElim = boolToLLVMBool(nfp)
|
||||
}
|
||||
|
||||
func (options *MCJITCompilerOptions) SetMCJITEnableFastISel(fastisel bool) {
|
||||
options.C.EnableFastISel = boolToLLVMBool(fastisel)
|
||||
}
|
||||
|
||||
func (options *MCJITCompilerOptions) SetMCJITCodeModel(CodeModel CodeModel) {
|
||||
options.C.CodeModel = C.LLVMCodeModel(CodeModel)
|
||||
}
|
||||
|
||||
// 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 NewMCJITCompilerOptions() MCJITCompilerOptions {
|
||||
var options C.struct_LLVMMCJITCompilerOptions
|
||||
C.LLVMInitializeMCJITCompilerOptions(&options, C.size_t(unsafe.Sizeof(C.struct_LLVMMCJITCompilerOptions{})))
|
||||
return MCJITCompilerOptions{options}
|
||||
}
|
||||
|
||||
func NewMCJITCompiler(m Module, options MCJITCompilerOptions) (ee ExecutionEngine, err error) {
|
||||
var cmsg *C.char
|
||||
fail := C.LLVMCreateMCJITCompilerForModule(&ee.C, m.C, &options.C, C.size_t(unsafe.Sizeof(C.struct_LLVMMCJITCompilerOptions{})), &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)
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
//===- executionengine_test.go - Tests for executionengine ----------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
}
|
||||
|
||||
options := NewMCJITCompilerOptions()
|
||||
options.SetMCJITOptimizationLevel(2)
|
||||
options.SetMCJITEnableFastISel(true)
|
||||
options.SetMCJITNoFramePointerElim(true)
|
||||
options.SetMCJITCodeModel(CodeModelJITDefault)
|
||||
engine, err := NewMCJITCompiler(mod, options)
|
||||
if err != nil {
|
||||
t.Errorf("Error creating JIT: %s", err)
|
||||
return
|
||||
}
|
||||
defer engine.Dispose()
|
||||
|
||||
pass := NewPassManager()
|
||||
defer pass.Dispose()
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,164 +0,0 @@
|
||||
//===- ir_test.go - Tests for ir ------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file tests bindings for the ir component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testAttribute(t *testing.T, name string) {
|
||||
mod := NewModule("")
|
||||
defer mod.Dispose()
|
||||
|
||||
ftyp := FunctionType(VoidType(), nil, false)
|
||||
fn := AddFunction(mod, "foo", ftyp)
|
||||
|
||||
kind := AttributeKindID(name)
|
||||
attr := mod.Context().CreateEnumAttribute(kind, 0)
|
||||
|
||||
fn.AddFunctionAttr(attr)
|
||||
newattr := fn.GetEnumFunctionAttribute(kind)
|
||||
if attr != newattr {
|
||||
t.Errorf("got attribute %p, want %p", newattr.C, attr.C)
|
||||
}
|
||||
|
||||
text := mod.String()
|
||||
if !strings.Contains(text, " "+name+" ") {
|
||||
t.Errorf("expected attribute '%s', got:\n%s", name, text)
|
||||
}
|
||||
|
||||
fn.RemoveEnumFunctionAttribute(kind)
|
||||
newattr = fn.GetEnumFunctionAttribute(kind)
|
||||
if !newattr.IsNil() {
|
||||
t.Errorf("got attribute %p, want 0", newattr.C)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttributes(t *testing.T) {
|
||||
// Tests that our attribute constants haven't drifted from LLVM's.
|
||||
attrTests := []string{
|
||||
"sanitize_address",
|
||||
"alwaysinline",
|
||||
"builtin",
|
||||
"convergent",
|
||||
"inlinehint",
|
||||
"inreg",
|
||||
"jumptable",
|
||||
"minsize",
|
||||
"naked",
|
||||
"nest",
|
||||
"noalias",
|
||||
"nobuiltin",
|
||||
"nocapture",
|
||||
"noduplicate",
|
||||
"noimplicitfloat",
|
||||
"noinline",
|
||||
"nonlazybind",
|
||||
"nonnull",
|
||||
"noredzone",
|
||||
"noreturn",
|
||||
"nounwind",
|
||||
"nosanitize_bounds",
|
||||
"nosanitize_coverage",
|
||||
"optnone",
|
||||
"optsize",
|
||||
"readnone",
|
||||
"readonly",
|
||||
"returned",
|
||||
"returns_twice",
|
||||
"signext",
|
||||
"safestack",
|
||||
"ssp",
|
||||
"sspreq",
|
||||
"sspstrong",
|
||||
"sanitize_thread",
|
||||
"sanitize_memory",
|
||||
"zeroext",
|
||||
"cold",
|
||||
"nocf_check",
|
||||
}
|
||||
|
||||
for _, name := range attrTests {
|
||||
testAttribute(t, name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebugLoc(t *testing.T) {
|
||||
mod := NewModule("")
|
||||
defer mod.Dispose()
|
||||
|
||||
ctx := mod.Context()
|
||||
|
||||
b := ctx.NewBuilder()
|
||||
defer b.Dispose()
|
||||
|
||||
d := NewDIBuilder(mod)
|
||||
defer func() {
|
||||
d.Destroy()
|
||||
}()
|
||||
file := d.CreateFile("dummy_file", "dummy_dir")
|
||||
voidInfo := d.CreateBasicType(DIBasicType{Name: "void"})
|
||||
typeInfo := d.CreateSubroutineType(DISubroutineType{
|
||||
File: file,
|
||||
Parameters: []Metadata{voidInfo},
|
||||
Flags: 0,
|
||||
})
|
||||
scope := d.CreateFunction(file, DIFunction{
|
||||
Name: "foo",
|
||||
LinkageName: "foo",
|
||||
Line: 10,
|
||||
ScopeLine: 10,
|
||||
Type: typeInfo,
|
||||
File: file,
|
||||
IsDefinition: true,
|
||||
})
|
||||
|
||||
b.SetCurrentDebugLocation(10, 20, scope, Metadata{})
|
||||
loc := b.GetCurrentDebugLocation()
|
||||
if loc.Line != 10 {
|
||||
t.Errorf("Got line %d, though wanted 10", loc.Line)
|
||||
}
|
||||
if loc.Col != 20 {
|
||||
t.Errorf("Got column %d, though wanted 20", loc.Col)
|
||||
}
|
||||
if loc.Scope.C != scope.C {
|
||||
t.Errorf("Got metadata %v as scope, though wanted %v", loc.Scope.C, scope.C)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubtypes(t *testing.T) {
|
||||
cont := NewContext()
|
||||
defer cont.Dispose()
|
||||
|
||||
int_pointer := PointerType(cont.Int32Type(), 0)
|
||||
int_inner := int_pointer.Subtypes()
|
||||
if len(int_inner) != 1 {
|
||||
t.Errorf("Got size %d, though wanted 1", len(int_inner))
|
||||
}
|
||||
if int_inner[0] != cont.Int32Type() {
|
||||
t.Errorf("Expected int32 type")
|
||||
}
|
||||
|
||||
st_pointer := cont.StructType([]Type{cont.Int32Type(), cont.Int8Type()}, false)
|
||||
st_inner := st_pointer.Subtypes()
|
||||
if len(st_inner) != 2 {
|
||||
t.Errorf("Got size %d, though wanted 2", len(int_inner))
|
||||
}
|
||||
if st_inner[0] != cont.Int32Type() {
|
||||
t.Errorf("Expected first struct field to be int32")
|
||||
}
|
||||
if st_inner[1] != cont.Int8Type() {
|
||||
t.Errorf("Expected second struct field to be int8")
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
//===- linker.go - Bindings for linker ------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines bindings for the linker component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/Linker.h"
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import "errors"
|
||||
|
||||
func LinkModules(Dest, Src Module) error {
|
||||
failed := C.LLVMLinkModules2(Dest.C, Src.C)
|
||||
if failed != 0 {
|
||||
err := errors.New("Linking failed")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// +build !byollvm
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#cgo CXXFLAGS: -std=c++14
|
||||
#cgo CPPFLAGS: @LLVM_CFLAGS@
|
||||
#cgo LDFLAGS: @LLVM_LDFLAGS@
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type (run_build_sh int)
|
@ -1,18 +0,0 @@
|
||||
//===- llvm_dep.go - creates LLVM dependency ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file ensures that the LLVM libraries are built before using the
|
||||
// bindings.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// +build !byollvm
|
||||
|
||||
package llvm
|
||||
|
||||
var _ run_build_sh
|
@ -1,106 +0,0 @@
|
||||
//===- string.go - Stringer implementation for Type -----------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 MetadataTypeKind:
|
||||
return "MetadataTypeKind"
|
||||
case VectorTypeKind:
|
||||
return "VectorTypeKind"
|
||||
case ScalableVectorTypeKind:
|
||||
return "ScalableVectorTypeKind"
|
||||
}
|
||||
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
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
//===- string_test.go - test Stringer implementation for Type -------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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)
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//===- support.go - Bindings for support ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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)
|
||||
}
|
@ -1,296 +0,0 @@
|
||||
//===- target.go - Bindings for target ------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines bindings for the target component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#include "llvm-c/Core.h"
|
||||
#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
|
||||
CodeModelTiny CodeModel = C.LLVMCodeModelTiny
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// CreateTargetData returns a new TargetData describing the TargetMachine's
|
||||
// data layout. The returned TargetData is owned by the caller, who is
|
||||
// responsible for disposing of it by calling the TargetData.Dispose method.
|
||||
func (tm TargetMachine) CreateTargetData() TargetData {
|
||||
return TargetData{C.LLVMCreateTargetDataLayout(tm.C)}
|
||||
}
|
||||
|
||||
// Triple returns the triple describing the machine (arch-vendor-os).
|
||||
func (tm TargetMachine) Triple() string {
|
||||
cstr := C.LLVMGetTargetMachineTriple(tm.C)
|
||||
return C.GoString(cstr)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
//===- transforms_instrumentation.go - Bindings for instrumentation -------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines bindings for the instrumentation component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#include "InstrumentationBindings.h"
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func (pm PassManager) AddDataFlowSanitizerPass(abilist []string) {
|
||||
abiliststrs := make([]*C.char, len(abilist))
|
||||
for i, arg := range abilist {
|
||||
abiliststrs[i] = C.CString(arg)
|
||||
defer C.free(unsafe.Pointer(abiliststrs[i]))
|
||||
}
|
||||
C.LLVMAddDataFlowSanitizerPass(pm.C, C.int(len(abilist)), &abiliststrs[0])
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
//===- transforms_ipo.go - Bindings for ipo -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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) 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) 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) }
|
@ -1,63 +0,0 @@
|
||||
//===- transforms_pmbuilder.go - Bindings for PassManagerBuilder ----------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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)
|
||||
}
|
||||
|
||||
func (pmb PassManagerBuilder) SetDisableUnitAtATime(val bool) {
|
||||
C.LLVMPassManagerBuilderSetDisableUnitAtATime(pmb.C, boolToLLVMBool(val))
|
||||
}
|
||||
|
||||
func (pmb PassManagerBuilder) SetDisableUnrollLoops(val bool) {
|
||||
C.LLVMPassManagerBuilderSetDisableUnrollLoops(pmb.C, boolToLLVMBool(val))
|
||||
}
|
||||
|
||||
func (pmb PassManagerBuilder) SetDisableSimplifyLibCalls(val bool) {
|
||||
C.LLVMPassManagerBuilderSetDisableSimplifyLibCalls(pmb.C, boolToLLVMBool(val))
|
||||
}
|
||||
|
||||
func (pmb PassManagerBuilder) UseInlinerWithThreshold(threshold uint) {
|
||||
C.LLVMPassManagerBuilderUseInlinerWithThreshold(pmb.C, C.uint(threshold))
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
//===- transforms_scalar.go - Bindings for scalaropts ---------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines bindings for the scalaropts component.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#include "llvm-c/Transforms/Scalar.h"
|
||||
#include "llvm-c/Transforms/Utils.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) 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) AddDemoteMemoryToRegisterPass() { C.LLVMAddDemoteMemoryToRegisterPass(pm.C) }
|
||||
func (pm PassManager) AddVerifierPass() { C.LLVMAddVerifierPass(pm.C) }
|
@ -1,20 +0,0 @@
|
||||
//===- version.go - LLVM version info -------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines LLVM version information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const Version = C.LLVM_VERSION_STRING
|
@ -603,25 +603,6 @@ else()
|
||||
message(STATUS "Doxygen disabled.")
|
||||
endif()
|
||||
|
||||
set(LLVM_BINDINGS "")
|
||||
find_program(GO_EXECUTABLE NAMES go DOC "go executable")
|
||||
if(WIN32 OR NOT LLVM_ENABLE_BINDINGS)
|
||||
message(STATUS "Go bindings disabled.")
|
||||
else()
|
||||
if(GO_EXECUTABLE STREQUAL "GO_EXECUTABLE-NOTFOUND")
|
||||
message(STATUS "Go bindings disabled.")
|
||||
else()
|
||||
execute_process(COMMAND ${GO_EXECUTABLE} run ${PROJECT_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()
|
||||
endif()
|
||||
|
||||
find_program(GOLD_EXECUTABLE NAMES ${LLVM_DEFAULT_TARGET_TRIPLE}-ld.gold ld.gold ${LLVM_DEFAULT_TARGET_TRIPLE}-ld ld DOC "The gold linker")
|
||||
set(LLVM_BINUTILS_INCDIR "" CACHE PATH
|
||||
"PATH to binutils/include containing plugin-api.h for gold plugin.")
|
||||
@ -659,6 +640,7 @@ if(CMAKE_HOST_APPLE AND APPLE)
|
||||
endif()
|
||||
|
||||
# Keep the version requirements in sync with bindings/ocaml/README.txt.
|
||||
set(LLVM_BINDINGS "")
|
||||
include(FindOCaml)
|
||||
include(AddOCaml)
|
||||
if(WIN32 OR NOT LLVM_ENABLE_BINDINGS)
|
||||
|
@ -1,5 +0,0 @@
|
||||
; RUN: llvm-go test llvm.org/llvm/bindings/go/llvm
|
||||
|
||||
; REQUIRES: shell, default_triple
|
||||
;; Building Go bindings with Clang is currently unsupported on AIX.
|
||||
; UNSUPPORTED: asan, ubsan, msan, -aix
|
@ -1,63 +0,0 @@
|
||||
import os
|
||||
import pipes
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
if not 'go' in config.root.llvm_bindings:
|
||||
config.unsupported = True
|
||||
|
||||
if not config.root.include_go_tests:
|
||||
config.unsupported = True
|
||||
|
||||
if config.have_tf_aot or config.have_tf_api:
|
||||
config.unsupported = True
|
||||
|
||||
def find_executable(executable, path=None):
|
||||
if path is None:
|
||||
path = os.environ['PATH']
|
||||
paths = path.split(os.pathsep)
|
||||
base, ext = os.path.splitext(executable)
|
||||
|
||||
if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'):
|
||||
executable = executable + '.exe'
|
||||
|
||||
if not os.path.isfile(executable):
|
||||
for p in paths:
|
||||
f = os.path.join(p, executable)
|
||||
if os.path.isfile(f):
|
||||
return f
|
||||
return None
|
||||
else:
|
||||
return executable
|
||||
|
||||
# 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.
|
||||
#
|
||||
# Go tools also have problems with ccache, so we disable it.
|
||||
def fixup_compiler_path(compiler):
|
||||
args = shlex.split(compiler)
|
||||
if args[0].endswith('ccache') or args[0].endswith('gomacc'):
|
||||
args = args[1:]
|
||||
|
||||
path = find_executable(args[0])
|
||||
|
||||
try:
|
||||
if path.endswith('/cc') and os.readlink(path) == 'clang':
|
||||
args[0] = path[:len(path)-2] + 'clang'
|
||||
except (AttributeError, OSError):
|
||||
pass
|
||||
|
||||
try:
|
||||
if path.endswith('/c++') and os.readlink(path) == 'clang++':
|
||||
args[0] = path[:len(path)-3] + 'clang++'
|
||||
except (AttributeError, OSError):
|
||||
pass
|
||||
|
||||
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)
|
||||
config.environment['CGO_LDFLAGS'] = config.host_ldflags
|
@ -162,10 +162,6 @@ if(TARGET LLVMgold)
|
||||
set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS} LLVMgold)
|
||||
endif()
|
||||
|
||||
if(TARGET llvm-go)
|
||||
set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS} llvm-go)
|
||||
endif()
|
||||
|
||||
if(TARGET LTO)
|
||||
set(LLVM_TEST_DEPENDS ${LLVM_TEST_DEPENDS} LTO)
|
||||
endif()
|
||||
|
@ -142,7 +142,6 @@ tools = [
|
||||
ToolSubst('%llvm', FindTool('llvm'), unresolved='ignore'),
|
||||
ToolSubst('%lli', FindTool('lli'), post='.', extra_args=lli_args),
|
||||
ToolSubst('%llc_dwarf', FindTool('llc'), extra_args=llc_args),
|
||||
ToolSubst('%go', config.go_executable, unresolved='ignore'),
|
||||
ToolSubst('%gold', config.gold_executable, unresolved='ignore'),
|
||||
ToolSubst('%ld64', ld64_cmd, unresolved='ignore'),
|
||||
ToolSubst('%ocamlc', ocamlc_command, unresolved='ignore'),
|
||||
@ -175,7 +174,6 @@ tools.extend([
|
||||
|
||||
# The following tools are optional
|
||||
tools.extend([
|
||||
ToolSubst('llvm-go', unresolved='ignore'),
|
||||
ToolSubst('llvm-mt', unresolved='ignore'),
|
||||
ToolSubst('Kaleidoscope-Ch3', unresolved='ignore'),
|
||||
ToolSubst('Kaleidoscope-Ch4', unresolved='ignore'),
|
||||
|
@ -22,7 +22,6 @@ config.ocamlfind_executable = "@OCAMLFIND@"
|
||||
config.have_ocamlopt = @HAVE_OCAMLOPT@
|
||||
config.ocaml_flags = "@OCAMLFLAGS@"
|
||||
config.include_go_tests = @LLVM_INCLUDE_GO_TESTS@
|
||||
config.go_executable = "@GO_EXECUTABLE@"
|
||||
config.ptxas_executable = "@PTXAS_EXECUTABLE@"
|
||||
config.enable_shared = @ENABLE_SHARED@
|
||||
config.enable_assertions = @ENABLE_ASSERTIONS@
|
||||
|
@ -1,9 +0,0 @@
|
||||
if(LLVM_BINDINGS MATCHES "go")
|
||||
set(binpath ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX})
|
||||
add_custom_command(OUTPUT ${binpath}
|
||||
COMMAND ${GO_EXECUTABLE} build -o ${binpath} llvm-go.go
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/llvm-go.go
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Building Go executable llvm-go")
|
||||
add_custom_target(llvm-go ALL DEPENDS ${binpath})
|
||||
endif()
|
@ -1,315 +0,0 @@
|
||||
//===-- llvm-go.go - go tool wrapper for LLVM -----------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tool lets us build LLVM components within the tree by setting up a
|
||||
// $GOPATH that resembles a tree fetched in the normal way with "go get".
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
linkmodeComponentLibs = "component-libs"
|
||||
linkmodeDylib = "dylib"
|
||||
)
|
||||
|
||||
type pkg struct {
|
||||
llvmpath, pkgpath string
|
||||
}
|
||||
|
||||
var packages = []pkg{
|
||||
{"bindings/go/llvm", "llvm.org/llvm/bindings/go/llvm"},
|
||||
}
|
||||
|
||||
type compilerFlags struct {
|
||||
cpp, cxx, ld string
|
||||
}
|
||||
|
||||
var components = []string{
|
||||
"all-targets",
|
||||
"analysis",
|
||||
"asmparser",
|
||||
"asmprinter",
|
||||
"bitreader",
|
||||
"bitwriter",
|
||||
"codegen",
|
||||
"core",
|
||||
"coroutines",
|
||||
"debuginfodwarf",
|
||||
"executionengine",
|
||||
"instrumentation",
|
||||
"interpreter",
|
||||
"ipo",
|
||||
"irreader",
|
||||
"linker",
|
||||
"mc",
|
||||
"mcjit",
|
||||
"objcarcopts",
|
||||
"option",
|
||||
"profiledata",
|
||||
"scalaropts",
|
||||
"support",
|
||||
"target",
|
||||
}
|
||||
|
||||
func llvmConfig(args ...string) string {
|
||||
configpath := os.Getenv("LLVM_CONFIG")
|
||||
if configpath == "" {
|
||||
bin, _ := filepath.Split(os.Args[0])
|
||||
configpath = filepath.Join(bin, "llvm-config")
|
||||
}
|
||||
|
||||
cmd := exec.Command(configpath, args...)
|
||||
cmd.Stderr = os.Stderr
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
outstr := string(out)
|
||||
outstr = strings.TrimSuffix(outstr, "\n")
|
||||
outstr = strings.Replace(outstr, "\n", " ", -1)
|
||||
return outstr
|
||||
}
|
||||
|
||||
func llvmFlags() compilerFlags {
|
||||
args := append([]string{"--ldflags", "--libs", "--system-libs"}, components...)
|
||||
ldflags := llvmConfig(args...)
|
||||
stdLibOption := ""
|
||||
if strings.Contains(llvmConfig("--cxxflags"), "-stdlib=libc++") {
|
||||
// If libc++ is used to build LLVM libraries, -stdlib=libc++ is
|
||||
// needed to resolve dependent symbols
|
||||
stdLibOption = "-stdlib=libc++"
|
||||
}
|
||||
if runtime.GOOS == "aix" {
|
||||
// AIX linker does not honour `-rpath`, the closest substitution
|
||||
// is `-blibpath`
|
||||
ldflags = "-Wl,-blibpath:" + llvmConfig("--libdir") + " " + ldflags
|
||||
} else if runtime.GOOS != "darwin" {
|
||||
// OS X doesn't like -rpath with cgo. See:
|
||||
// https://github.com/golang/go/issues/7293
|
||||
ldflags = "-Wl,-rpath," + llvmConfig("--libdir") + " " + ldflags
|
||||
}
|
||||
return compilerFlags{
|
||||
cpp: llvmConfig("--cppflags"),
|
||||
cxx: "-std=c++14" + " " + stdLibOption,
|
||||
ld: ldflags,
|
||||
}
|
||||
}
|
||||
|
||||
func addTag(args []string, tag string) []string {
|
||||
args = append([]string{}, args...)
|
||||
addedTag := false
|
||||
for i, a := range args {
|
||||
if strings.HasPrefix(a, "-tags=") {
|
||||
args[i] = a + " " + tag
|
||||
addedTag = true
|
||||
} else if a == "-tags" && i+1 < len(args) {
|
||||
args[i+1] = args[i+1] + " " + tag
|
||||
addedTag = true
|
||||
}
|
||||
}
|
||||
if !addedTag {
|
||||
args = append([]string{args[0], "-tags", tag}, args[1:]...)
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func printComponents() {
|
||||
fmt.Println(strings.Join(components, " "))
|
||||
}
|
||||
|
||||
func printConfig() {
|
||||
flags := llvmFlags()
|
||||
|
||||
fmt.Printf(`// +build !byollvm
|
||||
|
||||
// This file is generated by llvm-go, do not edit.
|
||||
|
||||
package llvm
|
||||
|
||||
/*
|
||||
#cgo CPPFLAGS: %s
|
||||
#cgo CXXFLAGS: %s
|
||||
#cgo LDFLAGS: %s
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type (run_build_sh int)
|
||||
`, flags.cpp, flags.cxx, flags.ld)
|
||||
}
|
||||
|
||||
func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags string, packages []pkg) {
|
||||
args = addTag(args, "byollvm")
|
||||
|
||||
srcdir := llvmConfig("--src-root")
|
||||
|
||||
tmpgopath, err := ioutil.TempDir("", "gopath")
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
for _, p := range packages {
|
||||
path := filepath.Join(tmpgopath, "src", p.pkgpath)
|
||||
err := os.MkdirAll(filepath.Dir(path), os.ModePerm)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
abspath := p.llvmpath
|
||||
if !filepath.IsAbs(abspath) {
|
||||
abspath = filepath.Join(srcdir, abspath)
|
||||
}
|
||||
|
||||
err = os.Symlink(abspath, path)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
newpath := os.Getenv("PATH")
|
||||
|
||||
newgopathlist := []string{tmpgopath}
|
||||
newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...)
|
||||
newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator))
|
||||
|
||||
flags := llvmFlags()
|
||||
|
||||
newenv := []string{
|
||||
"CC=" + cc,
|
||||
"CXX=" + cxx,
|
||||
"CGO_CPPFLAGS=" + flags.cpp + " " + cppflags,
|
||||
"CGO_CXXFLAGS=" + flags.cxx + " " + cxxflags,
|
||||
"CGO_LDFLAGS=" + flags.ld + " " + ldflags,
|
||||
"GOPATH=" + newgopath,
|
||||
"PATH=" + newpath,
|
||||
}
|
||||
if llgo != "" {
|
||||
newenv = append(newenv, "GCCGO="+llgo)
|
||||
}
|
||||
|
||||
for _, v := range os.Environ() {
|
||||
if !strings.HasPrefix(v, "CC=") &&
|
||||
!strings.HasPrefix(v, "CXX=") &&
|
||||
!strings.HasPrefix(v, "CGO_CPPFLAGS=") &&
|
||||
!strings.HasPrefix(v, "CGO_CXXFLAGS=") &&
|
||||
!strings.HasPrefix(v, "CGO_LDFLAGS=") &&
|
||||
!strings.HasPrefix(v, "GCCGO=") &&
|
||||
!strings.HasPrefix(v, "GOPATH=") &&
|
||||
!strings.HasPrefix(v, "PATH=") {
|
||||
newenv = append(newenv, v)
|
||||
}
|
||||
}
|
||||
|
||||
gocmdpath, err := exec.LookPath(gocmd)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
proc, err := os.StartProcess(gocmdpath, append([]string{gocmd}, args...),
|
||||
&os.ProcAttr{
|
||||
Env: newenv,
|
||||
Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
|
||||
})
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
ps, err := proc.Wait()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
os.RemoveAll(tmpgopath)
|
||||
|
||||
if !ps.Success() {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Println(`Usage: llvm-go subcommand [flags]
|
||||
|
||||
Available subcommands: build get install run test print-components print-config`)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func main() {
|
||||
cc := os.Getenv("CC")
|
||||
cxx := os.Getenv("CXX")
|
||||
cppflags := os.Getenv("CGO_CPPFLAGS")
|
||||
cxxflags := os.Getenv("CGO_CXXFLAGS")
|
||||
ldflags := os.Getenv("CGO_LDFLAGS")
|
||||
gocmd := "go"
|
||||
llgo := ""
|
||||
packagesString := ""
|
||||
|
||||
flags := []struct {
|
||||
name string
|
||||
dest *string
|
||||
}{
|
||||
{"cc", &cc},
|
||||
{"cxx", &cxx},
|
||||
{"go", &gocmd},
|
||||
{"llgo", &llgo},
|
||||
{"cppflags", &cppflags},
|
||||
{"ldflags", &ldflags},
|
||||
{"packages", &packagesString},
|
||||
}
|
||||
|
||||
args := os.Args[1:]
|
||||
LOOP:
|
||||
for {
|
||||
if len(args) == 0 {
|
||||
usage()
|
||||
}
|
||||
for _, flag := range flags {
|
||||
if strings.HasPrefix(args[0], flag.name+"=") {
|
||||
*flag.dest = args[0][len(flag.name)+1:]
|
||||
args = args[1:]
|
||||
continue LOOP
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
packages := packages
|
||||
if packagesString != "" {
|
||||
for _, field := range strings.Fields(packagesString) {
|
||||
pos := strings.IndexRune(field, '=')
|
||||
if pos == -1 {
|
||||
fmt.Fprintf(os.Stderr, "invalid packages value %q, expected 'pkgpath=llvmpath [pkgpath=llvmpath ...]'\n", packagesString)
|
||||
os.Exit(1)
|
||||
}
|
||||
packages = append(packages, pkg{
|
||||
pkgpath: field[:pos],
|
||||
llvmpath: field[pos+1:],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
switch args[0] {
|
||||
case "build", "get", "install", "run", "test":
|
||||
runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags, packages)
|
||||
case "print-components":
|
||||
printComponents()
|
||||
case "print-config":
|
||||
printConfig()
|
||||
default:
|
||||
usage()
|
||||
}
|
||||
}
|
@ -23,10 +23,6 @@ class FindTool(object):
|
||||
|
||||
if self.name == 'llc' and os.environ.get('LLVM_ENABLE_MACHINE_VERIFIER') == '1':
|
||||
command += ' -verify-machineinstrs'
|
||||
elif self.name == 'llvm-go':
|
||||
exe = getattr(config.config, 'go_executable', None)
|
||||
if exe:
|
||||
command += ' go=' + exe
|
||||
return command
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user