• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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<http://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 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::F_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 = TargetMachine::CGFT_ObjectFile;
159
160  if (TargetMachine->addPassesToEmitFile(pass, dest, 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