1*9880d681SAndroid Build Coastguard Worker================================================== 2*9880d681SAndroid Build Coastguard WorkerKaleidoscope: Extending the Language: Control Flow 3*9880d681SAndroid Build Coastguard Worker================================================== 4*9880d681SAndroid Build Coastguard Worker 5*9880d681SAndroid Build Coastguard Worker.. contents:: 6*9880d681SAndroid Build Coastguard Worker :local: 7*9880d681SAndroid Build Coastguard Worker 8*9880d681SAndroid Build Coastguard WorkerChapter 5 Introduction 9*9880d681SAndroid Build Coastguard Worker====================== 10*9880d681SAndroid Build Coastguard Worker 11*9880d681SAndroid Build Coastguard WorkerWelcome to Chapter 5 of the "`Implementing a language with 12*9880d681SAndroid Build Coastguard WorkerLLVM <index.html>`_" tutorial. Parts 1-4 described the implementation of 13*9880d681SAndroid Build Coastguard Workerthe simple Kaleidoscope language and included support for generating 14*9880d681SAndroid Build Coastguard WorkerLLVM IR, followed by optimizations and a JIT compiler. Unfortunately, as 15*9880d681SAndroid Build Coastguard Workerpresented, Kaleidoscope is mostly useless: it has no control flow other 16*9880d681SAndroid Build Coastguard Workerthan call and return. This means that you can't have conditional 17*9880d681SAndroid Build Coastguard Workerbranches in the code, significantly limiting its power. In this episode 18*9880d681SAndroid Build Coastguard Workerof "build that compiler", we'll extend Kaleidoscope to have an 19*9880d681SAndroid Build Coastguard Workerif/then/else expression plus a simple 'for' loop. 20*9880d681SAndroid Build Coastguard Worker 21*9880d681SAndroid Build Coastguard WorkerIf/Then/Else 22*9880d681SAndroid Build Coastguard Worker============ 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard WorkerExtending Kaleidoscope to support if/then/else is quite straightforward. 25*9880d681SAndroid Build Coastguard WorkerIt basically requires adding lexer support for this "new" concept to the 26*9880d681SAndroid Build Coastguard Workerlexer, parser, AST, and LLVM code emitter. This example is nice, because 27*9880d681SAndroid Build Coastguard Workerit shows how easy it is to "grow" a language over time, incrementally 28*9880d681SAndroid Build Coastguard Workerextending it as new ideas are discovered. 29*9880d681SAndroid Build Coastguard Worker 30*9880d681SAndroid Build Coastguard WorkerBefore we get going on "how" we add this extension, lets talk about 31*9880d681SAndroid Build Coastguard Worker"what" we want. The basic idea is that we want to be able to write this 32*9880d681SAndroid Build Coastguard Workersort of thing: 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard Worker:: 35*9880d681SAndroid Build Coastguard Worker 36*9880d681SAndroid Build Coastguard Worker def fib(x) 37*9880d681SAndroid Build Coastguard Worker if x < 3 then 38*9880d681SAndroid Build Coastguard Worker 1 39*9880d681SAndroid Build Coastguard Worker else 40*9880d681SAndroid Build Coastguard Worker fib(x-1)+fib(x-2); 41*9880d681SAndroid Build Coastguard Worker 42*9880d681SAndroid Build Coastguard WorkerIn Kaleidoscope, every construct is an expression: there are no 43*9880d681SAndroid Build Coastguard Workerstatements. As such, the if/then/else expression needs to return a value 44*9880d681SAndroid Build Coastguard Workerlike any other. Since we're using a mostly functional form, we'll have 45*9880d681SAndroid Build Coastguard Workerit evaluate its conditional, then return the 'then' or 'else' value 46*9880d681SAndroid Build Coastguard Workerbased on how the condition was resolved. This is very similar to the C 47*9880d681SAndroid Build Coastguard Worker"?:" expression. 48*9880d681SAndroid Build Coastguard Worker 49*9880d681SAndroid Build Coastguard WorkerThe semantics of the if/then/else expression is that it evaluates the 50*9880d681SAndroid Build Coastguard Workercondition to a boolean equality value: 0.0 is considered to be false and 51*9880d681SAndroid Build Coastguard Workereverything else is considered to be true. If the condition is true, the 52*9880d681SAndroid Build Coastguard Workerfirst subexpression is evaluated and returned, if the condition is 53*9880d681SAndroid Build Coastguard Workerfalse, the second subexpression is evaluated and returned. Since 54*9880d681SAndroid Build Coastguard WorkerKaleidoscope allows side-effects, this behavior is important to nail 55*9880d681SAndroid Build Coastguard Workerdown. 56*9880d681SAndroid Build Coastguard Worker 57*9880d681SAndroid Build Coastguard WorkerNow that we know what we "want", lets break this down into its 58*9880d681SAndroid Build Coastguard Workerconstituent pieces. 59*9880d681SAndroid Build Coastguard Worker 60*9880d681SAndroid Build Coastguard WorkerLexer Extensions for If/Then/Else 61*9880d681SAndroid Build Coastguard Worker--------------------------------- 62*9880d681SAndroid Build Coastguard Worker 63*9880d681SAndroid Build Coastguard WorkerThe lexer extensions are straightforward. First we add new variants for 64*9880d681SAndroid Build Coastguard Workerthe relevant tokens: 65*9880d681SAndroid Build Coastguard Worker 66*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 67*9880d681SAndroid Build Coastguard Worker 68*9880d681SAndroid Build Coastguard Worker (* control *) 69*9880d681SAndroid Build Coastguard Worker | If | Then | Else | For | In 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard WorkerOnce we have that, we recognize the new keywords in the lexer. This is 72*9880d681SAndroid Build Coastguard Workerpretty simple stuff: 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 75*9880d681SAndroid Build Coastguard Worker 76*9880d681SAndroid Build Coastguard Worker ... 77*9880d681SAndroid Build Coastguard Worker match Buffer.contents buffer with 78*9880d681SAndroid Build Coastguard Worker | "def" -> [< 'Token.Def; stream >] 79*9880d681SAndroid Build Coastguard Worker | "extern" -> [< 'Token.Extern; stream >] 80*9880d681SAndroid Build Coastguard Worker | "if" -> [< 'Token.If; stream >] 81*9880d681SAndroid Build Coastguard Worker | "then" -> [< 'Token.Then; stream >] 82*9880d681SAndroid Build Coastguard Worker | "else" -> [< 'Token.Else; stream >] 83*9880d681SAndroid Build Coastguard Worker | "for" -> [< 'Token.For; stream >] 84*9880d681SAndroid Build Coastguard Worker | "in" -> [< 'Token.In; stream >] 85*9880d681SAndroid Build Coastguard Worker | id -> [< 'Token.Ident id; stream >] 86*9880d681SAndroid Build Coastguard Worker 87*9880d681SAndroid Build Coastguard WorkerAST Extensions for If/Then/Else 88*9880d681SAndroid Build Coastguard Worker------------------------------- 89*9880d681SAndroid Build Coastguard Worker 90*9880d681SAndroid Build Coastguard WorkerTo represent the new expression we add a new AST variant for it: 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 93*9880d681SAndroid Build Coastguard Worker 94*9880d681SAndroid Build Coastguard Worker type expr = 95*9880d681SAndroid Build Coastguard Worker ... 96*9880d681SAndroid Build Coastguard Worker (* variant for if/then/else. *) 97*9880d681SAndroid Build Coastguard Worker | If of expr * expr * expr 98*9880d681SAndroid Build Coastguard Worker 99*9880d681SAndroid Build Coastguard WorkerThe AST variant just has pointers to the various subexpressions. 100*9880d681SAndroid Build Coastguard Worker 101*9880d681SAndroid Build Coastguard WorkerParser Extensions for If/Then/Else 102*9880d681SAndroid Build Coastguard Worker---------------------------------- 103*9880d681SAndroid Build Coastguard Worker 104*9880d681SAndroid Build Coastguard WorkerNow that we have the relevant tokens coming from the lexer and we have 105*9880d681SAndroid Build Coastguard Workerthe AST node to build, our parsing logic is relatively straightforward. 106*9880d681SAndroid Build Coastguard WorkerFirst we define a new parsing function: 107*9880d681SAndroid Build Coastguard Worker 108*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker let rec parse_primary = parser 111*9880d681SAndroid Build Coastguard Worker ... 112*9880d681SAndroid Build Coastguard Worker (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) 113*9880d681SAndroid Build Coastguard Worker | [< 'Token.If; c=parse_expr; 114*9880d681SAndroid Build Coastguard Worker 'Token.Then ?? "expected 'then'"; t=parse_expr; 115*9880d681SAndroid Build Coastguard Worker 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> 116*9880d681SAndroid Build Coastguard Worker Ast.If (c, t, e) 117*9880d681SAndroid Build Coastguard Worker 118*9880d681SAndroid Build Coastguard WorkerNext we hook it up as a primary expression: 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 121*9880d681SAndroid Build Coastguard Worker 122*9880d681SAndroid Build Coastguard Worker let rec parse_primary = parser 123*9880d681SAndroid Build Coastguard Worker ... 124*9880d681SAndroid Build Coastguard Worker (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) 125*9880d681SAndroid Build Coastguard Worker | [< 'Token.If; c=parse_expr; 126*9880d681SAndroid Build Coastguard Worker 'Token.Then ?? "expected 'then'"; t=parse_expr; 127*9880d681SAndroid Build Coastguard Worker 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> 128*9880d681SAndroid Build Coastguard Worker Ast.If (c, t, e) 129*9880d681SAndroid Build Coastguard Worker 130*9880d681SAndroid Build Coastguard WorkerLLVM IR for If/Then/Else 131*9880d681SAndroid Build Coastguard Worker------------------------ 132*9880d681SAndroid Build Coastguard Worker 133*9880d681SAndroid Build Coastguard WorkerNow that we have it parsing and building the AST, the final piece is 134*9880d681SAndroid Build Coastguard Workeradding LLVM code generation support. This is the most interesting part 135*9880d681SAndroid Build Coastguard Workerof the if/then/else example, because this is where it starts to 136*9880d681SAndroid Build Coastguard Workerintroduce new concepts. All of the code above has been thoroughly 137*9880d681SAndroid Build Coastguard Workerdescribed in previous chapters. 138*9880d681SAndroid Build Coastguard Worker 139*9880d681SAndroid Build Coastguard WorkerTo motivate the code we want to produce, lets take a look at a simple 140*9880d681SAndroid Build Coastguard Workerexample. Consider: 141*9880d681SAndroid Build Coastguard Worker 142*9880d681SAndroid Build Coastguard Worker:: 143*9880d681SAndroid Build Coastguard Worker 144*9880d681SAndroid Build Coastguard Worker extern foo(); 145*9880d681SAndroid Build Coastguard Worker extern bar(); 146*9880d681SAndroid Build Coastguard Worker def baz(x) if x then foo() else bar(); 147*9880d681SAndroid Build Coastguard Worker 148*9880d681SAndroid Build Coastguard WorkerIf you disable optimizations, the code you'll (soon) get from 149*9880d681SAndroid Build Coastguard WorkerKaleidoscope looks like this: 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Worker.. code-block:: llvm 152*9880d681SAndroid Build Coastguard Worker 153*9880d681SAndroid Build Coastguard Worker declare double @foo() 154*9880d681SAndroid Build Coastguard Worker 155*9880d681SAndroid Build Coastguard Worker declare double @bar() 156*9880d681SAndroid Build Coastguard Worker 157*9880d681SAndroid Build Coastguard Worker define double @baz(double %x) { 158*9880d681SAndroid Build Coastguard Worker entry: 159*9880d681SAndroid Build Coastguard Worker %ifcond = fcmp one double %x, 0.000000e+00 160*9880d681SAndroid Build Coastguard Worker br i1 %ifcond, label %then, label %else 161*9880d681SAndroid Build Coastguard Worker 162*9880d681SAndroid Build Coastguard Worker then: ; preds = %entry 163*9880d681SAndroid Build Coastguard Worker %calltmp = call double @foo() 164*9880d681SAndroid Build Coastguard Worker br label %ifcont 165*9880d681SAndroid Build Coastguard Worker 166*9880d681SAndroid Build Coastguard Worker else: ; preds = %entry 167*9880d681SAndroid Build Coastguard Worker %calltmp1 = call double @bar() 168*9880d681SAndroid Build Coastguard Worker br label %ifcont 169*9880d681SAndroid Build Coastguard Worker 170*9880d681SAndroid Build Coastguard Worker ifcont: ; preds = %else, %then 171*9880d681SAndroid Build Coastguard Worker %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ] 172*9880d681SAndroid Build Coastguard Worker ret double %iftmp 173*9880d681SAndroid Build Coastguard Worker } 174*9880d681SAndroid Build Coastguard Worker 175*9880d681SAndroid Build Coastguard WorkerTo visualize the control flow graph, you can use a nifty feature of the 176*9880d681SAndroid Build Coastguard WorkerLLVM '`opt <http://llvm.org/cmds/opt.html>`_' tool. If you put this LLVM 177*9880d681SAndroid Build Coastguard WorkerIR into "t.ll" and run "``llvm-as < t.ll | opt -analyze -view-cfg``", `a 178*9880d681SAndroid Build Coastguard Workerwindow will pop up <../ProgrammersManual.html#viewing-graphs-while-debugging-code>`_ and you'll 179*9880d681SAndroid Build Coastguard Workersee this graph: 180*9880d681SAndroid Build Coastguard Worker 181*9880d681SAndroid Build Coastguard Worker.. figure:: LangImpl05-cfg.png 182*9880d681SAndroid Build Coastguard Worker :align: center 183*9880d681SAndroid Build Coastguard Worker :alt: Example CFG 184*9880d681SAndroid Build Coastguard Worker 185*9880d681SAndroid Build Coastguard Worker Example CFG 186*9880d681SAndroid Build Coastguard Worker 187*9880d681SAndroid Build Coastguard WorkerAnother way to get this is to call 188*9880d681SAndroid Build Coastguard Worker"``Llvm_analysis.view_function_cfg f``" or 189*9880d681SAndroid Build Coastguard Worker"``Llvm_analysis.view_function_cfg_only f``" (where ``f`` is a 190*9880d681SAndroid Build Coastguard Worker"``Function``") either by inserting actual calls into the code and 191*9880d681SAndroid Build Coastguard Workerrecompiling or by calling these in the debugger. LLVM has many nice 192*9880d681SAndroid Build Coastguard Workerfeatures for visualizing various graphs. 193*9880d681SAndroid Build Coastguard Worker 194*9880d681SAndroid Build Coastguard WorkerGetting back to the generated code, it is fairly simple: the entry block 195*9880d681SAndroid Build Coastguard Workerevaluates the conditional expression ("x" in our case here) and compares 196*9880d681SAndroid Build Coastguard Workerthe result to 0.0 with the "``fcmp one``" instruction ('one' is "Ordered 197*9880d681SAndroid Build Coastguard Workerand Not Equal"). Based on the result of this expression, the code jumps 198*9880d681SAndroid Build Coastguard Workerto either the "then" or "else" blocks, which contain the expressions for 199*9880d681SAndroid Build Coastguard Workerthe true/false cases. 200*9880d681SAndroid Build Coastguard Worker 201*9880d681SAndroid Build Coastguard WorkerOnce the then/else blocks are finished executing, they both branch back 202*9880d681SAndroid Build Coastguard Workerto the 'ifcont' block to execute the code that happens after the 203*9880d681SAndroid Build Coastguard Workerif/then/else. In this case the only thing left to do is to return to the 204*9880d681SAndroid Build Coastguard Workercaller of the function. The question then becomes: how does the code 205*9880d681SAndroid Build Coastguard Workerknow which expression to return? 206*9880d681SAndroid Build Coastguard Worker 207*9880d681SAndroid Build Coastguard WorkerThe answer to this question involves an important SSA operation: the 208*9880d681SAndroid Build Coastguard Worker`Phi 209*9880d681SAndroid Build Coastguard Workeroperation <http://en.wikipedia.org/wiki/Static_single_assignment_form>`_. 210*9880d681SAndroid Build Coastguard WorkerIf you're not familiar with SSA, `the wikipedia 211*9880d681SAndroid Build Coastguard Workerarticle <http://en.wikipedia.org/wiki/Static_single_assignment_form>`_ 212*9880d681SAndroid Build Coastguard Workeris a good introduction and there are various other introductions to it 213*9880d681SAndroid Build Coastguard Workeravailable on your favorite search engine. The short version is that 214*9880d681SAndroid Build Coastguard Worker"execution" of the Phi operation requires "remembering" which block 215*9880d681SAndroid Build Coastguard Workercontrol came from. The Phi operation takes on the value corresponding to 216*9880d681SAndroid Build Coastguard Workerthe input control block. In this case, if control comes in from the 217*9880d681SAndroid Build Coastguard Worker"then" block, it gets the value of "calltmp". If control comes from the 218*9880d681SAndroid Build Coastguard Worker"else" block, it gets the value of "calltmp1". 219*9880d681SAndroid Build Coastguard Worker 220*9880d681SAndroid Build Coastguard WorkerAt this point, you are probably starting to think "Oh no! This means my 221*9880d681SAndroid Build Coastguard Workersimple and elegant front-end will have to start generating SSA form in 222*9880d681SAndroid Build Coastguard Workerorder to use LLVM!". Fortunately, this is not the case, and we strongly 223*9880d681SAndroid Build Coastguard Workeradvise *not* implementing an SSA construction algorithm in your 224*9880d681SAndroid Build Coastguard Workerfront-end unless there is an amazingly good reason to do so. In 225*9880d681SAndroid Build Coastguard Workerpractice, there are two sorts of values that float around in code 226*9880d681SAndroid Build Coastguard Workerwritten for your average imperative programming language that might need 227*9880d681SAndroid Build Coastguard WorkerPhi nodes: 228*9880d681SAndroid Build Coastguard Worker 229*9880d681SAndroid Build Coastguard Worker#. Code that involves user variables: ``x = 1; x = x + 1;`` 230*9880d681SAndroid Build Coastguard Worker#. Values that are implicit in the structure of your AST, such as the 231*9880d681SAndroid Build Coastguard Worker Phi node in this case. 232*9880d681SAndroid Build Coastguard Worker 233*9880d681SAndroid Build Coastguard WorkerIn `Chapter 7 <OCamlLangImpl7.html>`_ of this tutorial ("mutable 234*9880d681SAndroid Build Coastguard Workervariables"), we'll talk about #1 in depth. For now, just believe me that 235*9880d681SAndroid Build Coastguard Workeryou don't need SSA construction to handle this case. For #2, you have 236*9880d681SAndroid Build Coastguard Workerthe choice of using the techniques that we will describe for #1, or you 237*9880d681SAndroid Build Coastguard Workercan insert Phi nodes directly, if convenient. In this case, it is really 238*9880d681SAndroid Build Coastguard Workerreally easy to generate the Phi node, so we choose to do it directly. 239*9880d681SAndroid Build Coastguard Worker 240*9880d681SAndroid Build Coastguard WorkerOkay, enough of the motivation and overview, lets generate code! 241*9880d681SAndroid Build Coastguard Worker 242*9880d681SAndroid Build Coastguard WorkerCode Generation for If/Then/Else 243*9880d681SAndroid Build Coastguard Worker-------------------------------- 244*9880d681SAndroid Build Coastguard Worker 245*9880d681SAndroid Build Coastguard WorkerIn order to generate code for this, we implement the ``Codegen`` method 246*9880d681SAndroid Build Coastguard Workerfor ``IfExprAST``: 247*9880d681SAndroid Build Coastguard Worker 248*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 249*9880d681SAndroid Build Coastguard Worker 250*9880d681SAndroid Build Coastguard Worker let rec codegen_expr = function 251*9880d681SAndroid Build Coastguard Worker ... 252*9880d681SAndroid Build Coastguard Worker | Ast.If (cond, then_, else_) -> 253*9880d681SAndroid Build Coastguard Worker let cond = codegen_expr cond in 254*9880d681SAndroid Build Coastguard Worker 255*9880d681SAndroid Build Coastguard Worker (* Convert condition to a bool by comparing equal to 0.0 *) 256*9880d681SAndroid Build Coastguard Worker let zero = const_float double_type 0.0 in 257*9880d681SAndroid Build Coastguard Worker let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in 258*9880d681SAndroid Build Coastguard Worker 259*9880d681SAndroid Build Coastguard WorkerThis code is straightforward and similar to what we saw before. We emit 260*9880d681SAndroid Build Coastguard Workerthe expression for the condition, then compare that value to zero to get 261*9880d681SAndroid Build Coastguard Workera truth value as a 1-bit (bool) value. 262*9880d681SAndroid Build Coastguard Worker 263*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 264*9880d681SAndroid Build Coastguard Worker 265*9880d681SAndroid Build Coastguard Worker (* Grab the first block so that we might later add the conditional branch 266*9880d681SAndroid Build Coastguard Worker * to it at the end of the function. *) 267*9880d681SAndroid Build Coastguard Worker let start_bb = insertion_block builder in 268*9880d681SAndroid Build Coastguard Worker let the_function = block_parent start_bb in 269*9880d681SAndroid Build Coastguard Worker 270*9880d681SAndroid Build Coastguard Worker let then_bb = append_block context "then" the_function in 271*9880d681SAndroid Build Coastguard Worker position_at_end then_bb builder; 272*9880d681SAndroid Build Coastguard Worker 273*9880d681SAndroid Build Coastguard WorkerAs opposed to the `C++ tutorial <LangImpl5.html>`_, we have to build our 274*9880d681SAndroid Build Coastguard Workerbasic blocks bottom up since we can't have dangling BasicBlocks. We 275*9880d681SAndroid Build Coastguard Workerstart off by saving a pointer to the first block (which might not be the 276*9880d681SAndroid Build Coastguard Workerentry block), which we'll need to build a conditional branch later. We 277*9880d681SAndroid Build Coastguard Workerdo this by asking the ``builder`` for the current BasicBlock. The fourth 278*9880d681SAndroid Build Coastguard Workerline gets the current Function object that is being built. It gets this 279*9880d681SAndroid Build Coastguard Workerby the ``start_bb`` for its "parent" (the function it is currently 280*9880d681SAndroid Build Coastguard Workerembedded into). 281*9880d681SAndroid Build Coastguard Worker 282*9880d681SAndroid Build Coastguard WorkerOnce it has that, it creates one block. It is automatically appended 283*9880d681SAndroid Build Coastguard Workerinto the function's list of blocks. 284*9880d681SAndroid Build Coastguard Worker 285*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 286*9880d681SAndroid Build Coastguard Worker 287*9880d681SAndroid Build Coastguard Worker (* Emit 'then' value. *) 288*9880d681SAndroid Build Coastguard Worker position_at_end then_bb builder; 289*9880d681SAndroid Build Coastguard Worker let then_val = codegen_expr then_ in 290*9880d681SAndroid Build Coastguard Worker 291*9880d681SAndroid Build Coastguard Worker (* Codegen of 'then' can change the current block, update then_bb for the 292*9880d681SAndroid Build Coastguard Worker * phi. We create a new name because one is used for the phi node, and the 293*9880d681SAndroid Build Coastguard Worker * other is used for the conditional branch. *) 294*9880d681SAndroid Build Coastguard Worker let new_then_bb = insertion_block builder in 295*9880d681SAndroid Build Coastguard Worker 296*9880d681SAndroid Build Coastguard WorkerWe move the builder to start inserting into the "then" block. Strictly 297*9880d681SAndroid Build Coastguard Workerspeaking, this call moves the insertion point to be at the end of the 298*9880d681SAndroid Build Coastguard Workerspecified block. However, since the "then" block is empty, it also 299*9880d681SAndroid Build Coastguard Workerstarts out by inserting at the beginning of the block. :) 300*9880d681SAndroid Build Coastguard Worker 301*9880d681SAndroid Build Coastguard WorkerOnce the insertion point is set, we recursively codegen the "then" 302*9880d681SAndroid Build Coastguard Workerexpression from the AST. 303*9880d681SAndroid Build Coastguard Worker 304*9880d681SAndroid Build Coastguard WorkerThe final line here is quite subtle, but is very important. The basic 305*9880d681SAndroid Build Coastguard Workerissue is that when we create the Phi node in the merge block, we need to 306*9880d681SAndroid Build Coastguard Workerset up the block/value pairs that indicate how the Phi will work. 307*9880d681SAndroid Build Coastguard WorkerImportantly, the Phi node expects to have an entry for each predecessor 308*9880d681SAndroid Build Coastguard Workerof the block in the CFG. Why then, are we getting the current block when 309*9880d681SAndroid Build Coastguard Workerwe just set it to ThenBB 5 lines above? The problem is that the "Then" 310*9880d681SAndroid Build Coastguard Workerexpression may actually itself change the block that the Builder is 311*9880d681SAndroid Build Coastguard Workeremitting into if, for example, it contains a nested "if/then/else" 312*9880d681SAndroid Build Coastguard Workerexpression. Because calling Codegen recursively could arbitrarily change 313*9880d681SAndroid Build Coastguard Workerthe notion of the current block, we are required to get an up-to-date 314*9880d681SAndroid Build Coastguard Workervalue for code that will set up the Phi node. 315*9880d681SAndroid Build Coastguard Worker 316*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 317*9880d681SAndroid Build Coastguard Worker 318*9880d681SAndroid Build Coastguard Worker (* Emit 'else' value. *) 319*9880d681SAndroid Build Coastguard Worker let else_bb = append_block context "else" the_function in 320*9880d681SAndroid Build Coastguard Worker position_at_end else_bb builder; 321*9880d681SAndroid Build Coastguard Worker let else_val = codegen_expr else_ in 322*9880d681SAndroid Build Coastguard Worker 323*9880d681SAndroid Build Coastguard Worker (* Codegen of 'else' can change the current block, update else_bb for the 324*9880d681SAndroid Build Coastguard Worker * phi. *) 325*9880d681SAndroid Build Coastguard Worker let new_else_bb = insertion_block builder in 326*9880d681SAndroid Build Coastguard Worker 327*9880d681SAndroid Build Coastguard WorkerCode generation for the 'else' block is basically identical to codegen 328*9880d681SAndroid Build Coastguard Workerfor the 'then' block. 329*9880d681SAndroid Build Coastguard Worker 330*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 331*9880d681SAndroid Build Coastguard Worker 332*9880d681SAndroid Build Coastguard Worker (* Emit merge block. *) 333*9880d681SAndroid Build Coastguard Worker let merge_bb = append_block context "ifcont" the_function in 334*9880d681SAndroid Build Coastguard Worker position_at_end merge_bb builder; 335*9880d681SAndroid Build Coastguard Worker let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in 336*9880d681SAndroid Build Coastguard Worker let phi = build_phi incoming "iftmp" builder in 337*9880d681SAndroid Build Coastguard Worker 338*9880d681SAndroid Build Coastguard WorkerThe first two lines here are now familiar: the first adds the "merge" 339*9880d681SAndroid Build Coastguard Workerblock to the Function object. The second changes the insertion 340*9880d681SAndroid Build Coastguard Workerpoint so that newly created code will go into the "merge" block. Once 341*9880d681SAndroid Build Coastguard Workerthat is done, we need to create the PHI node and set up the block/value 342*9880d681SAndroid Build Coastguard Workerpairs for the PHI. 343*9880d681SAndroid Build Coastguard Worker 344*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 345*9880d681SAndroid Build Coastguard Worker 346*9880d681SAndroid Build Coastguard Worker (* Return to the start block to add the conditional branch. *) 347*9880d681SAndroid Build Coastguard Worker position_at_end start_bb builder; 348*9880d681SAndroid Build Coastguard Worker ignore (build_cond_br cond_val then_bb else_bb builder); 349*9880d681SAndroid Build Coastguard Worker 350*9880d681SAndroid Build Coastguard WorkerOnce the blocks are created, we can emit the conditional branch that 351*9880d681SAndroid Build Coastguard Workerchooses between them. Note that creating new blocks does not implicitly 352*9880d681SAndroid Build Coastguard Workeraffect the IRBuilder, so it is still inserting into the block that the 353*9880d681SAndroid Build Coastguard Workercondition went into. This is why we needed to save the "start" block. 354*9880d681SAndroid Build Coastguard Worker 355*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 356*9880d681SAndroid Build Coastguard Worker 357*9880d681SAndroid Build Coastguard Worker (* Set a unconditional branch at the end of the 'then' block and the 358*9880d681SAndroid Build Coastguard Worker * 'else' block to the 'merge' block. *) 359*9880d681SAndroid Build Coastguard Worker position_at_end new_then_bb builder; ignore (build_br merge_bb builder); 360*9880d681SAndroid Build Coastguard Worker position_at_end new_else_bb builder; ignore (build_br merge_bb builder); 361*9880d681SAndroid Build Coastguard Worker 362*9880d681SAndroid Build Coastguard Worker (* Finally, set the builder to the end of the merge block. *) 363*9880d681SAndroid Build Coastguard Worker position_at_end merge_bb builder; 364*9880d681SAndroid Build Coastguard Worker 365*9880d681SAndroid Build Coastguard Worker phi 366*9880d681SAndroid Build Coastguard Worker 367*9880d681SAndroid Build Coastguard WorkerTo finish off the blocks, we create an unconditional branch to the merge 368*9880d681SAndroid Build Coastguard Workerblock. One interesting (and very important) aspect of the LLVM IR is 369*9880d681SAndroid Build Coastguard Workerthat it `requires all basic blocks to be 370*9880d681SAndroid Build Coastguard Worker"terminated" <../LangRef.html#functionstructure>`_ with a `control flow 371*9880d681SAndroid Build Coastguard Workerinstruction <../LangRef.html#terminators>`_ such as return or branch. 372*9880d681SAndroid Build Coastguard WorkerThis means that all control flow, *including fall throughs* must be made 373*9880d681SAndroid Build Coastguard Workerexplicit in the LLVM IR. If you violate this rule, the verifier will 374*9880d681SAndroid Build Coastguard Workeremit an error. 375*9880d681SAndroid Build Coastguard Worker 376*9880d681SAndroid Build Coastguard WorkerFinally, the CodeGen function returns the phi node as the value computed 377*9880d681SAndroid Build Coastguard Workerby the if/then/else expression. In our example above, this returned 378*9880d681SAndroid Build Coastguard Workervalue will feed into the code for the top-level function, which will 379*9880d681SAndroid Build Coastguard Workercreate the return instruction. 380*9880d681SAndroid Build Coastguard Worker 381*9880d681SAndroid Build Coastguard WorkerOverall, we now have the ability to execute conditional code in 382*9880d681SAndroid Build Coastguard WorkerKaleidoscope. With this extension, Kaleidoscope is a fairly complete 383*9880d681SAndroid Build Coastguard Workerlanguage that can calculate a wide variety of numeric functions. Next up 384*9880d681SAndroid Build Coastguard Workerwe'll add another useful expression that is familiar from non-functional 385*9880d681SAndroid Build Coastguard Workerlanguages... 386*9880d681SAndroid Build Coastguard Worker 387*9880d681SAndroid Build Coastguard Worker'for' Loop Expression 388*9880d681SAndroid Build Coastguard Worker===================== 389*9880d681SAndroid Build Coastguard Worker 390*9880d681SAndroid Build Coastguard WorkerNow that we know how to add basic control flow constructs to the 391*9880d681SAndroid Build Coastguard Workerlanguage, we have the tools to add more powerful things. Lets add 392*9880d681SAndroid Build Coastguard Workersomething more aggressive, a 'for' expression: 393*9880d681SAndroid Build Coastguard Worker 394*9880d681SAndroid Build Coastguard Worker:: 395*9880d681SAndroid Build Coastguard Worker 396*9880d681SAndroid Build Coastguard Worker extern putchard(char); 397*9880d681SAndroid Build Coastguard Worker def printstar(n) 398*9880d681SAndroid Build Coastguard Worker for i = 1, i < n, 1.0 in 399*9880d681SAndroid Build Coastguard Worker putchard(42); # ascii 42 = '*' 400*9880d681SAndroid Build Coastguard Worker 401*9880d681SAndroid Build Coastguard Worker # print 100 '*' characters 402*9880d681SAndroid Build Coastguard Worker printstar(100); 403*9880d681SAndroid Build Coastguard Worker 404*9880d681SAndroid Build Coastguard WorkerThis expression defines a new variable ("i" in this case) which iterates 405*9880d681SAndroid Build Coastguard Workerfrom a starting value, while the condition ("i < n" in this case) is 406*9880d681SAndroid Build Coastguard Workertrue, incrementing by an optional step value ("1.0" in this case). If 407*9880d681SAndroid Build Coastguard Workerthe step value is omitted, it defaults to 1.0. While the loop is true, 408*9880d681SAndroid Build Coastguard Workerit executes its body expression. Because we don't have anything better 409*9880d681SAndroid Build Coastguard Workerto return, we'll just define the loop as always returning 0.0. In the 410*9880d681SAndroid Build Coastguard Workerfuture when we have mutable variables, it will get more useful. 411*9880d681SAndroid Build Coastguard Worker 412*9880d681SAndroid Build Coastguard WorkerAs before, lets talk about the changes that we need to Kaleidoscope to 413*9880d681SAndroid Build Coastguard Workersupport this. 414*9880d681SAndroid Build Coastguard Worker 415*9880d681SAndroid Build Coastguard WorkerLexer Extensions for the 'for' Loop 416*9880d681SAndroid Build Coastguard Worker----------------------------------- 417*9880d681SAndroid Build Coastguard Worker 418*9880d681SAndroid Build Coastguard WorkerThe lexer extensions are the same sort of thing as for if/then/else: 419*9880d681SAndroid Build Coastguard Worker 420*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 421*9880d681SAndroid Build Coastguard Worker 422*9880d681SAndroid Build Coastguard Worker ... in Token.token ... 423*9880d681SAndroid Build Coastguard Worker (* control *) 424*9880d681SAndroid Build Coastguard Worker | If | Then | Else 425*9880d681SAndroid Build Coastguard Worker | For | In 426*9880d681SAndroid Build Coastguard Worker 427*9880d681SAndroid Build Coastguard Worker ... in Lexer.lex_ident... 428*9880d681SAndroid Build Coastguard Worker match Buffer.contents buffer with 429*9880d681SAndroid Build Coastguard Worker | "def" -> [< 'Token.Def; stream >] 430*9880d681SAndroid Build Coastguard Worker | "extern" -> [< 'Token.Extern; stream >] 431*9880d681SAndroid Build Coastguard Worker | "if" -> [< 'Token.If; stream >] 432*9880d681SAndroid Build Coastguard Worker | "then" -> [< 'Token.Then; stream >] 433*9880d681SAndroid Build Coastguard Worker | "else" -> [< 'Token.Else; stream >] 434*9880d681SAndroid Build Coastguard Worker | "for" -> [< 'Token.For; stream >] 435*9880d681SAndroid Build Coastguard Worker | "in" -> [< 'Token.In; stream >] 436*9880d681SAndroid Build Coastguard Worker | id -> [< 'Token.Ident id; stream >] 437*9880d681SAndroid Build Coastguard Worker 438*9880d681SAndroid Build Coastguard WorkerAST Extensions for the 'for' Loop 439*9880d681SAndroid Build Coastguard Worker--------------------------------- 440*9880d681SAndroid Build Coastguard Worker 441*9880d681SAndroid Build Coastguard WorkerThe AST variant is just as simple. It basically boils down to capturing 442*9880d681SAndroid Build Coastguard Workerthe variable name and the constituent expressions in the node. 443*9880d681SAndroid Build Coastguard Worker 444*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 445*9880d681SAndroid Build Coastguard Worker 446*9880d681SAndroid Build Coastguard Worker type expr = 447*9880d681SAndroid Build Coastguard Worker ... 448*9880d681SAndroid Build Coastguard Worker (* variant for for/in. *) 449*9880d681SAndroid Build Coastguard Worker | For of string * expr * expr * expr option * expr 450*9880d681SAndroid Build Coastguard Worker 451*9880d681SAndroid Build Coastguard WorkerParser Extensions for the 'for' Loop 452*9880d681SAndroid Build Coastguard Worker------------------------------------ 453*9880d681SAndroid Build Coastguard Worker 454*9880d681SAndroid Build Coastguard WorkerThe parser code is also fairly standard. The only interesting thing here 455*9880d681SAndroid Build Coastguard Workeris handling of the optional step value. The parser code handles it by 456*9880d681SAndroid Build Coastguard Workerchecking to see if the second comma is present. If not, it sets the step 457*9880d681SAndroid Build Coastguard Workervalue to null in the AST node: 458*9880d681SAndroid Build Coastguard Worker 459*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 460*9880d681SAndroid Build Coastguard Worker 461*9880d681SAndroid Build Coastguard Worker let rec parse_primary = parser 462*9880d681SAndroid Build Coastguard Worker ... 463*9880d681SAndroid Build Coastguard Worker (* forexpr 464*9880d681SAndroid Build Coastguard Worker ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) 465*9880d681SAndroid Build Coastguard Worker | [< 'Token.For; 466*9880d681SAndroid Build Coastguard Worker 'Token.Ident id ?? "expected identifier after for"; 467*9880d681SAndroid Build Coastguard Worker 'Token.Kwd '=' ?? "expected '=' after for"; 468*9880d681SAndroid Build Coastguard Worker stream >] -> 469*9880d681SAndroid Build Coastguard Worker begin parser 470*9880d681SAndroid Build Coastguard Worker | [< 471*9880d681SAndroid Build Coastguard Worker start=parse_expr; 472*9880d681SAndroid Build Coastguard Worker 'Token.Kwd ',' ?? "expected ',' after for"; 473*9880d681SAndroid Build Coastguard Worker end_=parse_expr; 474*9880d681SAndroid Build Coastguard Worker stream >] -> 475*9880d681SAndroid Build Coastguard Worker let step = 476*9880d681SAndroid Build Coastguard Worker begin parser 477*9880d681SAndroid Build Coastguard Worker | [< 'Token.Kwd ','; step=parse_expr >] -> Some step 478*9880d681SAndroid Build Coastguard Worker | [< >] -> None 479*9880d681SAndroid Build Coastguard Worker end stream 480*9880d681SAndroid Build Coastguard Worker in 481*9880d681SAndroid Build Coastguard Worker begin parser 482*9880d681SAndroid Build Coastguard Worker | [< 'Token.In; body=parse_expr >] -> 483*9880d681SAndroid Build Coastguard Worker Ast.For (id, start, end_, step, body) 484*9880d681SAndroid Build Coastguard Worker | [< >] -> 485*9880d681SAndroid Build Coastguard Worker raise (Stream.Error "expected 'in' after for") 486*9880d681SAndroid Build Coastguard Worker end stream 487*9880d681SAndroid Build Coastguard Worker | [< >] -> 488*9880d681SAndroid Build Coastguard Worker raise (Stream.Error "expected '=' after for") 489*9880d681SAndroid Build Coastguard Worker end stream 490*9880d681SAndroid Build Coastguard Worker 491*9880d681SAndroid Build Coastguard WorkerLLVM IR for the 'for' Loop 492*9880d681SAndroid Build Coastguard Worker-------------------------- 493*9880d681SAndroid Build Coastguard Worker 494*9880d681SAndroid Build Coastguard WorkerNow we get to the good part: the LLVM IR we want to generate for this 495*9880d681SAndroid Build Coastguard Workerthing. With the simple example above, we get this LLVM IR (note that 496*9880d681SAndroid Build Coastguard Workerthis dump is generated with optimizations disabled for clarity): 497*9880d681SAndroid Build Coastguard Worker 498*9880d681SAndroid Build Coastguard Worker.. code-block:: llvm 499*9880d681SAndroid Build Coastguard Worker 500*9880d681SAndroid Build Coastguard Worker declare double @putchard(double) 501*9880d681SAndroid Build Coastguard Worker 502*9880d681SAndroid Build Coastguard Worker define double @printstar(double %n) { 503*9880d681SAndroid Build Coastguard Worker entry: 504*9880d681SAndroid Build Coastguard Worker ; initial value = 1.0 (inlined into phi) 505*9880d681SAndroid Build Coastguard Worker br label %loop 506*9880d681SAndroid Build Coastguard Worker 507*9880d681SAndroid Build Coastguard Worker loop: ; preds = %loop, %entry 508*9880d681SAndroid Build Coastguard Worker %i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ] 509*9880d681SAndroid Build Coastguard Worker ; body 510*9880d681SAndroid Build Coastguard Worker %calltmp = call double @putchard(double 4.200000e+01) 511*9880d681SAndroid Build Coastguard Worker ; increment 512*9880d681SAndroid Build Coastguard Worker %nextvar = fadd double %i, 1.000000e+00 513*9880d681SAndroid Build Coastguard Worker 514*9880d681SAndroid Build Coastguard Worker ; termination test 515*9880d681SAndroid Build Coastguard Worker %cmptmp = fcmp ult double %i, %n 516*9880d681SAndroid Build Coastguard Worker %booltmp = uitofp i1 %cmptmp to double 517*9880d681SAndroid Build Coastguard Worker %loopcond = fcmp one double %booltmp, 0.000000e+00 518*9880d681SAndroid Build Coastguard Worker br i1 %loopcond, label %loop, label %afterloop 519*9880d681SAndroid Build Coastguard Worker 520*9880d681SAndroid Build Coastguard Worker afterloop: ; preds = %loop 521*9880d681SAndroid Build Coastguard Worker ; loop always returns 0.0 522*9880d681SAndroid Build Coastguard Worker ret double 0.000000e+00 523*9880d681SAndroid Build Coastguard Worker } 524*9880d681SAndroid Build Coastguard Worker 525*9880d681SAndroid Build Coastguard WorkerThis loop contains all the same constructs we saw before: a phi node, 526*9880d681SAndroid Build Coastguard Workerseveral expressions, and some basic blocks. Lets see how this fits 527*9880d681SAndroid Build Coastguard Workertogether. 528*9880d681SAndroid Build Coastguard Worker 529*9880d681SAndroid Build Coastguard WorkerCode Generation for the 'for' Loop 530*9880d681SAndroid Build Coastguard Worker---------------------------------- 531*9880d681SAndroid Build Coastguard Worker 532*9880d681SAndroid Build Coastguard WorkerThe first part of Codegen is very simple: we just output the start 533*9880d681SAndroid Build Coastguard Workerexpression for the loop value: 534*9880d681SAndroid Build Coastguard Worker 535*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 536*9880d681SAndroid Build Coastguard Worker 537*9880d681SAndroid Build Coastguard Worker let rec codegen_expr = function 538*9880d681SAndroid Build Coastguard Worker ... 539*9880d681SAndroid Build Coastguard Worker | Ast.For (var_name, start, end_, step, body) -> 540*9880d681SAndroid Build Coastguard Worker (* Emit the start code first, without 'variable' in scope. *) 541*9880d681SAndroid Build Coastguard Worker let start_val = codegen_expr start in 542*9880d681SAndroid Build Coastguard Worker 543*9880d681SAndroid Build Coastguard WorkerWith this out of the way, the next step is to set up the LLVM basic 544*9880d681SAndroid Build Coastguard Workerblock for the start of the loop body. In the case above, the whole loop 545*9880d681SAndroid Build Coastguard Workerbody is one block, but remember that the body code itself could consist 546*9880d681SAndroid Build Coastguard Workerof multiple blocks (e.g. if it contains an if/then/else or a for/in 547*9880d681SAndroid Build Coastguard Workerexpression). 548*9880d681SAndroid Build Coastguard Worker 549*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 550*9880d681SAndroid Build Coastguard Worker 551*9880d681SAndroid Build Coastguard Worker (* Make the new basic block for the loop header, inserting after current 552*9880d681SAndroid Build Coastguard Worker * block. *) 553*9880d681SAndroid Build Coastguard Worker let preheader_bb = insertion_block builder in 554*9880d681SAndroid Build Coastguard Worker let the_function = block_parent preheader_bb in 555*9880d681SAndroid Build Coastguard Worker let loop_bb = append_block context "loop" the_function in 556*9880d681SAndroid Build Coastguard Worker 557*9880d681SAndroid Build Coastguard Worker (* Insert an explicit fall through from the current block to the 558*9880d681SAndroid Build Coastguard Worker * loop_bb. *) 559*9880d681SAndroid Build Coastguard Worker ignore (build_br loop_bb builder); 560*9880d681SAndroid Build Coastguard Worker 561*9880d681SAndroid Build Coastguard WorkerThis code is similar to what we saw for if/then/else. Because we will 562*9880d681SAndroid Build Coastguard Workerneed it to create the Phi node, we remember the block that falls through 563*9880d681SAndroid Build Coastguard Workerinto the loop. Once we have that, we create the actual block that starts 564*9880d681SAndroid Build Coastguard Workerthe loop and create an unconditional branch for the fall-through between 565*9880d681SAndroid Build Coastguard Workerthe two blocks. 566*9880d681SAndroid Build Coastguard Worker 567*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 568*9880d681SAndroid Build Coastguard Worker 569*9880d681SAndroid Build Coastguard Worker (* Start insertion in loop_bb. *) 570*9880d681SAndroid Build Coastguard Worker position_at_end loop_bb builder; 571*9880d681SAndroid Build Coastguard Worker 572*9880d681SAndroid Build Coastguard Worker (* Start the PHI node with an entry for start. *) 573*9880d681SAndroid Build Coastguard Worker let variable = build_phi [(start_val, preheader_bb)] var_name builder in 574*9880d681SAndroid Build Coastguard Worker 575*9880d681SAndroid Build Coastguard WorkerNow that the "preheader" for the loop is set up, we switch to emitting 576*9880d681SAndroid Build Coastguard Workercode for the loop body. To begin with, we move the insertion point and 577*9880d681SAndroid Build Coastguard Workercreate the PHI node for the loop induction variable. Since we already 578*9880d681SAndroid Build Coastguard Workerknow the incoming value for the starting value, we add it to the Phi 579*9880d681SAndroid Build Coastguard Workernode. Note that the Phi will eventually get a second value for the 580*9880d681SAndroid Build Coastguard Workerbackedge, but we can't set it up yet (because it doesn't exist!). 581*9880d681SAndroid Build Coastguard Worker 582*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 583*9880d681SAndroid Build Coastguard Worker 584*9880d681SAndroid Build Coastguard Worker (* Within the loop, the variable is defined equal to the PHI node. If it 585*9880d681SAndroid Build Coastguard Worker * shadows an existing variable, we have to restore it, so save it 586*9880d681SAndroid Build Coastguard Worker * now. *) 587*9880d681SAndroid Build Coastguard Worker let old_val = 588*9880d681SAndroid Build Coastguard Worker try Some (Hashtbl.find named_values var_name) with Not_found -> None 589*9880d681SAndroid Build Coastguard Worker in 590*9880d681SAndroid Build Coastguard Worker Hashtbl.add named_values var_name variable; 591*9880d681SAndroid Build Coastguard Worker 592*9880d681SAndroid Build Coastguard Worker (* Emit the body of the loop. This, like any other expr, can change the 593*9880d681SAndroid Build Coastguard Worker * current BB. Note that we ignore the value computed by the body, but 594*9880d681SAndroid Build Coastguard Worker * don't allow an error *) 595*9880d681SAndroid Build Coastguard Worker ignore (codegen_expr body); 596*9880d681SAndroid Build Coastguard Worker 597*9880d681SAndroid Build Coastguard WorkerNow the code starts to get more interesting. Our 'for' loop introduces a 598*9880d681SAndroid Build Coastguard Workernew variable to the symbol table. This means that our symbol table can 599*9880d681SAndroid Build Coastguard Workernow contain either function arguments or loop variables. To handle this, 600*9880d681SAndroid Build Coastguard Workerbefore we codegen the body of the loop, we add the loop variable as the 601*9880d681SAndroid Build Coastguard Workercurrent value for its name. Note that it is possible that there is a 602*9880d681SAndroid Build Coastguard Workervariable of the same name in the outer scope. It would be easy to make 603*9880d681SAndroid Build Coastguard Workerthis an error (emit an error and return null if there is already an 604*9880d681SAndroid Build Coastguard Workerentry for VarName) but we choose to allow shadowing of variables. In 605*9880d681SAndroid Build Coastguard Workerorder to handle this correctly, we remember the Value that we are 606*9880d681SAndroid Build Coastguard Workerpotentially shadowing in ``old_val`` (which will be None if there is no 607*9880d681SAndroid Build Coastguard Workershadowed variable). 608*9880d681SAndroid Build Coastguard Worker 609*9880d681SAndroid Build Coastguard WorkerOnce the loop variable is set into the symbol table, the code 610*9880d681SAndroid Build Coastguard Workerrecursively codegen's the body. This allows the body to use the loop 611*9880d681SAndroid Build Coastguard Workervariable: any references to it will naturally find it in the symbol 612*9880d681SAndroid Build Coastguard Workertable. 613*9880d681SAndroid Build Coastguard Worker 614*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 615*9880d681SAndroid Build Coastguard Worker 616*9880d681SAndroid Build Coastguard Worker (* Emit the step value. *) 617*9880d681SAndroid Build Coastguard Worker let step_val = 618*9880d681SAndroid Build Coastguard Worker match step with 619*9880d681SAndroid Build Coastguard Worker | Some step -> codegen_expr step 620*9880d681SAndroid Build Coastguard Worker (* If not specified, use 1.0. *) 621*9880d681SAndroid Build Coastguard Worker | None -> const_float double_type 1.0 622*9880d681SAndroid Build Coastguard Worker in 623*9880d681SAndroid Build Coastguard Worker 624*9880d681SAndroid Build Coastguard Worker let next_var = build_add variable step_val "nextvar" builder in 625*9880d681SAndroid Build Coastguard Worker 626*9880d681SAndroid Build Coastguard WorkerNow that the body is emitted, we compute the next value of the iteration 627*9880d681SAndroid Build Coastguard Workervariable by adding the step value, or 1.0 if it isn't present. 628*9880d681SAndroid Build Coastguard Worker'``next_var``' will be the value of the loop variable on the next 629*9880d681SAndroid Build Coastguard Workeriteration of the loop. 630*9880d681SAndroid Build Coastguard Worker 631*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 632*9880d681SAndroid Build Coastguard Worker 633*9880d681SAndroid Build Coastguard Worker (* Compute the end condition. *) 634*9880d681SAndroid Build Coastguard Worker let end_cond = codegen_expr end_ in 635*9880d681SAndroid Build Coastguard Worker 636*9880d681SAndroid Build Coastguard Worker (* Convert condition to a bool by comparing equal to 0.0. *) 637*9880d681SAndroid Build Coastguard Worker let zero = const_float double_type 0.0 in 638*9880d681SAndroid Build Coastguard Worker let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in 639*9880d681SAndroid Build Coastguard Worker 640*9880d681SAndroid Build Coastguard WorkerFinally, we evaluate the exit value of the loop, to determine whether 641*9880d681SAndroid Build Coastguard Workerthe loop should exit. This mirrors the condition evaluation for the 642*9880d681SAndroid Build Coastguard Workerif/then/else statement. 643*9880d681SAndroid Build Coastguard Worker 644*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 645*9880d681SAndroid Build Coastguard Worker 646*9880d681SAndroid Build Coastguard Worker (* Create the "after loop" block and insert it. *) 647*9880d681SAndroid Build Coastguard Worker let loop_end_bb = insertion_block builder in 648*9880d681SAndroid Build Coastguard Worker let after_bb = append_block context "afterloop" the_function in 649*9880d681SAndroid Build Coastguard Worker 650*9880d681SAndroid Build Coastguard Worker (* Insert the conditional branch into the end of loop_end_bb. *) 651*9880d681SAndroid Build Coastguard Worker ignore (build_cond_br end_cond loop_bb after_bb builder); 652*9880d681SAndroid Build Coastguard Worker 653*9880d681SAndroid Build Coastguard Worker (* Any new code will be inserted in after_bb. *) 654*9880d681SAndroid Build Coastguard Worker position_at_end after_bb builder; 655*9880d681SAndroid Build Coastguard Worker 656*9880d681SAndroid Build Coastguard WorkerWith the code for the body of the loop complete, we just need to finish 657*9880d681SAndroid Build Coastguard Workerup the control flow for it. This code remembers the end block (for the 658*9880d681SAndroid Build Coastguard Workerphi node), then creates the block for the loop exit ("afterloop"). Based 659*9880d681SAndroid Build Coastguard Workeron the value of the exit condition, it creates a conditional branch that 660*9880d681SAndroid Build Coastguard Workerchooses between executing the loop again and exiting the loop. Any 661*9880d681SAndroid Build Coastguard Workerfuture code is emitted in the "afterloop" block, so it sets the 662*9880d681SAndroid Build Coastguard Workerinsertion position to it. 663*9880d681SAndroid Build Coastguard Worker 664*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 665*9880d681SAndroid Build Coastguard Worker 666*9880d681SAndroid Build Coastguard Worker (* Add a new entry to the PHI node for the backedge. *) 667*9880d681SAndroid Build Coastguard Worker add_incoming (next_var, loop_end_bb) variable; 668*9880d681SAndroid Build Coastguard Worker 669*9880d681SAndroid Build Coastguard Worker (* Restore the unshadowed variable. *) 670*9880d681SAndroid Build Coastguard Worker begin match old_val with 671*9880d681SAndroid Build Coastguard Worker | Some old_val -> Hashtbl.add named_values var_name old_val 672*9880d681SAndroid Build Coastguard Worker | None -> () 673*9880d681SAndroid Build Coastguard Worker end; 674*9880d681SAndroid Build Coastguard Worker 675*9880d681SAndroid Build Coastguard Worker (* for expr always returns 0.0. *) 676*9880d681SAndroid Build Coastguard Worker const_null double_type 677*9880d681SAndroid Build Coastguard Worker 678*9880d681SAndroid Build Coastguard WorkerThe final code handles various cleanups: now that we have the 679*9880d681SAndroid Build Coastguard Worker"``next_var``" value, we can add the incoming value to the loop PHI 680*9880d681SAndroid Build Coastguard Workernode. After that, we remove the loop variable from the symbol table, so 681*9880d681SAndroid Build Coastguard Workerthat it isn't in scope after the for loop. Finally, code generation of 682*9880d681SAndroid Build Coastguard Workerthe for loop always returns 0.0, so that is what we return from 683*9880d681SAndroid Build Coastguard Worker``Codegen.codegen_expr``. 684*9880d681SAndroid Build Coastguard Worker 685*9880d681SAndroid Build Coastguard WorkerWith this, we conclude the "adding control flow to Kaleidoscope" chapter 686*9880d681SAndroid Build Coastguard Workerof the tutorial. In this chapter we added two control flow constructs, 687*9880d681SAndroid Build Coastguard Workerand used them to motivate a couple of aspects of the LLVM IR that are 688*9880d681SAndroid Build Coastguard Workerimportant for front-end implementors to know. In the next chapter of our 689*9880d681SAndroid Build Coastguard Workersaga, we will get a bit crazier and add `user-defined 690*9880d681SAndroid Build Coastguard Workeroperators <OCamlLangImpl6.html>`_ to our poor innocent language. 691*9880d681SAndroid Build Coastguard Worker 692*9880d681SAndroid Build Coastguard WorkerFull Code Listing 693*9880d681SAndroid Build Coastguard Worker================= 694*9880d681SAndroid Build Coastguard Worker 695*9880d681SAndroid Build Coastguard WorkerHere is the complete code listing for our running example, enhanced with 696*9880d681SAndroid Build Coastguard Workerthe if/then/else and for expressions.. To build this example, use: 697*9880d681SAndroid Build Coastguard Worker 698*9880d681SAndroid Build Coastguard Worker.. code-block:: bash 699*9880d681SAndroid Build Coastguard Worker 700*9880d681SAndroid Build Coastguard Worker # Compile 701*9880d681SAndroid Build Coastguard Worker ocamlbuild toy.byte 702*9880d681SAndroid Build Coastguard Worker # Run 703*9880d681SAndroid Build Coastguard Worker ./toy.byte 704*9880d681SAndroid Build Coastguard Worker 705*9880d681SAndroid Build Coastguard WorkerHere is the code: 706*9880d681SAndroid Build Coastguard Worker 707*9880d681SAndroid Build Coastguard Worker\_tags: 708*9880d681SAndroid Build Coastguard Worker :: 709*9880d681SAndroid Build Coastguard Worker 710*9880d681SAndroid Build Coastguard Worker <{lexer,parser}.ml>: use_camlp4, pp(camlp4of) 711*9880d681SAndroid Build Coastguard Worker <*.{byte,native}>: g++, use_llvm, use_llvm_analysis 712*9880d681SAndroid Build Coastguard Worker <*.{byte,native}>: use_llvm_executionengine, use_llvm_target 713*9880d681SAndroid Build Coastguard Worker <*.{byte,native}>: use_llvm_scalar_opts, use_bindings 714*9880d681SAndroid Build Coastguard Worker 715*9880d681SAndroid Build Coastguard Workermyocamlbuild.ml: 716*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 717*9880d681SAndroid Build Coastguard Worker 718*9880d681SAndroid Build Coastguard Worker open Ocamlbuild_plugin;; 719*9880d681SAndroid Build Coastguard Worker 720*9880d681SAndroid Build Coastguard Worker ocaml_lib ~extern:true "llvm";; 721*9880d681SAndroid Build Coastguard Worker ocaml_lib ~extern:true "llvm_analysis";; 722*9880d681SAndroid Build Coastguard Worker ocaml_lib ~extern:true "llvm_executionengine";; 723*9880d681SAndroid Build Coastguard Worker ocaml_lib ~extern:true "llvm_target";; 724*9880d681SAndroid Build Coastguard Worker ocaml_lib ~extern:true "llvm_scalar_opts";; 725*9880d681SAndroid Build Coastguard Worker 726*9880d681SAndroid Build Coastguard Worker flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; 727*9880d681SAndroid Build Coastguard Worker dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; 728*9880d681SAndroid Build Coastguard Worker 729*9880d681SAndroid Build Coastguard Workertoken.ml: 730*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 731*9880d681SAndroid Build Coastguard Worker 732*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 733*9880d681SAndroid Build Coastguard Worker * Lexer Tokens 734*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 735*9880d681SAndroid Build Coastguard Worker 736*9880d681SAndroid Build Coastguard Worker (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of 737*9880d681SAndroid Build Coastguard Worker * these others for known things. *) 738*9880d681SAndroid Build Coastguard Worker type token = 739*9880d681SAndroid Build Coastguard Worker (* commands *) 740*9880d681SAndroid Build Coastguard Worker | Def | Extern 741*9880d681SAndroid Build Coastguard Worker 742*9880d681SAndroid Build Coastguard Worker (* primary *) 743*9880d681SAndroid Build Coastguard Worker | Ident of string | Number of float 744*9880d681SAndroid Build Coastguard Worker 745*9880d681SAndroid Build Coastguard Worker (* unknown *) 746*9880d681SAndroid Build Coastguard Worker | Kwd of char 747*9880d681SAndroid Build Coastguard Worker 748*9880d681SAndroid Build Coastguard Worker (* control *) 749*9880d681SAndroid Build Coastguard Worker | If | Then | Else 750*9880d681SAndroid Build Coastguard Worker | For | In 751*9880d681SAndroid Build Coastguard Worker 752*9880d681SAndroid Build Coastguard Workerlexer.ml: 753*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 754*9880d681SAndroid Build Coastguard Worker 755*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 756*9880d681SAndroid Build Coastguard Worker * Lexer 757*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 758*9880d681SAndroid Build Coastguard Worker 759*9880d681SAndroid Build Coastguard Worker let rec lex = parser 760*9880d681SAndroid Build Coastguard Worker (* Skip any whitespace. *) 761*9880d681SAndroid Build Coastguard Worker | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream 762*9880d681SAndroid Build Coastguard Worker 763*9880d681SAndroid Build Coastguard Worker (* identifier: [a-zA-Z][a-zA-Z0-9] *) 764*9880d681SAndroid Build Coastguard Worker | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> 765*9880d681SAndroid Build Coastguard Worker let buffer = Buffer.create 1 in 766*9880d681SAndroid Build Coastguard Worker Buffer.add_char buffer c; 767*9880d681SAndroid Build Coastguard Worker lex_ident buffer stream 768*9880d681SAndroid Build Coastguard Worker 769*9880d681SAndroid Build Coastguard Worker (* number: [0-9.]+ *) 770*9880d681SAndroid Build Coastguard Worker | [< ' ('0' .. '9' as c); stream >] -> 771*9880d681SAndroid Build Coastguard Worker let buffer = Buffer.create 1 in 772*9880d681SAndroid Build Coastguard Worker Buffer.add_char buffer c; 773*9880d681SAndroid Build Coastguard Worker lex_number buffer stream 774*9880d681SAndroid Build Coastguard Worker 775*9880d681SAndroid Build Coastguard Worker (* Comment until end of line. *) 776*9880d681SAndroid Build Coastguard Worker | [< ' ('#'); stream >] -> 777*9880d681SAndroid Build Coastguard Worker lex_comment stream 778*9880d681SAndroid Build Coastguard Worker 779*9880d681SAndroid Build Coastguard Worker (* Otherwise, just return the character as its ascii value. *) 780*9880d681SAndroid Build Coastguard Worker | [< 'c; stream >] -> 781*9880d681SAndroid Build Coastguard Worker [< 'Token.Kwd c; lex stream >] 782*9880d681SAndroid Build Coastguard Worker 783*9880d681SAndroid Build Coastguard Worker (* end of stream. *) 784*9880d681SAndroid Build Coastguard Worker | [< >] -> [< >] 785*9880d681SAndroid Build Coastguard Worker 786*9880d681SAndroid Build Coastguard Worker and lex_number buffer = parser 787*9880d681SAndroid Build Coastguard Worker | [< ' ('0' .. '9' | '.' as c); stream >] -> 788*9880d681SAndroid Build Coastguard Worker Buffer.add_char buffer c; 789*9880d681SAndroid Build Coastguard Worker lex_number buffer stream 790*9880d681SAndroid Build Coastguard Worker | [< stream=lex >] -> 791*9880d681SAndroid Build Coastguard Worker [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] 792*9880d681SAndroid Build Coastguard Worker 793*9880d681SAndroid Build Coastguard Worker and lex_ident buffer = parser 794*9880d681SAndroid Build Coastguard Worker | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> 795*9880d681SAndroid Build Coastguard Worker Buffer.add_char buffer c; 796*9880d681SAndroid Build Coastguard Worker lex_ident buffer stream 797*9880d681SAndroid Build Coastguard Worker | [< stream=lex >] -> 798*9880d681SAndroid Build Coastguard Worker match Buffer.contents buffer with 799*9880d681SAndroid Build Coastguard Worker | "def" -> [< 'Token.Def; stream >] 800*9880d681SAndroid Build Coastguard Worker | "extern" -> [< 'Token.Extern; stream >] 801*9880d681SAndroid Build Coastguard Worker | "if" -> [< 'Token.If; stream >] 802*9880d681SAndroid Build Coastguard Worker | "then" -> [< 'Token.Then; stream >] 803*9880d681SAndroid Build Coastguard Worker | "else" -> [< 'Token.Else; stream >] 804*9880d681SAndroid Build Coastguard Worker | "for" -> [< 'Token.For; stream >] 805*9880d681SAndroid Build Coastguard Worker | "in" -> [< 'Token.In; stream >] 806*9880d681SAndroid Build Coastguard Worker | id -> [< 'Token.Ident id; stream >] 807*9880d681SAndroid Build Coastguard Worker 808*9880d681SAndroid Build Coastguard Worker and lex_comment = parser 809*9880d681SAndroid Build Coastguard Worker | [< ' ('\n'); stream=lex >] -> stream 810*9880d681SAndroid Build Coastguard Worker | [< 'c; e=lex_comment >] -> e 811*9880d681SAndroid Build Coastguard Worker | [< >] -> [< >] 812*9880d681SAndroid Build Coastguard Worker 813*9880d681SAndroid Build Coastguard Workerast.ml: 814*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 815*9880d681SAndroid Build Coastguard Worker 816*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 817*9880d681SAndroid Build Coastguard Worker * Abstract Syntax Tree (aka Parse Tree) 818*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 819*9880d681SAndroid Build Coastguard Worker 820*9880d681SAndroid Build Coastguard Worker (* expr - Base type for all expression nodes. *) 821*9880d681SAndroid Build Coastguard Worker type expr = 822*9880d681SAndroid Build Coastguard Worker (* variant for numeric literals like "1.0". *) 823*9880d681SAndroid Build Coastguard Worker | Number of float 824*9880d681SAndroid Build Coastguard Worker 825*9880d681SAndroid Build Coastguard Worker (* variant for referencing a variable, like "a". *) 826*9880d681SAndroid Build Coastguard Worker | Variable of string 827*9880d681SAndroid Build Coastguard Worker 828*9880d681SAndroid Build Coastguard Worker (* variant for a binary operator. *) 829*9880d681SAndroid Build Coastguard Worker | Binary of char * expr * expr 830*9880d681SAndroid Build Coastguard Worker 831*9880d681SAndroid Build Coastguard Worker (* variant for function calls. *) 832*9880d681SAndroid Build Coastguard Worker | Call of string * expr array 833*9880d681SAndroid Build Coastguard Worker 834*9880d681SAndroid Build Coastguard Worker (* variant for if/then/else. *) 835*9880d681SAndroid Build Coastguard Worker | If of expr * expr * expr 836*9880d681SAndroid Build Coastguard Worker 837*9880d681SAndroid Build Coastguard Worker (* variant for for/in. *) 838*9880d681SAndroid Build Coastguard Worker | For of string * expr * expr * expr option * expr 839*9880d681SAndroid Build Coastguard Worker 840*9880d681SAndroid Build Coastguard Worker (* proto - This type represents the "prototype" for a function, which captures 841*9880d681SAndroid Build Coastguard Worker * its name, and its argument names (thus implicitly the number of arguments the 842*9880d681SAndroid Build Coastguard Worker * function takes). *) 843*9880d681SAndroid Build Coastguard Worker type proto = Prototype of string * string array 844*9880d681SAndroid Build Coastguard Worker 845*9880d681SAndroid Build Coastguard Worker (* func - This type represents a function definition itself. *) 846*9880d681SAndroid Build Coastguard Worker type func = Function of proto * expr 847*9880d681SAndroid Build Coastguard Worker 848*9880d681SAndroid Build Coastguard Workerparser.ml: 849*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 850*9880d681SAndroid Build Coastguard Worker 851*9880d681SAndroid Build Coastguard Worker (*===---------------------------------------------------------------------=== 852*9880d681SAndroid Build Coastguard Worker * Parser 853*9880d681SAndroid Build Coastguard Worker *===---------------------------------------------------------------------===*) 854*9880d681SAndroid Build Coastguard Worker 855*9880d681SAndroid Build Coastguard Worker (* binop_precedence - This holds the precedence for each binary operator that is 856*9880d681SAndroid Build Coastguard Worker * defined *) 857*9880d681SAndroid Build Coastguard Worker let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 858*9880d681SAndroid Build Coastguard Worker 859*9880d681SAndroid Build Coastguard Worker (* precedence - Get the precedence of the pending binary operator token. *) 860*9880d681SAndroid Build Coastguard Worker let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 861*9880d681SAndroid Build Coastguard Worker 862*9880d681SAndroid Build Coastguard Worker (* primary 863*9880d681SAndroid Build Coastguard Worker * ::= identifier 864*9880d681SAndroid Build Coastguard Worker * ::= numberexpr 865*9880d681SAndroid Build Coastguard Worker * ::= parenexpr 866*9880d681SAndroid Build Coastguard Worker * ::= ifexpr 867*9880d681SAndroid Build Coastguard Worker * ::= forexpr *) 868*9880d681SAndroid Build Coastguard Worker let rec parse_primary = parser 869*9880d681SAndroid Build Coastguard Worker (* numberexpr ::= number *) 870*9880d681SAndroid Build Coastguard Worker | [< 'Token.Number n >] -> Ast.Number n 871*9880d681SAndroid Build Coastguard Worker 872*9880d681SAndroid Build Coastguard Worker (* parenexpr ::= '(' expression ')' *) 873*9880d681SAndroid Build Coastguard Worker | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e 874*9880d681SAndroid Build Coastguard Worker 875*9880d681SAndroid Build Coastguard Worker (* identifierexpr 876*9880d681SAndroid Build Coastguard Worker * ::= identifier 877*9880d681SAndroid Build Coastguard Worker * ::= identifier '(' argumentexpr ')' *) 878*9880d681SAndroid Build Coastguard Worker | [< 'Token.Ident id; stream >] -> 879*9880d681SAndroid Build Coastguard Worker let rec parse_args accumulator = parser 880*9880d681SAndroid Build Coastguard Worker | [< e=parse_expr; stream >] -> 881*9880d681SAndroid Build Coastguard Worker begin parser 882*9880d681SAndroid Build Coastguard Worker | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e 883*9880d681SAndroid Build Coastguard Worker | [< >] -> e :: accumulator 884*9880d681SAndroid Build Coastguard Worker end stream 885*9880d681SAndroid Build Coastguard Worker | [< >] -> accumulator 886*9880d681SAndroid Build Coastguard Worker in 887*9880d681SAndroid Build Coastguard Worker let rec parse_ident id = parser 888*9880d681SAndroid Build Coastguard Worker (* Call. *) 889*9880d681SAndroid Build Coastguard Worker | [< 'Token.Kwd '('; 890*9880d681SAndroid Build Coastguard Worker args=parse_args []; 891*9880d681SAndroid Build Coastguard Worker 'Token.Kwd ')' ?? "expected ')'">] -> 892*9880d681SAndroid Build Coastguard Worker Ast.Call (id, Array.of_list (List.rev args)) 893*9880d681SAndroid Build Coastguard Worker 894*9880d681SAndroid Build Coastguard Worker (* Simple variable ref. *) 895*9880d681SAndroid Build Coastguard Worker | [< >] -> Ast.Variable id 896*9880d681SAndroid Build Coastguard Worker in 897*9880d681SAndroid Build Coastguard Worker parse_ident id stream 898*9880d681SAndroid Build Coastguard Worker 899*9880d681SAndroid Build Coastguard Worker (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) 900*9880d681SAndroid Build Coastguard Worker | [< 'Token.If; c=parse_expr; 901*9880d681SAndroid Build Coastguard Worker 'Token.Then ?? "expected 'then'"; t=parse_expr; 902*9880d681SAndroid Build Coastguard Worker 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> 903*9880d681SAndroid Build Coastguard Worker Ast.If (c, t, e) 904*9880d681SAndroid Build Coastguard Worker 905*9880d681SAndroid Build Coastguard Worker (* forexpr 906*9880d681SAndroid Build Coastguard Worker ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) 907*9880d681SAndroid Build Coastguard Worker | [< 'Token.For; 908*9880d681SAndroid Build Coastguard Worker 'Token.Ident id ?? "expected identifier after for"; 909*9880d681SAndroid Build Coastguard Worker 'Token.Kwd '=' ?? "expected '=' after for"; 910*9880d681SAndroid Build Coastguard Worker stream >] -> 911*9880d681SAndroid Build Coastguard Worker begin parser 912*9880d681SAndroid Build Coastguard Worker | [< 913*9880d681SAndroid Build Coastguard Worker start=parse_expr; 914*9880d681SAndroid Build Coastguard Worker 'Token.Kwd ',' ?? "expected ',' after for"; 915*9880d681SAndroid Build Coastguard Worker end_=parse_expr; 916*9880d681SAndroid Build Coastguard Worker stream >] -> 917*9880d681SAndroid Build Coastguard Worker let step = 918*9880d681SAndroid Build Coastguard Worker begin parser 919*9880d681SAndroid Build Coastguard Worker | [< 'Token.Kwd ','; step=parse_expr >] -> Some step 920*9880d681SAndroid Build Coastguard Worker | [< >] -> None 921*9880d681SAndroid Build Coastguard Worker end stream 922*9880d681SAndroid Build Coastguard Worker in 923*9880d681SAndroid Build Coastguard Worker begin parser 924*9880d681SAndroid Build Coastguard Worker | [< 'Token.In; body=parse_expr >] -> 925*9880d681SAndroid Build Coastguard Worker Ast.For (id, start, end_, step, body) 926*9880d681SAndroid Build Coastguard Worker | [< >] -> 927*9880d681SAndroid Build Coastguard Worker raise (Stream.Error "expected 'in' after for") 928*9880d681SAndroid Build Coastguard Worker end stream 929*9880d681SAndroid Build Coastguard Worker | [< >] -> 930*9880d681SAndroid Build Coastguard Worker raise (Stream.Error "expected '=' after for") 931*9880d681SAndroid Build Coastguard Worker end stream 932*9880d681SAndroid Build Coastguard Worker 933*9880d681SAndroid Build Coastguard Worker | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") 934*9880d681SAndroid Build Coastguard Worker 935*9880d681SAndroid Build Coastguard Worker (* binoprhs 936*9880d681SAndroid Build Coastguard Worker * ::= ('+' primary)* *) 937*9880d681SAndroid Build Coastguard Worker and parse_bin_rhs expr_prec lhs stream = 938*9880d681SAndroid Build Coastguard Worker match Stream.peek stream with 939*9880d681SAndroid Build Coastguard Worker (* If this is a binop, find its precedence. *) 940*9880d681SAndroid Build Coastguard Worker | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> 941*9880d681SAndroid Build Coastguard Worker let token_prec = precedence c in 942*9880d681SAndroid Build Coastguard Worker 943*9880d681SAndroid Build Coastguard Worker (* If this is a binop that binds at least as tightly as the current binop, 944*9880d681SAndroid Build Coastguard Worker * consume it, otherwise we are done. *) 945*9880d681SAndroid Build Coastguard Worker if token_prec < expr_prec then lhs else begin 946*9880d681SAndroid Build Coastguard Worker (* Eat the binop. *) 947*9880d681SAndroid Build Coastguard Worker Stream.junk stream; 948*9880d681SAndroid Build Coastguard Worker 949*9880d681SAndroid Build Coastguard Worker (* Parse the primary expression after the binary operator. *) 950*9880d681SAndroid Build Coastguard Worker let rhs = parse_primary stream in 951*9880d681SAndroid Build Coastguard Worker 952*9880d681SAndroid Build Coastguard Worker (* Okay, we know this is a binop. *) 953*9880d681SAndroid Build Coastguard Worker let rhs = 954*9880d681SAndroid Build Coastguard Worker match Stream.peek stream with 955*9880d681SAndroid Build Coastguard Worker | Some (Token.Kwd c2) -> 956*9880d681SAndroid Build Coastguard Worker (* If BinOp binds less tightly with rhs than the operator after 957*9880d681SAndroid Build Coastguard Worker * rhs, let the pending operator take rhs as its lhs. *) 958*9880d681SAndroid Build Coastguard Worker let next_prec = precedence c2 in 959*9880d681SAndroid Build Coastguard Worker if token_prec < next_prec 960*9880d681SAndroid Build Coastguard Worker then parse_bin_rhs (token_prec + 1) rhs stream 961*9880d681SAndroid Build Coastguard Worker else rhs 962*9880d681SAndroid Build Coastguard Worker | _ -> rhs 963*9880d681SAndroid Build Coastguard Worker in 964*9880d681SAndroid Build Coastguard Worker 965*9880d681SAndroid Build Coastguard Worker (* Merge lhs/rhs. *) 966*9880d681SAndroid Build Coastguard Worker let lhs = Ast.Binary (c, lhs, rhs) in 967*9880d681SAndroid Build Coastguard Worker parse_bin_rhs expr_prec lhs stream 968*9880d681SAndroid Build Coastguard Worker end 969*9880d681SAndroid Build Coastguard Worker | _ -> lhs 970*9880d681SAndroid Build Coastguard Worker 971*9880d681SAndroid Build Coastguard Worker (* expression 972*9880d681SAndroid Build Coastguard Worker * ::= primary binoprhs *) 973*9880d681SAndroid Build Coastguard Worker and parse_expr = parser 974*9880d681SAndroid Build Coastguard Worker | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream 975*9880d681SAndroid Build Coastguard Worker 976*9880d681SAndroid Build Coastguard Worker (* prototype 977*9880d681SAndroid Build Coastguard Worker * ::= id '(' id* ')' *) 978*9880d681SAndroid Build Coastguard Worker let parse_prototype = 979*9880d681SAndroid Build Coastguard Worker let rec parse_args accumulator = parser 980*9880d681SAndroid Build Coastguard Worker | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e 981*9880d681SAndroid Build Coastguard Worker | [< >] -> accumulator 982*9880d681SAndroid Build Coastguard Worker in 983*9880d681SAndroid Build Coastguard Worker 984*9880d681SAndroid Build Coastguard Worker parser 985*9880d681SAndroid Build Coastguard Worker | [< 'Token.Ident id; 986*9880d681SAndroid Build Coastguard Worker 'Token.Kwd '(' ?? "expected '(' in prototype"; 987*9880d681SAndroid Build Coastguard Worker args=parse_args []; 988*9880d681SAndroid Build Coastguard Worker 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> 989*9880d681SAndroid Build Coastguard Worker (* success. *) 990*9880d681SAndroid Build Coastguard Worker Ast.Prototype (id, Array.of_list (List.rev args)) 991*9880d681SAndroid Build Coastguard Worker 992*9880d681SAndroid Build Coastguard Worker | [< >] -> 993*9880d681SAndroid Build Coastguard Worker raise (Stream.Error "expected function name in prototype") 994*9880d681SAndroid Build Coastguard Worker 995*9880d681SAndroid Build Coastguard Worker (* definition ::= 'def' prototype expression *) 996*9880d681SAndroid Build Coastguard Worker let parse_definition = parser 997*9880d681SAndroid Build Coastguard Worker | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> 998*9880d681SAndroid Build Coastguard Worker Ast.Function (p, e) 999*9880d681SAndroid Build Coastguard Worker 1000*9880d681SAndroid Build Coastguard Worker (* toplevelexpr ::= expression *) 1001*9880d681SAndroid Build Coastguard Worker let parse_toplevel = parser 1002*9880d681SAndroid Build Coastguard Worker | [< e=parse_expr >] -> 1003*9880d681SAndroid Build Coastguard Worker (* Make an anonymous proto. *) 1004*9880d681SAndroid Build Coastguard Worker Ast.Function (Ast.Prototype ("", [||]), e) 1005*9880d681SAndroid Build Coastguard Worker 1006*9880d681SAndroid Build Coastguard Worker (* external ::= 'extern' prototype *) 1007*9880d681SAndroid Build Coastguard Worker let parse_extern = parser 1008*9880d681SAndroid Build Coastguard Worker | [< 'Token.Extern; e=parse_prototype >] -> e 1009*9880d681SAndroid Build Coastguard Worker 1010*9880d681SAndroid Build Coastguard Workercodegen.ml: 1011*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 1012*9880d681SAndroid Build Coastguard Worker 1013*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 1014*9880d681SAndroid Build Coastguard Worker * Code Generation 1015*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 1016*9880d681SAndroid Build Coastguard Worker 1017*9880d681SAndroid Build Coastguard Worker open Llvm 1018*9880d681SAndroid Build Coastguard Worker 1019*9880d681SAndroid Build Coastguard Worker exception Error of string 1020*9880d681SAndroid Build Coastguard Worker 1021*9880d681SAndroid Build Coastguard Worker let context = global_context () 1022*9880d681SAndroid Build Coastguard Worker let the_module = create_module context "my cool jit" 1023*9880d681SAndroid Build Coastguard Worker let builder = builder context 1024*9880d681SAndroid Build Coastguard Worker let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 1025*9880d681SAndroid Build Coastguard Worker let double_type = double_type context 1026*9880d681SAndroid Build Coastguard Worker 1027*9880d681SAndroid Build Coastguard Worker let rec codegen_expr = function 1028*9880d681SAndroid Build Coastguard Worker | Ast.Number n -> const_float double_type n 1029*9880d681SAndroid Build Coastguard Worker | Ast.Variable name -> 1030*9880d681SAndroid Build Coastguard Worker (try Hashtbl.find named_values name with 1031*9880d681SAndroid Build Coastguard Worker | Not_found -> raise (Error "unknown variable name")) 1032*9880d681SAndroid Build Coastguard Worker | Ast.Binary (op, lhs, rhs) -> 1033*9880d681SAndroid Build Coastguard Worker let lhs_val = codegen_expr lhs in 1034*9880d681SAndroid Build Coastguard Worker let rhs_val = codegen_expr rhs in 1035*9880d681SAndroid Build Coastguard Worker begin 1036*9880d681SAndroid Build Coastguard Worker match op with 1037*9880d681SAndroid Build Coastguard Worker | '+' -> build_add lhs_val rhs_val "addtmp" builder 1038*9880d681SAndroid Build Coastguard Worker | '-' -> build_sub lhs_val rhs_val "subtmp" builder 1039*9880d681SAndroid Build Coastguard Worker | '*' -> build_mul lhs_val rhs_val "multmp" builder 1040*9880d681SAndroid Build Coastguard Worker | '<' -> 1041*9880d681SAndroid Build Coastguard Worker (* Convert bool 0/1 to double 0.0 or 1.0 *) 1042*9880d681SAndroid Build Coastguard Worker let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in 1043*9880d681SAndroid Build Coastguard Worker build_uitofp i double_type "booltmp" builder 1044*9880d681SAndroid Build Coastguard Worker | _ -> raise (Error "invalid binary operator") 1045*9880d681SAndroid Build Coastguard Worker end 1046*9880d681SAndroid Build Coastguard Worker | Ast.Call (callee, args) -> 1047*9880d681SAndroid Build Coastguard Worker (* Look up the name in the module table. *) 1048*9880d681SAndroid Build Coastguard Worker let callee = 1049*9880d681SAndroid Build Coastguard Worker match lookup_function callee the_module with 1050*9880d681SAndroid Build Coastguard Worker | Some callee -> callee 1051*9880d681SAndroid Build Coastguard Worker | None -> raise (Error "unknown function referenced") 1052*9880d681SAndroid Build Coastguard Worker in 1053*9880d681SAndroid Build Coastguard Worker let params = params callee in 1054*9880d681SAndroid Build Coastguard Worker 1055*9880d681SAndroid Build Coastguard Worker (* If argument mismatch error. *) 1056*9880d681SAndroid Build Coastguard Worker if Array.length params == Array.length args then () else 1057*9880d681SAndroid Build Coastguard Worker raise (Error "incorrect # arguments passed"); 1058*9880d681SAndroid Build Coastguard Worker let args = Array.map codegen_expr args in 1059*9880d681SAndroid Build Coastguard Worker build_call callee args "calltmp" builder 1060*9880d681SAndroid Build Coastguard Worker | Ast.If (cond, then_, else_) -> 1061*9880d681SAndroid Build Coastguard Worker let cond = codegen_expr cond in 1062*9880d681SAndroid Build Coastguard Worker 1063*9880d681SAndroid Build Coastguard Worker (* Convert condition to a bool by comparing equal to 0.0 *) 1064*9880d681SAndroid Build Coastguard Worker let zero = const_float double_type 0.0 in 1065*9880d681SAndroid Build Coastguard Worker let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in 1066*9880d681SAndroid Build Coastguard Worker 1067*9880d681SAndroid Build Coastguard Worker (* Grab the first block so that we might later add the conditional branch 1068*9880d681SAndroid Build Coastguard Worker * to it at the end of the function. *) 1069*9880d681SAndroid Build Coastguard Worker let start_bb = insertion_block builder in 1070*9880d681SAndroid Build Coastguard Worker let the_function = block_parent start_bb in 1071*9880d681SAndroid Build Coastguard Worker 1072*9880d681SAndroid Build Coastguard Worker let then_bb = append_block context "then" the_function in 1073*9880d681SAndroid Build Coastguard Worker 1074*9880d681SAndroid Build Coastguard Worker (* Emit 'then' value. *) 1075*9880d681SAndroid Build Coastguard Worker position_at_end then_bb builder; 1076*9880d681SAndroid Build Coastguard Worker let then_val = codegen_expr then_ in 1077*9880d681SAndroid Build Coastguard Worker 1078*9880d681SAndroid Build Coastguard Worker (* Codegen of 'then' can change the current block, update then_bb for the 1079*9880d681SAndroid Build Coastguard Worker * phi. We create a new name because one is used for the phi node, and the 1080*9880d681SAndroid Build Coastguard Worker * other is used for the conditional branch. *) 1081*9880d681SAndroid Build Coastguard Worker let new_then_bb = insertion_block builder in 1082*9880d681SAndroid Build Coastguard Worker 1083*9880d681SAndroid Build Coastguard Worker (* Emit 'else' value. *) 1084*9880d681SAndroid Build Coastguard Worker let else_bb = append_block context "else" the_function in 1085*9880d681SAndroid Build Coastguard Worker position_at_end else_bb builder; 1086*9880d681SAndroid Build Coastguard Worker let else_val = codegen_expr else_ in 1087*9880d681SAndroid Build Coastguard Worker 1088*9880d681SAndroid Build Coastguard Worker (* Codegen of 'else' can change the current block, update else_bb for the 1089*9880d681SAndroid Build Coastguard Worker * phi. *) 1090*9880d681SAndroid Build Coastguard Worker let new_else_bb = insertion_block builder in 1091*9880d681SAndroid Build Coastguard Worker 1092*9880d681SAndroid Build Coastguard Worker (* Emit merge block. *) 1093*9880d681SAndroid Build Coastguard Worker let merge_bb = append_block context "ifcont" the_function in 1094*9880d681SAndroid Build Coastguard Worker position_at_end merge_bb builder; 1095*9880d681SAndroid Build Coastguard Worker let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in 1096*9880d681SAndroid Build Coastguard Worker let phi = build_phi incoming "iftmp" builder in 1097*9880d681SAndroid Build Coastguard Worker 1098*9880d681SAndroid Build Coastguard Worker (* Return to the start block to add the conditional branch. *) 1099*9880d681SAndroid Build Coastguard Worker position_at_end start_bb builder; 1100*9880d681SAndroid Build Coastguard Worker ignore (build_cond_br cond_val then_bb else_bb builder); 1101*9880d681SAndroid Build Coastguard Worker 1102*9880d681SAndroid Build Coastguard Worker (* Set a unconditional branch at the end of the 'then' block and the 1103*9880d681SAndroid Build Coastguard Worker * 'else' block to the 'merge' block. *) 1104*9880d681SAndroid Build Coastguard Worker position_at_end new_then_bb builder; ignore (build_br merge_bb builder); 1105*9880d681SAndroid Build Coastguard Worker position_at_end new_else_bb builder; ignore (build_br merge_bb builder); 1106*9880d681SAndroid Build Coastguard Worker 1107*9880d681SAndroid Build Coastguard Worker (* Finally, set the builder to the end of the merge block. *) 1108*9880d681SAndroid Build Coastguard Worker position_at_end merge_bb builder; 1109*9880d681SAndroid Build Coastguard Worker 1110*9880d681SAndroid Build Coastguard Worker phi 1111*9880d681SAndroid Build Coastguard Worker | Ast.For (var_name, start, end_, step, body) -> 1112*9880d681SAndroid Build Coastguard Worker (* Emit the start code first, without 'variable' in scope. *) 1113*9880d681SAndroid Build Coastguard Worker let start_val = codegen_expr start in 1114*9880d681SAndroid Build Coastguard Worker 1115*9880d681SAndroid Build Coastguard Worker (* Make the new basic block for the loop header, inserting after current 1116*9880d681SAndroid Build Coastguard Worker * block. *) 1117*9880d681SAndroid Build Coastguard Worker let preheader_bb = insertion_block builder in 1118*9880d681SAndroid Build Coastguard Worker let the_function = block_parent preheader_bb in 1119*9880d681SAndroid Build Coastguard Worker let loop_bb = append_block context "loop" the_function in 1120*9880d681SAndroid Build Coastguard Worker 1121*9880d681SAndroid Build Coastguard Worker (* Insert an explicit fall through from the current block to the 1122*9880d681SAndroid Build Coastguard Worker * loop_bb. *) 1123*9880d681SAndroid Build Coastguard Worker ignore (build_br loop_bb builder); 1124*9880d681SAndroid Build Coastguard Worker 1125*9880d681SAndroid Build Coastguard Worker (* Start insertion in loop_bb. *) 1126*9880d681SAndroid Build Coastguard Worker position_at_end loop_bb builder; 1127*9880d681SAndroid Build Coastguard Worker 1128*9880d681SAndroid Build Coastguard Worker (* Start the PHI node with an entry for start. *) 1129*9880d681SAndroid Build Coastguard Worker let variable = build_phi [(start_val, preheader_bb)] var_name builder in 1130*9880d681SAndroid Build Coastguard Worker 1131*9880d681SAndroid Build Coastguard Worker (* Within the loop, the variable is defined equal to the PHI node. If it 1132*9880d681SAndroid Build Coastguard Worker * shadows an existing variable, we have to restore it, so save it 1133*9880d681SAndroid Build Coastguard Worker * now. *) 1134*9880d681SAndroid Build Coastguard Worker let old_val = 1135*9880d681SAndroid Build Coastguard Worker try Some (Hashtbl.find named_values var_name) with Not_found -> None 1136*9880d681SAndroid Build Coastguard Worker in 1137*9880d681SAndroid Build Coastguard Worker Hashtbl.add named_values var_name variable; 1138*9880d681SAndroid Build Coastguard Worker 1139*9880d681SAndroid Build Coastguard Worker (* Emit the body of the loop. This, like any other expr, can change the 1140*9880d681SAndroid Build Coastguard Worker * current BB. Note that we ignore the value computed by the body, but 1141*9880d681SAndroid Build Coastguard Worker * don't allow an error *) 1142*9880d681SAndroid Build Coastguard Worker ignore (codegen_expr body); 1143*9880d681SAndroid Build Coastguard Worker 1144*9880d681SAndroid Build Coastguard Worker (* Emit the step value. *) 1145*9880d681SAndroid Build Coastguard Worker let step_val = 1146*9880d681SAndroid Build Coastguard Worker match step with 1147*9880d681SAndroid Build Coastguard Worker | Some step -> codegen_expr step 1148*9880d681SAndroid Build Coastguard Worker (* If not specified, use 1.0. *) 1149*9880d681SAndroid Build Coastguard Worker | None -> const_float double_type 1.0 1150*9880d681SAndroid Build Coastguard Worker in 1151*9880d681SAndroid Build Coastguard Worker 1152*9880d681SAndroid Build Coastguard Worker let next_var = build_add variable step_val "nextvar" builder in 1153*9880d681SAndroid Build Coastguard Worker 1154*9880d681SAndroid Build Coastguard Worker (* Compute the end condition. *) 1155*9880d681SAndroid Build Coastguard Worker let end_cond = codegen_expr end_ in 1156*9880d681SAndroid Build Coastguard Worker 1157*9880d681SAndroid Build Coastguard Worker (* Convert condition to a bool by comparing equal to 0.0. *) 1158*9880d681SAndroid Build Coastguard Worker let zero = const_float double_type 0.0 in 1159*9880d681SAndroid Build Coastguard Worker let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in 1160*9880d681SAndroid Build Coastguard Worker 1161*9880d681SAndroid Build Coastguard Worker (* Create the "after loop" block and insert it. *) 1162*9880d681SAndroid Build Coastguard Worker let loop_end_bb = insertion_block builder in 1163*9880d681SAndroid Build Coastguard Worker let after_bb = append_block context "afterloop" the_function in 1164*9880d681SAndroid Build Coastguard Worker 1165*9880d681SAndroid Build Coastguard Worker (* Insert the conditional branch into the end of loop_end_bb. *) 1166*9880d681SAndroid Build Coastguard Worker ignore (build_cond_br end_cond loop_bb after_bb builder); 1167*9880d681SAndroid Build Coastguard Worker 1168*9880d681SAndroid Build Coastguard Worker (* Any new code will be inserted in after_bb. *) 1169*9880d681SAndroid Build Coastguard Worker position_at_end after_bb builder; 1170*9880d681SAndroid Build Coastguard Worker 1171*9880d681SAndroid Build Coastguard Worker (* Add a new entry to the PHI node for the backedge. *) 1172*9880d681SAndroid Build Coastguard Worker add_incoming (next_var, loop_end_bb) variable; 1173*9880d681SAndroid Build Coastguard Worker 1174*9880d681SAndroid Build Coastguard Worker (* Restore the unshadowed variable. *) 1175*9880d681SAndroid Build Coastguard Worker begin match old_val with 1176*9880d681SAndroid Build Coastguard Worker | Some old_val -> Hashtbl.add named_values var_name old_val 1177*9880d681SAndroid Build Coastguard Worker | None -> () 1178*9880d681SAndroid Build Coastguard Worker end; 1179*9880d681SAndroid Build Coastguard Worker 1180*9880d681SAndroid Build Coastguard Worker (* for expr always returns 0.0. *) 1181*9880d681SAndroid Build Coastguard Worker const_null double_type 1182*9880d681SAndroid Build Coastguard Worker 1183*9880d681SAndroid Build Coastguard Worker let codegen_proto = function 1184*9880d681SAndroid Build Coastguard Worker | Ast.Prototype (name, args) -> 1185*9880d681SAndroid Build Coastguard Worker (* Make the function type: double(double,double) etc. *) 1186*9880d681SAndroid Build Coastguard Worker let doubles = Array.make (Array.length args) double_type in 1187*9880d681SAndroid Build Coastguard Worker let ft = function_type double_type doubles in 1188*9880d681SAndroid Build Coastguard Worker let f = 1189*9880d681SAndroid Build Coastguard Worker match lookup_function name the_module with 1190*9880d681SAndroid Build Coastguard Worker | None -> declare_function name ft the_module 1191*9880d681SAndroid Build Coastguard Worker 1192*9880d681SAndroid Build Coastguard Worker (* If 'f' conflicted, there was already something named 'name'. If it 1193*9880d681SAndroid Build Coastguard Worker * has a body, don't allow redefinition or reextern. *) 1194*9880d681SAndroid Build Coastguard Worker | Some f -> 1195*9880d681SAndroid Build Coastguard Worker (* If 'f' already has a body, reject this. *) 1196*9880d681SAndroid Build Coastguard Worker if block_begin f <> At_end f then 1197*9880d681SAndroid Build Coastguard Worker raise (Error "redefinition of function"); 1198*9880d681SAndroid Build Coastguard Worker 1199*9880d681SAndroid Build Coastguard Worker (* If 'f' took a different number of arguments, reject. *) 1200*9880d681SAndroid Build Coastguard Worker if element_type (type_of f) <> ft then 1201*9880d681SAndroid Build Coastguard Worker raise (Error "redefinition of function with different # args"); 1202*9880d681SAndroid Build Coastguard Worker f 1203*9880d681SAndroid Build Coastguard Worker in 1204*9880d681SAndroid Build Coastguard Worker 1205*9880d681SAndroid Build Coastguard Worker (* Set names for all arguments. *) 1206*9880d681SAndroid Build Coastguard Worker Array.iteri (fun i a -> 1207*9880d681SAndroid Build Coastguard Worker let n = args.(i) in 1208*9880d681SAndroid Build Coastguard Worker set_value_name n a; 1209*9880d681SAndroid Build Coastguard Worker Hashtbl.add named_values n a; 1210*9880d681SAndroid Build Coastguard Worker ) (params f); 1211*9880d681SAndroid Build Coastguard Worker f 1212*9880d681SAndroid Build Coastguard Worker 1213*9880d681SAndroid Build Coastguard Worker let codegen_func the_fpm = function 1214*9880d681SAndroid Build Coastguard Worker | Ast.Function (proto, body) -> 1215*9880d681SAndroid Build Coastguard Worker Hashtbl.clear named_values; 1216*9880d681SAndroid Build Coastguard Worker let the_function = codegen_proto proto in 1217*9880d681SAndroid Build Coastguard Worker 1218*9880d681SAndroid Build Coastguard Worker (* Create a new basic block to start insertion into. *) 1219*9880d681SAndroid Build Coastguard Worker let bb = append_block context "entry" the_function in 1220*9880d681SAndroid Build Coastguard Worker position_at_end bb builder; 1221*9880d681SAndroid Build Coastguard Worker 1222*9880d681SAndroid Build Coastguard Worker try 1223*9880d681SAndroid Build Coastguard Worker let ret_val = codegen_expr body in 1224*9880d681SAndroid Build Coastguard Worker 1225*9880d681SAndroid Build Coastguard Worker (* Finish off the function. *) 1226*9880d681SAndroid Build Coastguard Worker let _ = build_ret ret_val builder in 1227*9880d681SAndroid Build Coastguard Worker 1228*9880d681SAndroid Build Coastguard Worker (* Validate the generated code, checking for consistency. *) 1229*9880d681SAndroid Build Coastguard Worker Llvm_analysis.assert_valid_function the_function; 1230*9880d681SAndroid Build Coastguard Worker 1231*9880d681SAndroid Build Coastguard Worker (* Optimize the function. *) 1232*9880d681SAndroid Build Coastguard Worker let _ = PassManager.run_function the_function the_fpm in 1233*9880d681SAndroid Build Coastguard Worker 1234*9880d681SAndroid Build Coastguard Worker the_function 1235*9880d681SAndroid Build Coastguard Worker with e -> 1236*9880d681SAndroid Build Coastguard Worker delete_function the_function; 1237*9880d681SAndroid Build Coastguard Worker raise e 1238*9880d681SAndroid Build Coastguard Worker 1239*9880d681SAndroid Build Coastguard Workertoplevel.ml: 1240*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 1241*9880d681SAndroid Build Coastguard Worker 1242*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 1243*9880d681SAndroid Build Coastguard Worker * Top-Level parsing and JIT Driver 1244*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 1245*9880d681SAndroid Build Coastguard Worker 1246*9880d681SAndroid Build Coastguard Worker open Llvm 1247*9880d681SAndroid Build Coastguard Worker open Llvm_executionengine 1248*9880d681SAndroid Build Coastguard Worker 1249*9880d681SAndroid Build Coastguard Worker (* top ::= definition | external | expression | ';' *) 1250*9880d681SAndroid Build Coastguard Worker let rec main_loop the_fpm the_execution_engine stream = 1251*9880d681SAndroid Build Coastguard Worker match Stream.peek stream with 1252*9880d681SAndroid Build Coastguard Worker | None -> () 1253*9880d681SAndroid Build Coastguard Worker 1254*9880d681SAndroid Build Coastguard Worker (* ignore top-level semicolons. *) 1255*9880d681SAndroid Build Coastguard Worker | Some (Token.Kwd ';') -> 1256*9880d681SAndroid Build Coastguard Worker Stream.junk stream; 1257*9880d681SAndroid Build Coastguard Worker main_loop the_fpm the_execution_engine stream 1258*9880d681SAndroid Build Coastguard Worker 1259*9880d681SAndroid Build Coastguard Worker | Some token -> 1260*9880d681SAndroid Build Coastguard Worker begin 1261*9880d681SAndroid Build Coastguard Worker try match token with 1262*9880d681SAndroid Build Coastguard Worker | Token.Def -> 1263*9880d681SAndroid Build Coastguard Worker let e = Parser.parse_definition stream in 1264*9880d681SAndroid Build Coastguard Worker print_endline "parsed a function definition."; 1265*9880d681SAndroid Build Coastguard Worker dump_value (Codegen.codegen_func the_fpm e); 1266*9880d681SAndroid Build Coastguard Worker | Token.Extern -> 1267*9880d681SAndroid Build Coastguard Worker let e = Parser.parse_extern stream in 1268*9880d681SAndroid Build Coastguard Worker print_endline "parsed an extern."; 1269*9880d681SAndroid Build Coastguard Worker dump_value (Codegen.codegen_proto e); 1270*9880d681SAndroid Build Coastguard Worker | _ -> 1271*9880d681SAndroid Build Coastguard Worker (* Evaluate a top-level expression into an anonymous function. *) 1272*9880d681SAndroid Build Coastguard Worker let e = Parser.parse_toplevel stream in 1273*9880d681SAndroid Build Coastguard Worker print_endline "parsed a top-level expr"; 1274*9880d681SAndroid Build Coastguard Worker let the_function = Codegen.codegen_func the_fpm e in 1275*9880d681SAndroid Build Coastguard Worker dump_value the_function; 1276*9880d681SAndroid Build Coastguard Worker 1277*9880d681SAndroid Build Coastguard Worker (* JIT the function, returning a function pointer. *) 1278*9880d681SAndroid Build Coastguard Worker let result = ExecutionEngine.run_function the_function [||] 1279*9880d681SAndroid Build Coastguard Worker the_execution_engine in 1280*9880d681SAndroid Build Coastguard Worker 1281*9880d681SAndroid Build Coastguard Worker print_string "Evaluated to "; 1282*9880d681SAndroid Build Coastguard Worker print_float (GenericValue.as_float Codegen.double_type result); 1283*9880d681SAndroid Build Coastguard Worker print_newline (); 1284*9880d681SAndroid Build Coastguard Worker with Stream.Error s | Codegen.Error s -> 1285*9880d681SAndroid Build Coastguard Worker (* Skip token for error recovery. *) 1286*9880d681SAndroid Build Coastguard Worker Stream.junk stream; 1287*9880d681SAndroid Build Coastguard Worker print_endline s; 1288*9880d681SAndroid Build Coastguard Worker end; 1289*9880d681SAndroid Build Coastguard Worker print_string "ready> "; flush stdout; 1290*9880d681SAndroid Build Coastguard Worker main_loop the_fpm the_execution_engine stream 1291*9880d681SAndroid Build Coastguard Worker 1292*9880d681SAndroid Build Coastguard Workertoy.ml: 1293*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 1294*9880d681SAndroid Build Coastguard Worker 1295*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 1296*9880d681SAndroid Build Coastguard Worker * Main driver code. 1297*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 1298*9880d681SAndroid Build Coastguard Worker 1299*9880d681SAndroid Build Coastguard Worker open Llvm 1300*9880d681SAndroid Build Coastguard Worker open Llvm_executionengine 1301*9880d681SAndroid Build Coastguard Worker open Llvm_target 1302*9880d681SAndroid Build Coastguard Worker open Llvm_scalar_opts 1303*9880d681SAndroid Build Coastguard Worker 1304*9880d681SAndroid Build Coastguard Worker let main () = 1305*9880d681SAndroid Build Coastguard Worker ignore (initialize_native_target ()); 1306*9880d681SAndroid Build Coastguard Worker 1307*9880d681SAndroid Build Coastguard Worker (* Install standard binary operators. 1308*9880d681SAndroid Build Coastguard Worker * 1 is the lowest precedence. *) 1309*9880d681SAndroid Build Coastguard Worker Hashtbl.add Parser.binop_precedence '<' 10; 1310*9880d681SAndroid Build Coastguard Worker Hashtbl.add Parser.binop_precedence '+' 20; 1311*9880d681SAndroid Build Coastguard Worker Hashtbl.add Parser.binop_precedence '-' 20; 1312*9880d681SAndroid Build Coastguard Worker Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) 1313*9880d681SAndroid Build Coastguard Worker 1314*9880d681SAndroid Build Coastguard Worker (* Prime the first token. *) 1315*9880d681SAndroid Build Coastguard Worker print_string "ready> "; flush stdout; 1316*9880d681SAndroid Build Coastguard Worker let stream = Lexer.lex (Stream.of_channel stdin) in 1317*9880d681SAndroid Build Coastguard Worker 1318*9880d681SAndroid Build Coastguard Worker (* Create the JIT. *) 1319*9880d681SAndroid Build Coastguard Worker let the_execution_engine = ExecutionEngine.create Codegen.the_module in 1320*9880d681SAndroid Build Coastguard Worker let the_fpm = PassManager.create_function Codegen.the_module in 1321*9880d681SAndroid Build Coastguard Worker 1322*9880d681SAndroid Build Coastguard Worker (* Set up the optimizer pipeline. Start with registering info about how the 1323*9880d681SAndroid Build Coastguard Worker * target lays out data structures. *) 1324*9880d681SAndroid Build Coastguard Worker DataLayout.add (ExecutionEngine.target_data the_execution_engine) the_fpm; 1325*9880d681SAndroid Build Coastguard Worker 1326*9880d681SAndroid Build Coastguard Worker (* Do simple "peephole" optimizations and bit-twiddling optzn. *) 1327*9880d681SAndroid Build Coastguard Worker add_instruction_combination the_fpm; 1328*9880d681SAndroid Build Coastguard Worker 1329*9880d681SAndroid Build Coastguard Worker (* reassociate expressions. *) 1330*9880d681SAndroid Build Coastguard Worker add_reassociation the_fpm; 1331*9880d681SAndroid Build Coastguard Worker 1332*9880d681SAndroid Build Coastguard Worker (* Eliminate Common SubExpressions. *) 1333*9880d681SAndroid Build Coastguard Worker add_gvn the_fpm; 1334*9880d681SAndroid Build Coastguard Worker 1335*9880d681SAndroid Build Coastguard Worker (* Simplify the control flow graph (deleting unreachable blocks, etc). *) 1336*9880d681SAndroid Build Coastguard Worker add_cfg_simplification the_fpm; 1337*9880d681SAndroid Build Coastguard Worker 1338*9880d681SAndroid Build Coastguard Worker ignore (PassManager.initialize the_fpm); 1339*9880d681SAndroid Build Coastguard Worker 1340*9880d681SAndroid Build Coastguard Worker (* Run the main "interpreter loop" now. *) 1341*9880d681SAndroid Build Coastguard Worker Toplevel.main_loop the_fpm the_execution_engine stream; 1342*9880d681SAndroid Build Coastguard Worker 1343*9880d681SAndroid Build Coastguard Worker (* Print out all the generated code. *) 1344*9880d681SAndroid Build Coastguard Worker dump_module Codegen.the_module 1345*9880d681SAndroid Build Coastguard Worker ;; 1346*9880d681SAndroid Build Coastguard Worker 1347*9880d681SAndroid Build Coastguard Worker main () 1348*9880d681SAndroid Build Coastguard Worker 1349*9880d681SAndroid Build Coastguard Workerbindings.c 1350*9880d681SAndroid Build Coastguard Worker .. code-block:: c 1351*9880d681SAndroid Build Coastguard Worker 1352*9880d681SAndroid Build Coastguard Worker #include <stdio.h> 1353*9880d681SAndroid Build Coastguard Worker 1354*9880d681SAndroid Build Coastguard Worker /* putchard - putchar that takes a double and returns 0. */ 1355*9880d681SAndroid Build Coastguard Worker extern double putchard(double X) { 1356*9880d681SAndroid Build Coastguard Worker putchar((char)X); 1357*9880d681SAndroid Build Coastguard Worker return 0; 1358*9880d681SAndroid Build Coastguard Worker } 1359*9880d681SAndroid Build Coastguard Worker 1360*9880d681SAndroid Build Coastguard Worker`Next: Extending the language: user-defined 1361*9880d681SAndroid Build Coastguard Workeroperators <OCamlLangImpl6.html>`_ 1362*9880d681SAndroid Build Coastguard Worker 1363