1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 2 "http://www.w3.org/TR/html4/strict.dtd"> 3 4<html> 5<head> 6 <title>Kaleidoscope: Adding JIT and Optimizer Support</title> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 8 <meta name="author" content="Chris Lattner"> 9 <meta name="author" content="Erick Tryzelaar"> 10 <link rel="stylesheet" href="../llvm.css" type="text/css"> 11</head> 12 13<body> 14 15<h1>Kaleidoscope: Adding JIT and Optimizer Support</h1> 16 17<ul> 18<li><a href="index.html">Up to Tutorial Index</a></li> 19<li>Chapter 4 20 <ol> 21 <li><a href="#intro">Chapter 4 Introduction</a></li> 22 <li><a href="#trivialconstfold">Trivial Constant Folding</a></li> 23 <li><a href="#optimizerpasses">LLVM Optimization Passes</a></li> 24 <li><a href="#jit">Adding a JIT Compiler</a></li> 25 <li><a href="#code">Full Code Listing</a></li> 26 </ol> 27</li> 28<li><a href="OCamlLangImpl5.html">Chapter 5</a>: Extending the Language: Control 29Flow</li> 30</ul> 31 32<div class="doc_author"> 33 <p> 34 Written by <a href="mailto:sabre@nondot.org">Chris Lattner</a> 35 and <a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a> 36 </p> 37</div> 38 39<!-- *********************************************************************** --> 40<h2><a name="intro">Chapter 4 Introduction</a></h2> 41<!-- *********************************************************************** --> 42 43<div> 44 45<p>Welcome to Chapter 4 of the "<a href="index.html">Implementing a language 46with LLVM</a>" tutorial. Chapters 1-3 described the implementation of a simple 47language and added support for generating LLVM IR. This chapter describes 48two new techniques: adding optimizer support to your language, and adding JIT 49compiler support. These additions will demonstrate how to get nice, efficient code 50for the Kaleidoscope language.</p> 51 52</div> 53 54<!-- *********************************************************************** --> 55<h2><a name="trivialconstfold">Trivial Constant Folding</a></h2> 56<!-- *********************************************************************** --> 57 58<div> 59 60<p><b>Note:</b> the default <tt>IRBuilder</tt> now always includes the constant 61folding optimisations below.<p> 62 63<p> 64Our demonstration for Chapter 3 is elegant and easy to extend. Unfortunately, 65it does not produce wonderful code. For example, when compiling simple code, 66we don't get obvious optimizations:</p> 67 68<div class="doc_code"> 69<pre> 70ready> <b>def test(x) 1+2+x;</b> 71Read function definition: 72define double @test(double %x) { 73entry: 74 %addtmp = fadd double 1.000000e+00, 2.000000e+00 75 %addtmp1 = fadd double %addtmp, %x 76 ret double %addtmp1 77} 78</pre> 79</div> 80 81<p>This code is a very, very literal transcription of the AST built by parsing 82the input. As such, this transcription lacks optimizations like constant folding 83(we'd like to get "<tt>add x, 3.0</tt>" in the example above) as well as other 84more important optimizations. Constant folding, in particular, is a very common 85and very important optimization: so much so that many language implementors 86implement constant folding support in their AST representation.</p> 87 88<p>With LLVM, you don't need this support in the AST. Since all calls to build 89LLVM IR go through the LLVM builder, it would be nice if the builder itself 90checked to see if there was a constant folding opportunity when you call it. 91If so, it could just do the constant fold and return the constant instead of 92creating an instruction. This is exactly what the <tt>LLVMFoldingBuilder</tt> 93class does. 94 95<p>All we did was switch from <tt>LLVMBuilder</tt> to 96<tt>LLVMFoldingBuilder</tt>. Though we change no other code, we now have all of our 97instructions implicitly constant folded without us having to do anything 98about it. For example, the input above now compiles to:</p> 99 100<div class="doc_code"> 101<pre> 102ready> <b>def test(x) 1+2+x;</b> 103Read function definition: 104define double @test(double %x) { 105entry: 106 %addtmp = fadd double 3.000000e+00, %x 107 ret double %addtmp 108} 109</pre> 110</div> 111 112<p>Well, that was easy :). In practice, we recommend always using 113<tt>LLVMFoldingBuilder</tt> when generating code like this. It has no 114"syntactic overhead" for its use (you don't have to uglify your compiler with 115constant checks everywhere) and it can dramatically reduce the amount of 116LLVM IR that is generated in some cases (particular for languages with a macro 117preprocessor or that use a lot of constants).</p> 118 119<p>On the other hand, the <tt>LLVMFoldingBuilder</tt> is limited by the fact 120that it does all of its analysis inline with the code as it is built. If you 121take a slightly more complex example:</p> 122 123<div class="doc_code"> 124<pre> 125ready> <b>def test(x) (1+2+x)*(x+(1+2));</b> 126ready> Read function definition: 127define double @test(double %x) { 128entry: 129 %addtmp = fadd double 3.000000e+00, %x 130 %addtmp1 = fadd double %x, 3.000000e+00 131 %multmp = fmul double %addtmp, %addtmp1 132 ret double %multmp 133} 134</pre> 135</div> 136 137<p>In this case, the LHS and RHS of the multiplication are the same value. We'd 138really like to see this generate "<tt>tmp = x+3; result = tmp*tmp;</tt>" instead 139of computing "<tt>x*3</tt>" twice.</p> 140 141<p>Unfortunately, no amount of local analysis will be able to detect and correct 142this. This requires two transformations: reassociation of expressions (to 143make the add's lexically identical) and Common Subexpression Elimination (CSE) 144to delete the redundant add instruction. Fortunately, LLVM provides a broad 145range of optimizations that you can use, in the form of "passes".</p> 146 147</div> 148 149<!-- *********************************************************************** --> 150<h2><a name="optimizerpasses">LLVM Optimization Passes</a></h2> 151<!-- *********************************************************************** --> 152 153<div> 154 155<p>LLVM provides many optimization passes, which do many different sorts of 156things and have different tradeoffs. Unlike other systems, LLVM doesn't hold 157to the mistaken notion that one set of optimizations is right for all languages 158and for all situations. LLVM allows a compiler implementor to make complete 159decisions about what optimizations to use, in which order, and in what 160situation.</p> 161 162<p>As a concrete example, LLVM supports both "whole module" passes, which look 163across as large of body of code as they can (often a whole file, but if run 164at link time, this can be a substantial portion of the whole program). It also 165supports and includes "per-function" passes which just operate on a single 166function at a time, without looking at other functions. For more information 167on passes and how they are run, see the <a href="../WritingAnLLVMPass.html">How 168to Write a Pass</a> document and the <a href="../Passes.html">List of LLVM 169Passes</a>.</p> 170 171<p>For Kaleidoscope, we are currently generating functions on the fly, one at 172a time, as the user types them in. We aren't shooting for the ultimate 173optimization experience in this setting, but we also want to catch the easy and 174quick stuff where possible. As such, we will choose to run a few per-function 175optimizations as the user types the function in. If we wanted to make a "static 176Kaleidoscope compiler", we would use exactly the code we have now, except that 177we would defer running the optimizer until the entire file has been parsed.</p> 178 179<p>In order to get per-function optimizations going, we need to set up a 180<a href="../WritingAnLLVMPass.html#passmanager">Llvm.PassManager</a> to hold and 181organize the LLVM optimizations that we want to run. Once we have that, we can 182add a set of optimizations to run. The code looks like this:</p> 183 184<div class="doc_code"> 185<pre> 186 (* Create the JIT. *) 187 let the_execution_engine = ExecutionEngine.create Codegen.the_module in 188 let the_fpm = PassManager.create_function Codegen.the_module in 189 190 (* Set up the optimizer pipeline. Start with registering info about how the 191 * target lays out data structures. *) 192 TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm; 193 194 (* Do simple "peephole" optimizations and bit-twiddling optzn. *) 195 add_instruction_combining the_fpm; 196 197 (* reassociate expressions. *) 198 add_reassociation the_fpm; 199 200 (* Eliminate Common SubExpressions. *) 201 add_gvn the_fpm; 202 203 (* Simplify the control flow graph (deleting unreachable blocks, etc). *) 204 add_cfg_simplification the_fpm; 205 206 ignore (PassManager.initialize the_fpm); 207 208 (* Run the main "interpreter loop" now. *) 209 Toplevel.main_loop the_fpm the_execution_engine stream; 210</pre> 211</div> 212 213<p>The meat of the matter here, is the definition of "<tt>the_fpm</tt>". It 214requires a pointer to the <tt>the_module</tt> to construct itself. Once it is 215set up, we use a series of "add" calls to add a bunch of LLVM passes. The 216first pass is basically boilerplate, it adds a pass so that later optimizations 217know how the data structures in the program are laid out. The 218"<tt>the_execution_engine</tt>" variable is related to the JIT, which we will 219get to in the next section.</p> 220 221<p>In this case, we choose to add 4 optimization passes. The passes we chose 222here are a pretty standard set of "cleanup" optimizations that are useful for 223a wide variety of code. I won't delve into what they do but, believe me, 224they are a good starting place :).</p> 225 226<p>Once the <tt>Llvm.PassManager.</tt> is set up, we need to make use of it. 227We do this by running it after our newly created function is constructed (in 228<tt>Codegen.codegen_func</tt>), but before it is returned to the client:</p> 229 230<div class="doc_code"> 231<pre> 232let codegen_func the_fpm = function 233 ... 234 try 235 let ret_val = codegen_expr body in 236 237 (* Finish off the function. *) 238 let _ = build_ret ret_val builder in 239 240 (* Validate the generated code, checking for consistency. *) 241 Llvm_analysis.assert_valid_function the_function; 242 243 (* Optimize the function. *) 244 let _ = PassManager.run_function the_function the_fpm in 245 246 the_function 247</pre> 248</div> 249 250<p>As you can see, this is pretty straightforward. The <tt>the_fpm</tt> 251optimizes and updates the LLVM Function* in place, improving (hopefully) its 252body. With this in place, we can try our test above again:</p> 253 254<div class="doc_code"> 255<pre> 256ready> <b>def test(x) (1+2+x)*(x+(1+2));</b> 257ready> Read function definition: 258define double @test(double %x) { 259entry: 260 %addtmp = fadd double %x, 3.000000e+00 261 %multmp = fmul double %addtmp, %addtmp 262 ret double %multmp 263} 264</pre> 265</div> 266 267<p>As expected, we now get our nicely optimized code, saving a floating point 268add instruction from every execution of this function.</p> 269 270<p>LLVM provides a wide variety of optimizations that can be used in certain 271circumstances. Some <a href="../Passes.html">documentation about the various 272passes</a> is available, but it isn't very complete. Another good source of 273ideas can come from looking at the passes that <tt>llvm-gcc</tt> or 274<tt>llvm-ld</tt> run to get started. The "<tt>opt</tt>" tool allows you to 275experiment with passes from the command line, so you can see if they do 276anything.</p> 277 278<p>Now that we have reasonable code coming out of our front-end, lets talk about 279executing it!</p> 280 281</div> 282 283<!-- *********************************************************************** --> 284<h2><a name="jit">Adding a JIT Compiler</a></h2> 285<!-- *********************************************************************** --> 286 287<div> 288 289<p>Code that is available in LLVM IR can have a wide variety of tools 290applied to it. For example, you can run optimizations on it (as we did above), 291you can dump it out in textual or binary forms, you can compile the code to an 292assembly file (.s) for some target, or you can JIT compile it. The nice thing 293about the LLVM IR representation is that it is the "common currency" between 294many different parts of the compiler. 295</p> 296 297<p>In this section, we'll add JIT compiler support to our interpreter. The 298basic idea that we want for Kaleidoscope is to have the user enter function 299bodies as they do now, but immediately evaluate the top-level expressions they 300type in. For example, if they type in "1 + 2;", we should evaluate and print 301out 3. If they define a function, they should be able to call it from the 302command line.</p> 303 304<p>In order to do this, we first declare and initialize the JIT. This is done 305by adding a global variable and a call in <tt>main</tt>:</p> 306 307<div class="doc_code"> 308<pre> 309... 310let main () = 311 ... 312 <b>(* Create the JIT. *) 313 let the_execution_engine = ExecutionEngine.create Codegen.the_module in</b> 314 ... 315</pre> 316</div> 317 318<p>This creates an abstract "Execution Engine" which can be either a JIT 319compiler or the LLVM interpreter. LLVM will automatically pick a JIT compiler 320for you if one is available for your platform, otherwise it will fall back to 321the interpreter.</p> 322 323<p>Once the <tt>Llvm_executionengine.ExecutionEngine.t</tt> is created, the JIT 324is ready to be used. There are a variety of APIs that are useful, but the 325simplest one is the "<tt>Llvm_executionengine.ExecutionEngine.run_function</tt>" 326function. This method JIT compiles the specified LLVM Function and returns a 327function pointer to the generated machine code. In our case, this means that we 328can change the code that parses a top-level expression to look like this:</p> 329 330<div class="doc_code"> 331<pre> 332 (* Evaluate a top-level expression into an anonymous function. *) 333 let e = Parser.parse_toplevel stream in 334 print_endline "parsed a top-level expr"; 335 let the_function = Codegen.codegen_func the_fpm e in 336 dump_value the_function; 337 338 (* JIT the function, returning a function pointer. *) 339 let result = ExecutionEngine.run_function the_function [||] 340 the_execution_engine in 341 342 print_string "Evaluated to "; 343 print_float (GenericValue.as_float Codegen.double_type result); 344 print_newline (); 345</pre> 346</div> 347 348<p>Recall that we compile top-level expressions into a self-contained LLVM 349function that takes no arguments and returns the computed double. Because the 350LLVM JIT compiler matches the native platform ABI, this means that you can just 351cast the result pointer to a function pointer of that type and call it directly. 352This means, there is no difference between JIT compiled code and native machine 353code that is statically linked into your application.</p> 354 355<p>With just these two changes, lets see how Kaleidoscope works now!</p> 356 357<div class="doc_code"> 358<pre> 359ready> <b>4+5;</b> 360define double @""() { 361entry: 362 ret double 9.000000e+00 363} 364 365<em>Evaluated to 9.000000</em> 366</pre> 367</div> 368 369<p>Well this looks like it is basically working. The dump of the function 370shows the "no argument function that always returns double" that we synthesize 371for each top level expression that is typed in. This demonstrates very basic 372functionality, but can we do more?</p> 373 374<div class="doc_code"> 375<pre> 376ready> <b>def testfunc(x y) x + y*2; </b> 377Read function definition: 378define double @testfunc(double %x, double %y) { 379entry: 380 %multmp = fmul double %y, 2.000000e+00 381 %addtmp = fadd double %multmp, %x 382 ret double %addtmp 383} 384 385ready> <b>testfunc(4, 10);</b> 386define double @""() { 387entry: 388 %calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01) 389 ret double %calltmp 390} 391 392<em>Evaluated to 24.000000</em> 393</pre> 394</div> 395 396<p>This illustrates that we can now call user code, but there is something a bit 397subtle going on here. Note that we only invoke the JIT on the anonymous 398functions that <em>call testfunc</em>, but we never invoked it 399on <em>testfunc</em> itself. What actually happened here is that the JIT 400scanned for all non-JIT'd functions transitively called from the anonymous 401function and compiled all of them before returning 402from <tt>run_function</tt>.</p> 403 404<p>The JIT provides a number of other more advanced interfaces for things like 405freeing allocated machine code, rejit'ing functions to update them, etc. 406However, even with this simple code, we get some surprisingly powerful 407capabilities - check this out (I removed the dump of the anonymous functions, 408you should get the idea by now :) :</p> 409 410<div class="doc_code"> 411<pre> 412ready> <b>extern sin(x);</b> 413Read extern: 414declare double @sin(double) 415 416ready> <b>extern cos(x);</b> 417Read extern: 418declare double @cos(double) 419 420ready> <b>sin(1.0);</b> 421<em>Evaluated to 0.841471</em> 422 423ready> <b>def foo(x) sin(x)*sin(x) + cos(x)*cos(x);</b> 424Read function definition: 425define double @foo(double %x) { 426entry: 427 %calltmp = call double @sin(double %x) 428 %multmp = fmul double %calltmp, %calltmp 429 %calltmp2 = call double @cos(double %x) 430 %multmp4 = fmul double %calltmp2, %calltmp2 431 %addtmp = fadd double %multmp, %multmp4 432 ret double %addtmp 433} 434 435ready> <b>foo(4.0);</b> 436<em>Evaluated to 1.000000</em> 437</pre> 438</div> 439 440<p>Whoa, how does the JIT know about sin and cos? The answer is surprisingly 441simple: in this example, the JIT started execution of a function and got to a 442function call. It realized that the function was not yet JIT compiled and 443invoked the standard set of routines to resolve the function. In this case, 444there is no body defined for the function, so the JIT ended up calling 445"<tt>dlsym("sin")</tt>" on the Kaleidoscope process itself. Since 446"<tt>sin</tt>" is defined within the JIT's address space, it simply patches up 447calls in the module to call the libm version of <tt>sin</tt> directly.</p> 448 449<p>The LLVM JIT provides a number of interfaces (look in the 450<tt>llvm_executionengine.mli</tt> file) for controlling how unknown functions 451get resolved. It allows you to establish explicit mappings between IR objects 452and addresses (useful for LLVM global variables that you want to map to static 453tables, for example), allows you to dynamically decide on the fly based on the 454function name, and even allows you to have the JIT compile functions lazily the 455first time they're called.</p> 456 457<p>One interesting application of this is that we can now extend the language 458by writing arbitrary C code to implement operations. For example, if we add: 459</p> 460 461<div class="doc_code"> 462<pre> 463/* putchard - putchar that takes a double and returns 0. */ 464extern "C" 465double putchard(double X) { 466 putchar((char)X); 467 return 0; 468} 469</pre> 470</div> 471 472<p>Now we can produce simple output to the console by using things like: 473"<tt>extern putchard(x); putchard(120);</tt>", which prints a lowercase 'x' on 474the console (120 is the ASCII code for 'x'). Similar code could be used to 475implement file I/O, console input, and many other capabilities in 476Kaleidoscope.</p> 477 478<p>This completes the JIT and optimizer chapter of the Kaleidoscope tutorial. At 479this point, we can compile a non-Turing-complete programming language, optimize 480and JIT compile it in a user-driven way. Next up we'll look into <a 481href="OCamlLangImpl5.html">extending the language with control flow 482constructs</a>, tackling some interesting LLVM IR issues along the way.</p> 483 484</div> 485 486<!-- *********************************************************************** --> 487<h2><a name="code">Full Code Listing</a></h2> 488<!-- *********************************************************************** --> 489 490<div> 491 492<p> 493Here is the complete code listing for our running example, enhanced with the 494LLVM JIT and optimizer. To build this example, use: 495</p> 496 497<div class="doc_code"> 498<pre> 499# Compile 500ocamlbuild toy.byte 501# Run 502./toy.byte 503</pre> 504</div> 505 506<p>Here is the code:</p> 507 508<dl> 509<dt>_tags:</dt> 510<dd class="doc_code"> 511<pre> 512<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) 513<*.{byte,native}>: g++, use_llvm, use_llvm_analysis 514<*.{byte,native}>: use_llvm_executionengine, use_llvm_target 515<*.{byte,native}>: use_llvm_scalar_opts, use_bindings 516</pre> 517</dd> 518 519<dt>myocamlbuild.ml:</dt> 520<dd class="doc_code"> 521<pre> 522open Ocamlbuild_plugin;; 523 524ocaml_lib ~extern:true "llvm";; 525ocaml_lib ~extern:true "llvm_analysis";; 526ocaml_lib ~extern:true "llvm_executionengine";; 527ocaml_lib ~extern:true "llvm_target";; 528ocaml_lib ~extern:true "llvm_scalar_opts";; 529 530flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; 531dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; 532</pre> 533</dd> 534 535<dt>token.ml:</dt> 536<dd class="doc_code"> 537<pre> 538(*===----------------------------------------------------------------------=== 539 * Lexer Tokens 540 *===----------------------------------------------------------------------===*) 541 542(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of 543 * these others for known things. *) 544type token = 545 (* commands *) 546 | Def | Extern 547 548 (* primary *) 549 | Ident of string | Number of float 550 551 (* unknown *) 552 | Kwd of char 553</pre> 554</dd> 555 556<dt>lexer.ml:</dt> 557<dd class="doc_code"> 558<pre> 559(*===----------------------------------------------------------------------=== 560 * Lexer 561 *===----------------------------------------------------------------------===*) 562 563let rec lex = parser 564 (* Skip any whitespace. *) 565 | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream 566 567 (* identifier: [a-zA-Z][a-zA-Z0-9] *) 568 | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> 569 let buffer = Buffer.create 1 in 570 Buffer.add_char buffer c; 571 lex_ident buffer stream 572 573 (* number: [0-9.]+ *) 574 | [< ' ('0' .. '9' as c); stream >] -> 575 let buffer = Buffer.create 1 in 576 Buffer.add_char buffer c; 577 lex_number buffer stream 578 579 (* Comment until end of line. *) 580 | [< ' ('#'); stream >] -> 581 lex_comment stream 582 583 (* Otherwise, just return the character as its ascii value. *) 584 | [< 'c; stream >] -> 585 [< 'Token.Kwd c; lex stream >] 586 587 (* end of stream. *) 588 | [< >] -> [< >] 589 590and lex_number buffer = parser 591 | [< ' ('0' .. '9' | '.' as c); stream >] -> 592 Buffer.add_char buffer c; 593 lex_number buffer stream 594 | [< stream=lex >] -> 595 [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] 596 597and lex_ident buffer = parser 598 | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> 599 Buffer.add_char buffer c; 600 lex_ident buffer stream 601 | [< stream=lex >] -> 602 match Buffer.contents buffer with 603 | "def" -> [< 'Token.Def; stream >] 604 | "extern" -> [< 'Token.Extern; stream >] 605 | id -> [< 'Token.Ident id; stream >] 606 607and lex_comment = parser 608 | [< ' ('\n'); stream=lex >] -> stream 609 | [< 'c; e=lex_comment >] -> e 610 | [< >] -> [< >] 611</pre> 612</dd> 613 614<dt>ast.ml:</dt> 615<dd class="doc_code"> 616<pre> 617(*===----------------------------------------------------------------------=== 618 * Abstract Syntax Tree (aka Parse Tree) 619 *===----------------------------------------------------------------------===*) 620 621(* expr - Base type for all expression nodes. *) 622type expr = 623 (* variant for numeric literals like "1.0". *) 624 | Number of float 625 626 (* variant for referencing a variable, like "a". *) 627 | Variable of string 628 629 (* variant for a binary operator. *) 630 | Binary of char * expr * expr 631 632 (* variant for function calls. *) 633 | Call of string * expr array 634 635(* proto - This type represents the "prototype" for a function, which captures 636 * its name, and its argument names (thus implicitly the number of arguments the 637 * function takes). *) 638type proto = Prototype of string * string array 639 640(* func - This type represents a function definition itself. *) 641type func = Function of proto * expr 642</pre> 643</dd> 644 645<dt>parser.ml:</dt> 646<dd class="doc_code"> 647<pre> 648(*===---------------------------------------------------------------------=== 649 * Parser 650 *===---------------------------------------------------------------------===*) 651 652(* binop_precedence - This holds the precedence for each binary operator that is 653 * defined *) 654let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 655 656(* precedence - Get the precedence of the pending binary operator token. *) 657let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 658 659(* primary 660 * ::= identifier 661 * ::= numberexpr 662 * ::= parenexpr *) 663let rec parse_primary = parser 664 (* numberexpr ::= number *) 665 | [< 'Token.Number n >] -> Ast.Number n 666 667 (* parenexpr ::= '(' expression ')' *) 668 | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e 669 670 (* identifierexpr 671 * ::= identifier 672 * ::= identifier '(' argumentexpr ')' *) 673 | [< 'Token.Ident id; stream >] -> 674 let rec parse_args accumulator = parser 675 | [< e=parse_expr; stream >] -> 676 begin parser 677 | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e 678 | [< >] -> e :: accumulator 679 end stream 680 | [< >] -> accumulator 681 in 682 let rec parse_ident id = parser 683 (* Call. *) 684 | [< 'Token.Kwd '('; 685 args=parse_args []; 686 'Token.Kwd ')' ?? "expected ')'">] -> 687 Ast.Call (id, Array.of_list (List.rev args)) 688 689 (* Simple variable ref. *) 690 | [< >] -> Ast.Variable id 691 in 692 parse_ident id stream 693 694 | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") 695 696(* binoprhs 697 * ::= ('+' primary)* *) 698and parse_bin_rhs expr_prec lhs stream = 699 match Stream.peek stream with 700 (* If this is a binop, find its precedence. *) 701 | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> 702 let token_prec = precedence c in 703 704 (* If this is a binop that binds at least as tightly as the current binop, 705 * consume it, otherwise we are done. *) 706 if token_prec < expr_prec then lhs else begin 707 (* Eat the binop. *) 708 Stream.junk stream; 709 710 (* Parse the primary expression after the binary operator. *) 711 let rhs = parse_primary stream in 712 713 (* Okay, we know this is a binop. *) 714 let rhs = 715 match Stream.peek stream with 716 | Some (Token.Kwd c2) -> 717 (* If BinOp binds less tightly with rhs than the operator after 718 * rhs, let the pending operator take rhs as its lhs. *) 719 let next_prec = precedence c2 in 720 if token_prec < next_prec 721 then parse_bin_rhs (token_prec + 1) rhs stream 722 else rhs 723 | _ -> rhs 724 in 725 726 (* Merge lhs/rhs. *) 727 let lhs = Ast.Binary (c, lhs, rhs) in 728 parse_bin_rhs expr_prec lhs stream 729 end 730 | _ -> lhs 731 732(* expression 733 * ::= primary binoprhs *) 734and parse_expr = parser 735 | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream 736 737(* prototype 738 * ::= id '(' id* ')' *) 739let parse_prototype = 740 let rec parse_args accumulator = parser 741 | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e 742 | [< >] -> accumulator 743 in 744 745 parser 746 | [< 'Token.Ident id; 747 'Token.Kwd '(' ?? "expected '(' in prototype"; 748 args=parse_args []; 749 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> 750 (* success. *) 751 Ast.Prototype (id, Array.of_list (List.rev args)) 752 753 | [< >] -> 754 raise (Stream.Error "expected function name in prototype") 755 756(* definition ::= 'def' prototype expression *) 757let parse_definition = parser 758 | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> 759 Ast.Function (p, e) 760 761(* toplevelexpr ::= expression *) 762let parse_toplevel = parser 763 | [< e=parse_expr >] -> 764 (* Make an anonymous proto. *) 765 Ast.Function (Ast.Prototype ("", [||]), e) 766 767(* external ::= 'extern' prototype *) 768let parse_extern = parser 769 | [< 'Token.Extern; e=parse_prototype >] -> e 770</pre> 771</dd> 772 773<dt>codegen.ml:</dt> 774<dd class="doc_code"> 775<pre> 776(*===----------------------------------------------------------------------=== 777 * Code Generation 778 *===----------------------------------------------------------------------===*) 779 780open Llvm 781 782exception Error of string 783 784let context = global_context () 785let the_module = create_module context "my cool jit" 786let builder = builder context 787let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 788let double_type = double_type context 789 790let rec codegen_expr = function 791 | Ast.Number n -> const_float double_type n 792 | Ast.Variable name -> 793 (try Hashtbl.find named_values name with 794 | Not_found -> raise (Error "unknown variable name")) 795 | Ast.Binary (op, lhs, rhs) -> 796 let lhs_val = codegen_expr lhs in 797 let rhs_val = codegen_expr rhs in 798 begin 799 match op with 800 | '+' -> build_add lhs_val rhs_val "addtmp" builder 801 | '-' -> build_sub lhs_val rhs_val "subtmp" builder 802 | '*' -> build_mul lhs_val rhs_val "multmp" builder 803 | '<' -> 804 (* Convert bool 0/1 to double 0.0 or 1.0 *) 805 let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in 806 build_uitofp i double_type "booltmp" builder 807 | _ -> raise (Error "invalid binary operator") 808 end 809 | Ast.Call (callee, args) -> 810 (* Look up the name in the module table. *) 811 let callee = 812 match lookup_function callee the_module with 813 | Some callee -> callee 814 | None -> raise (Error "unknown function referenced") 815 in 816 let params = params callee in 817 818 (* If argument mismatch error. *) 819 if Array.length params == Array.length args then () else 820 raise (Error "incorrect # arguments passed"); 821 let args = Array.map codegen_expr args in 822 build_call callee args "calltmp" builder 823 824let codegen_proto = function 825 | Ast.Prototype (name, args) -> 826 (* Make the function type: double(double,double) etc. *) 827 let doubles = Array.make (Array.length args) double_type in 828 let ft = function_type double_type doubles in 829 let f = 830 match lookup_function name the_module with 831 | None -> declare_function name ft the_module 832 833 (* If 'f' conflicted, there was already something named 'name'. If it 834 * has a body, don't allow redefinition or reextern. *) 835 | Some f -> 836 (* If 'f' already has a body, reject this. *) 837 if block_begin f <> At_end f then 838 raise (Error "redefinition of function"); 839 840 (* If 'f' took a different number of arguments, reject. *) 841 if element_type (type_of f) <> ft then 842 raise (Error "redefinition of function with different # args"); 843 f 844 in 845 846 (* Set names for all arguments. *) 847 Array.iteri (fun i a -> 848 let n = args.(i) in 849 set_value_name n a; 850 Hashtbl.add named_values n a; 851 ) (params f); 852 f 853 854let codegen_func the_fpm = function 855 | Ast.Function (proto, body) -> 856 Hashtbl.clear named_values; 857 let the_function = codegen_proto proto in 858 859 (* Create a new basic block to start insertion into. *) 860 let bb = append_block context "entry" the_function in 861 position_at_end bb builder; 862 863 try 864 let ret_val = codegen_expr body in 865 866 (* Finish off the function. *) 867 let _ = build_ret ret_val builder in 868 869 (* Validate the generated code, checking for consistency. *) 870 Llvm_analysis.assert_valid_function the_function; 871 872 (* Optimize the function. *) 873 let _ = PassManager.run_function the_function the_fpm in 874 875 the_function 876 with e -> 877 delete_function the_function; 878 raise e 879</pre> 880</dd> 881 882<dt>toplevel.ml:</dt> 883<dd class="doc_code"> 884<pre> 885(*===----------------------------------------------------------------------=== 886 * Top-Level parsing and JIT Driver 887 *===----------------------------------------------------------------------===*) 888 889open Llvm 890open Llvm_executionengine 891 892(* top ::= definition | external | expression | ';' *) 893let rec main_loop the_fpm the_execution_engine stream = 894 match Stream.peek stream with 895 | None -> () 896 897 (* ignore top-level semicolons. *) 898 | Some (Token.Kwd ';') -> 899 Stream.junk stream; 900 main_loop the_fpm the_execution_engine stream 901 902 | Some token -> 903 begin 904 try match token with 905 | Token.Def -> 906 let e = Parser.parse_definition stream in 907 print_endline "parsed a function definition."; 908 dump_value (Codegen.codegen_func the_fpm e); 909 | Token.Extern -> 910 let e = Parser.parse_extern stream in 911 print_endline "parsed an extern."; 912 dump_value (Codegen.codegen_proto e); 913 | _ -> 914 (* Evaluate a top-level expression into an anonymous function. *) 915 let e = Parser.parse_toplevel stream in 916 print_endline "parsed a top-level expr"; 917 let the_function = Codegen.codegen_func the_fpm e in 918 dump_value the_function; 919 920 (* JIT the function, returning a function pointer. *) 921 let result = ExecutionEngine.run_function the_function [||] 922 the_execution_engine in 923 924 print_string "Evaluated to "; 925 print_float (GenericValue.as_float Codegen.double_type result); 926 print_newline (); 927 with Stream.Error s | Codegen.Error s -> 928 (* Skip token for error recovery. *) 929 Stream.junk stream; 930 print_endline s; 931 end; 932 print_string "ready> "; flush stdout; 933 main_loop the_fpm the_execution_engine stream 934</pre> 935</dd> 936 937<dt>toy.ml:</dt> 938<dd class="doc_code"> 939<pre> 940(*===----------------------------------------------------------------------=== 941 * Main driver code. 942 *===----------------------------------------------------------------------===*) 943 944open Llvm 945open Llvm_executionengine 946open Llvm_target 947open Llvm_scalar_opts 948 949let main () = 950 ignore (initialize_native_target ()); 951 952 (* Install standard binary operators. 953 * 1 is the lowest precedence. *) 954 Hashtbl.add Parser.binop_precedence '<' 10; 955 Hashtbl.add Parser.binop_precedence '+' 20; 956 Hashtbl.add Parser.binop_precedence '-' 20; 957 Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) 958 959 (* Prime the first token. *) 960 print_string "ready> "; flush stdout; 961 let stream = Lexer.lex (Stream.of_channel stdin) in 962 963 (* Create the JIT. *) 964 let the_execution_engine = ExecutionEngine.create Codegen.the_module in 965 let the_fpm = PassManager.create_function Codegen.the_module in 966 967 (* Set up the optimizer pipeline. Start with registering info about how the 968 * target lays out data structures. *) 969 TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm; 970 971 (* Do simple "peephole" optimizations and bit-twiddling optzn. *) 972 add_instruction_combination the_fpm; 973 974 (* reassociate expressions. *) 975 add_reassociation the_fpm; 976 977 (* Eliminate Common SubExpressions. *) 978 add_gvn the_fpm; 979 980 (* Simplify the control flow graph (deleting unreachable blocks, etc). *) 981 add_cfg_simplification the_fpm; 982 983 ignore (PassManager.initialize the_fpm); 984 985 (* Run the main "interpreter loop" now. *) 986 Toplevel.main_loop the_fpm the_execution_engine stream; 987 988 (* Print out all the generated code. *) 989 dump_module Codegen.the_module 990;; 991 992main () 993</pre> 994</dd> 995 996<dt>bindings.c</dt> 997<dd class="doc_code"> 998<pre> 999#include <stdio.h> 1000 1001/* putchard - putchar that takes a double and returns 0. */ 1002extern double putchard(double X) { 1003 putchar((char)X); 1004 return 0; 1005} 1006</pre> 1007</dd> 1008</dl> 1009 1010<a href="OCamlLangImpl5.html">Next: Extending the language: control flow</a> 1011</div> 1012 1013<!-- *********************************************************************** --> 1014<hr> 1015<address> 1016 <a href="http://jigsaw.w3.org/css-validator/check/referer"><img 1017 src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!"></a> 1018 <a href="http://validator.w3.org/check/referer"><img 1019 src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"></a> 1020 1021 <a href="mailto:sabre@nondot.org">Chris Lattner</a><br> 1022 <a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br> 1023 <a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br> 1024 Last modified: $Date: 2011-04-22 20:30:22 -0400 (Fri, 22 Apr 2011) $ 1025</address> 1026</body> 1027</html> 1028