From c9f95165b5602d1759bc7a3f2ba80e7f70212318 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Mon, 27 Jul 2026 08:55:09 +0800 Subject: [PATCH 1/5] go-llvm: add explicit GoALLC LLVM configuration --- .gitignore | 1 + README.markdown | 14 ++- gen_llvm_config.sh | 180 ++++++++++++++++++++++++++++++++++++++ gen_llvm_config_static.sh | 33 +------ llvm_config_llvm14.go | 2 +- llvm_config_llvm15.go | 2 +- llvm_config_llvm16.go | 2 +- llvm_config_llvm17.go | 2 +- llvm_config_llvm18.go | 2 +- llvm_config_llvm19.go | 2 +- llvm_config_llvm20.go | 2 +- llvm_config_llvm21.go | 2 +- llvm_config_llvm22.go | 2 +- llvm_config_llvm23.go | 2 +- llvm_config_static.go | 14 --- 15 files changed, 206 insertions(+), 56 deletions(-) create mode 100755 gen_llvm_config.sh mode change 100644 => 100755 gen_llvm_config_static.sh delete mode 100644 llvm_config_static.go diff --git a/.gitignore b/.gitignore index 68f25aa..918c368 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ llvm-*.src.tar.xz llvm-*/ +llvm_config_goallc_generated.go diff --git a/README.markdown b/README.markdown index 6c60343..9163f0c 100644 --- a/README.markdown +++ b/README.markdown @@ -13,9 +13,17 @@ build tag, for example `-tags=llvm17` to use LLVM 17. When using a manually built LLVM 22 or newer, combine the version and custom-build tags, for example `-tags="byollvm llvm23"`. -The GoALLC in-tree static LLVM payload is selected explicitly with -`-tags=staticllvm`. Add a version tag when the payload is not LLVM 23, for -example `-tags="staticllvm llvm20"`. +GoALLC uses an explicit LLVM payload directory instead of ambient cgo +environment variables. Generate the project configuration with: + + ./gen_llvm_config.sh --llvm-dir /path/to/llvm --link dynamic + +The directory must contain `bin/llvm-config`, `include/llvm-c`, and `lib`. +`--link` accepts `dynamic` (the default) or `static`; both modes use the same +directory layout. The generated file is selected by the `goallc` build tag. +Static mode uses `llvm-config` to select the LLVM archives and their system +libraries, including correct archive grouping on Linux and dependency ordering +on macOS. ## Usage diff --git a/gen_llvm_config.sh b/gen_llvm_config.sh new file mode 100755 index 0000000..ceb3997 --- /dev/null +++ b/gen_llvm_config.sh @@ -0,0 +1,180 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + cat <<'EOF' +usage: gen_llvm_config.sh [--llvm-dir DIR] [--link dynamic|static] [--output FILE] + +Generate the project-specific cgo configuration used by GoALLC. DIR must use +the common LLVM payload layout: + + DIR/bin/llvm-config + DIR/include/llvm-c + DIR/lib + +The default directory is ./llvm, the default link mode is dynamic, and the +default output is ./llvm_config_goallc_generated.go. +EOF +} + +script_dir="$(cd "$(dirname "$0")" && pwd -P)" +llvm_dir="${script_dir}/llvm" +link_mode="dynamic" +output="${script_dir}/llvm_config_goallc_generated.go" + +while [[ $# -gt 0 ]]; do + case "$1" in + --llvm-dir) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + llvm_dir="$2" + shift 2 + ;; + --link) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + link_mode="$2" + shift 2 + ;; + --output) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + output="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "gen_llvm_config.sh: unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +case "$link_mode" in + dynamic|static) ;; + *) + echo "gen_llvm_config.sh: --link must be dynamic or static" >&2 + exit 2 + ;; +esac + +if [[ ! -d "$llvm_dir/include/llvm-c" ]]; then + echo "gen_llvm_config.sh: LLVM C headers not found under $llvm_dir/include" >&2 + exit 1 +fi +if [[ ! -d "$llvm_dir/lib" ]]; then + echo "gen_llvm_config.sh: LLVM library directory not found: $llvm_dir/lib" >&2 + exit 1 +fi +if [[ ! -x "$llvm_dir/bin/llvm-config" ]]; then + echo "gen_llvm_config.sh: executable llvm-config not found: $llvm_dir/bin/llvm-config" >&2 + exit 1 +fi + +llvm_dir="$(cd "$llvm_dir" && pwd -P)" +if [[ "$llvm_dir" == *[[:space:]#]* ]]; then + echo "gen_llvm_config.sh: LLVM directory must not contain whitespace or '#': $llvm_dir" >&2 + exit 1 +fi + +llvm_config="${llvm_dir}/bin/llvm-config" +llvm_version="$("$llvm_config" --version)" +llvm_major="${llvm_version%%.*}" +if [[ "$llvm_major" != "23" ]]; then + echo "gen_llvm_config.sh: GoALLC requires LLVM 23, found $llvm_version" >&2 + exit 1 +fi + +host_uname="$(uname -s)" +case "$host_uname" in + Darwin) + cgo_os="darwin" + ;; + Linux) + cgo_os="linux" + ;; + *) + echo "gen_llvm_config.sh: unsupported host: $host_uname" >&2 + exit 1 + ;; +esac + +cppflags="-I${llvm_dir}/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS" +if [[ "$cgo_os" == "linux" ]]; then + cppflags="$cppflags -D_GNU_SOURCE" +fi + +if [[ "$link_mode" == "dynamic" ]]; then + if [[ "$cgo_os" == "darwin" ]]; then + compgen -G "${llvm_dir}/lib/libLLVM*.dylib" >/dev/null || + { echo "gen_llvm_config.sh: libLLVM dylib not found under $llvm_dir/lib" >&2; exit 1; } + ldflags="-L${llvm_dir}/lib -Wl,-rpath,${llvm_dir}/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM" + else + compgen -G "${llvm_dir}/lib/libLLVM*.so*" >/dev/null || + { echo "gen_llvm_config.sh: libLLVM shared library not found under $llvm_dir/lib" >&2; exit 1; } + ldflags="-L${llvm_dir}/lib -Wl,-rpath,${llvm_dir}/lib -lLLVM" + fi +else + # The public binding exposes InitializeAllTargets and the interpreter, so + # their archives must be present even when the host target is the only one + # used by a particular program. + components=(core analysis bitreader bitwriter irreader linker passes all-targets executionengine mcjit interpreter target) + configured_libfiles="$("$llvm_config" --link-static --libfiles "${components[@]}")" + system_libs="$("$llvm_config" --link-static --system-libs "${components[@]}")" + if [[ " $system_libs " == *" -lzstd "* ]] && command -v pkg-config >/dev/null 2>&1; then + zstd_libdirs="$(pkg-config --libs-only-L libzstd 2>/dev/null || true)" + if [[ -n "$zstd_libdirs" ]]; then + system_libs="$zstd_libdirs $system_libs" + fi + fi + if [[ -z "$configured_libfiles" ]]; then + echo "gen_llvm_config.sh: llvm-config returned no static libraries" >&2 + exit 1 + fi + + libfiles="" + for configured_archive in $configured_libfiles; do + archive="${llvm_dir}/lib/$(basename "$configured_archive")" + [[ -f "$archive" ]] || + { echo "gen_llvm_config.sh: static LLVM archive not found: $archive" >&2; exit 1; } + libfiles="${libfiles} ${archive}" + done + libfiles="${libfiles# }" + + if [[ "$cgo_os" == "darwin" ]]; then + # llvm-config emits archives in dependency order. Pass them as direct + # linker inputs: cgo permits archive paths, and Darwin ld consumes this + # order without the GNU-only --start-group option. + ldflags="$libfiles $system_libs" + else + ldflags="-Wl,--start-group $libfiles -Wl,--end-group $system_libs" + fi +fi + +output_dir="$(dirname "$output")" +mkdir -p "$output_dir" +tmp_output="${output}.tmp.$$" +trap 'rm -f "$tmp_output"' EXIT + +cat >"$tmp_output" < "./llvm_config_static.go" <&2 +exec "${script_dir}/gen_llvm_config.sh" "$@" --link static diff --git a/llvm_config_llvm14.go b/llvm_config_llvm14.go index 154b4f5..9241575 100644 --- a/llvm_config_llvm14.go +++ b/llvm_config_llvm14.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm14 +//go:build !goallc && !byollvm && !staticllvm && llvm14 package llvm diff --git a/llvm_config_llvm15.go b/llvm_config_llvm15.go index bf4c451..e42d342 100644 --- a/llvm_config_llvm15.go +++ b/llvm_config_llvm15.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm15 +//go:build !goallc && !byollvm && !staticllvm && llvm15 package llvm diff --git a/llvm_config_llvm16.go b/llvm_config_llvm16.go index 6d742ed..c1e7b8f 100644 --- a/llvm_config_llvm16.go +++ b/llvm_config_llvm16.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm16 +//go:build !goallc && !byollvm && !staticllvm && llvm16 package llvm diff --git a/llvm_config_llvm17.go b/llvm_config_llvm17.go index 58a377c..046c70f 100644 --- a/llvm_config_llvm17.go +++ b/llvm_config_llvm17.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm17 +//go:build !goallc && !byollvm && !staticllvm && llvm17 package llvm diff --git a/llvm_config_llvm18.go b/llvm_config_llvm18.go index 7a706bf..83020f2 100644 --- a/llvm_config_llvm18.go +++ b/llvm_config_llvm18.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm18 +//go:build !goallc && !byollvm && !staticllvm && llvm18 package llvm diff --git a/llvm_config_llvm19.go b/llvm_config_llvm19.go index bbe44d8..71e300c 100644 --- a/llvm_config_llvm19.go +++ b/llvm_config_llvm19.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm19 +//go:build !goallc && !byollvm && !staticllvm && llvm19 package llvm diff --git a/llvm_config_llvm20.go b/llvm_config_llvm20.go index 224418c..ca40948 100644 --- a/llvm_config_llvm20.go +++ b/llvm_config_llvm20.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm20 +//go:build !goallc && !byollvm && !staticllvm && llvm20 package llvm diff --git a/llvm_config_llvm21.go b/llvm_config_llvm21.go index de236b4..a11f57c 100644 --- a/llvm_config_llvm21.go +++ b/llvm_config_llvm21.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm21 +//go:build !goallc && !byollvm && !staticllvm && llvm21 package llvm diff --git a/llvm_config_llvm22.go b/llvm_config_llvm22.go index e468b61..eda7c60 100644 --- a/llvm_config_llvm22.go +++ b/llvm_config_llvm22.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && llvm22 +//go:build !goallc && !byollvm && !staticllvm && llvm22 package llvm diff --git a/llvm_config_llvm23.go b/llvm_config_llvm23.go index ddfeb87..fab21af 100644 --- a/llvm_config_llvm23.go +++ b/llvm_config_llvm23.go @@ -1,4 +1,4 @@ -//go:build !byollvm && !staticllvm && !llvm14 && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 && !llvm20 && !llvm21 && !llvm22 +//go:build !goallc && !byollvm && !staticllvm && !llvm14 && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 && !llvm20 && !llvm21 && !llvm22 package llvm diff --git a/llvm_config_static.go b/llvm_config_static.go deleted file mode 100644 index 24e172d..0000000 --- a/llvm_config_static.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build !byollvm && staticllvm - -// Code generated by gen_llvm_config_static.sh; DO NOT EDIT. - -package llvm - -/* -#cgo linux CPPFLAGS: -I${SRCDIR}/llvm/include/ -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -#cgo linux CXXFLAGS: -std=c++17 -#cgo linux LDFLAGS: -Wl,--start-group -lz -lzstd -L${SRCDIR}/llvm/lib -lLLVMAArch64AsmParser -lLLVMAArch64CodeGen -lLLVMAArch64Desc -lLLVMAArch64Disassembler -lLLVMAArch64Info -lLLVMAArch64Utils -lLLVMAggressiveInstCombine -lLLVMAnalysis -lLLVMAsmParser -lLLVMAsmPrinter -lLLVMBinaryFormat -lLLVMBitReader -lLLVMBitstreamReader -lLLVMBitWriter -lLLVMCAS -lLLVMCFGuard -lLLVMCFIVerify -lLLVMCGData -lLLVMCodeGen -lLLVMCodeGenTypes -lLLVMCore -lLLVMCoroutines -lLLVMCoverage -lLLVMDebugInfoBTF -lLLVMDebugInfoCodeView -lLLVMDebuginfod -lLLVMDebugInfoDWARF -lLLVMDebugInfoDWARFLowLevel -lLLVMDebugInfoGSYM -lLLVMDebugInfoLogicalView -lLLVMDebugInfoMSF -lLLVMDebugInfoPDB -lLLVMDemangle -lLLVMDiff -lLLVMDlltoolDriver -lLLVMDWARFCFIChecker -lLLVMDWARFLinker -lLLVMDWARFLinkerClassic -lLLVMDWARFLinkerParallel -lLLVMDWP -lLLVMExecutionEngine -lLLVMExegesis -lLLVMExegesisAArch64 -lLLVMExegesisX86 -lLLVMExtensions -lLLVMFileCheck -lLLVMFrontendAtomic -lLLVMFrontendDirective -lLLVMFrontendDriver -lLLVMFrontendHLSL -lLLVMFrontendOffloading -lLLVMFrontendOpenACC -lLLVMFrontendOpenMP -lLLVMFuzzerCLI -lLLVMFuzzMutate -lLLVMGlobalISel -lLLVMHipStdPar -lLLVMInstCombine -lLLVMInstrumentation -lLLVMInterfaceStub -lLLVMInterpreter -lLLVMipo -lLLVMIRPrinter -lLLVMIRReader -lLLVMJITLink -lLLVMLibDriver -lLLVMLineEditor -lLLVMLinker -lLLVMLTO -lLLVMMC -lLLVMMCA -lLLVMMCDisassembler -lLLVMMCJIT -lLLVMMCParser -lLLVMMIRParser -lLLVMObjCARCOpts -lLLVMObjCopy -lLLVMObject -lLLVMObjectYAML -lLLVMOptDriver -lLLVMOption -lLLVMOrcDebugging -lLLVMOrcJIT -lLLVMOrcShared -lLLVMOrcTargetProcess -lLLVMPasses -lLLVMProfileData -lLLVMRemarks -lLLVMRuntimeDyld -lLLVMSandboxIR -lLLVMScalarOpts -lLLVMSelectionDAG -lLLVMSupport -lLLVMSupportLSP -lLLVMSymbolize -lLLVMTableGen -lLLVMTableGenBasic -lLLVMTableGenCommon -lLLVMTarget -lLLVMTargetParser -lLLVMTelemetry -lLLVMTextAPI -lLLVMTextAPIBinaryReader -lLLVMTransformUtils -lLLVMVectorize -lLLVMWindowsDriver -lLLVMWindowsManifest -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Disassembler -lLLVMX86Info -lLLVMX86TargetMCA -lLLVMXRay -Wl,--end-group -*/ -import "C" - -type run_build_sh int From 913a3ce064c21b6c53c6cd074d715ea58c342f52 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Mon, 27 Jul 2026 10:17:11 +0800 Subject: [PATCH 2/5] go-llvm: use explicit custom LLVM build tags --- .github/workflows/test.yml | 95 +++++++------------- .gitignore | 2 +- README.markdown | 50 +++++------ branch_llvm23.go | 2 +- branch_pre23.go | 13 --- gen_llvm_config.sh | 180 ------------------------------------- gen_llvm_config_static.sh | 8 -- llvm/bin/.gitignore | 4 - llvm/include/.gitignore | 4 - llvm/lib/.gitignore | 4 - llvm/share/.gitignore | 4 - llvm_config.go | 9 ++ llvm_config_llvm14.go | 16 ---- llvm_config_llvm15.go | 16 ---- llvm_config_llvm16.go | 16 ---- llvm_config_llvm17.go | 16 ---- llvm_config_llvm18.go | 16 ---- llvm_config_llvm19.go | 19 ---- llvm_config_llvm20.go | 19 ---- llvm_config_llvm21.go | 19 ---- llvm_config_llvm22.go | 19 ---- llvm_config_llvm23.go | 19 ---- llvm_dep.go | 10 +-- llvm_link_dynamic.go | 11 +++ llvm_link_static.go | 11 +++ llvm_version_23.go | 5 ++ opcode_llvm23.go | 2 +- opcode_pre23.go | 10 --- passes_llvm23_test.go | 2 +- passes_pre23_test.go | 7 -- switch_llvm22.go | 2 +- switch_pre22.go | 15 ---- 32 files changed, 100 insertions(+), 525 deletions(-) delete mode 100644 branch_pre23.go delete mode 100755 gen_llvm_config.sh delete mode 100755 gen_llvm_config_static.sh delete mode 100644 llvm/bin/.gitignore delete mode 100644 llvm/include/.gitignore delete mode 100644 llvm/lib/.gitignore delete mode 100644 llvm/share/.gitignore create mode 100644 llvm_config.go delete mode 100644 llvm_config_llvm14.go delete mode 100644 llvm_config_llvm15.go delete mode 100644 llvm_config_llvm16.go delete mode 100644 llvm_config_llvm17.go delete mode 100644 llvm_config_llvm18.go delete mode 100644 llvm_config_llvm19.go delete mode 100644 llvm_config_llvm20.go delete mode 100644 llvm_config_llvm21.go delete mode 100644 llvm_config_llvm22.go delete mode 100644 llvm_config_llvm23.go create mode 100644 llvm_link_dynamic.go create mode 100644 llvm_link_static.go create mode 100644 llvm_version_23.go delete mode 100644 opcode_pre23.go delete mode 100644 passes_pre23_test.go delete mode 100644 switch_pre22.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4cdd5d8..6ae9b76 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,76 +1,41 @@ -# Test whether we can link to LLVM installed from apt.llvm.org or Homebrew. ---- - name: Test on: [push, pull_request] jobs: - test-macos: - runs-on: macos-latest + test: + runs-on: ubuntu-24.04 strategy: matrix: - llvm: [14, 15, 16, 17, 18, 19, 20, 21, 22] + link: [dynamic, static] steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v5 + - uses: actions/checkout@v4 + - uses: actions/checkout@v4 with: - go-version: '1.24' - # Optional step when a LLVM version is very new. - - name: Update Homebrew - run: brew update - - name: Install LLVM - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@${{ matrix.llvm }} - - name: Test LLVM ${{ matrix.llvm }} - run: - go test -v -tags=llvm${{ matrix.llvm }} - test-linux: - runs-on: ubuntu-22.04 - strategy: - matrix: - llvm: [14, 15, 16, 17, 18, 19, 20, 21, 22, 23] - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v5 + repository: goallc/llvm-project + ref: codex/goallc-static-library + path: llvm-project + - uses: actions/setup-go@v5 with: - go-version: '1.24' - - name: Install LLVM + go-version: '1.25' + - name: Configure custom LLVM 23 + run: > + cmake -S llvm-project/llvm -B llvm-build -G Ninja + -DCMAKE_BUILD_TYPE=Release + -DLLVM_TARGETS_TO_BUILD=X86 + -DLLVM_BUILD_LLVM_DYLIB=ON + -DLLVM_LINK_LLVM_DYLIB=ON + -DLLVM_BUILD_GOALLC_STATIC=ON + -DLLVM_INCLUDE_BENCHMARKS=OFF + -DLLVM_INCLUDE_EXAMPLES=OFF + -DLLVM_INCLUDE_TESTS=OFF + - name: Build custom LLVM libraries + run: cmake --build llvm-build --target LLVM LLVMGoALLC -j2 + - name: Assemble LLVM payload run: | - suite=llvm-toolchain-jammy-${{ matrix.llvm }} - if [ "${{ matrix.llvm }}" = 23 ]; then - suite=llvm-toolchain-jammy - fi - echo "deb http://apt.llvm.org/jammy/ ${suite} main" | sudo tee /etc/apt/sources.list.d/llvm.list - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo apt-get update - sudo apt-get install --no-install-recommends llvm-${{ matrix.llvm }}-dev - - name: Test LLVM ${{ matrix.llvm }} - run: - go test -v -tags=llvm${{ matrix.llvm }} - - name: Test default LLVM - if: matrix.llvm == 23 - run: - go test -v - test-linux-fedora: - # Fedora uses different paths than other systems, so testing it separately. - runs-on: ubuntu-24.04 - strategy: - matrix: - llvm: [19, 20, 21] - container: fedora:43 - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Install dependencies (default LLVM) - if: matrix.llvm == 21 - run: dnf install --assumeyes g++ golang llvm-devel - - name: Install dependencies (older LLVM) - if: matrix.llvm != 21 - run: dnf install --assumeyes g++ golang llvm${{ matrix.llvm }}-devel - - name: Test LLVM ${{ matrix.llvm }} - run: - go test -v -tags=llvm${{ matrix.llvm }} + mkdir -p llvm/include + cp -R llvm-project/llvm/include/. llvm/include/ + cp -R llvm-build/include/. llvm/include/ + ln -s ../llvm-build/lib llvm/lib + - name: Test bindings + run: go test -v -tags="llvm23 ${{ matrix.link }}llvm" ./... diff --git a/.gitignore b/.gitignore index 918c368..0c6a9f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ llvm-*.src.tar.xz llvm-*/ -llvm_config_goallc_generated.go +/llvm diff --git a/README.markdown b/README.markdown index 9163f0c..6ab36b9 100644 --- a/README.markdown +++ b/README.markdown @@ -1,40 +1,38 @@ -# Go bindings to system LLVM +# Go bindings for GoALLC LLVM -This library provides bindings to a system-installed LLVM. +This repository contains the LLVM Go bindings used by GoALLC. It intentionally +targets the customized LLVM build maintained by the GoALLC project; a +system-installed LLVM is not supported. -Currently supported: +## LLVM payload - * LLVM 23, 22, 21, 20, 19, 18, 17, 16, 15 and 14 from [apt.llvm.org](http://apt.llvm.org/) on Debian/Ubuntu. - * LLVM 23, 22, 21, 20, 19, 18, 17, 16, 15 and 14 from Homebrew on macOS. - * Any of the above versions with a manually built LLVM through the `byollvm` build tag. You need to set up `CFLAGS`/`LDFLAGS` etc yourself in this case. +The binding always reads headers and libraries below `${SRCDIR}/llvm`: -LLVM 23 is selected by default. You can select another LLVM version using a -build tag, for example `-tags=llvm17` to use LLVM 17. When using a manually -built LLVM 22 or newer, combine the version and custom-build tags, for example -`-tags="byollvm llvm23"`. + llvm/include/llvm-c + llvm/lib -GoALLC uses an explicit LLVM payload directory instead of ambient cgo -environment variables. Generate the project configuration with: +`llvm` is not committed. The caller must create it as a symlink to an LLVM +payload with this layout. GoALLC's `cmd/dist` manages that symlink from its +`-llvm-dir` option, whose default is `$GOROOT/llvm`. - ./gen_llvm_config.sh --llvm-dir /path/to/llvm --link dynamic +## Build tags -The directory must contain `bin/llvm-config`, `include/llvm-c`, and `lib`. -`--link` accepts `dynamic` (the default) or `static`; both modes use the same -directory layout. The generated file is selected by the `goallc` build tag. -Static mode uses `llvm-config` to select the LLVM archives and their system -libraries, including correct archive grouping on Linux and dependency ordering -on macOS. +The LLVM API version and link mode are independent, mandatory build-tag axes: -## Usage +* `llvm23` selects the LLVM 23 API. A future LLVM 24 port will add `llvm24` + without changing how the payload path or link mode is selected. +* `dynamicllvm` links `llvm/lib/libLLVM`; it is the GoALLC default. +* `staticllvm` links the customized aggregate archive + `llvm/lib/libLLVMGoALLC.a`. -If you have a supported LLVM installation, you should be able to do a simple `go get`: +For example: - go get tinygo.org/x/go-llvm + go test -tags='llvm23 dynamicllvm' ./... + go test -tags='llvm23 staticllvm' ./... -You can use build tags to select a LLVM version. For example, use `-tags=llvm15` to select LLVM 15. Setting a build tag for a LLVM version that is not supported will be ignored. +Do not select multiple version tags or multiple link-mode tags in one build. ## License -These LLVM bindings for Go originally come from LLVM, but they have since been [removed](https://discourse.llvm.org/t/rfc-remove-the-go-bindings/65725). Still, they remain under the same license as they were originally, which is the [Apache License 2.0 (with LLVM exceptions)](http://releases.llvm.org/9.0.0/LICENSE.TXT). Check upstream LLVM for detailed copyright information. - -This README, the backports\* files, and the Makefile are separate from LLVM but are licensed under the same license. +These bindings originated in LLVM and remain licensed under the Apache License +2.0 with LLVM Exceptions. See `LICENSE.txt`. diff --git a/branch_llvm23.go b/branch_llvm23.go index a19065f..c31cc09 100644 --- a/branch_llvm23.go +++ b/branch_llvm23.go @@ -1,4 +1,4 @@ -//go:build llvm23 || (!byollvm && !llvm14 && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 && !llvm20 && !llvm21 && !llvm22) +//go:build llvm23 package llvm diff --git a/branch_pre23.go b/branch_pre23.go deleted file mode 100644 index e3b33bf..0000000 --- a/branch_pre23.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !llvm23 && (byollvm || llvm14 || llvm15 || llvm16 || llvm17 || llvm18 || llvm19 || llvm20 || llvm21 || llvm22) - -package llvm - -/* -#include "llvm-c/Core.h" -*/ -import "C" - -func (v Value) IsABranchInst() (rv Value) { - rv.C = C.LLVMIsABranchInst(v.C) - return -} diff --git a/gen_llvm_config.sh b/gen_llvm_config.sh deleted file mode 100755 index ceb3997..0000000 --- a/gen_llvm_config.sh +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -usage() { - cat <<'EOF' -usage: gen_llvm_config.sh [--llvm-dir DIR] [--link dynamic|static] [--output FILE] - -Generate the project-specific cgo configuration used by GoALLC. DIR must use -the common LLVM payload layout: - - DIR/bin/llvm-config - DIR/include/llvm-c - DIR/lib - -The default directory is ./llvm, the default link mode is dynamic, and the -default output is ./llvm_config_goallc_generated.go. -EOF -} - -script_dir="$(cd "$(dirname "$0")" && pwd -P)" -llvm_dir="${script_dir}/llvm" -link_mode="dynamic" -output="${script_dir}/llvm_config_goallc_generated.go" - -while [[ $# -gt 0 ]]; do - case "$1" in - --llvm-dir) - [[ $# -ge 2 ]] || { usage >&2; exit 2; } - llvm_dir="$2" - shift 2 - ;; - --link) - [[ $# -ge 2 ]] || { usage >&2; exit 2; } - link_mode="$2" - shift 2 - ;; - --output) - [[ $# -ge 2 ]] || { usage >&2; exit 2; } - output="$2" - shift 2 - ;; - -h|--help) - usage - exit 0 - ;; - *) - echo "gen_llvm_config.sh: unknown argument: $1" >&2 - usage >&2 - exit 2 - ;; - esac -done - -case "$link_mode" in - dynamic|static) ;; - *) - echo "gen_llvm_config.sh: --link must be dynamic or static" >&2 - exit 2 - ;; -esac - -if [[ ! -d "$llvm_dir/include/llvm-c" ]]; then - echo "gen_llvm_config.sh: LLVM C headers not found under $llvm_dir/include" >&2 - exit 1 -fi -if [[ ! -d "$llvm_dir/lib" ]]; then - echo "gen_llvm_config.sh: LLVM library directory not found: $llvm_dir/lib" >&2 - exit 1 -fi -if [[ ! -x "$llvm_dir/bin/llvm-config" ]]; then - echo "gen_llvm_config.sh: executable llvm-config not found: $llvm_dir/bin/llvm-config" >&2 - exit 1 -fi - -llvm_dir="$(cd "$llvm_dir" && pwd -P)" -if [[ "$llvm_dir" == *[[:space:]#]* ]]; then - echo "gen_llvm_config.sh: LLVM directory must not contain whitespace or '#': $llvm_dir" >&2 - exit 1 -fi - -llvm_config="${llvm_dir}/bin/llvm-config" -llvm_version="$("$llvm_config" --version)" -llvm_major="${llvm_version%%.*}" -if [[ "$llvm_major" != "23" ]]; then - echo "gen_llvm_config.sh: GoALLC requires LLVM 23, found $llvm_version" >&2 - exit 1 -fi - -host_uname="$(uname -s)" -case "$host_uname" in - Darwin) - cgo_os="darwin" - ;; - Linux) - cgo_os="linux" - ;; - *) - echo "gen_llvm_config.sh: unsupported host: $host_uname" >&2 - exit 1 - ;; -esac - -cppflags="-I${llvm_dir}/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS" -if [[ "$cgo_os" == "linux" ]]; then - cppflags="$cppflags -D_GNU_SOURCE" -fi - -if [[ "$link_mode" == "dynamic" ]]; then - if [[ "$cgo_os" == "darwin" ]]; then - compgen -G "${llvm_dir}/lib/libLLVM*.dylib" >/dev/null || - { echo "gen_llvm_config.sh: libLLVM dylib not found under $llvm_dir/lib" >&2; exit 1; } - ldflags="-L${llvm_dir}/lib -Wl,-rpath,${llvm_dir}/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM" - else - compgen -G "${llvm_dir}/lib/libLLVM*.so*" >/dev/null || - { echo "gen_llvm_config.sh: libLLVM shared library not found under $llvm_dir/lib" >&2; exit 1; } - ldflags="-L${llvm_dir}/lib -Wl,-rpath,${llvm_dir}/lib -lLLVM" - fi -else - # The public binding exposes InitializeAllTargets and the interpreter, so - # their archives must be present even when the host target is the only one - # used by a particular program. - components=(core analysis bitreader bitwriter irreader linker passes all-targets executionengine mcjit interpreter target) - configured_libfiles="$("$llvm_config" --link-static --libfiles "${components[@]}")" - system_libs="$("$llvm_config" --link-static --system-libs "${components[@]}")" - if [[ " $system_libs " == *" -lzstd "* ]] && command -v pkg-config >/dev/null 2>&1; then - zstd_libdirs="$(pkg-config --libs-only-L libzstd 2>/dev/null || true)" - if [[ -n "$zstd_libdirs" ]]; then - system_libs="$zstd_libdirs $system_libs" - fi - fi - if [[ -z "$configured_libfiles" ]]; then - echo "gen_llvm_config.sh: llvm-config returned no static libraries" >&2 - exit 1 - fi - - libfiles="" - for configured_archive in $configured_libfiles; do - archive="${llvm_dir}/lib/$(basename "$configured_archive")" - [[ -f "$archive" ]] || - { echo "gen_llvm_config.sh: static LLVM archive not found: $archive" >&2; exit 1; } - libfiles="${libfiles} ${archive}" - done - libfiles="${libfiles# }" - - if [[ "$cgo_os" == "darwin" ]]; then - # llvm-config emits archives in dependency order. Pass them as direct - # linker inputs: cgo permits archive paths, and Darwin ld consumes this - # order without the GNU-only --start-group option. - ldflags="$libfiles $system_libs" - else - ldflags="-Wl,--start-group $libfiles -Wl,--end-group $system_libs" - fi -fi - -output_dir="$(dirname "$output")" -mkdir -p "$output_dir" -tmp_output="${output}.tmp.$$" -trap 'rm -f "$tmp_output"' EXIT - -cat >"$tmp_output" <&2 -exec "${script_dir}/gen_llvm_config.sh" "$@" --link static diff --git a/llvm/bin/.gitignore b/llvm/bin/.gitignore deleted file mode 100644 index 86d0cb2..0000000 --- a/llvm/bin/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/llvm/include/.gitignore b/llvm/include/.gitignore deleted file mode 100644 index 86d0cb2..0000000 --- a/llvm/include/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/llvm/lib/.gitignore b/llvm/lib/.gitignore deleted file mode 100644 index 86d0cb2..0000000 --- a/llvm/lib/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/llvm/share/.gitignore b/llvm/share/.gitignore deleted file mode 100644 index 86d0cb2..0000000 --- a/llvm/share/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/llvm_config.go b/llvm_config.go new file mode 100644 index 0000000..e9f5875 --- /dev/null +++ b/llvm_config.go @@ -0,0 +1,9 @@ +package llvm + +/* +#cgo darwin CPPFLAGS: -I${SRCDIR}/llvm/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS +#cgo linux CPPFLAGS: -I${SRCDIR}/llvm/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS +#cgo darwin CXXFLAGS: -std=c++17 +#cgo linux CXXFLAGS: -std=c++17 +*/ +import "C" diff --git a/llvm_config_llvm14.go b/llvm_config_llvm14.go deleted file mode 100644 index 9241575..0000000 --- a/llvm_config_llvm14.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm14 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@14/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++14 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@14/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@14/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++14 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@14/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo linux CPPFLAGS: -I/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++14 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-14/lib -lLLVM-14 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm15.go b/llvm_config_llvm15.go deleted file mode 100644 index e42d342..0000000 --- a/llvm_config_llvm15.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm15 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@15/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++14 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@15/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@15/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++14 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@15/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo linux CPPFLAGS: -I/usr/lib/llvm-15/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++14 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-15/lib -lLLVM-15 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm16.go b/llvm_config_llvm16.go deleted file mode 100644 index c1e7b8f..0000000 --- a/llvm_config_llvm16.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm16 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@16/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++17 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@16/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@16/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++17 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@16/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo linux CPPFLAGS: -I/usr/lib/llvm-16/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++17 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-16/lib -lLLVM-16 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm17.go b/llvm_config_llvm17.go deleted file mode 100644 index 046c70f..0000000 --- a/llvm_config_llvm17.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm17 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@17/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++17 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@17/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@17/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++17 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@17/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo linux CPPFLAGS: -I/usr/include/llvm-17 -I/usr/include/llvm-c-17 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++17 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-17/lib -lLLVM-17 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm18.go b/llvm_config_llvm18.go deleted file mode 100644 index 83020f2..0000000 --- a/llvm_config_llvm18.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm18 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@18/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++17 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@18/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@18/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++17 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@18/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo linux CPPFLAGS: -I/usr/include/llvm-18 -I/usr/include/llvm-c-18 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++17 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-18/lib -lLLVM-18 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm19.go b/llvm_config_llvm19.go deleted file mode 100644 index 71e300c..0000000 --- a/llvm_config_llvm19.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm19 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@19/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++17 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@19/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@19/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++17 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@19/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo freebsd CPPFLAGS: -I/usr/local/llvm19/include -I/usr/local/llvm19/include/llvm-c -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo freebsd CXXFLAGS: -std=c++17 -// #cgo freebsd LDFLAGS: -L/usr/local/llvm19/lib -lLLVM -// #cgo linux CPPFLAGS: -I/usr/include/llvm-19 -I/usr/include/llvm-c-19 -I/usr/lib64/llvm19/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++17 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-19/lib -L/usr/lib64/llvm19/lib -lLLVM-19 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm20.go b/llvm_config_llvm20.go deleted file mode 100644 index ca40948..0000000 --- a/llvm_config_llvm20.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm20 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@20/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++17 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@20/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@20/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++17 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@20/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo freebsd CPPFLAGS: -I/usr/local/llvm20/include -I/usr/local/llvm20/include/llvm-c -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo freebsd CXXFLAGS: -std=c++17 -// #cgo freebsd LDFLAGS: -L/usr/local/llvm20/lib -lLLVM -// #cgo linux CPPFLAGS: -I/usr/include/llvm-20 -I/usr/include/llvm-c-20 -I/usr/lib64/llvm20/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++17 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-20/lib -L/usr/lib64/llvm20/lib64 -lLLVM-20 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm21.go b/llvm_config_llvm21.go deleted file mode 100644 index a11f57c..0000000 --- a/llvm_config_llvm21.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm21 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@21/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++17 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@21/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@21/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++17 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@21/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo freebsd CPPFLAGS: -I/usr/local/llvm21/include -I/usr/local/llvm21/include/llvm-c -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo freebsd CXXFLAGS: -std=c++17 -// #cgo freebsd LDFLAGS: -L/usr/local/llvm21/lib -lLLVM -// #cgo linux CPPFLAGS: -I/usr/include/llvm-21 -I/usr/include/llvm-c-21 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++17 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-21/lib -lLLVM-21 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm22.go b/llvm_config_llvm22.go deleted file mode 100644 index eda7c60..0000000 --- a/llvm_config_llvm22.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && llvm22 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@22/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++17 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@22/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@22/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++17 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@22/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo freebsd CPPFLAGS: -I/usr/local/llvm22/include -I/usr/local/llvm22/include/llvm-c -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo freebsd CXXFLAGS: -std=c++17 -// #cgo freebsd LDFLAGS: -L/usr/local/llvm22/lib -lLLVM -// #cgo linux CPPFLAGS: -I/usr/include/llvm-22 -I/usr/include/llvm-c-22 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++17 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-22/lib -lLLVM-22 -import "C" - -type run_build_sh int diff --git a/llvm_config_llvm23.go b/llvm_config_llvm23.go deleted file mode 100644 index fab21af..0000000 --- a/llvm_config_llvm23.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build !goallc && !byollvm && !staticllvm && !llvm14 && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 && !llvm20 && !llvm21 && !llvm22 - -package llvm - -// #cgo darwin,amd64 CPPFLAGS: -I/usr/local/opt/llvm@23/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,amd64 CXXFLAGS: -std=c++17 -// #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@23/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo darwin,arm64 CPPFLAGS: -I/opt/homebrew/opt/llvm@23/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo darwin,arm64 CXXFLAGS: -std=c++17 -// #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@23/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM -lz -lm -// #cgo freebsd CPPFLAGS: -I/usr/local/llvm23/include -I/usr/local/llvm23/include/llvm-c -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo freebsd CXXFLAGS: -std=c++17 -// #cgo freebsd LDFLAGS: -L/usr/local/llvm23/lib -lLLVM -// #cgo linux CPPFLAGS: -I/usr/include/llvm-23 -I/usr/include/llvm-c-23 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -// #cgo linux CXXFLAGS: -std=c++17 -// #cgo linux LDFLAGS: -L/usr/lib/llvm-23/lib -lLLVM-23 -import "C" - -type run_build_sh int diff --git a/llvm_dep.go b/llvm_dep.go index cdce01b..570fa84 100644 --- a/llvm_dep.go +++ b/llvm_dep.go @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// // -// This file ensures that the LLVM libraries are built before using the -// bindings. +// This file makes selecting an LLVM API version and link mode mandatory. // //===----------------------------------------------------------------------===// -//go:build !byollvm - package llvm -var _ run_build_sh +var ( + _ llvmVersionSelected + _ llvmLinkModeSelected +) diff --git a/llvm_link_dynamic.go b/llvm_link_dynamic.go new file mode 100644 index 0000000..9fbe9ef --- /dev/null +++ b/llvm_link_dynamic.go @@ -0,0 +1,11 @@ +//go:build dynamicllvm + +package llvm + +/* +#cgo darwin LDFLAGS: -L${SRCDIR}/llvm/lib -Wl,-rpath,${SRCDIR}/llvm/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM +#cgo linux LDFLAGS: -L${SRCDIR}/llvm/lib -Wl,-rpath,${SRCDIR}/llvm/lib -lLLVM +*/ +import "C" + +type llvmLinkModeSelected struct{} diff --git a/llvm_link_static.go b/llvm_link_static.go new file mode 100644 index 0000000..17b3cad --- /dev/null +++ b/llvm_link_static.go @@ -0,0 +1,11 @@ +//go:build staticllvm + +package llvm + +/* +#cgo darwin LDFLAGS: -L${SRCDIR}/llvm/lib -lLLVMGoALLC -lm -lz -lxml2 +#cgo linux LDFLAGS: -L${SRCDIR}/llvm/lib -lLLVMGoALLC -lm -lz -lxml2 -ldl -lpthread +*/ +import "C" + +type llvmLinkModeSelected struct{} diff --git a/llvm_version_23.go b/llvm_version_23.go new file mode 100644 index 0000000..0a60710 --- /dev/null +++ b/llvm_version_23.go @@ -0,0 +1,5 @@ +//go:build llvm23 + +package llvm + +type llvmVersionSelected struct{} diff --git a/opcode_llvm23.go b/opcode_llvm23.go index f126e80..9507220 100644 --- a/opcode_llvm23.go +++ b/opcode_llvm23.go @@ -1,4 +1,4 @@ -//go:build llvm23 || (!byollvm && !llvm14 && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 && !llvm20 && !llvm21 && !llvm22) +//go:build llvm23 package llvm diff --git a/opcode_pre23.go b/opcode_pre23.go deleted file mode 100644 index 9a32080..0000000 --- a/opcode_pre23.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !llvm23 && (byollvm || llvm14 || llvm15 || llvm16 || llvm17 || llvm18 || llvm19 || llvm20 || llvm21 || llvm22) - -package llvm - -/* -#include "llvm-c/Core.h" -*/ -import "C" - -const Br Opcode = C.LLVMBr diff --git a/passes_llvm23_test.go b/passes_llvm23_test.go index c348317..df6f891 100644 --- a/passes_llvm23_test.go +++ b/passes_llvm23_test.go @@ -1,4 +1,4 @@ -//go:build llvm23 || (!byollvm && !llvm14 && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 && !llvm20 && !llvm21 && !llvm22) +//go:build llvm23 package llvm diff --git a/passes_pre23_test.go b/passes_pre23_test.go deleted file mode 100644 index 316dcf4..0000000 --- a/passes_pre23_test.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !llvm23 && (byollvm || llvm14 || llvm15 || llvm16 || llvm17 || llvm18 || llvm19 || llvm20 || llvm21 || llvm22) - -package llvm - -const defaultTestPipeline = "default" - -func prepareDefaultTestPipeline(Context, Value) {} diff --git a/switch_llvm22.go b/switch_llvm22.go index 8df6966..cdb7cc2 100644 --- a/switch_llvm22.go +++ b/switch_llvm22.go @@ -1,4 +1,4 @@ -//go:build llvm22 || llvm23 || (!byollvm && !llvm14 && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19 && !llvm20 && !llvm21 && !llvm22) +//go:build llvm23 package llvm diff --git a/switch_pre22.go b/switch_pre22.go deleted file mode 100644 index 6bbfac9..0000000 --- a/switch_pre22.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build !llvm22 && !llvm23 && (byollvm || llvm14 || llvm15 || llvm16 || llvm17 || llvm18 || llvm19 || llvm20 || llvm21) - -package llvm - -// GetSwitchCaseValue obtains the case value for a successor of a switch -// instruction. i corresponds to the successor index; the first successor (0) -// is the default destination, so i must be greater than zero. -// -// Before LLVM 22, switch case values were stored as regular instruction -// operands (alternating with their destination blocks, after the leading -// condition/default-destination pair), so this is implemented via Operand -// access instead of the LLVM 22+-only LLVMGetSwitchCaseValue. -func (v Value) GetSwitchCaseValue(i int) Value { - return v.Operand(2 * i) -} From bbabd2cf14b65fe8f2fb14bc46915f53a7240e69 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Mon, 27 Jul 2026 10:18:32 +0800 Subject: [PATCH 3/5] go-llvm: include GoALLC binding extensions --- goallc_ext.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 goallc_ext.go diff --git a/goallc_ext.go b/goallc_ext.go new file mode 100644 index 0000000..cd6e34a --- /dev/null +++ b/goallc_ext.go @@ -0,0 +1,35 @@ +package llvm + +/* +#include "llvm-c/Core.h" +#include +*/ +import "C" + +import ( + "errors" + "unsafe" +) + +func LLVMPrintModuleToFile(module Module, filename string) error { + filenamestr := C.CString(filename) + defer C.free(unsafe.Pointer(filenamestr)) + var errmsg *C.char + if C.LLVMPrintModuleToFile(module.C, filenamestr, &errmsg) != 0 { + err := errors.New(C.GoString(errmsg)) + C.LLVMDisposeMessage(errmsg) + return err + } + return nil +} + +func LLVMSetValueName2(value Value, name string) { + namestr := C.CString(name) + defer C.free(unsafe.Pointer(namestr)) + C.LLVMSetValueName2(value.C, namestr, C.size_t(len(name))) +} + +func (c Context) PointerType(addressSpace uint32) (t Type) { + t.C = C.LLVMPointerTypeInContext(c.C, C.unsigned(addressSpace)) + return +} From 223f6a9716147cb75d582bcc2ab3c8492fa9634c Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Mon, 27 Jul 2026 12:53:05 +0800 Subject: [PATCH 4/5] go-llvm: make static aggregation a dist responsibility --- .github/workflows/test.yml | 31 ++++++++++++++++++++++--------- .gitignore | 1 + README.markdown | 11 ++++++++--- llvm_link_static.go | 4 ++-- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6ae9b76..4bb6e89 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,19 +1,19 @@ name: Test -on: [push, pull_request] +on: + push: + branches: [master] + pull_request: jobs: test: runs-on: ubuntu-24.04 - strategy: - matrix: - link: [dynamic, static] steps: - uses: actions/checkout@v4 - uses: actions/checkout@v4 with: repository: goallc/llvm-project - ref: codex/goallc-static-library + ref: llvm23.1.master path: llvm-project - uses: actions/setup-go@v5 with: @@ -25,17 +25,30 @@ jobs: -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON - -DLLVM_BUILD_GOALLC_STATIC=ON + -DLLVM_ENABLE_ZSTD=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF - name: Build custom LLVM libraries - run: cmake --build llvm-build --target LLVM LLVMGoALLC -j2 + run: cmake --build llvm-build --target LLVM llvm-ar llvm-config -j2 - name: Assemble LLVM payload run: | mkdir -p llvm/include cp -R llvm-project/llvm/include/. llvm/include/ cp -R llvm-build/include/. llvm/include/ ln -s ../llvm-build/lib llvm/lib - - name: Test bindings - run: go test -v -tags="llvm23 ${{ matrix.link }}llvm" ./... + - name: Test dynamic bindings + run: go test -v -tags="llvm23 dynamicllvm" ./... + - name: Assemble static LLVM archive + run: | + components=(core analysis bitreader bitwriter irreader linker passes all-targets executionengine mcjit interpreter target) + { + echo "CREATE $PWD/libLLVMGoALLC.a" + for archive in $(llvm-build/bin/llvm-config --link-static --libfiles "${components[@]}"); do + echo "ADDLIB $archive" + done + echo SAVE + echo END + } | llvm-build/bin/llvm-ar -M + - name: Test static bindings + run: go test -v -tags="llvm23 staticllvm" ./... diff --git a/.gitignore b/.gitignore index 0c6a9f2..e5b97b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ llvm-*.src.tar.xz llvm-*/ /llvm +/libLLVMGoALLC.a* diff --git a/README.markdown b/README.markdown index 6ab36b9..108378e 100644 --- a/README.markdown +++ b/README.markdown @@ -6,7 +6,8 @@ system-installed LLVM is not supported. ## LLVM payload -The binding always reads headers and libraries below `${SRCDIR}/llvm`: +The binding always reads LLVM headers below `${SRCDIR}/llvm`; dynamic linking +also reads the LLVM shared library there: llvm/include/llvm-c llvm/lib @@ -22,14 +23,18 @@ The LLVM API version and link mode are independent, mandatory build-tag axes: * `llvm23` selects the LLVM 23 API. A future LLVM 24 port will add `llvm24` without changing how the payload path or link mode is selected. * `dynamicllvm` links `llvm/lib/libLLVM`; it is the GoALLC default. -* `staticllvm` links the customized aggregate archive - `llvm/lib/libLLVMGoALLC.a`. +* `staticllvm` links `${SRCDIR}/libLLVMGoALLC.a`. GoALLC's `cmd/dist` + assembles and caches this build artifact from the selected payload's normal + LLVM component archives with `llvm-config` and `llvm-ar`. For example: go test -tags='llvm23 dynamicllvm' ./... go test -tags='llvm23 staticllvm' ./... +The static command requires `libLLVMGoALLC.a` to have been assembled first. +The GoALLC toolchain does this automatically for `-llvm-link=static`. + Do not select multiple version tags or multiple link-mode tags in one build. ## License diff --git a/llvm_link_static.go b/llvm_link_static.go index 17b3cad..c9667f6 100644 --- a/llvm_link_static.go +++ b/llvm_link_static.go @@ -3,8 +3,8 @@ package llvm /* -#cgo darwin LDFLAGS: -L${SRCDIR}/llvm/lib -lLLVMGoALLC -lm -lz -lxml2 -#cgo linux LDFLAGS: -L${SRCDIR}/llvm/lib -lLLVMGoALLC -lm -lz -lxml2 -ldl -lpthread +#cgo darwin LDFLAGS: -L${SRCDIR} -lLLVMGoALLC -lm -lz -lxml2 +#cgo linux LDFLAGS: -L${SRCDIR} -lLLVMGoALLC -lm -lz -lxml2 -ldl -lpthread -lrt */ import "C" From f21ebd5e6699bbb11416b28daacd2807662834d8 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Mon, 27 Jul 2026 14:00:12 +0800 Subject: [PATCH 5/5] ci: defer full tests to prebuilt LLVM payloads --- .github/workflows/test.yml | 49 +++++++------------------------------- README.markdown | 8 +++++++ 2 files changed, 16 insertions(+), 41 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4bb6e89..474acaf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: Test +name: Source checks on: push: @@ -6,49 +6,16 @@ on: pull_request: jobs: - test: + format: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - uses: actions/checkout@v4 - with: - repository: goallc/llvm-project - ref: llvm23.1.master - path: llvm-project - uses: actions/setup-go@v5 with: go-version: '1.25' - - name: Configure custom LLVM 23 - run: > - cmake -S llvm-project/llvm -B llvm-build -G Ninja - -DCMAKE_BUILD_TYPE=Release - -DLLVM_TARGETS_TO_BUILD=X86 - -DLLVM_BUILD_LLVM_DYLIB=ON - -DLLVM_LINK_LLVM_DYLIB=ON - -DLLVM_ENABLE_ZSTD=OFF - -DLLVM_INCLUDE_BENCHMARKS=OFF - -DLLVM_INCLUDE_EXAMPLES=OFF - -DLLVM_INCLUDE_TESTS=OFF - - name: Build custom LLVM libraries - run: cmake --build llvm-build --target LLVM llvm-ar llvm-config -j2 - - name: Assemble LLVM payload - run: | - mkdir -p llvm/include - cp -R llvm-project/llvm/include/. llvm/include/ - cp -R llvm-build/include/. llvm/include/ - ln -s ../llvm-build/lib llvm/lib - - name: Test dynamic bindings - run: go test -v -tags="llvm23 dynamicllvm" ./... - - name: Assemble static LLVM archive - run: | - components=(core analysis bitreader bitwriter irreader linker passes all-targets executionengine mcjit interpreter target) - { - echo "CREATE $PWD/libLLVMGoALLC.a" - for archive in $(llvm-build/bin/llvm-config --link-static --libfiles "${components[@]}"); do - echo "ADDLIB $archive" - done - echo SAVE - echo END - } | llvm-build/bin/llvm-ar -M - - name: Test static bindings - run: go test -v -tags="llvm23 staticllvm" ./... + - name: Check Go formatting + run: test -z "$(gofmt -l .)" + +# Full dynamic and static binding tests require the customized GoALLC LLVM +# payload. Restore those tests by downloading the project's prebuilt payload +# once it is published; do not build LLVM from source in this workflow. diff --git a/README.markdown b/README.markdown index 108378e..fd90b5e 100644 --- a/README.markdown +++ b/README.markdown @@ -37,6 +37,14 @@ The GoALLC toolchain does this automatically for `-llvm-link=static`. Do not select multiple version tags or multiple link-mode tags in one build. +## Continuous integration + +Automatic pull-request checks currently validate the binding source only. Full +dynamic and static tests require the customized GoALLC LLVM payload and are +validated as part of integration work. Once the project publishes prebuilt LLVM +payloads, CI will download those artifacts and run both link modes without +rebuilding LLVM from source. + ## License These bindings originated in LLVM and remain licensed under the Apache License