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":      ""
+}