1======================================== 2 Kaleidoscope: Compiling to Object Code 3======================================== 4 5.. contents:: 6 :local: 7 8Chapter 8 Introduction 9====================== 10 11Welcome to Chapter 8 of the "`Implementing a language with LLVM 12<index.html>`_" tutorial. This chapter describes how to compile our 13language down to object files. 14 15Choosing a target 16================= 17 18LLVM has native support for cross-compilation. You can compile to the 19architecture of your current machine, or just as easily compile for 20other architectures. In this tutorial, we'll target the current 21machine. 22 23To specify the architecture that you want to target, we use a string 24called a "target triple". This takes the form 25``<arch><sub>-<vendor>-<sys>-<abi>`` (see the `cross compilation docs 26<https://clang.llvm.org/docs/CrossCompilation.html#target-triple>`_). 27 28As an example, we can see what clang thinks is our current target 29triple: 30 31:: 32 33 $ clang --version | grep Target 34 Target: x86_64-unknown-linux-gnu 35 36Running this command may show something different on your machine as 37you might be using a different architecture or operating system to me. 38 39Fortunately, we don't need to hard-code a target triple to target the 40current machine. LLVM provides ``sys::getDefaultTargetTriple``, which 41returns the target triple of the current machine. 42 43.. code-block:: c++ 44 45 auto TargetTriple = sys::getDefaultTargetTriple(); 46 47LLVM doesn't require us to link in all the target 48functionality. For example, if we're just using the JIT, we don't need 49the assembly printers. Similarly, if we're only targeting certain 50architectures, we can only link in the functionality for those 51architectures. 52 53For this example, we'll initialize all the targets for emitting object 54code. 55 56.. code-block:: c++ 57 58 InitializeAllTargetInfos(); 59 InitializeAllTargets(); 60 InitializeAllTargetMCs(); 61 InitializeAllAsmParsers(); 62 InitializeAllAsmPrinters(); 63 64We can now use our target triple to get a ``Target``: 65 66.. code-block:: c++ 67 68 std::string Error; 69 auto Target = TargetRegistry::lookupTarget(TargetTriple, Error); 70 71 // Print an error and exit if we couldn't find the requested target. 72 // This generally occurs if we've forgotten to initialise the 73 // TargetRegistry or we have a bogus target triple. 74 if (!Target) { 75 errs() << Error; 76 return 1; 77 } 78 79Target Machine 80============== 81 82We will also need a ``TargetMachine``. This class provides a complete 83machine description of the machine we're targeting. If we want to 84target a specific feature (such as SSE) or a specific CPU (such as 85Intel's Sandylake), we do so now. 86 87To see which features and CPUs that LLVM knows about, we can use 88``llc``. For example, let's look at x86: 89 90:: 91 92 $ llvm-as < /dev/null | llc -march=x86 -mattr=help 93 Available CPUs for this target: 94 95 amdfam10 - Select the amdfam10 processor. 96 athlon - Select the athlon processor. 97 athlon-4 - Select the athlon-4 processor. 98 ... 99 100 Available features for this target: 101 102 16bit-mode - 16-bit mode (i8086). 103 32bit-mode - 32-bit mode (80386). 104 3dnow - Enable 3DNow! instructions. 105 3dnowa - Enable 3DNow! Athlon instructions. 106 ... 107 108For our example, we'll use the generic CPU without any additional 109features, options or relocation model. 110 111.. code-block:: c++ 112 113 auto CPU = "generic"; 114 auto Features = ""; 115 116 TargetOptions opt; 117 auto RM = Optional<Reloc::Model>(); 118 auto TargetMachine = Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM); 119 120 121Configuring the Module 122====================== 123 124We're now ready to configure our module, to specify the target and 125data layout. This isn't strictly necessary, but the `frontend 126performance guide <../Frontend/PerformanceTips.html>`_ recommends 127this. Optimizations benefit from knowing about the target and data 128layout. 129 130.. code-block:: c++ 131 132 TheModule->setDataLayout(TargetMachine->createDataLayout()); 133 TheModule->setTargetTriple(TargetTriple); 134 135Emit Object Code 136================ 137 138We're ready to emit object code! Let's define where we want to write 139our file to: 140 141.. code-block:: c++ 142 143 auto Filename = "output.o"; 144 std::error_code EC; 145 raw_fd_ostream dest(Filename, EC, sys::fs::OF_None); 146 147 if (EC) { 148 errs() << "Could not open file: " << EC.message(); 149 return 1; 150 } 151 152Finally, we define a pass that emits object code, then we run that 153pass: 154 155.. code-block:: c++ 156 157 legacy::PassManager pass; 158 auto FileType = CGFT_ObjectFile; 159 160 if (TargetMachine->addPassesToEmitFile(pass, dest, nullptr, FileType)) { 161 errs() << "TargetMachine can't emit a file of this type"; 162 return 1; 163 } 164 165 pass.run(*TheModule); 166 dest.flush(); 167 168Putting It All Together 169======================= 170 171Does it work? Let's give it a try. We need to compile our code, but 172note that the arguments to ``llvm-config`` are different to the previous chapters. 173 174:: 175 176 $ clang++ -g -O3 toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs all` -o toy 177 178Let's run it, and define a simple ``average`` function. Press Ctrl-D 179when you're done. 180 181:: 182 183 $ ./toy 184 ready> def average(x y) (x + y) * 0.5; 185 ^D 186 Wrote output.o 187 188We have an object file! To test it, let's write a simple program and 189link it with our output. Here's the source code: 190 191.. code-block:: c++ 192 193 #include <iostream> 194 195 extern "C" { 196 double average(double, double); 197 } 198 199 int main() { 200 std::cout << "average of 3.0 and 4.0: " << average(3.0, 4.0) << std::endl; 201 } 202 203We link our program to output.o and check the result is what we 204expected: 205 206:: 207 208 $ clang++ main.cpp output.o -o main 209 $ ./main 210 average of 3.0 and 4.0: 3.5 211 212Full Code Listing 213================= 214 215.. literalinclude:: ../../../examples/Kaleidoscope/Chapter8/toy.cpp 216 :language: c++ 217 218`Next: Adding Debug Information <LangImpl09.html>`_ 219