OS Specific LLVM Toolchain
|
This article's tone or style may not reflect the encyclopedic tone used throughout the wiki. See Wikipedia's article on tone for suggestions. |
|
|
This page is about creating an OS-specific LLVM toolchain. If using GCC, please refer to this page.
Also note that this tutorial is made for a very recent version of LLVM.
Until now you have been using a cross-compiler, which is very useful at the beginning as it allows you to easily generate code for a bare metal environment. However, the disadvantage of this approach is that the compiler does not know your operating system.
For example, when using Clang, one would use the triple x86_64-unknown-none. If you are, then you may prefer to be able to use x86_64-unknown-myos instead for many reasons, though a sysroot can replicate many of them.
Step 1: Clone LLVM
In order to edit LLVM components, you first need to clone the LLVM project git repository.
Step 2: Understanding
What we are going to do is making clang, lld and other toolchain components able to generate binaries for our operating system. To know what system it should target, LLVM uses triples, which are simple strings representing a given system. As said above, the triple we want to add is arch-unknown-myoswhere archis the computer architecture (e.g. x86_64) and myosis the name of your OS.
For example, type clang --versionin your terminal. If you are on a GNU/Linux system, you would see a similar output to the following:
<distro> clang version <version>
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: <directory>
As you can see, the default target triple is x86_64-pc-linux-gnu. Which means that the compiler would generate binaries for a GNU/Linux system on the x86_64 architecture.
pcis not very important, it is just an additional information.
Step 3: TripleName.def
The first thing we will do is defining our operating system triple. To do so, we must modify llvm/include/llvm/TargetParse/TripleName.def.
Add the following:
// other calls to TRIPLE_OS()
// ...
TRIPLE_OS(MyOS, "myos", "MyOS")
Step 4: Triple.h
Next, add your OS to llvm::Triple::OSType, which is defined in llvm/include/llvm/TargetParser/Triple.h.
// ...
enum OSType {
// ...
MyOS
LastOSType = MyOS
}
Step 5: OSTargets.h
Now we can add our own target. We can do this by adding a class which inherits from clang::targets::OSTargetInfo to clang/lib/Basic/Targets/OSTargets.h.
template<typename Target>
class LLVM_LIBRARY_VISIBILITY MyosTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
Builder.defineMacro("__myos__");
Builder.defineMacro("__ELF__"); // depends on your OS executables
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
DefineStd(Builder, "unix", Opts);
}
public:
MyosTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->WIntType = TargetInfo::UnsignedInt;
}
};
