LangImpl04.rst 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. :orphan:
  2. ==============================================
  3. Kaleidoscope: Adding JIT and Optimizer Support
  4. ==============================================
  5. .. contents::
  6. :local:
  7. Chapter 4 Introduction
  8. ======================
  9. Welcome to Chapter 4 of the "`Implementing a language with
  10. LLVM <index.html>`_" tutorial. Chapters 1-3 described the implementation
  11. of a simple language and added support for generating LLVM IR. This
  12. chapter describes two new techniques: adding optimizer support to your
  13. language, and adding JIT compiler support. These additions will
  14. demonstrate how to get nice, efficient code for the Kaleidoscope
  15. language.
  16. Trivial Constant Folding
  17. ========================
  18. Our demonstration for Chapter 3 is elegant and easy to extend.
  19. Unfortunately, it does not produce wonderful code. The IRBuilder,
  20. however, does give us obvious optimizations when compiling simple code:
  21. ::
  22. ready> def test(x) 1+2+x;
  23. Read function definition:
  24. define double @test(double %x) {
  25. entry:
  26. %addtmp = fadd double 3.000000e+00, %x
  27. ret double %addtmp
  28. }
  29. This code is not a literal transcription of the AST built by parsing the
  30. input. That would be:
  31. ::
  32. ready> def test(x) 1+2+x;
  33. Read function definition:
  34. define double @test(double %x) {
  35. entry:
  36. %addtmp = fadd double 2.000000e+00, 1.000000e+00
  37. %addtmp1 = fadd double %addtmp, %x
  38. ret double %addtmp1
  39. }
  40. Constant folding, as seen above, in particular, is a very common and
  41. very important optimization: so much so that many language implementors
  42. implement constant folding support in their AST representation.
  43. With LLVM, you don't need this support in the AST. Since all calls to
  44. build LLVM IR go through the LLVM IR builder, the builder itself checked
  45. to see if there was a constant folding opportunity when you call it. If
  46. so, it just does the constant fold and return the constant instead of
  47. creating an instruction.
  48. Well, that was easy :). In practice, we recommend always using
  49. ``IRBuilder`` when generating code like this. It has no "syntactic
  50. overhead" for its use (you don't have to uglify your compiler with
  51. constant checks everywhere) and it can dramatically reduce the amount of
  52. LLVM IR that is generated in some cases (particular for languages with a
  53. macro preprocessor or that use a lot of constants).
  54. On the other hand, the ``IRBuilder`` is limited by the fact that it does
  55. all of its analysis inline with the code as it is built. If you take a
  56. slightly more complex example:
  57. ::
  58. ready> def test(x) (1+2+x)*(x+(1+2));
  59. ready> Read function definition:
  60. define double @test(double %x) {
  61. entry:
  62. %addtmp = fadd double 3.000000e+00, %x
  63. %addtmp1 = fadd double %x, 3.000000e+00
  64. %multmp = fmul double %addtmp, %addtmp1
  65. ret double %multmp
  66. }
  67. In this case, the LHS and RHS of the multiplication are the same value.
  68. We'd really like to see this generate "``tmp = x+3; result = tmp*tmp;``"
  69. instead of computing "``x+3``" twice.
  70. Unfortunately, no amount of local analysis will be able to detect and
  71. correct this. This requires two transformations: reassociation of
  72. expressions (to make the add's lexically identical) and Common
  73. Subexpression Elimination (CSE) to delete the redundant add instruction.
  74. Fortunately, LLVM provides a broad range of optimizations that you can
  75. use, in the form of "passes".
  76. LLVM Optimization Passes
  77. ========================
  78. .. warning::
  79. Due to the transition to the new PassManager infrastructure this tutorial
  80. is based on ``llvm::legacy::FunctionPassManager`` which can be found in
  81. `LegacyPassManager.h <http://llvm.org/doxygen/classllvm_1_1legacy_1_1FunctionPassManager.html>`_.
  82. For the purpose of the this tutorial the above should be used until
  83. the pass manager transition is complete.
  84. LLVM provides many optimization passes, which do many different sorts of
  85. things and have different tradeoffs. Unlike other systems, LLVM doesn't
  86. hold to the mistaken notion that one set of optimizations is right for
  87. all languages and for all situations. LLVM allows a compiler implementor
  88. to make complete decisions about what optimizations to use, in which
  89. order, and in what situation.
  90. As a concrete example, LLVM supports both "whole module" passes, which
  91. look across as large of body of code as they can (often a whole file,
  92. but if run at link time, this can be a substantial portion of the whole
  93. program). It also supports and includes "per-function" passes which just
  94. operate on a single function at a time, without looking at other
  95. functions. For more information on passes and how they are run, see the
  96. `How to Write a Pass <../WritingAnLLVMPass.html>`_ document and the
  97. `List of LLVM Passes <../Passes.html>`_.
  98. For Kaleidoscope, we are currently generating functions on the fly, one
  99. at a time, as the user types them in. We aren't shooting for the
  100. ultimate optimization experience in this setting, but we also want to
  101. catch the easy and quick stuff where possible. As such, we will choose
  102. to run a few per-function optimizations as the user types the function
  103. in. If we wanted to make a "static Kaleidoscope compiler", we would use
  104. exactly the code we have now, except that we would defer running the
  105. optimizer until the entire file has been parsed.
  106. In order to get per-function optimizations going, we need to set up a
  107. `FunctionPassManager <../WritingAnLLVMPass.html#what-passmanager-doesr>`_ to hold
  108. and organize the LLVM optimizations that we want to run. Once we have
  109. that, we can add a set of optimizations to run. We'll need a new
  110. FunctionPassManager for each module that we want to optimize, so we'll
  111. write a function to create and initialize both the module and pass manager
  112. for us:
  113. .. code-block:: c++
  114. void InitializeModuleAndPassManager(void) {
  115. // Open a new module.
  116. TheModule = std::make_unique<Module>("my cool jit", TheContext);
  117. // Create a new pass manager attached to it.
  118. TheFPM = std::make_unique<FunctionPassManager>(TheModule.get());
  119. // Do simple "peephole" optimizations and bit-twiddling optzns.
  120. TheFPM->add(createInstructionCombiningPass());
  121. // Reassociate expressions.
  122. TheFPM->add(createReassociatePass());
  123. // Eliminate Common SubExpressions.
  124. TheFPM->add(createGVNPass());
  125. // Simplify the control flow graph (deleting unreachable blocks, etc).
  126. TheFPM->add(createCFGSimplificationPass());
  127. TheFPM->doInitialization();
  128. }
  129. This code initializes the global module ``TheModule``, and the function pass
  130. manager ``TheFPM``, which is attached to ``TheModule``. Once the pass manager is
  131. set up, we use a series of "add" calls to add a bunch of LLVM passes.
  132. In this case, we choose to add four optimization passes.
  133. The passes we choose here are a pretty standard set
  134. of "cleanup" optimizations that are useful for a wide variety of code. I won't
  135. delve into what they do but, believe me, they are a good starting place :).
  136. Once the PassManager is set up, we need to make use of it. We do this by
  137. running it after our newly created function is constructed (in
  138. ``FunctionAST::codegen()``), but before it is returned to the client:
  139. .. code-block:: c++
  140. if (Value *RetVal = Body->codegen()) {
  141. // Finish off the function.
  142. Builder.CreateRet(RetVal);
  143. // Validate the generated code, checking for consistency.
  144. verifyFunction(*TheFunction);
  145. // Optimize the function.
  146. TheFPM->run(*TheFunction);
  147. return TheFunction;
  148. }
  149. As you can see, this is pretty straightforward. The
  150. ``FunctionPassManager`` optimizes and updates the LLVM Function\* in
  151. place, improving (hopefully) its body. With this in place, we can try
  152. our test above again:
  153. ::
  154. ready> def test(x) (1+2+x)*(x+(1+2));
  155. ready> Read function definition:
  156. define double @test(double %x) {
  157. entry:
  158. %addtmp = fadd double %x, 3.000000e+00
  159. %multmp = fmul double %addtmp, %addtmp
  160. ret double %multmp
  161. }
  162. As expected, we now get our nicely optimized code, saving a floating
  163. point add instruction from every execution of this function.
  164. LLVM provides a wide variety of optimizations that can be used in
  165. certain circumstances. Some `documentation about the various
  166. passes <../Passes.html>`_ is available, but it isn't very complete.
  167. Another good source of ideas can come from looking at the passes that
  168. ``Clang`` runs to get started. The "``opt``" tool allows you to
  169. experiment with passes from the command line, so you can see if they do
  170. anything.
  171. Now that we have reasonable code coming out of our front-end, let's talk
  172. about executing it!
  173. Adding a JIT Compiler
  174. =====================
  175. Code that is available in LLVM IR can have a wide variety of tools
  176. applied to it. For example, you can run optimizations on it (as we did
  177. above), you can dump it out in textual or binary forms, you can compile
  178. the code to an assembly file (.s) for some target, or you can JIT
  179. compile it. The nice thing about the LLVM IR representation is that it
  180. is the "common currency" between many different parts of the compiler.
  181. In this section, we'll add JIT compiler support to our interpreter. The
  182. basic idea that we want for Kaleidoscope is to have the user enter
  183. function bodies as they do now, but immediately evaluate the top-level
  184. expressions they type in. For example, if they type in "1 + 2;", we
  185. should evaluate and print out 3. If they define a function, they should
  186. be able to call it from the command line.
  187. In order to do this, we first prepare the environment to create code for
  188. the current native target and declare and initialize the JIT. This is
  189. done by calling some ``InitializeNativeTarget\*`` functions and
  190. adding a global variable ``TheJIT``, and initializing it in
  191. ``main``:
  192. .. code-block:: c++
  193. static std::unique_ptr<KaleidoscopeJIT> TheJIT;
  194. ...
  195. int main() {
  196. InitializeNativeTarget();
  197. InitializeNativeTargetAsmPrinter();
  198. InitializeNativeTargetAsmParser();
  199. // Install standard binary operators.
  200. // 1 is lowest precedence.
  201. BinopPrecedence['<'] = 10;
  202. BinopPrecedence['+'] = 20;
  203. BinopPrecedence['-'] = 20;
  204. BinopPrecedence['*'] = 40; // highest.
  205. // Prime the first token.
  206. fprintf(stderr, "ready> ");
  207. getNextToken();
  208. TheJIT = std::make_unique<KaleidoscopeJIT>();
  209. // Run the main "interpreter loop" now.
  210. MainLoop();
  211. return 0;
  212. }
  213. We also need to setup the data layout for the JIT:
  214. .. code-block:: c++
  215. void InitializeModuleAndPassManager(void) {
  216. // Open a new module.
  217. TheModule = std::make_unique<Module>("my cool jit", TheContext);
  218. TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
  219. // Create a new pass manager attached to it.
  220. TheFPM = std::make_unique<FunctionPassManager>(TheModule.get());
  221. ...
  222. The KaleidoscopeJIT class is a simple JIT built specifically for these
  223. tutorials, available inside the LLVM source code
  224. at llvm-src/examples/Kaleidoscope/include/KaleidoscopeJIT.h.
  225. In later chapters we will look at how it works and extend it with
  226. new features, but for now we will take it as given. Its API is very simple:
  227. ``addModule`` adds an LLVM IR module to the JIT, making its functions
  228. available for execution; ``removeModule`` removes a module, freeing any
  229. memory associated with the code in that module; and ``findSymbol`` allows us
  230. to look up pointers to the compiled code.
  231. We can take this simple API and change our code that parses top-level expressions to
  232. look like this:
  233. .. code-block:: c++
  234. static void HandleTopLevelExpression() {
  235. // Evaluate a top-level expression into an anonymous function.
  236. if (auto FnAST = ParseTopLevelExpr()) {
  237. if (FnAST->codegen()) {
  238. // JIT the module containing the anonymous expression, keeping a handle so
  239. // we can free it later.
  240. auto H = TheJIT->addModule(std::move(TheModule));
  241. InitializeModuleAndPassManager();
  242. // Search the JIT for the __anon_expr symbol.
  243. auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
  244. assert(ExprSymbol && "Function not found");
  245. // Get the symbol's address and cast it to the right type (takes no
  246. // arguments, returns a double) so we can call it as a native function.
  247. double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
  248. fprintf(stderr, "Evaluated to %f\n", FP());
  249. // Delete the anonymous expression module from the JIT.
  250. TheJIT->removeModule(H);
  251. }
  252. If parsing and codegen succeed, the next step is to add the module containing
  253. the top-level expression to the JIT. We do this by calling addModule, which
  254. triggers code generation for all the functions in the module, and returns a
  255. handle that can be used to remove the module from the JIT later. Once the module
  256. has been added to the JIT it can no longer be modified, so we also open a new
  257. module to hold subsequent code by calling ``InitializeModuleAndPassManager()``.
  258. Once we've added the module to the JIT we need to get a pointer to the final
  259. generated code. We do this by calling the JIT's findSymbol method, and passing
  260. the name of the top-level expression function: ``__anon_expr``. Since we just
  261. added this function, we assert that findSymbol returned a result.
  262. Next, we get the in-memory address of the ``__anon_expr`` function by calling
  263. ``getAddress()`` on the symbol. Recall that we compile top-level expressions
  264. into a self-contained LLVM function that takes no arguments and returns the
  265. computed double. Because the LLVM JIT compiler matches the native platform ABI,
  266. this means that you can just cast the result pointer to a function pointer of
  267. that type and call it directly. This means, there is no difference between JIT
  268. compiled code and native machine code that is statically linked into your
  269. application.
  270. Finally, since we don't support re-evaluation of top-level expressions, we
  271. remove the module from the JIT when we're done to free the associated memory.
  272. Recall, however, that the module we created a few lines earlier (via
  273. ``InitializeModuleAndPassManager``) is still open and waiting for new code to be
  274. added.
  275. With just these two changes, let's see how Kaleidoscope works now!
  276. ::
  277. ready> 4+5;
  278. Read top-level expression:
  279. define double @0() {
  280. entry:
  281. ret double 9.000000e+00
  282. }
  283. Evaluated to 9.000000
  284. Well this looks like it is basically working. The dump of the function
  285. shows the "no argument function that always returns double" that we
  286. synthesize for each top-level expression that is typed in. This
  287. demonstrates very basic functionality, but can we do more?
  288. ::
  289. ready> def testfunc(x y) x + y*2;
  290. Read function definition:
  291. define double @testfunc(double %x, double %y) {
  292. entry:
  293. %multmp = fmul double %y, 2.000000e+00
  294. %addtmp = fadd double %multmp, %x
  295. ret double %addtmp
  296. }
  297. ready> testfunc(4, 10);
  298. Read top-level expression:
  299. define double @1() {
  300. entry:
  301. %calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
  302. ret double %calltmp
  303. }
  304. Evaluated to 24.000000
  305. ready> testfunc(5, 10);
  306. ready> LLVM ERROR: Program used external function 'testfunc' which could not be resolved!
  307. Function definitions and calls also work, but something went very wrong on that
  308. last line. The call looks valid, so what happened? As you may have guessed from
  309. the API a Module is a unit of allocation for the JIT, and testfunc was part
  310. of the same module that contained anonymous expression. When we removed that
  311. module from the JIT to free the memory for the anonymous expression, we deleted
  312. the definition of ``testfunc`` along with it. Then, when we tried to call
  313. testfunc a second time, the JIT could no longer find it.
  314. The easiest way to fix this is to put the anonymous expression in a separate
  315. module from the rest of the function definitions. The JIT will happily resolve
  316. function calls across module boundaries, as long as each of the functions called
  317. has a prototype, and is added to the JIT before it is called. By putting the
  318. anonymous expression in a different module we can delete it without affecting
  319. the rest of the functions.
  320. In fact, we're going to go a step further and put every function in its own
  321. module. Doing so allows us to exploit a useful property of the KaleidoscopeJIT
  322. that will make our environment more REPL-like: Functions can be added to the
  323. JIT more than once (unlike a module where every function must have a unique
  324. definition). When you look up a symbol in KaleidoscopeJIT it will always return
  325. the most recent definition:
  326. ::
  327. ready> def foo(x) x + 1;
  328. Read function definition:
  329. define double @foo(double %x) {
  330. entry:
  331. %addtmp = fadd double %x, 1.000000e+00
  332. ret double %addtmp
  333. }
  334. ready> foo(2);
  335. Evaluated to 3.000000
  336. ready> def foo(x) x + 2;
  337. define double @foo(double %x) {
  338. entry:
  339. %addtmp = fadd double %x, 2.000000e+00
  340. ret double %addtmp
  341. }
  342. ready> foo(2);
  343. Evaluated to 4.000000
  344. To allow each function to live in its own module we'll need a way to
  345. re-generate previous function declarations into each new module we open:
  346. .. code-block:: c++
  347. static std::unique_ptr<KaleidoscopeJIT> TheJIT;
  348. ...
  349. Function *getFunction(std::string Name) {
  350. // First, see if the function has already been added to the current module.
  351. if (auto *F = TheModule->getFunction(Name))
  352. return F;
  353. // If not, check whether we can codegen the declaration from some existing
  354. // prototype.
  355. auto FI = FunctionProtos.find(Name);
  356. if (FI != FunctionProtos.end())
  357. return FI->second->codegen();
  358. // If no existing prototype exists, return null.
  359. return nullptr;
  360. }
  361. ...
  362. Value *CallExprAST::codegen() {
  363. // Look up the name in the global module table.
  364. Function *CalleeF = getFunction(Callee);
  365. ...
  366. Function *FunctionAST::codegen() {
  367. // Transfer ownership of the prototype to the FunctionProtos map, but keep a
  368. // reference to it for use below.
  369. auto &P = *Proto;
  370. FunctionProtos[Proto->getName()] = std::move(Proto);
  371. Function *TheFunction = getFunction(P.getName());
  372. if (!TheFunction)
  373. return nullptr;
  374. To enable this, we'll start by adding a new global, ``FunctionProtos``, that
  375. holds the most recent prototype for each function. We'll also add a convenience
  376. method, ``getFunction()``, to replace calls to ``TheModule->getFunction()``.
  377. Our convenience method searches ``TheModule`` for an existing function
  378. declaration, falling back to generating a new declaration from FunctionProtos if
  379. it doesn't find one. In ``CallExprAST::codegen()`` we just need to replace the
  380. call to ``TheModule->getFunction()``. In ``FunctionAST::codegen()`` we need to
  381. update the FunctionProtos map first, then call ``getFunction()``. With this
  382. done, we can always obtain a function declaration in the current module for any
  383. previously declared function.
  384. We also need to update HandleDefinition and HandleExtern:
  385. .. code-block:: c++
  386. static void HandleDefinition() {
  387. if (auto FnAST = ParseDefinition()) {
  388. if (auto *FnIR = FnAST->codegen()) {
  389. fprintf(stderr, "Read function definition:");
  390. FnIR->print(errs());
  391. fprintf(stderr, "\n");
  392. TheJIT->addModule(std::move(TheModule));
  393. InitializeModuleAndPassManager();
  394. }
  395. } else {
  396. // Skip token for error recovery.
  397. getNextToken();
  398. }
  399. }
  400. static void HandleExtern() {
  401. if (auto ProtoAST = ParseExtern()) {
  402. if (auto *FnIR = ProtoAST->codegen()) {
  403. fprintf(stderr, "Read extern: ");
  404. FnIR->print(errs());
  405. fprintf(stderr, "\n");
  406. FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST);
  407. }
  408. } else {
  409. // Skip token for error recovery.
  410. getNextToken();
  411. }
  412. }
  413. In HandleDefinition, we add two lines to transfer the newly defined function to
  414. the JIT and open a new module. In HandleExtern, we just need to add one line to
  415. add the prototype to FunctionProtos.
  416. With these changes made, let's try our REPL again (I removed the dump of the
  417. anonymous functions this time, you should get the idea by now :) :
  418. ::
  419. ready> def foo(x) x + 1;
  420. ready> foo(2);
  421. Evaluated to 3.000000
  422. ready> def foo(x) x + 2;
  423. ready> foo(2);
  424. Evaluated to 4.000000
  425. It works!
  426. Even with this simple code, we get some surprisingly powerful capabilities -
  427. check this out:
  428. ::
  429. ready> extern sin(x);
  430. Read extern:
  431. declare double @sin(double)
  432. ready> extern cos(x);
  433. Read extern:
  434. declare double @cos(double)
  435. ready> sin(1.0);
  436. Read top-level expression:
  437. define double @2() {
  438. entry:
  439. ret double 0x3FEAED548F090CEE
  440. }
  441. Evaluated to 0.841471
  442. ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
  443. Read function definition:
  444. define double @foo(double %x) {
  445. entry:
  446. %calltmp = call double @sin(double %x)
  447. %multmp = fmul double %calltmp, %calltmp
  448. %calltmp2 = call double @cos(double %x)
  449. %multmp4 = fmul double %calltmp2, %calltmp2
  450. %addtmp = fadd double %multmp, %multmp4
  451. ret double %addtmp
  452. }
  453. ready> foo(4.0);
  454. Read top-level expression:
  455. define double @3() {
  456. entry:
  457. %calltmp = call double @foo(double 4.000000e+00)
  458. ret double %calltmp
  459. }
  460. Evaluated to 1.000000
  461. Whoa, how does the JIT know about sin and cos? The answer is surprisingly
  462. simple: The KaleidoscopeJIT has a straightforward symbol resolution rule that
  463. it uses to find symbols that aren't available in any given module: First
  464. it searches all the modules that have already been added to the JIT, from the
  465. most recent to the oldest, to find the newest definition. If no definition is
  466. found inside the JIT, it falls back to calling "``dlsym("sin")``" on the
  467. Kaleidoscope process itself. Since "``sin``" is defined within the JIT's
  468. address space, it simply patches up calls in the module to call the libm
  469. version of ``sin`` directly. But in some cases this even goes further:
  470. as sin and cos are names of standard math functions, the constant folder
  471. will directly evaluate the function calls to the correct result when called
  472. with constants like in the "``sin(1.0)``" above.
  473. In the future we'll see how tweaking this symbol resolution rule can be used to
  474. enable all sorts of useful features, from security (restricting the set of
  475. symbols available to JIT'd code), to dynamic code generation based on symbol
  476. names, and even lazy compilation.
  477. One immediate benefit of the symbol resolution rule is that we can now extend
  478. the language by writing arbitrary C++ code to implement operations. For example,
  479. if we add:
  480. .. code-block:: c++
  481. #ifdef _WIN32
  482. #define DLLEXPORT __declspec(dllexport)
  483. #else
  484. #define DLLEXPORT
  485. #endif
  486. /// putchard - putchar that takes a double and returns 0.
  487. extern "C" DLLEXPORT double putchard(double X) {
  488. fputc((char)X, stderr);
  489. return 0;
  490. }
  491. Note, that for Windows we need to actually export the functions because
  492. the dynamic symbol loader will use GetProcAddress to find the symbols.
  493. Now we can produce simple output to the console by using things like:
  494. "``extern putchard(x); putchard(120);``", which prints a lowercase 'x'
  495. on the console (120 is the ASCII code for 'x'). Similar code could be
  496. used to implement file I/O, console input, and many other capabilities
  497. in Kaleidoscope.
  498. This completes the JIT and optimizer chapter of the Kaleidoscope
  499. tutorial. At this point, we can compile a non-Turing-complete
  500. programming language, optimize and JIT compile it in a user-driven way.
  501. Next up we'll look into `extending the language with control flow
  502. constructs <LangImpl05.html>`_, tackling some interesting LLVM IR issues
  503. along the way.
  504. Full Code Listing
  505. =================
  506. Here is the complete code listing for our running example, enhanced with
  507. the LLVM JIT and optimizer. To build this example, use:
  508. .. code-block:: bash
  509. # Compile
  510. clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy
  511. # Run
  512. ./toy
  513. If you are compiling this on Linux, make sure to add the "-rdynamic"
  514. option as well. This makes sure that the external functions are resolved
  515. properly at runtime.
  516. Here is the code:
  517. .. literalinclude:: ../../../examples/Kaleidoscope/Chapter4/toy.cpp
  518. :language: c++
  519. `Next: Extending the language: control flow <LangImpl05.html>`_