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