Building a rustc target for Poplar
We want a target in rustc for building userspace programs for Poplar. It would be especially cool to get it
merged as an upstream Tier-3 target. This documents my progress, mainly as a reference for me to remember how it all
works.
How do I actually build and use rustc?
A useful baseline invocation for normal use is:
./x.py build -i library/std
The easiest way to test the built rustc is to create a rustup toolchain (from the root of the Rust repo):
rustup toolchain link poplar build/{host triple}/stage1 # If you built a stage-1 compiler (default with invocation above)
rustup toolchain link poplar build/{host triple}/stage2 # If you built a stage-2 compiler
It's easiest to call your toolchain poplar, as this is the name we use in the Makefiles for now.
You can then use this toolchain from Cargo anywhere on the system with:
cargo +poplar build # Or whatever command you need
Using a custom LLVM
- Fork Rust's
llvm-project cd src/llvm_projectgit remote add my_fork {url to your custom LLVM's repo}git fetch my_forkgit checkout my_fork/{the correct branch}cd ..git add llvm-projectgit commit -m "Move to custom LLVM"
Things to change in config.toml
This is as of 2020-09-29 - you need to remember to keep the config.toml up-to-date (as it's not checked in
upstream), and can cause confusing errors when it's out-of-date.
download-ci-llvm = trueunder[llvm]. This makes the build much faster, since we don't need a custom LLVM.assertions = trueunder[llvm]incremental = trueunder[rust]lld = trueunder[rust]. Without this, the toolchain can't findrust-lldwhen linking.llvm-tools = trueunder[rust]. This probably isn't needed, I just chucked it in in caserust-lldneeds it.
Adding the target
I used a slightly different layout to most targets (which have a base, which creates a TargetOptions, and then a
target that modifies and uses those options).
- Poplar targets generally need a custom linker script. I added one at
compiler/rustc_target/src/spec/x86_64_poplar.ld. - Make a module for the target (I called mine
compiler/rustc_target/src/spec/x86_64_poplar.rs). Copy from a existing one. Instead of a separatepoplar_base.rsto create theTargetOptions, we do it in the target itself. Weinclude_str!the linker script in here, so it's distributed as part of therustcbinary. - Add the target in the
supported_targets!macro incompiler/rustc_target/src/spec/mod.rs.
Adding the target to LLVM
I don't really know my way around the LLVM code base, so this was fairly cobbled together:
- In
llvm/include/llvm/ADT/Triple.h, add a variant for the OS in theOSTypeenum. I called itPoplar. Don't make it the last entry, to avoid having to change theLastOSTypevariant. - In
llvm/lib/Support/Triple.cpp, in the functionTriple::getOSTypeName, add the OS. I addedcase Poplar: return "poplar";. - In the same file, in the
parseOSfunction, add the OS. I added.StartsWith("poplar", Triple::Poplar). - This file also contains a function,
getDefaultFormat, that gives the default format for a platform. The default is ELF, so no changes were needed for Poplar, but they might be for another OS.
TIP: When you make a change in the llvm-project submodule, you will need to commit these changes, and then update
the submodule in the parent repo, or the bootstrap script will checkout the old version (without your changes) and
build an entire compiler without the changes you are trying to test.
NOTE: to avoid people from having to switch to our llvm-project fork, we don't actually use our LLVM target from
rustc (yet). I'm not sure why you need per-OS targets in LLVM, as it doesn't even seem to let us do any of the
things we wanted to (this totally might just be me not knowing how LLVM targets work).
Notes
- We needed to change the entry point to
_start, or it silently just doesn't emit any sections in the final image. - By default, it throws away our
.capssections. We need a way to emit it regardless - this is done by manually creating the program header and specifying that they should be kept withKEEP. There are two possible solutions that I can see: makerustcemit a linker script, or try and introduce these ideas intollvm/lldwith our target (I'm not even sure this is possible). - It looks like
lldhas no OS-specific code at all, and the only place that specifically-kept sections are added is in the linker script parser. Looks like we might have to actually create a file-based linker script (does literally noone else need to pass a linker script by command line??).