eBPF from Go - II
Following up from the previous blog post… I’ve got a JSON file with the string ‘bpf’ in the correct place. Let’s see what tinygo thinks of that:
% ./build/tinygo build -o miekg/main.bpf -target bpf ./miekg/main.go
No available targets are compatible with triple "bpf-unknown-unknown"
clang
indeed does not list bpf as a valid target, so this needs to be added.
The llvm build is configured from the main
GNUMakefile, with
-DLLVM_TARGETS_TO_BUILD...
. Using grep and find I found the “llvm/test/CodeGen” directory, which,
in addition to all listed targets also has a BPF directory. Let’s add BPF to that list and recompile.
% ./llvm-build/bin/clang -print-targets|grep bpf
bpf - BPF (host endian)
bpfeb - BPF (big endian)
bpfel - BPF (little endian)
That looks good, but WTH, ‘big endian’ and ’little endian’ – this matters when compiling to BPF…?
Anyhow: tinygo understands BPF:
% ./build/tinygo build -o miekg/main.bpf -target bpf ./miekg/main.go
'+bulk-memory' is not a recognized feature for this target (ignoring feature)
'+mutable-globals' is not a recognized feature for this target (ignoring feature)
'+nontrapping-fptoint' is not a recognized feature for this target (ignoring feature)
'+sign-ext' is not a recognized feature for this target (ignoring feature)
LLVM ERROR: unable to allocate function return #1
LLVM ERROR: unimplemented opcode: 192
LLVM ERROR: unimplemented opcode: 192
LLVM ERROR: unable to allocate function return #1
LLVM ERROR: unable to allocate function return #1
LLVM ERROR: unable to allocate function return #1
LLVM ERROR: unimplemented opcode: 192
failed to build /home/miek/src/github.com/miekg/tinygo/llvm-project/compiler-rt/lib/builtins/absvti2.c: signal: aborted (core dumped)
Next up: understand what the above means and figuring out “the rest”.
Current Diff⌗
For those following along at home, this is the current diff I have against tinygo:
diff --git a/GNUmakefile b/GNUmakefile
index 94d9c357..c50dccb1 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -244,7 +244,7 @@ llvm-source: $(LLVM_PROJECTDIR)/llvm ## Get LLVM sources
# Configure LLVM.
TINYGO_SOURCE_DIR=$(shell pwd)
$(LLVM_BUILDDIR)/build.ninja:
- mkdir -p $(LLVM_BUILDDIR) && cd $(LLVM_BUILDDIR) && cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;AVR;Mips;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=Xtensa" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF $(LLVM_OPTION)
+ mkdir -p $(LLVM_BUILDDIR) && cd $(LLVM_BUILDDIR) && cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;AVR;Mips;RISCV;WebAssembly;BPF" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=Xtensa" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF $(LLVM_OPTION)
$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja ## Build LLVM
cd $(LLVM_BUILDDIR) && ninja $(NINJA_BUILD_TARGETS)
diff --git a/targets/bpf.json b/targets/bpf.json
new file mode 100644
index 00000000..1bc2e5c0
--- /dev/null
+++ b/targets/bpf.json
@@ -0,0 +1,16 @@
+{
+ "llvm-target": "bpf",
+ "cpu": "generic",
+ "features": "",
+ "build-tags": ["tinygo.bpf", "linux"],
+ "goos": "linux",
+ "gc": "leaking",
+ "goarch": "amd64",
+ "linker": "ld.lld",
+ "rtlib": "",
+ "default-stack-size": 512,
+ "cflags": [ ],
+ "ldflags": [ ],
+ "extra-files": [ ],
+ "emulator": ""
+}