1*9880d681SAndroid Build Coastguard Worker======================================== 2*9880d681SAndroid Build Coastguard WorkerKaleidoscope: Code generation to LLVM IR 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 3 Introduction 9*9880d681SAndroid Build Coastguard Worker====================== 10*9880d681SAndroid Build Coastguard Worker 11*9880d681SAndroid Build Coastguard WorkerWelcome to Chapter 3 of the "`Implementing a language with 12*9880d681SAndroid Build Coastguard WorkerLLVM <index.html>`_" tutorial. This chapter shows you how to transform 13*9880d681SAndroid Build Coastguard Workerthe `Abstract Syntax Tree <OCamlLangImpl2.html>`_, built in Chapter 2, 14*9880d681SAndroid Build Coastguard Workerinto LLVM IR. This will teach you a little bit about how LLVM does 15*9880d681SAndroid Build Coastguard Workerthings, as well as demonstrate how easy it is to use. It's much more 16*9880d681SAndroid Build Coastguard Workerwork to build a lexer and parser than it is to generate LLVM IR code. :) 17*9880d681SAndroid Build Coastguard Worker 18*9880d681SAndroid Build Coastguard Worker**Please note**: the code in this chapter and later require LLVM 2.3 or 19*9880d681SAndroid Build Coastguard WorkerLLVM SVN to work. LLVM 2.2 and before will not work with it. 20*9880d681SAndroid Build Coastguard Worker 21*9880d681SAndroid Build Coastguard WorkerCode Generation Setup 22*9880d681SAndroid Build Coastguard Worker===================== 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard WorkerIn order to generate LLVM IR, we want some simple setup to get started. 25*9880d681SAndroid Build Coastguard WorkerFirst we define virtual code generation (codegen) methods in each AST 26*9880d681SAndroid Build Coastguard Workerclass: 27*9880d681SAndroid Build Coastguard Worker 28*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 29*9880d681SAndroid Build Coastguard Worker 30*9880d681SAndroid Build Coastguard Worker let rec codegen_expr = function 31*9880d681SAndroid Build Coastguard Worker | Ast.Number n -> ... 32*9880d681SAndroid Build Coastguard Worker | Ast.Variable name -> ... 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard WorkerThe ``Codegen.codegen_expr`` function says to emit IR for that AST node 35*9880d681SAndroid Build Coastguard Workeralong with all the things it depends on, and they all return an LLVM 36*9880d681SAndroid Build Coastguard WorkerValue object. "Value" is the class used to represent a "`Static Single 37*9880d681SAndroid Build Coastguard WorkerAssignment 38*9880d681SAndroid Build Coastguard Worker(SSA) <http://en.wikipedia.org/wiki/Static_single_assignment_form>`_ 39*9880d681SAndroid Build Coastguard Workerregister" or "SSA value" in LLVM. The most distinct aspect of SSA values 40*9880d681SAndroid Build Coastguard Workeris that their value is computed as the related instruction executes, and 41*9880d681SAndroid Build Coastguard Workerit does not get a new value until (and if) the instruction re-executes. 42*9880d681SAndroid Build Coastguard WorkerIn other words, there is no way to "change" an SSA value. For more 43*9880d681SAndroid Build Coastguard Workerinformation, please read up on `Static Single 44*9880d681SAndroid Build Coastguard WorkerAssignment <http://en.wikipedia.org/wiki/Static_single_assignment_form>`_ 45*9880d681SAndroid Build Coastguard Worker- the concepts are really quite natural once you grok them. 46*9880d681SAndroid Build Coastguard Worker 47*9880d681SAndroid Build Coastguard WorkerThe second thing we want is an "Error" exception like we used for the 48*9880d681SAndroid Build Coastguard Workerparser, which will be used to report errors found during code generation 49*9880d681SAndroid Build Coastguard Worker(for example, use of an undeclared parameter): 50*9880d681SAndroid Build Coastguard Worker 51*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 52*9880d681SAndroid Build Coastguard Worker 53*9880d681SAndroid Build Coastguard Worker exception Error of string 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Worker let context = global_context () 56*9880d681SAndroid Build Coastguard Worker let the_module = create_module context "my cool jit" 57*9880d681SAndroid Build Coastguard Worker let builder = builder context 58*9880d681SAndroid Build Coastguard Worker let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 59*9880d681SAndroid Build Coastguard Worker let double_type = double_type context 60*9880d681SAndroid Build Coastguard Worker 61*9880d681SAndroid Build Coastguard WorkerThe static variables will be used during code generation. 62*9880d681SAndroid Build Coastguard Worker``Codgen.the_module`` is the LLVM construct that contains all of the 63*9880d681SAndroid Build Coastguard Workerfunctions and global variables in a chunk of code. In many ways, it is 64*9880d681SAndroid Build Coastguard Workerthe top-level structure that the LLVM IR uses to contain code. 65*9880d681SAndroid Build Coastguard Worker 66*9880d681SAndroid Build Coastguard WorkerThe ``Codegen.builder`` object is a helper object that makes it easy to 67*9880d681SAndroid Build Coastguard Workergenerate LLVM instructions. Instances of the 68*9880d681SAndroid Build Coastguard Worker`IRBuilder <http://llvm.org/doxygen/IRBuilder_8h-source.html>`_ 69*9880d681SAndroid Build Coastguard Workerclass keep track of the current place to insert instructions and has 70*9880d681SAndroid Build Coastguard Workermethods to create new instructions. 71*9880d681SAndroid Build Coastguard Worker 72*9880d681SAndroid Build Coastguard WorkerThe ``Codegen.named_values`` map keeps track of which values are defined 73*9880d681SAndroid Build Coastguard Workerin the current scope and what their LLVM representation is. (In other 74*9880d681SAndroid Build Coastguard Workerwords, it is a symbol table for the code). In this form of Kaleidoscope, 75*9880d681SAndroid Build Coastguard Workerthe only things that can be referenced are function parameters. As such, 76*9880d681SAndroid Build Coastguard Workerfunction parameters will be in this map when generating code for their 77*9880d681SAndroid Build Coastguard Workerfunction body. 78*9880d681SAndroid Build Coastguard Worker 79*9880d681SAndroid Build Coastguard WorkerWith these basics in place, we can start talking about how to generate 80*9880d681SAndroid Build Coastguard Workercode for each expression. Note that this assumes that the 81*9880d681SAndroid Build Coastguard Worker``Codgen.builder`` has been set up to generate code *into* something. 82*9880d681SAndroid Build Coastguard WorkerFor now, we'll assume that this has already been done, and we'll just 83*9880d681SAndroid Build Coastguard Workeruse it to emit code. 84*9880d681SAndroid Build Coastguard Worker 85*9880d681SAndroid Build Coastguard WorkerExpression Code Generation 86*9880d681SAndroid Build Coastguard Worker========================== 87*9880d681SAndroid Build Coastguard Worker 88*9880d681SAndroid Build Coastguard WorkerGenerating LLVM code for expression nodes is very straightforward: less 89*9880d681SAndroid Build Coastguard Workerthan 30 lines of commented code for all four of our expression nodes. 90*9880d681SAndroid Build Coastguard WorkerFirst we'll do numeric literals: 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 93*9880d681SAndroid Build Coastguard Worker 94*9880d681SAndroid Build Coastguard Worker | Ast.Number n -> const_float double_type n 95*9880d681SAndroid Build Coastguard Worker 96*9880d681SAndroid Build Coastguard WorkerIn the LLVM IR, numeric constants are represented with the 97*9880d681SAndroid Build Coastguard Worker``ConstantFP`` class, which holds the numeric value in an ``APFloat`` 98*9880d681SAndroid Build Coastguard Workerinternally (``APFloat`` has the capability of holding floating point 99*9880d681SAndroid Build Coastguard Workerconstants of Arbitrary Precision). This code basically just creates 100*9880d681SAndroid Build Coastguard Workerand returns a ``ConstantFP``. Note that in the LLVM IR that constants 101*9880d681SAndroid Build Coastguard Workerare all uniqued together and shared. For this reason, the API uses "the 102*9880d681SAndroid Build Coastguard Workerfoo::get(..)" idiom instead of "new foo(..)" or "foo::Create(..)". 103*9880d681SAndroid Build Coastguard Worker 104*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 105*9880d681SAndroid Build Coastguard Worker 106*9880d681SAndroid Build Coastguard Worker | Ast.Variable name -> 107*9880d681SAndroid Build Coastguard Worker (try Hashtbl.find named_values name with 108*9880d681SAndroid Build Coastguard Worker | Not_found -> raise (Error "unknown variable name")) 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard WorkerReferences to variables are also quite simple using LLVM. In the simple 111*9880d681SAndroid Build Coastguard Workerversion of Kaleidoscope, we assume that the variable has already been 112*9880d681SAndroid Build Coastguard Workeremitted somewhere and its value is available. In practice, the only 113*9880d681SAndroid Build Coastguard Workervalues that can be in the ``Codegen.named_values`` map are function 114*9880d681SAndroid Build Coastguard Workerarguments. This code simply checks to see that the specified name is in 115*9880d681SAndroid Build Coastguard Workerthe map (if not, an unknown variable is being referenced) and returns 116*9880d681SAndroid Build Coastguard Workerthe value for it. In future chapters, we'll add support for `loop 117*9880d681SAndroid Build Coastguard Workerinduction variables <LangImpl5.html#for-loop-expression>`_ in the symbol table, and for 118*9880d681SAndroid Build Coastguard Worker`local variables <LangImpl7.html#user-defined-local-variables>`_. 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 121*9880d681SAndroid Build Coastguard Worker 122*9880d681SAndroid Build Coastguard Worker | Ast.Binary (op, lhs, rhs) -> 123*9880d681SAndroid Build Coastguard Worker let lhs_val = codegen_expr lhs in 124*9880d681SAndroid Build Coastguard Worker let rhs_val = codegen_expr rhs in 125*9880d681SAndroid Build Coastguard Worker begin 126*9880d681SAndroid Build Coastguard Worker match op with 127*9880d681SAndroid Build Coastguard Worker | '+' -> build_fadd lhs_val rhs_val "addtmp" builder 128*9880d681SAndroid Build Coastguard Worker | '-' -> build_fsub lhs_val rhs_val "subtmp" builder 129*9880d681SAndroid Build Coastguard Worker | '*' -> build_fmul lhs_val rhs_val "multmp" builder 130*9880d681SAndroid Build Coastguard Worker | '<' -> 131*9880d681SAndroid Build Coastguard Worker (* Convert bool 0/1 to double 0.0 or 1.0 *) 132*9880d681SAndroid Build Coastguard Worker let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in 133*9880d681SAndroid Build Coastguard Worker build_uitofp i double_type "booltmp" builder 134*9880d681SAndroid Build Coastguard Worker | _ -> raise (Error "invalid binary operator") 135*9880d681SAndroid Build Coastguard Worker end 136*9880d681SAndroid Build Coastguard Worker 137*9880d681SAndroid Build Coastguard WorkerBinary operators start to get more interesting. The basic idea here is 138*9880d681SAndroid Build Coastguard Workerthat we recursively emit code for the left-hand side of the expression, 139*9880d681SAndroid Build Coastguard Workerthen the right-hand side, then we compute the result of the binary 140*9880d681SAndroid Build Coastguard Workerexpression. In this code, we do a simple switch on the opcode to create 141*9880d681SAndroid Build Coastguard Workerthe right LLVM instruction. 142*9880d681SAndroid Build Coastguard Worker 143*9880d681SAndroid Build Coastguard WorkerIn the example above, the LLVM builder class is starting to show its 144*9880d681SAndroid Build Coastguard Workervalue. IRBuilder knows where to insert the newly created instruction, 145*9880d681SAndroid Build Coastguard Workerall you have to do is specify what instruction to create (e.g. with 146*9880d681SAndroid Build Coastguard Worker``Llvm.create_add``), which operands to use (``lhs`` and ``rhs`` here) 147*9880d681SAndroid Build Coastguard Workerand optionally provide a name for the generated instruction. 148*9880d681SAndroid Build Coastguard Worker 149*9880d681SAndroid Build Coastguard WorkerOne nice thing about LLVM is that the name is just a hint. For instance, 150*9880d681SAndroid Build Coastguard Workerif the code above emits multiple "addtmp" variables, LLVM will 151*9880d681SAndroid Build Coastguard Workerautomatically provide each one with an increasing, unique numeric 152*9880d681SAndroid Build Coastguard Workersuffix. Local value names for instructions are purely optional, but it 153*9880d681SAndroid Build Coastguard Workermakes it much easier to read the IR dumps. 154*9880d681SAndroid Build Coastguard Worker 155*9880d681SAndroid Build Coastguard Worker`LLVM instructions <../LangRef.html#instruction-reference>`_ are constrained by strict 156*9880d681SAndroid Build Coastguard Workerrules: for example, the Left and Right operators of an `add 157*9880d681SAndroid Build Coastguard Workerinstruction <../LangRef.html#add-instruction>`_ must have the same type, and the 158*9880d681SAndroid Build Coastguard Workerresult type of the add must match the operand types. Because all values 159*9880d681SAndroid Build Coastguard Workerin Kaleidoscope are doubles, this makes for very simple code for add, 160*9880d681SAndroid Build Coastguard Workersub and mul. 161*9880d681SAndroid Build Coastguard Worker 162*9880d681SAndroid Build Coastguard WorkerOn the other hand, LLVM specifies that the `fcmp 163*9880d681SAndroid Build Coastguard Workerinstruction <../LangRef.html#fcmp-instruction>`_ always returns an 'i1' value (a 164*9880d681SAndroid Build Coastguard Workerone bit integer). The problem with this is that Kaleidoscope wants the 165*9880d681SAndroid Build Coastguard Workervalue to be a 0.0 or 1.0 value. In order to get these semantics, we 166*9880d681SAndroid Build Coastguard Workercombine the fcmp instruction with a `uitofp 167*9880d681SAndroid Build Coastguard Workerinstruction <../LangRef.html#uitofp-to-instruction>`_. This instruction converts its 168*9880d681SAndroid Build Coastguard Workerinput integer into a floating point value by treating the input as an 169*9880d681SAndroid Build Coastguard Workerunsigned value. In contrast, if we used the `sitofp 170*9880d681SAndroid Build Coastguard Workerinstruction <../LangRef.html#sitofp-to-instruction>`_, the Kaleidoscope '<' operator 171*9880d681SAndroid Build Coastguard Workerwould return 0.0 and -1.0, depending on the input value. 172*9880d681SAndroid Build Coastguard Worker 173*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 174*9880d681SAndroid Build Coastguard Worker 175*9880d681SAndroid Build Coastguard Worker | Ast.Call (callee, args) -> 176*9880d681SAndroid Build Coastguard Worker (* Look up the name in the module table. *) 177*9880d681SAndroid Build Coastguard Worker let callee = 178*9880d681SAndroid Build Coastguard Worker match lookup_function callee the_module with 179*9880d681SAndroid Build Coastguard Worker | Some callee -> callee 180*9880d681SAndroid Build Coastguard Worker | None -> raise (Error "unknown function referenced") 181*9880d681SAndroid Build Coastguard Worker in 182*9880d681SAndroid Build Coastguard Worker let params = params callee in 183*9880d681SAndroid Build Coastguard Worker 184*9880d681SAndroid Build Coastguard Worker (* If argument mismatch error. *) 185*9880d681SAndroid Build Coastguard Worker if Array.length params == Array.length args then () else 186*9880d681SAndroid Build Coastguard Worker raise (Error "incorrect # arguments passed"); 187*9880d681SAndroid Build Coastguard Worker let args = Array.map codegen_expr args in 188*9880d681SAndroid Build Coastguard Worker build_call callee args "calltmp" builder 189*9880d681SAndroid Build Coastguard Worker 190*9880d681SAndroid Build Coastguard WorkerCode generation for function calls is quite straightforward with LLVM. 191*9880d681SAndroid Build Coastguard WorkerThe code above initially does a function name lookup in the LLVM 192*9880d681SAndroid Build Coastguard WorkerModule's symbol table. Recall that the LLVM Module is the container that 193*9880d681SAndroid Build Coastguard Workerholds all of the functions we are JIT'ing. By giving each function the 194*9880d681SAndroid Build Coastguard Workersame name as what the user specifies, we can use the LLVM symbol table 195*9880d681SAndroid Build Coastguard Workerto resolve function names for us. 196*9880d681SAndroid Build Coastguard Worker 197*9880d681SAndroid Build Coastguard WorkerOnce we have the function to call, we recursively codegen each argument 198*9880d681SAndroid Build Coastguard Workerthat is to be passed in, and create an LLVM `call 199*9880d681SAndroid Build Coastguard Workerinstruction <../LangRef.html#call-instruction>`_. Note that LLVM uses the native C 200*9880d681SAndroid Build Coastguard Workercalling conventions by default, allowing these calls to also call into 201*9880d681SAndroid Build Coastguard Workerstandard library functions like "sin" and "cos", with no additional 202*9880d681SAndroid Build Coastguard Workereffort. 203*9880d681SAndroid Build Coastguard Worker 204*9880d681SAndroid Build Coastguard WorkerThis wraps up our handling of the four basic expressions that we have so 205*9880d681SAndroid Build Coastguard Workerfar in Kaleidoscope. Feel free to go in and add some more. For example, 206*9880d681SAndroid Build Coastguard Workerby browsing the `LLVM language reference <../LangRef.html>`_ you'll find 207*9880d681SAndroid Build Coastguard Workerseveral other interesting instructions that are really easy to plug into 208*9880d681SAndroid Build Coastguard Workerour basic framework. 209*9880d681SAndroid Build Coastguard Worker 210*9880d681SAndroid Build Coastguard WorkerFunction Code Generation 211*9880d681SAndroid Build Coastguard Worker======================== 212*9880d681SAndroid Build Coastguard Worker 213*9880d681SAndroid Build Coastguard WorkerCode generation for prototypes and functions must handle a number of 214*9880d681SAndroid Build Coastguard Workerdetails, which make their code less beautiful than expression code 215*9880d681SAndroid Build Coastguard Workergeneration, but allows us to illustrate some important points. First, 216*9880d681SAndroid Build Coastguard Workerlets talk about code generation for prototypes: they are used both for 217*9880d681SAndroid Build Coastguard Workerfunction bodies and external function declarations. The code starts 218*9880d681SAndroid Build Coastguard Workerwith: 219*9880d681SAndroid Build Coastguard Worker 220*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 221*9880d681SAndroid Build Coastguard Worker 222*9880d681SAndroid Build Coastguard Worker let codegen_proto = function 223*9880d681SAndroid Build Coastguard Worker | Ast.Prototype (name, args) -> 224*9880d681SAndroid Build Coastguard Worker (* Make the function type: double(double,double) etc. *) 225*9880d681SAndroid Build Coastguard Worker let doubles = Array.make (Array.length args) double_type in 226*9880d681SAndroid Build Coastguard Worker let ft = function_type double_type doubles in 227*9880d681SAndroid Build Coastguard Worker let f = 228*9880d681SAndroid Build Coastguard Worker match lookup_function name the_module with 229*9880d681SAndroid Build Coastguard Worker 230*9880d681SAndroid Build Coastguard WorkerThis code packs a lot of power into a few lines. Note first that this 231*9880d681SAndroid Build Coastguard Workerfunction returns a "Function\*" instead of a "Value\*" (although at the 232*9880d681SAndroid Build Coastguard Workermoment they both are modeled by ``llvalue`` in ocaml). Because a 233*9880d681SAndroid Build Coastguard Worker"prototype" really talks about the external interface for a function 234*9880d681SAndroid Build Coastguard Worker(not the value computed by an expression), it makes sense for it to 235*9880d681SAndroid Build Coastguard Workerreturn the LLVM Function it corresponds to when codegen'd. 236*9880d681SAndroid Build Coastguard Worker 237*9880d681SAndroid Build Coastguard WorkerThe call to ``Llvm.function_type`` creates the ``Llvm.llvalue`` that 238*9880d681SAndroid Build Coastguard Workershould be used for a given Prototype. Since all function arguments in 239*9880d681SAndroid Build Coastguard WorkerKaleidoscope are of type double, the first line creates a vector of "N" 240*9880d681SAndroid Build Coastguard WorkerLLVM double types. It then uses the ``Llvm.function_type`` method to 241*9880d681SAndroid Build Coastguard Workercreate a function type that takes "N" doubles as arguments, returns one 242*9880d681SAndroid Build Coastguard Workerdouble as a result, and that is not vararg (that uses the function 243*9880d681SAndroid Build Coastguard Worker``Llvm.var_arg_function_type``). Note that Types in LLVM are uniqued 244*9880d681SAndroid Build Coastguard Workerjust like ``Constant``'s are, so you don't "new" a type, you "get" it. 245*9880d681SAndroid Build Coastguard Worker 246*9880d681SAndroid Build Coastguard WorkerThe final line above checks if the function has already been defined in 247*9880d681SAndroid Build Coastguard Worker``Codegen.the_module``. If not, we will create it. 248*9880d681SAndroid Build Coastguard Worker 249*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 250*9880d681SAndroid Build Coastguard Worker 251*9880d681SAndroid Build Coastguard Worker | None -> declare_function name ft the_module 252*9880d681SAndroid Build Coastguard Worker 253*9880d681SAndroid Build Coastguard WorkerThis indicates the type and name to use, as well as which module to 254*9880d681SAndroid Build Coastguard Workerinsert into. By default we assume a function has 255*9880d681SAndroid Build Coastguard Worker``Llvm.Linkage.ExternalLinkage``. "`external 256*9880d681SAndroid Build Coastguard Workerlinkage <../LangRef.html#linkage>`_" means that the function may be defined 257*9880d681SAndroid Build Coastguard Workeroutside the current module and/or that it is callable by functions 258*9880d681SAndroid Build Coastguard Workeroutside the module. The "``name``" passed in is the name the user 259*9880d681SAndroid Build Coastguard Workerspecified: this name is registered in "``Codegen.the_module``"s symbol 260*9880d681SAndroid Build Coastguard Workertable, which is used by the function call code above. 261*9880d681SAndroid Build Coastguard Worker 262*9880d681SAndroid Build Coastguard WorkerIn Kaleidoscope, I choose to allow redefinitions of functions in two 263*9880d681SAndroid Build Coastguard Workercases: first, we want to allow 'extern'ing a function more than once, as 264*9880d681SAndroid Build Coastguard Workerlong as the prototypes for the externs match (since all arguments have 265*9880d681SAndroid Build Coastguard Workerthe same type, we just have to check that the number of arguments 266*9880d681SAndroid Build Coastguard Workermatch). Second, we want to allow 'extern'ing a function and then 267*9880d681SAndroid Build Coastguard Workerdefining a body for it. This is useful when defining mutually recursive 268*9880d681SAndroid Build Coastguard Workerfunctions. 269*9880d681SAndroid Build Coastguard Worker 270*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 271*9880d681SAndroid Build Coastguard Worker 272*9880d681SAndroid Build Coastguard Worker (* If 'f' conflicted, there was already something named 'name'. If it 273*9880d681SAndroid Build Coastguard Worker * has a body, don't allow redefinition or reextern. *) 274*9880d681SAndroid Build Coastguard Worker | Some f -> 275*9880d681SAndroid Build Coastguard Worker (* If 'f' already has a body, reject this. *) 276*9880d681SAndroid Build Coastguard Worker if Array.length (basic_blocks f) == 0 then () else 277*9880d681SAndroid Build Coastguard Worker raise (Error "redefinition of function"); 278*9880d681SAndroid Build Coastguard Worker 279*9880d681SAndroid Build Coastguard Worker (* If 'f' took a different number of arguments, reject. *) 280*9880d681SAndroid Build Coastguard Worker if Array.length (params f) == Array.length args then () else 281*9880d681SAndroid Build Coastguard Worker raise (Error "redefinition of function with different # args"); 282*9880d681SAndroid Build Coastguard Worker f 283*9880d681SAndroid Build Coastguard Worker in 284*9880d681SAndroid Build Coastguard Worker 285*9880d681SAndroid Build Coastguard WorkerIn order to verify the logic above, we first check to see if the 286*9880d681SAndroid Build Coastguard Workerpre-existing function is "empty". In this case, empty means that it has 287*9880d681SAndroid Build Coastguard Workerno basic blocks in it, which means it has no body. If it has no body, it 288*9880d681SAndroid Build Coastguard Workeris a forward declaration. Since we don't allow anything after a full 289*9880d681SAndroid Build Coastguard Workerdefinition of the function, the code rejects this case. If the previous 290*9880d681SAndroid Build Coastguard Workerreference to a function was an 'extern', we simply verify that the 291*9880d681SAndroid Build Coastguard Workernumber of arguments for that definition and this one match up. If not, 292*9880d681SAndroid Build Coastguard Workerwe emit an error. 293*9880d681SAndroid Build Coastguard Worker 294*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 295*9880d681SAndroid Build Coastguard Worker 296*9880d681SAndroid Build Coastguard Worker (* Set names for all arguments. *) 297*9880d681SAndroid Build Coastguard Worker Array.iteri (fun i a -> 298*9880d681SAndroid Build Coastguard Worker let n = args.(i) in 299*9880d681SAndroid Build Coastguard Worker set_value_name n a; 300*9880d681SAndroid Build Coastguard Worker Hashtbl.add named_values n a; 301*9880d681SAndroid Build Coastguard Worker ) (params f); 302*9880d681SAndroid Build Coastguard Worker f 303*9880d681SAndroid Build Coastguard Worker 304*9880d681SAndroid Build Coastguard WorkerThe last bit of code for prototypes loops over all of the arguments in 305*9880d681SAndroid Build Coastguard Workerthe function, setting the name of the LLVM Argument objects to match, 306*9880d681SAndroid Build Coastguard Workerand registering the arguments in the ``Codegen.named_values`` map for 307*9880d681SAndroid Build Coastguard Workerfuture use by the ``Ast.Variable`` variant. Once this is set up, it 308*9880d681SAndroid Build Coastguard Workerreturns the Function object to the caller. Note that we don't check for 309*9880d681SAndroid Build Coastguard Workerconflicting argument names here (e.g. "extern foo(a b a)"). Doing so 310*9880d681SAndroid Build Coastguard Workerwould be very straight-forward with the mechanics we have already used 311*9880d681SAndroid Build Coastguard Workerabove. 312*9880d681SAndroid Build Coastguard Worker 313*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 314*9880d681SAndroid Build Coastguard Worker 315*9880d681SAndroid Build Coastguard Worker let codegen_func = function 316*9880d681SAndroid Build Coastguard Worker | Ast.Function (proto, body) -> 317*9880d681SAndroid Build Coastguard Worker Hashtbl.clear named_values; 318*9880d681SAndroid Build Coastguard Worker let the_function = codegen_proto proto in 319*9880d681SAndroid Build Coastguard Worker 320*9880d681SAndroid Build Coastguard WorkerCode generation for function definitions starts out simply enough: we 321*9880d681SAndroid Build Coastguard Workerjust codegen the prototype (Proto) and verify that it is ok. We then 322*9880d681SAndroid Build Coastguard Workerclear out the ``Codegen.named_values`` map to make sure that there isn't 323*9880d681SAndroid Build Coastguard Workeranything in it from the last function we compiled. Code generation of 324*9880d681SAndroid Build Coastguard Workerthe prototype ensures that there is an LLVM Function object that is 325*9880d681SAndroid Build Coastguard Workerready to go for us. 326*9880d681SAndroid Build Coastguard Worker 327*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 328*9880d681SAndroid Build Coastguard Worker 329*9880d681SAndroid Build Coastguard Worker (* Create a new basic block to start insertion into. *) 330*9880d681SAndroid Build Coastguard Worker let bb = append_block context "entry" the_function in 331*9880d681SAndroid Build Coastguard Worker position_at_end bb builder; 332*9880d681SAndroid Build Coastguard Worker 333*9880d681SAndroid Build Coastguard Worker try 334*9880d681SAndroid Build Coastguard Worker let ret_val = codegen_expr body in 335*9880d681SAndroid Build Coastguard Worker 336*9880d681SAndroid Build Coastguard WorkerNow we get to the point where the ``Codegen.builder`` is set up. The 337*9880d681SAndroid Build Coastguard Workerfirst line creates a new `basic 338*9880d681SAndroid Build Coastguard Workerblock <http://en.wikipedia.org/wiki/Basic_block>`_ (named "entry"), 339*9880d681SAndroid Build Coastguard Workerwhich is inserted into ``the_function``. The second line then tells the 340*9880d681SAndroid Build Coastguard Workerbuilder that new instructions should be inserted into the end of the new 341*9880d681SAndroid Build Coastguard Workerbasic block. Basic blocks in LLVM are an important part of functions 342*9880d681SAndroid Build Coastguard Workerthat define the `Control Flow 343*9880d681SAndroid Build Coastguard WorkerGraph <http://en.wikipedia.org/wiki/Control_flow_graph>`_. Since we 344*9880d681SAndroid Build Coastguard Workerdon't have any control flow, our functions will only contain one block 345*9880d681SAndroid Build Coastguard Workerat this point. We'll fix this in `Chapter 5 <OCamlLangImpl5.html>`_ :). 346*9880d681SAndroid Build Coastguard Worker 347*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 348*9880d681SAndroid Build Coastguard Worker 349*9880d681SAndroid Build Coastguard Worker let ret_val = codegen_expr body in 350*9880d681SAndroid Build Coastguard Worker 351*9880d681SAndroid Build Coastguard Worker (* Finish off the function. *) 352*9880d681SAndroid Build Coastguard Worker let _ = build_ret ret_val builder in 353*9880d681SAndroid Build Coastguard Worker 354*9880d681SAndroid Build Coastguard Worker (* Validate the generated code, checking for consistency. *) 355*9880d681SAndroid Build Coastguard Worker Llvm_analysis.assert_valid_function the_function; 356*9880d681SAndroid Build Coastguard Worker 357*9880d681SAndroid Build Coastguard Worker the_function 358*9880d681SAndroid Build Coastguard Worker 359*9880d681SAndroid Build Coastguard WorkerOnce the insertion point is set up, we call the ``Codegen.codegen_func`` 360*9880d681SAndroid Build Coastguard Workermethod for the root expression of the function. If no error happens, 361*9880d681SAndroid Build Coastguard Workerthis emits code to compute the expression into the entry block and 362*9880d681SAndroid Build Coastguard Workerreturns the value that was computed. Assuming no error, we then create 363*9880d681SAndroid Build Coastguard Workeran LLVM `ret instruction <../LangRef.html#ret-instruction>`_, which completes the 364*9880d681SAndroid Build Coastguard Workerfunction. Once the function is built, we call 365*9880d681SAndroid Build Coastguard Worker``Llvm_analysis.assert_valid_function``, which is provided by LLVM. This 366*9880d681SAndroid Build Coastguard Workerfunction does a variety of consistency checks on the generated code, to 367*9880d681SAndroid Build Coastguard Workerdetermine if our compiler is doing everything right. Using this is 368*9880d681SAndroid Build Coastguard Workerimportant: it can catch a lot of bugs. Once the function is finished and 369*9880d681SAndroid Build Coastguard Workervalidated, we return it. 370*9880d681SAndroid Build Coastguard Worker 371*9880d681SAndroid Build Coastguard Worker.. code-block:: ocaml 372*9880d681SAndroid Build Coastguard Worker 373*9880d681SAndroid Build Coastguard Worker with e -> 374*9880d681SAndroid Build Coastguard Worker delete_function the_function; 375*9880d681SAndroid Build Coastguard Worker raise e 376*9880d681SAndroid Build Coastguard Worker 377*9880d681SAndroid Build Coastguard WorkerThe only piece left here is handling of the error case. For simplicity, 378*9880d681SAndroid Build Coastguard Workerwe handle this by merely deleting the function we produced with the 379*9880d681SAndroid Build Coastguard Worker``Llvm.delete_function`` method. This allows the user to redefine a 380*9880d681SAndroid Build Coastguard Workerfunction that they incorrectly typed in before: if we didn't delete it, 381*9880d681SAndroid Build Coastguard Workerit would live in the symbol table, with a body, preventing future 382*9880d681SAndroid Build Coastguard Workerredefinition. 383*9880d681SAndroid Build Coastguard Worker 384*9880d681SAndroid Build Coastguard WorkerThis code does have a bug, though. Since the ``Codegen.codegen_proto`` 385*9880d681SAndroid Build Coastguard Workercan return a previously defined forward declaration, our code can 386*9880d681SAndroid Build Coastguard Workeractually delete a forward declaration. There are a number of ways to fix 387*9880d681SAndroid Build Coastguard Workerthis bug, see what you can come up with! Here is a testcase: 388*9880d681SAndroid Build Coastguard Worker 389*9880d681SAndroid Build Coastguard Worker:: 390*9880d681SAndroid Build Coastguard Worker 391*9880d681SAndroid Build Coastguard Worker extern foo(a b); # ok, defines foo. 392*9880d681SAndroid Build Coastguard Worker def foo(a b) c; # error, 'c' is invalid. 393*9880d681SAndroid Build Coastguard Worker def bar() foo(1, 2); # error, unknown function "foo" 394*9880d681SAndroid Build Coastguard Worker 395*9880d681SAndroid Build Coastguard WorkerDriver Changes and Closing Thoughts 396*9880d681SAndroid Build Coastguard Worker=================================== 397*9880d681SAndroid Build Coastguard Worker 398*9880d681SAndroid Build Coastguard WorkerFor now, code generation to LLVM doesn't really get us much, except that 399*9880d681SAndroid Build Coastguard Workerwe can look at the pretty IR calls. The sample code inserts calls to 400*9880d681SAndroid Build Coastguard WorkerCodegen into the "``Toplevel.main_loop``", and then dumps out the LLVM 401*9880d681SAndroid Build Coastguard WorkerIR. This gives a nice way to look at the LLVM IR for simple functions. 402*9880d681SAndroid Build Coastguard WorkerFor example: 403*9880d681SAndroid Build Coastguard Worker 404*9880d681SAndroid Build Coastguard Worker:: 405*9880d681SAndroid Build Coastguard Worker 406*9880d681SAndroid Build Coastguard Worker ready> 4+5; 407*9880d681SAndroid Build Coastguard Worker Read top-level expression: 408*9880d681SAndroid Build Coastguard Worker define double @""() { 409*9880d681SAndroid Build Coastguard Worker entry: 410*9880d681SAndroid Build Coastguard Worker %addtmp = fadd double 4.000000e+00, 5.000000e+00 411*9880d681SAndroid Build Coastguard Worker ret double %addtmp 412*9880d681SAndroid Build Coastguard Worker } 413*9880d681SAndroid Build Coastguard Worker 414*9880d681SAndroid Build Coastguard WorkerNote how the parser turns the top-level expression into anonymous 415*9880d681SAndroid Build Coastguard Workerfunctions for us. This will be handy when we add `JIT 416*9880d681SAndroid Build Coastguard Workersupport <OCamlLangImpl4.html#adding-a-jit-compiler>`_ in the next chapter. Also note that 417*9880d681SAndroid Build Coastguard Workerthe code is very literally transcribed, no optimizations are being 418*9880d681SAndroid Build Coastguard Workerperformed. We will `add 419*9880d681SAndroid Build Coastguard Workeroptimizations <OCamlLangImpl4.html#trivial-constant-folding>`_ explicitly in the 420*9880d681SAndroid Build Coastguard Workernext chapter. 421*9880d681SAndroid Build Coastguard Worker 422*9880d681SAndroid Build Coastguard Worker:: 423*9880d681SAndroid Build Coastguard Worker 424*9880d681SAndroid Build Coastguard Worker ready> def foo(a b) a*a + 2*a*b + b*b; 425*9880d681SAndroid Build Coastguard Worker Read function definition: 426*9880d681SAndroid Build Coastguard Worker define double @foo(double %a, double %b) { 427*9880d681SAndroid Build Coastguard Worker entry: 428*9880d681SAndroid Build Coastguard Worker %multmp = fmul double %a, %a 429*9880d681SAndroid Build Coastguard Worker %multmp1 = fmul double 2.000000e+00, %a 430*9880d681SAndroid Build Coastguard Worker %multmp2 = fmul double %multmp1, %b 431*9880d681SAndroid Build Coastguard Worker %addtmp = fadd double %multmp, %multmp2 432*9880d681SAndroid Build Coastguard Worker %multmp3 = fmul double %b, %b 433*9880d681SAndroid Build Coastguard Worker %addtmp4 = fadd double %addtmp, %multmp3 434*9880d681SAndroid Build Coastguard Worker ret double %addtmp4 435*9880d681SAndroid Build Coastguard Worker } 436*9880d681SAndroid Build Coastguard Worker 437*9880d681SAndroid Build Coastguard WorkerThis shows some simple arithmetic. Notice the striking similarity to the 438*9880d681SAndroid Build Coastguard WorkerLLVM builder calls that we use to create the instructions. 439*9880d681SAndroid Build Coastguard Worker 440*9880d681SAndroid Build Coastguard Worker:: 441*9880d681SAndroid Build Coastguard Worker 442*9880d681SAndroid Build Coastguard Worker ready> def bar(a) foo(a, 4.0) + bar(31337); 443*9880d681SAndroid Build Coastguard Worker Read function definition: 444*9880d681SAndroid Build Coastguard Worker define double @bar(double %a) { 445*9880d681SAndroid Build Coastguard Worker entry: 446*9880d681SAndroid Build Coastguard Worker %calltmp = call double @foo(double %a, double 4.000000e+00) 447*9880d681SAndroid Build Coastguard Worker %calltmp1 = call double @bar(double 3.133700e+04) 448*9880d681SAndroid Build Coastguard Worker %addtmp = fadd double %calltmp, %calltmp1 449*9880d681SAndroid Build Coastguard Worker ret double %addtmp 450*9880d681SAndroid Build Coastguard Worker } 451*9880d681SAndroid Build Coastguard Worker 452*9880d681SAndroid Build Coastguard WorkerThis shows some function calls. Note that this function will take a long 453*9880d681SAndroid Build Coastguard Workertime to execute if you call it. In the future we'll add conditional 454*9880d681SAndroid Build Coastguard Workercontrol flow to actually make recursion useful :). 455*9880d681SAndroid Build Coastguard Worker 456*9880d681SAndroid Build Coastguard Worker:: 457*9880d681SAndroid Build Coastguard Worker 458*9880d681SAndroid Build Coastguard Worker ready> extern cos(x); 459*9880d681SAndroid Build Coastguard Worker Read extern: 460*9880d681SAndroid Build Coastguard Worker declare double @cos(double) 461*9880d681SAndroid Build Coastguard Worker 462*9880d681SAndroid Build Coastguard Worker ready> cos(1.234); 463*9880d681SAndroid Build Coastguard Worker Read top-level expression: 464*9880d681SAndroid Build Coastguard Worker define double @""() { 465*9880d681SAndroid Build Coastguard Worker entry: 466*9880d681SAndroid Build Coastguard Worker %calltmp = call double @cos(double 1.234000e+00) 467*9880d681SAndroid Build Coastguard Worker ret double %calltmp 468*9880d681SAndroid Build Coastguard Worker } 469*9880d681SAndroid Build Coastguard Worker 470*9880d681SAndroid Build Coastguard WorkerThis shows an extern for the libm "cos" function, and a call to it. 471*9880d681SAndroid Build Coastguard Worker 472*9880d681SAndroid Build Coastguard Worker:: 473*9880d681SAndroid Build Coastguard Worker 474*9880d681SAndroid Build Coastguard Worker ready> ^D 475*9880d681SAndroid Build Coastguard Worker ; ModuleID = 'my cool jit' 476*9880d681SAndroid Build Coastguard Worker 477*9880d681SAndroid Build Coastguard Worker define double @""() { 478*9880d681SAndroid Build Coastguard Worker entry: 479*9880d681SAndroid Build Coastguard Worker %addtmp = fadd double 4.000000e+00, 5.000000e+00 480*9880d681SAndroid Build Coastguard Worker ret double %addtmp 481*9880d681SAndroid Build Coastguard Worker } 482*9880d681SAndroid Build Coastguard Worker 483*9880d681SAndroid Build Coastguard Worker define double @foo(double %a, double %b) { 484*9880d681SAndroid Build Coastguard Worker entry: 485*9880d681SAndroid Build Coastguard Worker %multmp = fmul double %a, %a 486*9880d681SAndroid Build Coastguard Worker %multmp1 = fmul double 2.000000e+00, %a 487*9880d681SAndroid Build Coastguard Worker %multmp2 = fmul double %multmp1, %b 488*9880d681SAndroid Build Coastguard Worker %addtmp = fadd double %multmp, %multmp2 489*9880d681SAndroid Build Coastguard Worker %multmp3 = fmul double %b, %b 490*9880d681SAndroid Build Coastguard Worker %addtmp4 = fadd double %addtmp, %multmp3 491*9880d681SAndroid Build Coastguard Worker ret double %addtmp4 492*9880d681SAndroid Build Coastguard Worker } 493*9880d681SAndroid Build Coastguard Worker 494*9880d681SAndroid Build Coastguard Worker define double @bar(double %a) { 495*9880d681SAndroid Build Coastguard Worker entry: 496*9880d681SAndroid Build Coastguard Worker %calltmp = call double @foo(double %a, double 4.000000e+00) 497*9880d681SAndroid Build Coastguard Worker %calltmp1 = call double @bar(double 3.133700e+04) 498*9880d681SAndroid Build Coastguard Worker %addtmp = fadd double %calltmp, %calltmp1 499*9880d681SAndroid Build Coastguard Worker ret double %addtmp 500*9880d681SAndroid Build Coastguard Worker } 501*9880d681SAndroid Build Coastguard Worker 502*9880d681SAndroid Build Coastguard Worker declare double @cos(double) 503*9880d681SAndroid Build Coastguard Worker 504*9880d681SAndroid Build Coastguard Worker define double @""() { 505*9880d681SAndroid Build Coastguard Worker entry: 506*9880d681SAndroid Build Coastguard Worker %calltmp = call double @cos(double 1.234000e+00) 507*9880d681SAndroid Build Coastguard Worker ret double %calltmp 508*9880d681SAndroid Build Coastguard Worker } 509*9880d681SAndroid Build Coastguard Worker 510*9880d681SAndroid Build Coastguard WorkerWhen you quit the current demo, it dumps out the IR for the entire 511*9880d681SAndroid Build Coastguard Workermodule generated. Here you can see the big picture with all the 512*9880d681SAndroid Build Coastguard Workerfunctions referencing each other. 513*9880d681SAndroid Build Coastguard Worker 514*9880d681SAndroid Build Coastguard WorkerThis wraps up the third chapter of the Kaleidoscope tutorial. Up next, 515*9880d681SAndroid Build Coastguard Workerwe'll describe how to `add JIT codegen and optimizer 516*9880d681SAndroid Build Coastguard Workersupport <OCamlLangImpl4.html>`_ to this so we can actually start running 517*9880d681SAndroid Build Coastguard Workercode! 518*9880d681SAndroid Build Coastguard Worker 519*9880d681SAndroid Build Coastguard WorkerFull Code Listing 520*9880d681SAndroid Build Coastguard Worker================= 521*9880d681SAndroid Build Coastguard Worker 522*9880d681SAndroid Build Coastguard WorkerHere is the complete code listing for our running example, enhanced with 523*9880d681SAndroid Build Coastguard Workerthe LLVM code generator. Because this uses the LLVM libraries, we need 524*9880d681SAndroid Build Coastguard Workerto link them in. To do this, we use the 525*9880d681SAndroid Build Coastguard Worker`llvm-config <http://llvm.org/cmds/llvm-config.html>`_ tool to inform 526*9880d681SAndroid Build Coastguard Workerour makefile/command line about which options to use: 527*9880d681SAndroid Build Coastguard Worker 528*9880d681SAndroid Build Coastguard Worker.. code-block:: bash 529*9880d681SAndroid Build Coastguard Worker 530*9880d681SAndroid Build Coastguard Worker # Compile 531*9880d681SAndroid Build Coastguard Worker ocamlbuild toy.byte 532*9880d681SAndroid Build Coastguard Worker # Run 533*9880d681SAndroid Build Coastguard Worker ./toy.byte 534*9880d681SAndroid Build Coastguard Worker 535*9880d681SAndroid Build Coastguard WorkerHere is the code: 536*9880d681SAndroid Build Coastguard Worker 537*9880d681SAndroid Build Coastguard Worker\_tags: 538*9880d681SAndroid Build Coastguard Worker :: 539*9880d681SAndroid Build Coastguard Worker 540*9880d681SAndroid Build Coastguard Worker <{lexer,parser}.ml>: use_camlp4, pp(camlp4of) 541*9880d681SAndroid Build Coastguard Worker <*.{byte,native}>: g++, use_llvm, use_llvm_analysis 542*9880d681SAndroid Build Coastguard Worker 543*9880d681SAndroid Build Coastguard Workermyocamlbuild.ml: 544*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 545*9880d681SAndroid Build Coastguard Worker 546*9880d681SAndroid Build Coastguard Worker open Ocamlbuild_plugin;; 547*9880d681SAndroid Build Coastguard Worker 548*9880d681SAndroid Build Coastguard Worker ocaml_lib ~extern:true "llvm";; 549*9880d681SAndroid Build Coastguard Worker ocaml_lib ~extern:true "llvm_analysis";; 550*9880d681SAndroid Build Coastguard Worker 551*9880d681SAndroid Build Coastguard Worker flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; 552*9880d681SAndroid Build Coastguard Worker 553*9880d681SAndroid Build Coastguard Workertoken.ml: 554*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 555*9880d681SAndroid Build Coastguard Worker 556*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 557*9880d681SAndroid Build Coastguard Worker * Lexer Tokens 558*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 559*9880d681SAndroid Build Coastguard Worker 560*9880d681SAndroid Build Coastguard Worker (* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of 561*9880d681SAndroid Build Coastguard Worker * these others for known things. *) 562*9880d681SAndroid Build Coastguard Worker type token = 563*9880d681SAndroid Build Coastguard Worker (* commands *) 564*9880d681SAndroid Build Coastguard Worker | Def | Extern 565*9880d681SAndroid Build Coastguard Worker 566*9880d681SAndroid Build Coastguard Worker (* primary *) 567*9880d681SAndroid Build Coastguard Worker | Ident of string | Number of float 568*9880d681SAndroid Build Coastguard Worker 569*9880d681SAndroid Build Coastguard Worker (* unknown *) 570*9880d681SAndroid Build Coastguard Worker | Kwd of char 571*9880d681SAndroid Build Coastguard Worker 572*9880d681SAndroid Build Coastguard Workerlexer.ml: 573*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 574*9880d681SAndroid Build Coastguard Worker 575*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 576*9880d681SAndroid Build Coastguard Worker * Lexer 577*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 578*9880d681SAndroid Build Coastguard Worker 579*9880d681SAndroid Build Coastguard Worker let rec lex = parser 580*9880d681SAndroid Build Coastguard Worker (* Skip any whitespace. *) 581*9880d681SAndroid Build Coastguard Worker | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream 582*9880d681SAndroid Build Coastguard Worker 583*9880d681SAndroid Build Coastguard Worker (* identifier: [a-zA-Z][a-zA-Z0-9] *) 584*9880d681SAndroid Build Coastguard Worker | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> 585*9880d681SAndroid Build Coastguard Worker let buffer = Buffer.create 1 in 586*9880d681SAndroid Build Coastguard Worker Buffer.add_char buffer c; 587*9880d681SAndroid Build Coastguard Worker lex_ident buffer stream 588*9880d681SAndroid Build Coastguard Worker 589*9880d681SAndroid Build Coastguard Worker (* number: [0-9.]+ *) 590*9880d681SAndroid Build Coastguard Worker | [< ' ('0' .. '9' as c); stream >] -> 591*9880d681SAndroid Build Coastguard Worker let buffer = Buffer.create 1 in 592*9880d681SAndroid Build Coastguard Worker Buffer.add_char buffer c; 593*9880d681SAndroid Build Coastguard Worker lex_number buffer stream 594*9880d681SAndroid Build Coastguard Worker 595*9880d681SAndroid Build Coastguard Worker (* Comment until end of line. *) 596*9880d681SAndroid Build Coastguard Worker | [< ' ('#'); stream >] -> 597*9880d681SAndroid Build Coastguard Worker lex_comment stream 598*9880d681SAndroid Build Coastguard Worker 599*9880d681SAndroid Build Coastguard Worker (* Otherwise, just return the character as its ascii value. *) 600*9880d681SAndroid Build Coastguard Worker | [< 'c; stream >] -> 601*9880d681SAndroid Build Coastguard Worker [< 'Token.Kwd c; lex stream >] 602*9880d681SAndroid Build Coastguard Worker 603*9880d681SAndroid Build Coastguard Worker (* end of stream. *) 604*9880d681SAndroid Build Coastguard Worker | [< >] -> [< >] 605*9880d681SAndroid Build Coastguard Worker 606*9880d681SAndroid Build Coastguard Worker and lex_number buffer = parser 607*9880d681SAndroid Build Coastguard Worker | [< ' ('0' .. '9' | '.' as c); stream >] -> 608*9880d681SAndroid Build Coastguard Worker Buffer.add_char buffer c; 609*9880d681SAndroid Build Coastguard Worker lex_number buffer stream 610*9880d681SAndroid Build Coastguard Worker | [< stream=lex >] -> 611*9880d681SAndroid Build Coastguard Worker [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] 612*9880d681SAndroid Build Coastguard Worker 613*9880d681SAndroid Build Coastguard Worker and lex_ident buffer = parser 614*9880d681SAndroid Build Coastguard Worker | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> 615*9880d681SAndroid Build Coastguard Worker Buffer.add_char buffer c; 616*9880d681SAndroid Build Coastguard Worker lex_ident buffer stream 617*9880d681SAndroid Build Coastguard Worker | [< stream=lex >] -> 618*9880d681SAndroid Build Coastguard Worker match Buffer.contents buffer with 619*9880d681SAndroid Build Coastguard Worker | "def" -> [< 'Token.Def; stream >] 620*9880d681SAndroid Build Coastguard Worker | "extern" -> [< 'Token.Extern; stream >] 621*9880d681SAndroid Build Coastguard Worker | id -> [< 'Token.Ident id; stream >] 622*9880d681SAndroid Build Coastguard Worker 623*9880d681SAndroid Build Coastguard Worker and lex_comment = parser 624*9880d681SAndroid Build Coastguard Worker | [< ' ('\n'); stream=lex >] -> stream 625*9880d681SAndroid Build Coastguard Worker | [< 'c; e=lex_comment >] -> e 626*9880d681SAndroid Build Coastguard Worker | [< >] -> [< >] 627*9880d681SAndroid Build Coastguard Worker 628*9880d681SAndroid Build Coastguard Workerast.ml: 629*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 630*9880d681SAndroid Build Coastguard Worker 631*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 632*9880d681SAndroid Build Coastguard Worker * Abstract Syntax Tree (aka Parse Tree) 633*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 634*9880d681SAndroid Build Coastguard Worker 635*9880d681SAndroid Build Coastguard Worker (* expr - Base type for all expression nodes. *) 636*9880d681SAndroid Build Coastguard Worker type expr = 637*9880d681SAndroid Build Coastguard Worker (* variant for numeric literals like "1.0". *) 638*9880d681SAndroid Build Coastguard Worker | Number of float 639*9880d681SAndroid Build Coastguard Worker 640*9880d681SAndroid Build Coastguard Worker (* variant for referencing a variable, like "a". *) 641*9880d681SAndroid Build Coastguard Worker | Variable of string 642*9880d681SAndroid Build Coastguard Worker 643*9880d681SAndroid Build Coastguard Worker (* variant for a binary operator. *) 644*9880d681SAndroid Build Coastguard Worker | Binary of char * expr * expr 645*9880d681SAndroid Build Coastguard Worker 646*9880d681SAndroid Build Coastguard Worker (* variant for function calls. *) 647*9880d681SAndroid Build Coastguard Worker | Call of string * expr array 648*9880d681SAndroid Build Coastguard Worker 649*9880d681SAndroid Build Coastguard Worker (* proto - This type represents the "prototype" for a function, which captures 650*9880d681SAndroid Build Coastguard Worker * its name, and its argument names (thus implicitly the number of arguments the 651*9880d681SAndroid Build Coastguard Worker * function takes). *) 652*9880d681SAndroid Build Coastguard Worker type proto = Prototype of string * string array 653*9880d681SAndroid Build Coastguard Worker 654*9880d681SAndroid Build Coastguard Worker (* func - This type represents a function definition itself. *) 655*9880d681SAndroid Build Coastguard Worker type func = Function of proto * expr 656*9880d681SAndroid Build Coastguard Worker 657*9880d681SAndroid Build Coastguard Workerparser.ml: 658*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 659*9880d681SAndroid Build Coastguard Worker 660*9880d681SAndroid Build Coastguard Worker (*===---------------------------------------------------------------------=== 661*9880d681SAndroid Build Coastguard Worker * Parser 662*9880d681SAndroid Build Coastguard Worker *===---------------------------------------------------------------------===*) 663*9880d681SAndroid Build Coastguard Worker 664*9880d681SAndroid Build Coastguard Worker (* binop_precedence - This holds the precedence for each binary operator that is 665*9880d681SAndroid Build Coastguard Worker * defined *) 666*9880d681SAndroid Build Coastguard Worker let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 667*9880d681SAndroid Build Coastguard Worker 668*9880d681SAndroid Build Coastguard Worker (* precedence - Get the precedence of the pending binary operator token. *) 669*9880d681SAndroid Build Coastguard Worker let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 670*9880d681SAndroid Build Coastguard Worker 671*9880d681SAndroid Build Coastguard Worker (* primary 672*9880d681SAndroid Build Coastguard Worker * ::= identifier 673*9880d681SAndroid Build Coastguard Worker * ::= numberexpr 674*9880d681SAndroid Build Coastguard Worker * ::= parenexpr *) 675*9880d681SAndroid Build Coastguard Worker let rec parse_primary = parser 676*9880d681SAndroid Build Coastguard Worker (* numberexpr ::= number *) 677*9880d681SAndroid Build Coastguard Worker | [< 'Token.Number n >] -> Ast.Number n 678*9880d681SAndroid Build Coastguard Worker 679*9880d681SAndroid Build Coastguard Worker (* parenexpr ::= '(' expression ')' *) 680*9880d681SAndroid Build Coastguard Worker | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e 681*9880d681SAndroid Build Coastguard Worker 682*9880d681SAndroid Build Coastguard Worker (* identifierexpr 683*9880d681SAndroid Build Coastguard Worker * ::= identifier 684*9880d681SAndroid Build Coastguard Worker * ::= identifier '(' argumentexpr ')' *) 685*9880d681SAndroid Build Coastguard Worker | [< 'Token.Ident id; stream >] -> 686*9880d681SAndroid Build Coastguard Worker let rec parse_args accumulator = parser 687*9880d681SAndroid Build Coastguard Worker | [< e=parse_expr; stream >] -> 688*9880d681SAndroid Build Coastguard Worker begin parser 689*9880d681SAndroid Build Coastguard Worker | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e 690*9880d681SAndroid Build Coastguard Worker | [< >] -> e :: accumulator 691*9880d681SAndroid Build Coastguard Worker end stream 692*9880d681SAndroid Build Coastguard Worker | [< >] -> accumulator 693*9880d681SAndroid Build Coastguard Worker in 694*9880d681SAndroid Build Coastguard Worker let rec parse_ident id = parser 695*9880d681SAndroid Build Coastguard Worker (* Call. *) 696*9880d681SAndroid Build Coastguard Worker | [< 'Token.Kwd '('; 697*9880d681SAndroid Build Coastguard Worker args=parse_args []; 698*9880d681SAndroid Build Coastguard Worker 'Token.Kwd ')' ?? "expected ')'">] -> 699*9880d681SAndroid Build Coastguard Worker Ast.Call (id, Array.of_list (List.rev args)) 700*9880d681SAndroid Build Coastguard Worker 701*9880d681SAndroid Build Coastguard Worker (* Simple variable ref. *) 702*9880d681SAndroid Build Coastguard Worker | [< >] -> Ast.Variable id 703*9880d681SAndroid Build Coastguard Worker in 704*9880d681SAndroid Build Coastguard Worker parse_ident id stream 705*9880d681SAndroid Build Coastguard Worker 706*9880d681SAndroid Build Coastguard Worker | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") 707*9880d681SAndroid Build Coastguard Worker 708*9880d681SAndroid Build Coastguard Worker (* binoprhs 709*9880d681SAndroid Build Coastguard Worker * ::= ('+' primary)* *) 710*9880d681SAndroid Build Coastguard Worker and parse_bin_rhs expr_prec lhs stream = 711*9880d681SAndroid Build Coastguard Worker match Stream.peek stream with 712*9880d681SAndroid Build Coastguard Worker (* If this is a binop, find its precedence. *) 713*9880d681SAndroid Build Coastguard Worker | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> 714*9880d681SAndroid Build Coastguard Worker let token_prec = precedence c in 715*9880d681SAndroid Build Coastguard Worker 716*9880d681SAndroid Build Coastguard Worker (* If this is a binop that binds at least as tightly as the current binop, 717*9880d681SAndroid Build Coastguard Worker * consume it, otherwise we are done. *) 718*9880d681SAndroid Build Coastguard Worker if token_prec < expr_prec then lhs else begin 719*9880d681SAndroid Build Coastguard Worker (* Eat the binop. *) 720*9880d681SAndroid Build Coastguard Worker Stream.junk stream; 721*9880d681SAndroid Build Coastguard Worker 722*9880d681SAndroid Build Coastguard Worker (* Parse the primary expression after the binary operator. *) 723*9880d681SAndroid Build Coastguard Worker let rhs = parse_primary stream in 724*9880d681SAndroid Build Coastguard Worker 725*9880d681SAndroid Build Coastguard Worker (* Okay, we know this is a binop. *) 726*9880d681SAndroid Build Coastguard Worker let rhs = 727*9880d681SAndroid Build Coastguard Worker match Stream.peek stream with 728*9880d681SAndroid Build Coastguard Worker | Some (Token.Kwd c2) -> 729*9880d681SAndroid Build Coastguard Worker (* If BinOp binds less tightly with rhs than the operator after 730*9880d681SAndroid Build Coastguard Worker * rhs, let the pending operator take rhs as its lhs. *) 731*9880d681SAndroid Build Coastguard Worker let next_prec = precedence c2 in 732*9880d681SAndroid Build Coastguard Worker if token_prec < next_prec 733*9880d681SAndroid Build Coastguard Worker then parse_bin_rhs (token_prec + 1) rhs stream 734*9880d681SAndroid Build Coastguard Worker else rhs 735*9880d681SAndroid Build Coastguard Worker | _ -> rhs 736*9880d681SAndroid Build Coastguard Worker in 737*9880d681SAndroid Build Coastguard Worker 738*9880d681SAndroid Build Coastguard Worker (* Merge lhs/rhs. *) 739*9880d681SAndroid Build Coastguard Worker let lhs = Ast.Binary (c, lhs, rhs) in 740*9880d681SAndroid Build Coastguard Worker parse_bin_rhs expr_prec lhs stream 741*9880d681SAndroid Build Coastguard Worker end 742*9880d681SAndroid Build Coastguard Worker | _ -> lhs 743*9880d681SAndroid Build Coastguard Worker 744*9880d681SAndroid Build Coastguard Worker (* expression 745*9880d681SAndroid Build Coastguard Worker * ::= primary binoprhs *) 746*9880d681SAndroid Build Coastguard Worker and parse_expr = parser 747*9880d681SAndroid Build Coastguard Worker | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream 748*9880d681SAndroid Build Coastguard Worker 749*9880d681SAndroid Build Coastguard Worker (* prototype 750*9880d681SAndroid Build Coastguard Worker * ::= id '(' id* ')' *) 751*9880d681SAndroid Build Coastguard Worker let parse_prototype = 752*9880d681SAndroid Build Coastguard Worker let rec parse_args accumulator = parser 753*9880d681SAndroid Build Coastguard Worker | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e 754*9880d681SAndroid Build Coastguard Worker | [< >] -> accumulator 755*9880d681SAndroid Build Coastguard Worker in 756*9880d681SAndroid Build Coastguard Worker 757*9880d681SAndroid Build Coastguard Worker parser 758*9880d681SAndroid Build Coastguard Worker | [< 'Token.Ident id; 759*9880d681SAndroid Build Coastguard Worker 'Token.Kwd '(' ?? "expected '(' in prototype"; 760*9880d681SAndroid Build Coastguard Worker args=parse_args []; 761*9880d681SAndroid Build Coastguard Worker 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> 762*9880d681SAndroid Build Coastguard Worker (* success. *) 763*9880d681SAndroid Build Coastguard Worker Ast.Prototype (id, Array.of_list (List.rev args)) 764*9880d681SAndroid Build Coastguard Worker 765*9880d681SAndroid Build Coastguard Worker | [< >] -> 766*9880d681SAndroid Build Coastguard Worker raise (Stream.Error "expected function name in prototype") 767*9880d681SAndroid Build Coastguard Worker 768*9880d681SAndroid Build Coastguard Worker (* definition ::= 'def' prototype expression *) 769*9880d681SAndroid Build Coastguard Worker let parse_definition = parser 770*9880d681SAndroid Build Coastguard Worker | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> 771*9880d681SAndroid Build Coastguard Worker Ast.Function (p, e) 772*9880d681SAndroid Build Coastguard Worker 773*9880d681SAndroid Build Coastguard Worker (* toplevelexpr ::= expression *) 774*9880d681SAndroid Build Coastguard Worker let parse_toplevel = parser 775*9880d681SAndroid Build Coastguard Worker | [< e=parse_expr >] -> 776*9880d681SAndroid Build Coastguard Worker (* Make an anonymous proto. *) 777*9880d681SAndroid Build Coastguard Worker Ast.Function (Ast.Prototype ("", [||]), e) 778*9880d681SAndroid Build Coastguard Worker 779*9880d681SAndroid Build Coastguard Worker (* external ::= 'extern' prototype *) 780*9880d681SAndroid Build Coastguard Worker let parse_extern = parser 781*9880d681SAndroid Build Coastguard Worker | [< 'Token.Extern; e=parse_prototype >] -> e 782*9880d681SAndroid Build Coastguard Worker 783*9880d681SAndroid Build Coastguard Workercodegen.ml: 784*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 785*9880d681SAndroid Build Coastguard Worker 786*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 787*9880d681SAndroid Build Coastguard Worker * Code Generation 788*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 789*9880d681SAndroid Build Coastguard Worker 790*9880d681SAndroid Build Coastguard Worker open Llvm 791*9880d681SAndroid Build Coastguard Worker 792*9880d681SAndroid Build Coastguard Worker exception Error of string 793*9880d681SAndroid Build Coastguard Worker 794*9880d681SAndroid Build Coastguard Worker let context = global_context () 795*9880d681SAndroid Build Coastguard Worker let the_module = create_module context "my cool jit" 796*9880d681SAndroid Build Coastguard Worker let builder = builder context 797*9880d681SAndroid Build Coastguard Worker let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 798*9880d681SAndroid Build Coastguard Worker let double_type = double_type context 799*9880d681SAndroid Build Coastguard Worker 800*9880d681SAndroid Build Coastguard Worker let rec codegen_expr = function 801*9880d681SAndroid Build Coastguard Worker | Ast.Number n -> const_float double_type n 802*9880d681SAndroid Build Coastguard Worker | Ast.Variable name -> 803*9880d681SAndroid Build Coastguard Worker (try Hashtbl.find named_values name with 804*9880d681SAndroid Build Coastguard Worker | Not_found -> raise (Error "unknown variable name")) 805*9880d681SAndroid Build Coastguard Worker | Ast.Binary (op, lhs, rhs) -> 806*9880d681SAndroid Build Coastguard Worker let lhs_val = codegen_expr lhs in 807*9880d681SAndroid Build Coastguard Worker let rhs_val = codegen_expr rhs in 808*9880d681SAndroid Build Coastguard Worker begin 809*9880d681SAndroid Build Coastguard Worker match op with 810*9880d681SAndroid Build Coastguard Worker | '+' -> build_add lhs_val rhs_val "addtmp" builder 811*9880d681SAndroid Build Coastguard Worker | '-' -> build_sub lhs_val rhs_val "subtmp" builder 812*9880d681SAndroid Build Coastguard Worker | '*' -> build_mul lhs_val rhs_val "multmp" builder 813*9880d681SAndroid Build Coastguard Worker | '<' -> 814*9880d681SAndroid Build Coastguard Worker (* Convert bool 0/1 to double 0.0 or 1.0 *) 815*9880d681SAndroid Build Coastguard Worker let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in 816*9880d681SAndroid Build Coastguard Worker build_uitofp i double_type "booltmp" builder 817*9880d681SAndroid Build Coastguard Worker | _ -> raise (Error "invalid binary operator") 818*9880d681SAndroid Build Coastguard Worker end 819*9880d681SAndroid Build Coastguard Worker | Ast.Call (callee, args) -> 820*9880d681SAndroid Build Coastguard Worker (* Look up the name in the module table. *) 821*9880d681SAndroid Build Coastguard Worker let callee = 822*9880d681SAndroid Build Coastguard Worker match lookup_function callee the_module with 823*9880d681SAndroid Build Coastguard Worker | Some callee -> callee 824*9880d681SAndroid Build Coastguard Worker | None -> raise (Error "unknown function referenced") 825*9880d681SAndroid Build Coastguard Worker in 826*9880d681SAndroid Build Coastguard Worker let params = params callee in 827*9880d681SAndroid Build Coastguard Worker 828*9880d681SAndroid Build Coastguard Worker (* If argument mismatch error. *) 829*9880d681SAndroid Build Coastguard Worker if Array.length params == Array.length args then () else 830*9880d681SAndroid Build Coastguard Worker raise (Error "incorrect # arguments passed"); 831*9880d681SAndroid Build Coastguard Worker let args = Array.map codegen_expr args in 832*9880d681SAndroid Build Coastguard Worker build_call callee args "calltmp" builder 833*9880d681SAndroid Build Coastguard Worker 834*9880d681SAndroid Build Coastguard Worker let codegen_proto = function 835*9880d681SAndroid Build Coastguard Worker | Ast.Prototype (name, args) -> 836*9880d681SAndroid Build Coastguard Worker (* Make the function type: double(double,double) etc. *) 837*9880d681SAndroid Build Coastguard Worker let doubles = Array.make (Array.length args) double_type in 838*9880d681SAndroid Build Coastguard Worker let ft = function_type double_type doubles in 839*9880d681SAndroid Build Coastguard Worker let f = 840*9880d681SAndroid Build Coastguard Worker match lookup_function name the_module with 841*9880d681SAndroid Build Coastguard Worker | None -> declare_function name ft the_module 842*9880d681SAndroid Build Coastguard Worker 843*9880d681SAndroid Build Coastguard Worker (* If 'f' conflicted, there was already something named 'name'. If it 844*9880d681SAndroid Build Coastguard Worker * has a body, don't allow redefinition or reextern. *) 845*9880d681SAndroid Build Coastguard Worker | Some f -> 846*9880d681SAndroid Build Coastguard Worker (* If 'f' already has a body, reject this. *) 847*9880d681SAndroid Build Coastguard Worker if block_begin f <> At_end f then 848*9880d681SAndroid Build Coastguard Worker raise (Error "redefinition of function"); 849*9880d681SAndroid Build Coastguard Worker 850*9880d681SAndroid Build Coastguard Worker (* If 'f' took a different number of arguments, reject. *) 851*9880d681SAndroid Build Coastguard Worker if element_type (type_of f) <> ft then 852*9880d681SAndroid Build Coastguard Worker raise (Error "redefinition of function with different # args"); 853*9880d681SAndroid Build Coastguard Worker f 854*9880d681SAndroid Build Coastguard Worker in 855*9880d681SAndroid Build Coastguard Worker 856*9880d681SAndroid Build Coastguard Worker (* Set names for all arguments. *) 857*9880d681SAndroid Build Coastguard Worker Array.iteri (fun i a -> 858*9880d681SAndroid Build Coastguard Worker let n = args.(i) in 859*9880d681SAndroid Build Coastguard Worker set_value_name n a; 860*9880d681SAndroid Build Coastguard Worker Hashtbl.add named_values n a; 861*9880d681SAndroid Build Coastguard Worker ) (params f); 862*9880d681SAndroid Build Coastguard Worker f 863*9880d681SAndroid Build Coastguard Worker 864*9880d681SAndroid Build Coastguard Worker let codegen_func = function 865*9880d681SAndroid Build Coastguard Worker | Ast.Function (proto, body) -> 866*9880d681SAndroid Build Coastguard Worker Hashtbl.clear named_values; 867*9880d681SAndroid Build Coastguard Worker let the_function = codegen_proto proto in 868*9880d681SAndroid Build Coastguard Worker 869*9880d681SAndroid Build Coastguard Worker (* Create a new basic block to start insertion into. *) 870*9880d681SAndroid Build Coastguard Worker let bb = append_block context "entry" the_function in 871*9880d681SAndroid Build Coastguard Worker position_at_end bb builder; 872*9880d681SAndroid Build Coastguard Worker 873*9880d681SAndroid Build Coastguard Worker try 874*9880d681SAndroid Build Coastguard Worker let ret_val = codegen_expr body in 875*9880d681SAndroid Build Coastguard Worker 876*9880d681SAndroid Build Coastguard Worker (* Finish off the function. *) 877*9880d681SAndroid Build Coastguard Worker let _ = build_ret ret_val builder in 878*9880d681SAndroid Build Coastguard Worker 879*9880d681SAndroid Build Coastguard Worker (* Validate the generated code, checking for consistency. *) 880*9880d681SAndroid Build Coastguard Worker Llvm_analysis.assert_valid_function the_function; 881*9880d681SAndroid Build Coastguard Worker 882*9880d681SAndroid Build Coastguard Worker the_function 883*9880d681SAndroid Build Coastguard Worker with e -> 884*9880d681SAndroid Build Coastguard Worker delete_function the_function; 885*9880d681SAndroid Build Coastguard Worker raise e 886*9880d681SAndroid Build Coastguard Worker 887*9880d681SAndroid Build Coastguard Workertoplevel.ml: 888*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 889*9880d681SAndroid Build Coastguard Worker 890*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 891*9880d681SAndroid Build Coastguard Worker * Top-Level parsing and JIT Driver 892*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 893*9880d681SAndroid Build Coastguard Worker 894*9880d681SAndroid Build Coastguard Worker open Llvm 895*9880d681SAndroid Build Coastguard Worker 896*9880d681SAndroid Build Coastguard Worker (* top ::= definition | external | expression | ';' *) 897*9880d681SAndroid Build Coastguard Worker let rec main_loop stream = 898*9880d681SAndroid Build Coastguard Worker match Stream.peek stream with 899*9880d681SAndroid Build Coastguard Worker | None -> () 900*9880d681SAndroid Build Coastguard Worker 901*9880d681SAndroid Build Coastguard Worker (* ignore top-level semicolons. *) 902*9880d681SAndroid Build Coastguard Worker | Some (Token.Kwd ';') -> 903*9880d681SAndroid Build Coastguard Worker Stream.junk stream; 904*9880d681SAndroid Build Coastguard Worker main_loop stream 905*9880d681SAndroid Build Coastguard Worker 906*9880d681SAndroid Build Coastguard Worker | Some token -> 907*9880d681SAndroid Build Coastguard Worker begin 908*9880d681SAndroid Build Coastguard Worker try match token with 909*9880d681SAndroid Build Coastguard Worker | Token.Def -> 910*9880d681SAndroid Build Coastguard Worker let e = Parser.parse_definition stream in 911*9880d681SAndroid Build Coastguard Worker print_endline "parsed a function definition."; 912*9880d681SAndroid Build Coastguard Worker dump_value (Codegen.codegen_func e); 913*9880d681SAndroid Build Coastguard Worker | Token.Extern -> 914*9880d681SAndroid Build Coastguard Worker let e = Parser.parse_extern stream in 915*9880d681SAndroid Build Coastguard Worker print_endline "parsed an extern."; 916*9880d681SAndroid Build Coastguard Worker dump_value (Codegen.codegen_proto e); 917*9880d681SAndroid Build Coastguard Worker | _ -> 918*9880d681SAndroid Build Coastguard Worker (* Evaluate a top-level expression into an anonymous function. *) 919*9880d681SAndroid Build Coastguard Worker let e = Parser.parse_toplevel stream in 920*9880d681SAndroid Build Coastguard Worker print_endline "parsed a top-level expr"; 921*9880d681SAndroid Build Coastguard Worker dump_value (Codegen.codegen_func e); 922*9880d681SAndroid Build Coastguard Worker with Stream.Error s | Codegen.Error s -> 923*9880d681SAndroid Build Coastguard Worker (* Skip token for error recovery. *) 924*9880d681SAndroid Build Coastguard Worker Stream.junk stream; 925*9880d681SAndroid Build Coastguard Worker print_endline s; 926*9880d681SAndroid Build Coastguard Worker end; 927*9880d681SAndroid Build Coastguard Worker print_string "ready> "; flush stdout; 928*9880d681SAndroid Build Coastguard Worker main_loop stream 929*9880d681SAndroid Build Coastguard Worker 930*9880d681SAndroid Build Coastguard Workertoy.ml: 931*9880d681SAndroid Build Coastguard Worker .. code-block:: ocaml 932*9880d681SAndroid Build Coastguard Worker 933*9880d681SAndroid Build Coastguard Worker (*===----------------------------------------------------------------------=== 934*9880d681SAndroid Build Coastguard Worker * Main driver code. 935*9880d681SAndroid Build Coastguard Worker *===----------------------------------------------------------------------===*) 936*9880d681SAndroid Build Coastguard Worker 937*9880d681SAndroid Build Coastguard Worker open Llvm 938*9880d681SAndroid Build Coastguard Worker 939*9880d681SAndroid Build Coastguard Worker let main () = 940*9880d681SAndroid Build Coastguard Worker (* Install standard binary operators. 941*9880d681SAndroid Build Coastguard Worker * 1 is the lowest precedence. *) 942*9880d681SAndroid Build Coastguard Worker Hashtbl.add Parser.binop_precedence '<' 10; 943*9880d681SAndroid Build Coastguard Worker Hashtbl.add Parser.binop_precedence '+' 20; 944*9880d681SAndroid Build Coastguard Worker Hashtbl.add Parser.binop_precedence '-' 20; 945*9880d681SAndroid Build Coastguard Worker Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) 946*9880d681SAndroid Build Coastguard Worker 947*9880d681SAndroid Build Coastguard Worker (* Prime the first token. *) 948*9880d681SAndroid Build Coastguard Worker print_string "ready> "; flush stdout; 949*9880d681SAndroid Build Coastguard Worker let stream = Lexer.lex (Stream.of_channel stdin) in 950*9880d681SAndroid Build Coastguard Worker 951*9880d681SAndroid Build Coastguard Worker (* Run the main "interpreter loop" now. *) 952*9880d681SAndroid Build Coastguard Worker Toplevel.main_loop stream; 953*9880d681SAndroid Build Coastguard Worker 954*9880d681SAndroid Build Coastguard Worker (* Print out all the generated code. *) 955*9880d681SAndroid Build Coastguard Worker dump_module Codegen.the_module 956*9880d681SAndroid Build Coastguard Worker ;; 957*9880d681SAndroid Build Coastguard Worker 958*9880d681SAndroid Build Coastguard Worker main () 959*9880d681SAndroid Build Coastguard Worker 960*9880d681SAndroid Build Coastguard Worker`Next: Adding JIT and Optimizer Support <OCamlLangImpl4.html>`_ 961*9880d681SAndroid Build Coastguard Worker 962