<div dir="ltr"><span style="font-size:13px">+ if (V == 0) {</span><br style="font-size:13px"><span style="font-size:13px">+ char ErrStr[256];</span><br style="font-size:13px"><span style="font-size:13px">+ sprintf(ErrStr, "Unknown variable name %s", Name.c_str());</span><br style="font-size:13px"><span style="font-size:13px">+ return ErrorP<Value>(ErrStr);</span><br style="font-size:13px"><span style="font-size:13px">+ }</span><br><div><span style="font-size:13px"><br></span></div><div><span style="font-size:13px">Buffer overflow?</span></div><div><span style="font-size:13px"><br></span></div><div><span style="font-size:13px">-- Sean Silva</span></div><div><span style="font-size:13px"><br></span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Feb 6, 2015 at 2:52 PM, Lang Hames <span dir="ltr"><<a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: lhames<br>
Date: Fri Feb 6 16:52:04 2015<br>
New Revision: 228456<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=228456&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=228456&view=rev</a><br>
Log:<br>
[Orc] Add a Kaleidoscope tutorial for Orc demonstrating eager compilation.<br>
<br>
This tutorial demonstrates a very basic custom Orc JIT stack that performs eager<br>
compilation: All modules are CodeGen'd immediately upon being added to the JIT.<br>
<br>
<br>
Added:<br>
llvm/trunk/examples/Kaleidoscope/Orc/<br>
llvm/trunk/examples/Kaleidoscope/Orc/initial/<br>
llvm/trunk/examples/Kaleidoscope/Orc/initial/Makefile<br>
llvm/trunk/examples/Kaleidoscope/Orc/initial/README.txt<br>
llvm/trunk/examples/Kaleidoscope/Orc/initial/toy.cpp<br>
<br>
Added: llvm/trunk/examples/Kaleidoscope/Orc/initial/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Orc/initial/Makefile?rev=228456&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Orc/initial/Makefile?rev=228456&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/examples/Kaleidoscope/Orc/initial/Makefile (added)<br>
+++ llvm/trunk/examples/Kaleidoscope/Orc/initial/Makefile Fri Feb 6 16:52:04 2015<br>
@@ -0,0 +1,9 @@<br>
+.PHONY: all<br>
+all: toy<br>
+<br>
+toy: toy.cpp<br>
+ clang++ -std=c++11 toy.cpp -g -O0 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --system-libs --libs core orcjit native` -o toy<br>
+<br>
+.PHONY: clean<br>
+clean:<br>
+ rm -f toy<br>
<br>
Added: llvm/trunk/examples/Kaleidoscope/Orc/initial/README.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Orc/initial/README.txt?rev=228456&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Orc/initial/README.txt?rev=228456&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/examples/Kaleidoscope/Orc/initial/README.txt (added)<br>
+++ llvm/trunk/examples/Kaleidoscope/Orc/initial/README.txt Fri Feb 6 16:52:04 2015<br>
@@ -0,0 +1,13 @@<br>
+//===----------------------------------------------------------------------===/<br>
+// Kaleidoscope with Orc - Initial Version<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+This version of Kaleidoscope with Orc demonstrates fully eager compilation. When<br>
+a function definition or top-level expression is entered it is immediately<br>
+translated (IRGen'd) to LLVM IR and added to the JIT, where it is code-gen'd to<br>
+native code and either stored (for function definitions) or executed (for<br>
+top-level expressions).<br>
+<br>
+This directory contain a Makefile that allow the code to be built in a<br>
+standalone manner, independent of the larger LLVM build infrastructure. To build<br>
+the program you will need to have 'clang++' and 'llvm-config' in your path.<br>
<br>
Added: llvm/trunk/examples/Kaleidoscope/Orc/initial/toy.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Orc/initial/toy.cpp?rev=228456&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/Orc/initial/toy.cpp?rev=228456&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/examples/Kaleidoscope/Orc/initial/toy.cpp (added)<br>
+++ llvm/trunk/examples/Kaleidoscope/Orc/initial/toy.cpp Fri Feb 6 16:52:04 2015<br>
@@ -0,0 +1,1319 @@<br>
+#include "llvm/Analysis/Passes.h"<br>
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"<br>
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"<br>
+#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"<br>
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"<br>
+#include "llvm/IR/DataLayout.h"<br>
+#include "llvm/IR/DerivedTypes.h"<br>
+#include "llvm/IR/IRBuilder.h"<br>
+#include "llvm/IR/LLVMContext.h"<br>
+#include "llvm/IR/Module.h"<br>
+#include "llvm/IR/Verifier.h"<br>
+#include "llvm/PassManager.h"<br>
+#include "llvm/Support/TargetSelect.h"<br>
+#include "llvm/Transforms/Scalar.h"<br>
+#include <cctype><br>
+#include <cstdio><br>
+#include <map><br>
+#include <string><br>
+#include <vector><br>
+using namespace llvm;<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Lexer<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one<br>
+// of these for known things.<br>
+enum Token {<br>
+ tok_eof = -1,<br>
+<br>
+ // commands<br>
+ tok_def = -2, tok_extern = -3,<br>
+<br>
+ // primary<br>
+ tok_identifier = -4, tok_number = -5,<br>
+<br>
+ // control<br>
+ tok_if = -6, tok_then = -7, tok_else = -8,<br>
+ tok_for = -9, tok_in = -10,<br>
+<br>
+ // operators<br>
+ tok_binary = -11, tok_unary = -12,<br>
+<br>
+ // var definition<br>
+ tok_var = -13<br>
+};<br>
+<br>
+static std::string IdentifierStr; // Filled in if tok_identifier<br>
+static double NumVal; // Filled in if tok_number<br>
+<br>
+/// gettok - Return the next token from standard input.<br>
+static int gettok() {<br>
+ static int LastChar = ' ';<br>
+<br>
+ // Skip any whitespace.<br>
+ while (isspace(LastChar))<br>
+ LastChar = getchar();<br>
+<br>
+ if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*<br>
+ IdentifierStr = LastChar;<br>
+ while (isalnum((LastChar = getchar())))<br>
+ IdentifierStr += LastChar;<br>
+<br>
+ if (IdentifierStr == "def") return tok_def;<br>
+ if (IdentifierStr == "extern") return tok_extern;<br>
+ if (IdentifierStr == "if") return tok_if;<br>
+ if (IdentifierStr == "then") return tok_then;<br>
+ if (IdentifierStr == "else") return tok_else;<br>
+ if (IdentifierStr == "for") return tok_for;<br>
+ if (IdentifierStr == "in") return tok_in;<br>
+ if (IdentifierStr == "binary") return tok_binary;<br>
+ if (IdentifierStr == "unary") return tok_unary;<br>
+ if (IdentifierStr == "var") return tok_var;<br>
+ return tok_identifier;<br>
+ }<br>
+<br>
+ if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+<br>
+ std::string NumStr;<br>
+ do {<br>
+ NumStr += LastChar;<br>
+ LastChar = getchar();<br>
+ } while (isdigit(LastChar) || LastChar == '.');<br>
+<br>
+ NumVal = strtod(NumStr.c_str(), 0);<br>
+ return tok_number;<br>
+ }<br>
+<br>
+ if (LastChar == '#') {<br>
+ // Comment until end of line.<br>
+ do LastChar = getchar();<br>
+ while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');<br>
+<br>
+ if (LastChar != EOF)<br>
+ return gettok();<br>
+ }<br>
+<br>
+ // Check for end of file. Don't eat the EOF.<br>
+ if (LastChar == EOF)<br>
+ return tok_eof;<br>
+<br>
+ // Otherwise, just return the character as its ascii value.<br>
+ int ThisChar = LastChar;<br>
+ LastChar = getchar();<br>
+ return ThisChar;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Abstract Syntax Tree (aka Parse Tree)<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+class IRGenContext;<br>
+<br>
+/// ExprAST - Base class for all expression nodes.<br>
+struct ExprAST {<br>
+ virtual ~ExprAST() {}<br>
+ virtual Value* IRGen(IRGenContext &C) = 0;<br>
+};<br>
+<br>
+/// NumberExprAST - Expression class for numeric literals like "1.0".<br>
+struct NumberExprAST : public ExprAST {<br>
+ NumberExprAST(double Val) : Val(Val) {}<br>
+ Value* IRGen(IRGenContext &C) override;<br>
+<br>
+ double Val;<br>
+};<br>
+<br>
+/// VariableExprAST - Expression class for referencing a variable, like "a".<br>
+struct VariableExprAST : public ExprAST {<br>
+ VariableExprAST(std::string Name) : Name(std::move(Name)) {}<br>
+ Value* IRGen(IRGenContext &C) override;<br>
+<br>
+ std::string Name;<br>
+};<br>
+<br>
+/// UnaryExprAST - Expression class for a unary operator.<br>
+struct UnaryExprAST : public ExprAST {<br>
+ UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand)<br>
+ : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {}<br>
+<br>
+ Value* IRGen(IRGenContext &C) override;<br>
+<br>
+ char Opcode;<br>
+ std::unique_ptr<ExprAST> Operand;<br>
+};<br>
+<br>
+/// BinaryExprAST - Expression class for a binary operator.<br>
+struct BinaryExprAST : public ExprAST {<br>
+ BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,<br>
+ std::unique_ptr<ExprAST> RHS)<br>
+ : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}<br>
+<br>
+ Value* IRGen(IRGenContext &C) override;<br>
+<br>
+ char Op;<br>
+ std::unique_ptr<ExprAST> LHS, RHS;<br>
+};<br>
+<br>
+/// CallExprAST - Expression class for function calls.<br>
+struct CallExprAST : public ExprAST {<br>
+ CallExprAST(std::string CalleeName,<br>
+ std::vector<std::unique_ptr<ExprAST>> Args)<br>
+ : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {}<br>
+<br>
+ Value* IRGen(IRGenContext &C) override;<br>
+<br>
+ std::string CalleeName;<br>
+ std::vector<std::unique_ptr<ExprAST>> Args;<br>
+};<br>
+<br>
+/// IfExprAST - Expression class for if/then/else.<br>
+struct IfExprAST : public ExprAST {<br>
+ IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then,<br>
+ std::unique_ptr<ExprAST> Else)<br>
+ : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {}<br>
+ Value* IRGen(IRGenContext &C) override;<br>
+<br>
+ std::unique_ptr<ExprAST> Cond, Then, Else;<br>
+};<br>
+<br>
+/// ForExprAST - Expression class for for/in.<br>
+struct ForExprAST : public ExprAST {<br>
+ ForExprAST(std::string VarName, std::unique_ptr<ExprAST> Start,<br>
+ std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step,<br>
+ std::unique_ptr<ExprAST> Body)<br>
+ : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)),<br>
+ Step(std::move(Step)), Body(std::move(Body)) {}<br>
+<br>
+ Value* IRGen(IRGenContext &C) override;<br>
+<br>
+ std::string VarName;<br>
+ std::unique_ptr<ExprAST> Start, End, Step, Body;<br>
+};<br>
+<br>
+/// VarExprAST - Expression class for var/in<br>
+struct VarExprAST : public ExprAST {<br>
+ typedef std::pair<std::string, std::unique_ptr<ExprAST>> Binding;<br>
+ typedef std::vector<Binding> BindingList;<br>
+<br>
+ VarExprAST(BindingList VarBindings, std::unique_ptr<ExprAST> Body)<br>
+ : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {}<br>
+<br>
+ Value* IRGen(IRGenContext &C) override;<br>
+<br>
+ BindingList VarBindings;<br>
+ std::unique_ptr<ExprAST> Body;<br>
+};<br>
+<br>
+/// PrototypeAST - This class represents the "prototype" for a function,<br>
+/// which captures its argument names as well as if it is an operator.<br>
+struct PrototypeAST {<br>
+ PrototypeAST(std::string Name, std::vector<std::string> Args,<br>
+ bool IsOperator = false, unsigned Precedence = 0)<br>
+ : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator),<br>
+ Precedence(Precedence) {}<br>
+<br>
+ Function* IRGen(IRGenContext &C);<br>
+ void CreateArgumentAllocas(Function *F, IRGenContext &C);<br>
+<br>
+ bool isUnaryOp() const { return IsOperator && Args.size() == 1; }<br>
+ bool isBinaryOp() const { return IsOperator && Args.size() == 2; }<br>
+<br>
+ char getOperatorName() const {<br>
+ assert(isUnaryOp() || isBinaryOp());<br>
+ return Name[Name.size()-1];<br>
+ }<br>
+<br>
+ std::string Name;<br>
+ std::vector<std::string> Args;<br>
+ bool IsOperator;<br>
+ unsigned Precedence; // Precedence if a binary op.<br>
+};<br>
+<br>
+/// FunctionAST - This class represents a function definition itself.<br>
+struct FunctionAST {<br>
+ FunctionAST(std::unique_ptr<PrototypeAST> Proto,<br>
+ std::unique_ptr<ExprAST> Body)<br>
+ : Proto(std::move(Proto)), Body(std::move(Body)) {}<br>
+<br>
+ Function* IRGen(IRGenContext &C);<br>
+<br>
+ std::unique_ptr<PrototypeAST> Proto;<br>
+ std::unique_ptr<ExprAST> Body;<br>
+};<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Parser<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current<br>
+/// token the parser is looking at. getNextToken reads another token from the<br>
+/// lexer and updates CurTok with its results.<br>
+static int CurTok;<br>
+static int getNextToken() {<br>
+ return CurTok = gettok();<br>
+}<br>
+<br>
+/// BinopPrecedence - This holds the precedence for each binary operator that is<br>
+/// defined.<br>
+static std::map<char, int> BinopPrecedence;<br>
+<br>
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.<br>
+static int GetTokPrecedence() {<br>
+ if (!isascii(CurTok))<br>
+ return -1;<br>
+<br>
+ // Make sure it's a declared binop.<br>
+ int TokPrec = BinopPrecedence[CurTok];<br>
+ if (TokPrec <= 0) return -1;<br>
+ return TokPrec;<br>
+}<br>
+<br>
+template <typename T><br>
+std::unique_ptr<T> ErrorU(const char *Str) {<br>
+ fprintf(stderr, "Error: %s\n", Str);<br>
+ return nullptr;<br>
+}<br>
+<br>
+template <typename T><br>
+T* ErrorP(const char *Str) {<br>
+ fprintf(stderr, "Error: %s\n", Str);<br>
+ return nullptr;<br>
+}<br>
+<br>
+static std::unique_ptr<ExprAST> ParseExpression();<br>
+<br>
+/// identifierexpr<br>
+/// ::= identifier<br>
+/// ::= identifier '(' expression* ')'<br>
+static std::unique_ptr<ExprAST> ParseIdentifierExpr() {<br>
+ std::string IdName = IdentifierStr;<br>
+<br>
+ getNextToken(); // eat identifier.<br>
+<br>
+ if (CurTok != '(') // Simple variable ref.<br>
+ return llvm::make_unique<VariableExprAST>(IdName);<br>
+<br>
+ // Call.<br>
+ getNextToken(); // eat (<br>
+ std::vector<std::unique_ptr<ExprAST>> Args;<br>
+ if (CurTok != ')') {<br>
+ while (1) {<br>
+ auto Arg = ParseExpression();<br>
+ if (!Arg) return nullptr;<br>
+ Args.push_back(std::move(Arg));<br>
+<br>
+ if (CurTok == ')') break;<br>
+<br>
+ if (CurTok != ',')<br>
+ return ErrorU<CallExprAST>("Expected ')' or ',' in argument list");<br>
+ getNextToken();<br>
+ }<br>
+ }<br>
+<br>
+ // Eat the ')'.<br>
+ getNextToken();<br>
+<br>
+ return llvm::make_unique<CallExprAST>(IdName, std::move(Args));<br>
+}<br>
+<br>
+/// numberexpr ::= number<br>
+static std::unique_ptr<NumberExprAST> ParseNumberExpr() {<br>
+ auto Result = llvm::make_unique<NumberExprAST>(NumVal);<br>
+ getNextToken(); // consume the number<br>
+ return Result;<br>
+}<br>
+<br>
+/// parenexpr ::= '(' expression ')'<br>
+static std::unique_ptr<ExprAST> ParseParenExpr() {<br>
+ getNextToken(); // eat (.<br>
+ auto V = ParseExpression();<br>
+ if (!V)<br>
+ return nullptr;<br>
+<br>
+ if (CurTok != ')')<br>
+ return ErrorU<ExprAST>("expected ')'");<br>
+ getNextToken(); // eat ).<br>
+ return V;<br>
+}<br>
+<br>
+/// ifexpr ::= 'if' expression 'then' expression 'else' expression<br>
+static std::unique_ptr<ExprAST> ParseIfExpr() {<br>
+ getNextToken(); // eat the if.<br>
+<br>
+ // condition.<br>
+ auto Cond = ParseExpression();<br>
+ if (!Cond)<br>
+ return nullptr;<br>
+<br>
+ if (CurTok != tok_then)<br>
+ return ErrorU<ExprAST>("expected then");<br>
+ getNextToken(); // eat the then<br>
+<br>
+ auto Then = ParseExpression();<br>
+ if (!Then)<br>
+ return nullptr;<br>
+<br>
+ if (CurTok != tok_else)<br>
+ return ErrorU<ExprAST>("expected else");<br>
+<br>
+ getNextToken();<br>
+<br>
+ auto Else = ParseExpression();<br>
+ if (!Else)<br>
+ return nullptr;<br>
+<br>
+ return llvm::make_unique<IfExprAST>(std::move(Cond), std::move(Then),<br>
+ std::move(Else));<br>
+}<br>
+<br>
+/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression<br>
+static std::unique_ptr<ForExprAST> ParseForExpr() {<br>
+ getNextToken(); // eat the for.<br>
+<br>
+ if (CurTok != tok_identifier)<br>
+ return ErrorU<ForExprAST>("expected identifier after for");<br>
+<br>
+ std::string IdName = IdentifierStr;<br>
+ getNextToken(); // eat identifier.<br>
+<br>
+ if (CurTok != '=')<br>
+ return ErrorU<ForExprAST>("expected '=' after for");<br>
+ getNextToken(); // eat '='.<br>
+<br>
+<br>
+ auto Start = ParseExpression();<br>
+ if (!Start)<br>
+ return nullptr;<br>
+ if (CurTok != ',')<br>
+ return ErrorU<ForExprAST>("expected ',' after for start value");<br>
+ getNextToken();<br>
+<br>
+ auto End = ParseExpression();<br>
+ if (!End)<br>
+ return nullptr;<br>
+<br>
+ // The step value is optional.<br>
+ std::unique_ptr<ExprAST> Step;<br>
+ if (CurTok == ',') {<br>
+ getNextToken();<br>
+ Step = ParseExpression();<br>
+ if (!Step)<br>
+ return nullptr;<br>
+ }<br>
+<br>
+ if (CurTok != tok_in)<br>
+ return ErrorU<ForExprAST>("expected 'in' after for");<br>
+ getNextToken(); // eat 'in'.<br>
+<br>
+ auto Body = ParseExpression();<br>
+ if (Body)<br>
+ return nullptr;<br>
+<br>
+ return llvm::make_unique<ForExprAST>(IdName, std::move(Start), std::move(End),<br>
+ std::move(Step), std::move(Body));<br>
+}<br>
+<br>
+/// varexpr ::= 'var' identifier ('=' expression)?<br>
+// (',' identifier ('=' expression)?)* 'in' expression<br>
+static std::unique_ptr<VarExprAST> ParseVarExpr() {<br>
+ getNextToken(); // eat the var.<br>
+<br>
+ VarExprAST::BindingList VarBindings;<br>
+<br>
+ // At least one variable name is required.<br>
+ if (CurTok != tok_identifier)<br>
+ return ErrorU<VarExprAST>("expected identifier after var");<br>
+<br>
+ while (1) {<br>
+ std::string Name = IdentifierStr;<br>
+ getNextToken(); // eat identifier.<br>
+<br>
+ // Read the optional initializer.<br>
+ std::unique_ptr<ExprAST> Init;<br>
+ if (CurTok == '=') {<br>
+ getNextToken(); // eat the '='.<br>
+<br>
+ Init = ParseExpression();<br>
+ if (!Init)<br>
+ return nullptr;<br>
+ }<br>
+<br>
+ VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init)));<br>
+<br>
+ // End of var list, exit loop.<br>
+ if (CurTok != ',') break;<br>
+ getNextToken(); // eat the ','.<br>
+<br>
+ if (CurTok != tok_identifier)<br>
+ return ErrorU<VarExprAST>("expected identifier list after var");<br>
+ }<br>
+<br>
+ // At this point, we have to have 'in'.<br>
+ if (CurTok != tok_in)<br>
+ return ErrorU<VarExprAST>("expected 'in' keyword after 'var'");<br>
+ getNextToken(); // eat 'in'.<br>
+<br>
+ auto Body = ParseExpression();<br>
+ if (!Body)<br>
+ return nullptr;<br>
+<br>
+ return llvm::make_unique<VarExprAST>(std::move(VarBindings), std::move(Body));<br>
+}<br>
+<br>
+/// primary<br>
+/// ::= identifierexpr<br>
+/// ::= numberexpr<br>
+/// ::= parenexpr<br>
+/// ::= ifexpr<br>
+/// ::= forexpr<br>
+/// ::= varexpr<br>
+static std::unique_ptr<ExprAST> ParsePrimary() {<br>
+ switch (CurTok) {<br>
+ default: return ErrorU<ExprAST>("unknown token when expecting an expression");<br>
+ case tok_identifier: return ParseIdentifierExpr();<br>
+ case tok_number: return ParseNumberExpr();<br>
+ case '(': return ParseParenExpr();<br>
+ case tok_if: return ParseIfExpr();<br>
+ case tok_for: return ParseForExpr();<br>
+ case tok_var: return ParseVarExpr();<br>
+ }<br>
+}<br>
+<br>
+/// unary<br>
+/// ::= primary<br>
+/// ::= '!' unary<br>
+static std::unique_ptr<ExprAST> ParseUnary() {<br>
+ // If the current token is not an operator, it must be a primary expr.<br>
+ if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')<br>
+ return ParsePrimary();<br>
+<br>
+ // If this is a unary operator, read it.<br>
+ int Opc = CurTok;<br>
+ getNextToken();<br>
+ if (auto Operand = ParseUnary())<br>
+ return llvm::make_unique<UnaryExprAST>(Opc, std::move(Operand));<br>
+ return nullptr;<br>
+}<br>
+<br>
+/// binoprhs<br>
+/// ::= ('+' unary)*<br>
+static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,<br>
+ std::unique_ptr<ExprAST> LHS) {<br>
+ // If this is a binop, find its precedence.<br>
+ while (1) {<br>
+ int TokPrec = GetTokPrecedence();<br>
+<br>
+ // If this is a binop that binds at least as tightly as the current binop,<br>
+ // consume it, otherwise we are done.<br>
+ if (TokPrec < ExprPrec)<br>
+ return LHS;<br>
+<br>
+ // Okay, we know this is a binop.<br>
+ int BinOp = CurTok;<br>
+ getNextToken(); // eat binop<br>
+<br>
+ // Parse the unary expression after the binary operator.<br>
+ auto RHS = ParseUnary();<br>
+ if (!RHS)<br>
+ return nullptr;<br>
+<br>
+ // If BinOp binds less tightly with RHS than the operator after RHS, let<br>
+ // the pending operator take RHS as its LHS.<br>
+ int NextPrec = GetTokPrecedence();<br>
+ if (TokPrec < NextPrec) {<br>
+ RHS = ParseBinOpRHS(TokPrec+1, std::move(RHS));<br>
+ if (!RHS)<br>
+ return nullptr;<br>
+ }<br>
+<br>
+ // Merge LHS/RHS.<br>
+ LHS = llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS));<br>
+ }<br>
+}<br>
+<br>
+/// expression<br>
+/// ::= unary binoprhs<br>
+///<br>
+static std::unique_ptr<ExprAST> ParseExpression() {<br>
+ auto LHS = ParseUnary();<br>
+ if (!LHS)<br>
+ return nullptr;<br>
+<br>
+ return ParseBinOpRHS(0, std::move(LHS));<br>
+}<br>
+<br>
+/// prototype<br>
+/// ::= id '(' id* ')'<br>
+/// ::= binary LETTER number? (id, id)<br>
+/// ::= unary LETTER (id)<br>
+static std::unique_ptr<PrototypeAST> ParsePrototype() {<br>
+ std::string FnName;<br>
+<br>
+ unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.<br>
+ unsigned BinaryPrecedence = 30;<br>
+<br>
+ switch (CurTok) {<br>
+ default:<br>
+ return ErrorU<PrototypeAST>("Expected function name in prototype");<br>
+ case tok_identifier:<br>
+ FnName = IdentifierStr;<br>
+ Kind = 0;<br>
+ getNextToken();<br>
+ break;<br>
+ case tok_unary:<br>
+ getNextToken();<br>
+ if (!isascii(CurTok))<br>
+ return ErrorU<PrototypeAST>("Expected unary operator");<br>
+ FnName = "unary";<br>
+ FnName += (char)CurTok;<br>
+ Kind = 1;<br>
+ getNextToken();<br>
+ break;<br>
+ case tok_binary:<br>
+ getNextToken();<br>
+ if (!isascii(CurTok))<br>
+ return ErrorU<PrototypeAST>("Expected binary operator");<br>
+ FnName = "binary";<br>
+ FnName += (char)CurTok;<br>
+ Kind = 2;<br>
+ getNextToken();<br>
+<br>
+ // Read the precedence if present.<br>
+ if (CurTok == tok_number) {<br>
+ if (NumVal < 1 || NumVal > 100)<br>
+ return ErrorU<PrototypeAST>("Invalid precedecnce: must be 1..100");<br>
+ BinaryPrecedence = (unsigned)NumVal;<br>
+ getNextToken();<br>
+ }<br>
+ break;<br>
+ }<br>
+<br>
+ if (CurTok != '(')<br>
+ return ErrorU<PrototypeAST>("Expected '(' in prototype");<br>
+<br>
+ std::vector<std::string> ArgNames;<br>
+ while (getNextToken() == tok_identifier)<br>
+ ArgNames.push_back(IdentifierStr);<br>
+ if (CurTok != ')')<br>
+ return ErrorU<PrototypeAST>("Expected ')' in prototype");<br>
+<br>
+ // success.<br>
+ getNextToken(); // eat ')'.<br>
+<br>
+ // Verify right number of names for operator.<br>
+ if (Kind && ArgNames.size() != Kind)<br>
+ return ErrorU<PrototypeAST>("Invalid number of operands for operator");<br>
+<br>
+ return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames), Kind != 0,<br>
+ BinaryPrecedence);<br>
+}<br>
+<br>
+/// definition ::= 'def' prototype expression<br>
+static std::unique_ptr<FunctionAST> ParseDefinition() {<br>
+ getNextToken(); // eat def.<br>
+ auto Proto = ParsePrototype();<br>
+ if (!Proto)<br>
+ return nullptr;<br>
+<br>
+ if (auto Body = ParseExpression())<br>
+ return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(Body));<br>
+ return nullptr;<br>
+}<br>
+<br>
+/// toplevelexpr ::= expression<br>
+static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {<br>
+ if (auto E = ParseExpression()) {<br>
+ // Make an anonymous proto.<br>
+ auto Proto =<br>
+ llvm::make_unique<PrototypeAST>("__anon_expr", std::vector<std::string>());<br>
+ return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));<br>
+ }<br>
+ return nullptr;<br>
+}<br>
+<br>
+/// external ::= 'extern' prototype<br>
+static std::unique_ptr<PrototypeAST> ParseExtern() {<br>
+ getNextToken(); // eat extern.<br>
+ return ParsePrototype();<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Code Generation<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+// FIXME: Obviously we can do better than this<br>
+std::string GenerateUniqueName(const char *root)<br>
+{<br>
+ static int i = 0;<br>
+ char s[16];<br>
+ sprintf(s, "%s%d", root, i++);<br>
+ std::string S = s;<br>
+ return S;<br>
+}<br>
+<br>
+std::string MakeLegalFunctionName(std::string Name)<br>
+{<br>
+ std::string NewName;<br>
+ assert(!Name.empty() && "Base name must not be empty");<br>
+<br>
+ // Start with what we have<br>
+ NewName = Name;<br>
+<br>
+ // Look for a numberic first character<br>
+ if (NewName.find_first_of("0123456789") == 0) {<br>
+ NewName.insert(0, 1, 'n');<br>
+ }<br>
+<br>
+ // Replace illegal characters with their ASCII equivalent<br>
+ std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";<br>
+ size_t pos;<br>
+ while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) {<br>
+ char old_c = NewName.at(pos);<br>
+ char new_str[16];<br>
+ sprintf(new_str, "%d", (int)old_c);<br>
+ NewName = NewName.replace(pos, 1, new_str);<br>
+ }<br>
+<br>
+ return NewName;<br>
+}<br>
+<br>
+class SessionContext {<br>
+public:<br>
+ SessionContext(LLVMContext &C) : Context(C) {}<br>
+ LLVMContext& getLLVMContext() const { return Context; }<br>
+ void addPrototypeAST(std::unique_ptr<PrototypeAST> P);<br>
+ PrototypeAST* getPrototypeAST(const std::string &Name);<br>
+private:<br>
+ typedef std::map<std::string, std::unique_ptr<PrototypeAST>> PrototypeMap;<br>
+ LLVMContext &Context;<br>
+ PrototypeMap Prototypes;<br>
+};<br>
+<br>
+void SessionContext::addPrototypeAST(std::unique_ptr<PrototypeAST> P) {<br>
+ Prototypes[P->Name] = std::move(P);<br>
+}<br>
+<br>
+PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) {<br>
+ PrototypeMap::iterator I = Prototypes.find(Name);<br>
+ if (I != Prototypes.end())<br>
+ return I->second.get();<br>
+ return nullptr;<br>
+}<br>
+<br>
+class IRGenContext {<br>
+public:<br>
+<br>
+ IRGenContext(SessionContext &S)<br>
+ : Session(S),<br>
+ M(new Module(GenerateUniqueName("jit_module_"),<br>
+ Session.getLLVMContext())),<br>
+ Builder(Session.getLLVMContext()) {}<br>
+<br>
+ SessionContext& getSession() { return Session; }<br>
+ Module& getM() const { return *M; }<br>
+ std::unique_ptr<Module> takeM() { return std::move(M); }<br>
+ IRBuilder<>& getBuilder() { return Builder; }<br>
+ LLVMContext& getLLVMContext() { return Session.getLLVMContext(); }<br>
+ Function* getPrototype(const std::string &Name);<br>
+<br>
+ std::map<std::string, AllocaInst*> NamedValues;<br>
+private:<br>
+ SessionContext &Session;<br>
+ std::unique_ptr<Module> M;<br>
+ IRBuilder<> Builder;<br>
+};<br>
+<br>
+Function* IRGenContext::getPrototype(const std::string &Name) {<br>
+ if (Function *ExistingProto = M->getFunction(Name))<br>
+ return ExistingProto;<br>
+ if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name))<br>
+ return ProtoAST->IRGen(*this);<br>
+ return nullptr;<br>
+}<br>
+<br>
+/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of<br>
+/// the function. This is used for mutable variables etc.<br>
+static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,<br>
+ const std::string &VarName) {<br>
+ IRBuilder<> TmpB(&TheFunction->getEntryBlock(),<br>
+ TheFunction->getEntryBlock().begin());<br>
+ return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0,<br>
+ VarName.c_str());<br>
+}<br>
+<br>
+Value *NumberExprAST::IRGen(IRGenContext &C) {<br>
+ return ConstantFP::get(C.getLLVMContext(), APFloat(Val));<br>
+}<br>
+<br>
+Value *VariableExprAST::IRGen(IRGenContext &C) {<br>
+ // Look this variable up in the function.<br>
+ Value *V = C.NamedValues[Name];<br>
+<br>
+ if (V == 0) {<br>
+ char ErrStr[256];<br>
+ sprintf(ErrStr, "Unknown variable name %s", Name.c_str());<br>
+ return ErrorP<Value>(ErrStr);<br>
+ }<br>
+<br>
+ // Load the value.<br>
+ return C.getBuilder().CreateLoad(V, Name.c_str());<br>
+}<br>
+<br>
+Value *UnaryExprAST::IRGen(IRGenContext &C) {<br>
+ if (Value *OperandV = Operand->IRGen(C)) {<br>
+ std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode);<br>
+ if (Function *F = C.getPrototype(FnName))<br>
+ return C.getBuilder().CreateCall(F, OperandV, "unop");<br>
+ return ErrorP<Value>("Unknown unary operator");<br>
+ }<br>
+<br>
+ // Could not codegen operand - return null.<br>
+ return nullptr;<br>
+}<br>
+<br>
+Value *BinaryExprAST::IRGen(IRGenContext &C) {<br>
+ // Special case '=' because we don't want to emit the LHS as an expression.<br>
+ if (Op == '=') {<br>
+ // Assignment requires the LHS to be an identifier.<br>
+ auto LHSVar = static_cast<VariableExprAST&>(*LHS);<br>
+ // Codegen the RHS.<br>
+ Value *Val = RHS->IRGen(C);<br>
+ if (!Val) return nullptr;<br>
+<br>
+ // Look up the name.<br>
+ if (auto Variable = C.NamedValues[LHSVar.Name]) {<br>
+ C.getBuilder().CreateStore(Val, Variable);<br>
+ return Val;<br>
+ }<br>
+ return ErrorP<Value>("Unknown variable name");<br>
+ }<br>
+<br>
+ Value *L = LHS->IRGen(C);<br>
+ Value *R = RHS->IRGen(C);<br>
+ if (!L || !R) return nullptr;<br>
+<br>
+ switch (Op) {<br>
+ case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp");<br>
+ case '-': return C.getBuilder().CreateFSub(L, R, "subtmp");<br>
+ case '*': return C.getBuilder().CreateFMul(L, R, "multmp");<br>
+ case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp");<br>
+ case '<':<br>
+ L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp");<br>
+ // Convert bool 0/1 to double 0.0 or 1.0<br>
+ return C.getBuilder().CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),<br>
+ "booltmp");<br>
+ default: break;<br>
+ }<br>
+<br>
+ // If it wasn't a builtin binary operator, it must be a user defined one. Emit<br>
+ // a call to it.<br>
+ std::string FnName = MakeLegalFunctionName(std::string("binary")+Op);<br>
+ if (Function *F = C.getPrototype(FnName)) {<br>
+ Value *Ops[] = { L, R };<br>
+ return C.getBuilder().CreateCall(F, Ops, "binop");<br>
+ }<br>
+<br>
+ return ErrorP<Value>("Unknown binary operator");<br>
+}<br>
+<br>
+Value *CallExprAST::IRGen(IRGenContext &C) {<br>
+ // Look up the name in the global module table.<br>
+ if (auto CalleeF = C.getPrototype(CalleeName)) {<br>
+ // If argument mismatch error.<br>
+ if (CalleeF->arg_size() != Args.size())<br>
+ return ErrorP<Value>("Incorrect # arguments passed");<br>
+<br>
+ std::vector<Value*> ArgsV;<br>
+ for (unsigned i = 0, e = Args.size(); i != e; ++i) {<br>
+ ArgsV.push_back(Args[i]->IRGen(C));<br>
+ if (!ArgsV.back()) return nullptr;<br>
+ }<br>
+<br>
+ return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp");<br>
+ }<br>
+<br>
+ return ErrorP<Value>("Unknown function referenced");<br>
+}<br>
+<br>
+Value *IfExprAST::IRGen(IRGenContext &C) {<br>
+ Value *CondV = Cond->IRGen(C);<br>
+ if (!CondV) return nullptr;<br>
+<br>
+ // Convert condition to a bool by comparing equal to 0.0.<br>
+ ConstantFP *FPZero =<br>
+ ConstantFP::get(C.getLLVMContext(), APFloat(0.0));<br>
+ CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond");<br>
+<br>
+ Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent();<br>
+<br>
+ // Create blocks for the then and else cases. Insert the 'then' block at the<br>
+ // end of the function.<br>
+ BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction);<br>
+ BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else");<br>
+ BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont");<br>
+<br>
+ C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB);<br>
+<br>
+ // Emit then value.<br>
+ C.getBuilder().SetInsertPoint(ThenBB);<br>
+<br>
+ Value *ThenV = Then->IRGen(C);<br>
+ if (!ThenV) return nullptr;<br>
+<br>
+ C.getBuilder().CreateBr(MergeBB);<br>
+ // Codegen of 'Then' can change the current block, update ThenBB for the PHI.<br>
+ ThenBB = C.getBuilder().GetInsertBlock();<br>
+<br>
+ // Emit else block.<br>
+ TheFunction->getBasicBlockList().push_back(ElseBB);<br>
+ C.getBuilder().SetInsertPoint(ElseBB);<br>
+<br>
+ Value *ElseV = Else->IRGen(C);<br>
+ if (!ElseV) return nullptr;<br>
+<br>
+ C.getBuilder().CreateBr(MergeBB);<br>
+ // Codegen of 'Else' can change the current block, update ElseBB for the PHI.<br>
+ ElseBB = C.getBuilder().GetInsertBlock();<br>
+<br>
+ // Emit merge block.<br>
+ TheFunction->getBasicBlockList().push_back(MergeBB);<br>
+ C.getBuilder().SetInsertPoint(MergeBB);<br>
+ PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2,<br>
+ "iftmp");<br>
+<br>
+ PN->addIncoming(ThenV, ThenBB);<br>
+ PN->addIncoming(ElseV, ElseBB);<br>
+ return PN;<br>
+}<br>
+<br>
+Value *ForExprAST::IRGen(IRGenContext &C) {<br>
+ // Output this as:<br>
+ // var = alloca double<br>
+ // ...<br>
+ // start = startexpr<br>
+ // store start -> var<br>
+ // goto loop<br>
+ // loop:<br>
+ // ...<br>
+ // bodyexpr<br>
+ // ...<br>
+ // loopend:<br>
+ // step = stepexpr<br>
+ // endcond = endexpr<br>
+ //<br>
+ // curvar = load var<br>
+ // nextvar = curvar + step<br>
+ // store nextvar -> var<br>
+ // br endcond, loop, endloop<br>
+ // outloop:<br>
+<br>
+ Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent();<br>
+<br>
+ // Create an alloca for the variable in the entry block.<br>
+ AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);<br>
+<br>
+ // Emit the start code first, without 'variable' in scope.<br>
+ Value *StartVal = Start->IRGen(C);<br>
+ if (!StartVal) return nullptr;<br>
+<br>
+ // Store the value into the alloca.<br>
+ C.getBuilder().CreateStore(StartVal, Alloca);<br>
+<br>
+ // Make the new basic block for the loop header, inserting after current<br>
+ // block.<br>
+ BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);<br>
+<br>
+ // Insert an explicit fall through from the current block to the LoopBB.<br>
+ C.getBuilder().CreateBr(LoopBB);<br>
+<br>
+ // Start insertion in LoopBB.<br>
+ C.getBuilder().SetInsertPoint(LoopBB);<br>
+<br>
+ // Within the loop, the variable is defined equal to the PHI node. If it<br>
+ // shadows an existing variable, we have to restore it, so save it now.<br>
+ AllocaInst *OldVal = C.NamedValues[VarName];<br>
+ C.NamedValues[VarName] = Alloca;<br>
+<br>
+ // Emit the body of the loop. This, like any other expr, can change the<br>
+ // current BB. Note that we ignore the value computed by the body, but don't<br>
+ // allow an error.<br>
+ if (!Body->IRGen(C))<br>
+ return nullptr;<br>
+<br>
+ // Emit the step value.<br>
+ Value *StepVal;<br>
+ if (Step) {<br>
+ StepVal = Step->IRGen(C);<br>
+ if (!StepVal) return nullptr;<br>
+ } else {<br>
+ // If not specified, use 1.0.<br>
+ StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));<br>
+ }<br>
+<br>
+ // Compute the end condition.<br>
+ Value *EndCond = End->IRGen(C);<br>
+ if (EndCond == 0) return EndCond;<br>
+<br>
+ // Reload, increment, and restore the alloca. This handles the case where<br>
+ // the body of the loop mutates the variable.<br>
+ Value *CurVar = C.getBuilder().CreateLoad(Alloca, VarName.c_str());<br>
+ Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar");<br>
+ C.getBuilder().CreateStore(NextVar, Alloca);<br>
+<br>
+ // Convert condition to a bool by comparing equal to 0.0.<br>
+ EndCond = C.getBuilder().CreateFCmpONE(EndCond,<br>
+ ConstantFP::get(getGlobalContext(), APFloat(0.0)),<br>
+ "loopcond");<br>
+<br>
+ // Create the "after loop" block and insert it.<br>
+ BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);<br>
+<br>
+ // Insert the conditional branch into the end of LoopEndBB.<br>
+ C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB);<br>
+<br>
+ // Any new code will be inserted in AfterBB.<br>
+ C.getBuilder().SetInsertPoint(AfterBB);<br>
+<br>
+ // Restore the unshadowed variable.<br>
+ if (OldVal)<br>
+ C.NamedValues[VarName] = OldVal;<br>
+ else<br>
+ C.NamedValues.erase(VarName);<br>
+<br>
+<br>
+ // for expr always returns 0.0.<br>
+ return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));<br>
+}<br>
+<br>
+Value *VarExprAST::IRGen(IRGenContext &C) {<br>
+ std::vector<AllocaInst *> OldBindings;<br>
+<br>
+ Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent();<br>
+<br>
+ // Register all variables and emit their initializer.<br>
+ for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) {<br>
+ auto &VarName = VarBindings[i].first;<br>
+ auto &Init = VarBindings[i].second;<br>
+<br>
+ // Emit the initializer before adding the variable to scope, this prevents<br>
+ // the initializer from referencing the variable itself, and permits stuff<br>
+ // like this:<br>
+ // var a = 1 in<br>
+ // var a = a in ... # refers to outer 'a'.<br>
+ Value *InitVal;<br>
+ if (Init) {<br>
+ InitVal = Init->IRGen(C);<br>
+ if (!InitVal) return nullptr;<br>
+ } else // If not specified, use 0.0.<br>
+ InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0));<br>
+<br>
+ AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);<br>
+ C.getBuilder().CreateStore(InitVal, Alloca);<br>
+<br>
+ // Remember the old variable binding so that we can restore the binding when<br>
+ // we unrecurse.<br>
+ OldBindings.push_back(C.NamedValues[VarName]);<br>
+<br>
+ // Remember this binding.<br>
+ C.NamedValues[VarName] = Alloca;<br>
+ }<br>
+<br>
+ // Codegen the body, now that all vars are in scope.<br>
+ Value *BodyVal = Body->IRGen(C);<br>
+ if (!BodyVal) return nullptr;<br>
+<br>
+ // Pop all our variables from scope.<br>
+ for (unsigned i = 0, e = VarBindings.size(); i != e; ++i)<br>
+ C.NamedValues[VarBindings[i].first] = OldBindings[i];<br>
+<br>
+ // Return the body computation.<br>
+ return BodyVal;<br>
+}<br>
+<br>
+Function *PrototypeAST::IRGen(IRGenContext &C) {<br>
+ std::string FnName = MakeLegalFunctionName(Name);<br>
+<br>
+ // Make the function type: double(double,double) etc.<br>
+ std::vector<Type*> Doubles(Args.size(),<br>
+ Type::getDoubleTy(getGlobalContext()));<br>
+ FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),<br>
+ Doubles, false);<br>
+ Function *F = Function::Create(FT, Function::ExternalLinkage, FnName,<br>
+ &C.getM());<br>
+<br>
+ // If F conflicted, there was already something named 'FnName'. If it has a<br>
+ // body, don't allow redefinition or reextern.<br>
+ if (F->getName() != FnName) {<br>
+ // Delete the one we just made and get the existing one.<br>
+ F->eraseFromParent();<br>
+ F = C.getM().getFunction(Name);<br>
+<br>
+ // If F already has a body, reject this.<br>
+ if (!F->empty()) {<br>
+ ErrorP<Function>("redefinition of function");<br>
+ return nullptr;<br>
+ }<br>
+<br>
+ // If F took a different number of args, reject.<br>
+ if (F->arg_size() != Args.size()) {<br>
+ ErrorP<Function>("redefinition of function with different # args");<br>
+ return nullptr;<br>
+ }<br>
+ }<br>
+<br>
+ // Set names for all arguments.<br>
+ unsigned Idx = 0;<br>
+ for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();<br>
+ ++AI, ++Idx)<br>
+ AI->setName(Args[Idx]);<br>
+<br>
+ return F;<br>
+}<br>
+<br>
+/// CreateArgumentAllocas - Create an alloca for each argument and register the<br>
+/// argument in the symbol table so that references to it will succeed.<br>
+void PrototypeAST::CreateArgumentAllocas(Function *F, IRGenContext &C) {<br>
+ Function::arg_iterator AI = F->arg_begin();<br>
+ for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {<br>
+ // Create an alloca for this variable.<br>
+ AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);<br>
+<br>
+ // Store the initial value into the alloca.<br>
+ C.getBuilder().CreateStore(AI, Alloca);<br>
+<br>
+ // Add arguments to variable symbol table.<br>
+ C.NamedValues[Args[Idx]] = Alloca;<br>
+ }<br>
+}<br>
+<br>
+Function *FunctionAST::IRGen(IRGenContext &C) {<br>
+ C.NamedValues.clear();<br>
+<br>
+ Function *TheFunction = Proto->IRGen(C);<br>
+ if (!TheFunction)<br>
+ return nullptr;<br>
+<br>
+ // If this is an operator, install it.<br>
+ if (Proto->isBinaryOp())<br>
+ BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence;<br>
+<br>
+ // Create a new basic block to start insertion into.<br>
+ BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);<br>
+ C.getBuilder().SetInsertPoint(BB);<br>
+<br>
+ // Add all arguments to the symbol table and create their allocas.<br>
+ Proto->CreateArgumentAllocas(TheFunction, C);<br>
+<br>
+ if (Value *RetVal = Body->IRGen(C)) {<br>
+ // Finish off the function.<br>
+ C.getBuilder().CreateRet(RetVal);<br>
+<br>
+ // Validate the generated code, checking for consistency.<br>
+ verifyFunction(*TheFunction);<br>
+<br>
+ return TheFunction;<br>
+ }<br>
+<br>
+ // Error reading body, remove function.<br>
+ TheFunction->eraseFromParent();<br>
+<br>
+ if (Proto->isBinaryOp())<br>
+ BinopPrecedence.erase(Proto->getOperatorName());<br>
+ return nullptr;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Top-Level parsing and JIT Driver<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+class KaleidoscopeJIT {<br>
+public:<br>
+ typedef ObjectLinkingLayer<> ObjLayerT;<br>
+ typedef IRCompileLayer<ObjLayerT> CompileLayerT;<br>
+<br>
+ typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;<br>
+<br>
+ KaleidoscopeJIT()<br>
+ : TM(EngineBuilder().selectTarget()),<br>
+ Mang(TM->getDataLayout()),<br>
+ CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {}<br>
+<br>
+ ModuleHandleT addModule(std::unique_ptr<Module> M) {<br>
+ if (!M->getDataLayout())<br>
+ M->setDataLayout(TM->getDataLayout());<br>
+<br>
+ // The LazyEmitLayer takes lists of modules, rather than single modules, so<br>
+ // we'll just build a single-element list.<br>
+ std::vector<std::unique_ptr<Module>> S;<br>
+ S.push_back(std::move(M));<br>
+<br>
+ // We need a memory manager to allocate memory and resolve symbols for this<br>
+ // new module. Create one that resolves symbols by looking back into the JIT.<br>
+ auto MM = createLookasideRTDyldMM<SectionMemoryManager>(<br>
+ [&](const std::string &S) {<br>
+ return getUnmangledSymbolAddress(S);<br>
+ },<br>
+ [](const std::string &S) { return 0; } );<br>
+<br>
+ return CompileLayer.addModuleSet(std::move(S), std::move(MM));<br>
+ }<br>
+<br>
+ void removeModule(ModuleHandleT H) { CompileLayer.removeModuleSet(H); }<br>
+<br>
+ uint64_t getUnmangledSymbolAddress(const std::string &Name) {<br>
+ return CompileLayer.getSymbolAddress(Name, false);<br>
+ }<br>
+<br>
+ uint64_t getSymbolAddress(const std::string Name) {<br>
+ std::string MangledName;<br>
+ {<br>
+ raw_string_ostream MangledNameStream(MangledName);<br>
+ Mang.getNameWithPrefix(MangledNameStream, Name);<br>
+ }<br>
+ return getUnmangledSymbolAddress(MangledName);<br>
+ }<br>
+<br>
+private:<br>
+<br>
+ std::unique_ptr<TargetMachine> TM;<br>
+ Mangler Mang;<br>
+<br>
+ ObjLayerT ObjectLayer;<br>
+ CompileLayerT CompileLayer;<br>
+};<br>
+<br>
+static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) {<br>
+ if (auto F = ParseDefinition()) {<br>
+ IRGenContext C(S);<br>
+ if (auto LF = F->IRGen(C)) {<br>
+#ifndef MINIMAL_STDERR_OUTPUT<br>
+ fprintf(stderr, "Read function definition:");<br>
+ LF->dump();<br>
+#endif<br>
+ J.addModule(C.takeM());<br>
+ S.addPrototypeAST(llvm::make_unique<PrototypeAST>(*F->Proto));<br>
+ }<br>
+ } else {<br>
+ // Skip token for error recovery.<br>
+ getNextToken();<br>
+ }<br>
+}<br>
+<br>
+static void HandleExtern(SessionContext &S) {<br>
+ if (auto P = ParseExtern())<br>
+ S.addPrototypeAST(std::move(P));<br>
+ else {<br>
+ // Skip token for error recovery.<br>
+ getNextToken();<br>
+ }<br>
+}<br>
+<br>
+static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) {<br>
+ // Evaluate a top-level expression into an anonymous function.<br>
+ if (auto F = ParseTopLevelExpr()) {<br>
+ IRGenContext C(S);<br>
+ if (auto ExprFunc = F->IRGen(C)) {<br>
+#ifndef MINIMAL_STDERR_OUTPUT<br>
+ fprintf(stderr, "Expression function:\n");<br>
+ ExprFunc->dump();<br>
+#endif<br>
+ // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove<br>
+ // this module as soon as we've executed Function ExprFunc.<br>
+ auto H = J.addModule(C.takeM());<br>
+<br>
+ // Get the address of the JIT'd function in memory.<br>
+ uint64_t ExprFuncAddr = J.getSymbolAddress("__anon_expr");<br>
+<br>
+ // Cast it to the right type (takes no arguments, returns a double) so we<br>
+ // can call it as a native function.<br>
+ double (*FP)() = (double (*)())(intptr_t)ExprFuncAddr;<br>
+#ifdef MINIMAL_STDERR_OUTPUT<br>
+ FP();<br>
+#else<br>
+ fprintf(stderr, "Evaluated to %f\n", FP());<br>
+#endif<br>
+<br>
+ // Remove the function.<br>
+ J.removeModule(H);<br>
+ }<br>
+ } else {<br>
+ // Skip token for error recovery.<br>
+ getNextToken();<br>
+ }<br>
+}<br>
+<br>
+/// top ::= definition | external | expression | ';'<br>
+static void MainLoop() {<br>
+ KaleidoscopeJIT J;<br>
+ SessionContext S(getGlobalContext());<br>
+<br>
+ while (1) {<br>
+#ifndef MINIMAL_STDERR_OUTPUT<br>
+ fprintf(stderr, "ready> ");<br>
+#endif<br>
+ switch (CurTok) {<br>
+ case tok_eof: return;<br>
+ case ';': getNextToken(); break; // ignore top-level semicolons.<br>
+ case tok_def: HandleDefinition(S, J); break;<br>
+ case tok_extern: HandleExtern(S); break;<br>
+ default: HandleTopLevelExpression(S, J); break;<br>
+ }<br>
+ }<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// "Library" functions that can be "extern'd" from user code.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+/// putchard - putchar that takes a double and returns 0.<br>
+extern "C"<br>
+double putchard(double X) {<br>
+ putchar((char)X);<br>
+ return 0;<br>
+}<br>
+<br>
+/// printd - printf that takes a double prints it as "%f\n", returning 0.<br>
+extern "C"<br>
+double printd(double X) {<br>
+ printf("%f", X);<br>
+ return 0;<br>
+}<br>
+<br>
+extern "C"<br>
+double printlf() {<br>
+ printf("\n");<br>
+ return 0;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Main driver code.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+int main() {<br>
+ InitializeNativeTarget();<br>
+ InitializeNativeTargetAsmPrinter();<br>
+ InitializeNativeTargetAsmParser();<br>
+ LLVMContext &Context = getGlobalContext();<br>
+<br>
+ // Install standard binary operators.<br>
+ // 1 is lowest precedence.<br>
+ BinopPrecedence['='] = 2;<br>
+ BinopPrecedence['<'] = 10;<br>
+ BinopPrecedence['+'] = 20;<br>
+ BinopPrecedence['-'] = 20;<br>
+ BinopPrecedence['/'] = 40;<br>
+ BinopPrecedence['*'] = 40; // highest.<br>
+<br>
+ // Prime the first token.<br>
+#ifndef MINIMAL_STDERR_OUTPUT<br>
+ fprintf(stderr, "ready> ");<br>
+#endif<br>
+ getNextToken();<br>
+<br>
+ // Run the main "interpreter loop" now.<br>
+ MainLoop();<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>