llvm.org GIT mirror llvm / dbbbccc
Adding example source to support MCJIT/Kaleidoscope blog posts. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186854 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Kaylor 7 years ago
20 changed file(s) with 9374 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 //===----------------------------------------------------------------------===/
1 // Kaleidoscope with MCJIT
2 //===----------------------------------------------------------------------===//
3
4 The files in this directory are meant to accompany a series of blog posts
5 that describe the process of porting the Kaleidoscope tutorial to use the MCJIT
6 execution engine instead of the older JIT engine.
7
8 When the blog posts are ready this file will be updated with links to the posts.
9
10 These directories contain Makefiles that allow the code to be built in a
11 standalone manner, independent of the larger LLVM build infrastructure.
0 all: toy-mcjit toy-jit toy-ir-gen
1
2 toy-mcjit : toy.cpp
3 clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native irreader` -o toy-mcjit
4
5 toy-jit : toy-jit.cpp
6 clang++ toy-jit.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core jit native irreader` -o toy-jit
7
8 # This is a special build for the purpose of converting Kaleidoscope input to an IR file
9 toy-ir-gen : toy-jit.cpp
10 clang++ toy-jit.cpp -g -O3 -rdynamic -fno-rtti -DDUMP_FINAL_MODULE `llvm-config --cppflags --ldflags --libs core jit native irreader` -o toy-ir-gen
0 //===----------------------------------------------------------------------===/
1 // Kaleidoscope with MCJIT
2 //===----------------------------------------------------------------------===//
3
4 The files in this directory are meant to accompany the first in a series of
5 three blog posts that describe the process of porting the Kaleidoscope tutorial
6 to use the MCJIT execution engine instead of the older JIT engine.
7
8 When the blog post is ready this file will be updated with a link to the post.
9
10 The source code in this directory demonstrates the third version of the
11 program, now modified to accept an input IR file on the command line and,
12 optionally, to use a basic caching mechanism to store generated object images.
13
14 The toy-jit.cpp file contains a version of the original JIT-based source code
15 that has been modified to support the input IR file command line option.
16
17 This directory contain a Makefile that allow the code to be built in a
18 standalone manner, independent of the larger LLVM build infrastructure. To build
19 the program you will need to have 'clang++' and 'llvm-config' in your path. If
20 you attempt to build using the LLVM 3.3 release, some minor modifications will
21 be required.
22
23 This directory also contains a Python script that may be used to generate random
24 input for the program and test scripts to capture data for rough performance
25 comparisons. Another Python script will split generated input files into
26 definitions and function calls for the purpose of testing the IR input and
27 caching facilities.
0 #!/usr/bin/env python
1
2 import sys
3 import random
4
5 class TimingScriptGenerator:
6 """Used to generate a bash script which will invoke the toy and time it"""
7 def __init__(self, scriptname, outputname):
8 self.timeFile = outputname
9 self.shfile = open(scriptname, 'w')
10 self.shfile.write("echo \"\" > %s\n" % self.timeFile)
11
12 def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls):
13 """Echo some comments and invoke both versions of toy"""
14 rootname = filename
15 if '.' in filename:
16 rootname = filename[:filename.rfind('.')]
17 self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile))
18 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
19 self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile)
20 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
21 self.shfile.write(" -o %s -a " % self.timeFile)
22 self.shfile.write("./toy-mcjit < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname))
23 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
24 self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile)
25 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
26 self.shfile.write(" -o %s -a " % self.timeFile)
27 self.shfile.write("./toy-jit < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname))
28 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
29 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
30
31 class KScriptGenerator:
32 """Used to generate random Kaleidoscope code"""
33 def __init__(self, filename):
34 self.kfile = open(filename, 'w')
35 self.nextFuncNum = 1
36 self.lastFuncNum = None
37 self.callWeighting = 0.1
38 # A mapping of calls within functions with no duplicates
39 self.calledFunctionTable = {}
40 # A list of function calls which will actually be executed
41 self.calledFunctions = []
42 # A comprehensive mapping of calls within functions
43 # used for computing the total number of calls
44 self.comprehensiveCalledFunctionTable = {}
45 self.totalCallsExecuted = 0
46
47 def updateTotalCallCount(self, callee):
48 # Count this call
49 self.totalCallsExecuted += 1
50 # Then count all the functions it calls
51 if callee in self.comprehensiveCalledFunctionTable:
52 for child in self.comprehensiveCalledFunctionTable[callee]:
53 self.updateTotalCallCount(child)
54
55 def updateFunctionCallMap(self, caller, callee):
56 """Maintains a map of functions that are called from other functions"""
57 if not caller in self.calledFunctionTable:
58 self.calledFunctionTable[caller] = []
59 if not callee in self.calledFunctionTable[caller]:
60 self.calledFunctionTable[caller].append(callee)
61 if not caller in self.comprehensiveCalledFunctionTable:
62 self.comprehensiveCalledFunctionTable[caller] = []
63 self.comprehensiveCalledFunctionTable[caller].append(callee)
64
65 def updateCalledFunctionList(self, callee):
66 """Maintains a list of functions that will actually be called"""
67 # Update the total call count
68 self.updateTotalCallCount(callee)
69 # If this function is already in the list, don't do anything else
70 if callee in self.calledFunctions:
71 return
72 # Add this function to the list of those that will be called.
73 self.calledFunctions.append(callee)
74 # If this function calls other functions, add them too
75 if callee in self.calledFunctionTable:
76 for subCallee in self.calledFunctionTable[callee]:
77 self.updateCalledFunctionList(subCallee)
78
79 def setCallWeighting(self, weight):
80 """ Sets the probably of generating a function call"""
81 self.callWeighting = weight
82
83 def writeln(self, line):
84 self.kfile.write(line + '\n')
85
86 def writeComment(self, comment):
87 self.writeln('# ' + comment)
88
89 def writeEmptyLine(self):
90 self.writeln("")
91
92 def writePredefinedFunctions(self):
93 self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands")
94 self.writeComment("and just returns the RHS.")
95 self.writeln("def binary : 1 (x y) y;")
96 self.writeEmptyLine()
97 self.writeComment("Helper functions defined within toy")
98 self.writeln("extern putchard(x);")
99 self.writeln("extern printd(d);")
100 self.writeln("extern printlf();")
101 self.writeEmptyLine()
102 self.writeComment("Print the result of a function call")
103 self.writeln("def printresult(N Result)")
104 self.writeln(" # 'result('")
105 self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :")
106 self.writeln(" printd(N) :");
107 self.writeln(" # ') = '")
108 self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :")
109 self.writeln(" printd(Result) :");
110 self.writeln(" printlf();")
111 self.writeEmptyLine()
112
113 def writeRandomOperation(self, LValue, LHS, RHS):
114 shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting)
115 if shouldCallFunc:
116 funcToCall = random.randrange(1, self.lastFuncNum - 1)
117 self.updateFunctionCallMap(self.lastFuncNum, funcToCall)
118 self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS))
119 else:
120 possibleOperations = ["+", "-", "*", "/"]
121 operation = random.choice(possibleOperations)
122 if operation == "-":
123 # Don't let our intermediate value become zero
124 # This is complicated by the fact that '<' is our only comparison operator
125 self.writeln(" if %s < %s then" % (LHS, RHS))
126 self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS))
127 self.writeln(" else if %s < %s then" % (RHS, LHS))
128 self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS))
129 self.writeln(" else")
130 self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100)))
131 else:
132 self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS))
133
134 def getNextFuncNum(self):
135 result = self.nextFuncNum
136 self.nextFuncNum += 1
137 self.lastFuncNum = result
138 return result
139
140 def writeFunction(self, elements):
141 funcNum = self.getNextFuncNum()
142 self.writeComment("Auto-generated function number %d" % funcNum)
143 self.writeln("def func%d(X Y)" % funcNum)
144 self.writeln(" var temp1 = X,")
145 self.writeln(" temp2 = Y,")
146 self.writeln(" temp3 in")
147 # Initialize the variable names to be rotated
148 first = "temp3"
149 second = "temp1"
150 third = "temp2"
151 # Write some random operations
152 for i in range(elements):
153 self.writeRandomOperation(first, second, third)
154 # Rotate the variables
155 temp = first
156 first = second
157 second = third
158 third = temp
159 self.writeln(" " + third + ";")
160 self.writeEmptyLine()
161
162 def writeFunctionCall(self):
163 self.writeComment("Call the last function")
164 arg1 = random.uniform(1, 100)
165 arg2 = random.uniform(1, 100)
166 self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2))
167 self.writeEmptyLine()
168 self.updateCalledFunctionList(self.lastFuncNum)
169
170 def writeFinalFunctionCounts(self):
171 self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum))
172
173 def generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript):
174 """ Generate a random Kaleidoscope script based on the given parameters """
175 print "Generating " + filename
176 print(" %d functions, %d elements per function, %d functions between execution" %
177 (numFuncs, elementsPerFunc, funcsBetweenExec))
178 print(" Call weighting = %f" % callWeighting)
179 script = KScriptGenerator(filename)
180 script.setCallWeighting(callWeighting)
181 script.writeComment("===========================================================================")
182 script.writeComment("Auto-generated script")
183 script.writeComment(" %d functions, %d elements per function, %d functions between execution"
184 % (numFuncs, elementsPerFunc, funcsBetweenExec))
185 script.writeComment(" call weighting = %f" % callWeighting)
186 script.writeComment("===========================================================================")
187 script.writeEmptyLine()
188 script.writePredefinedFunctions()
189 funcsSinceLastExec = 0
190 for i in range(numFuncs):
191 script.writeFunction(elementsPerFunc)
192 funcsSinceLastExec += 1
193 if funcsSinceLastExec == funcsBetweenExec:
194 script.writeFunctionCall()
195 funcsSinceLastExec = 0
196 # Always end with a function call
197 if funcsSinceLastExec > 0:
198 script.writeFunctionCall()
199 script.writeEmptyLine()
200 script.writeFinalFunctionCounts()
201 funcsCalled = len(script.calledFunctions)
202 print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted)
203 timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted)
204
205 # Execution begins here
206 random.seed()
207
208 timingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt")
209
210 dataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0),
211 (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0),
212 ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)]
213
214 # Generate the code
215 for (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets:
216 filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100))
217 generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript)
218 print "All done!"
0 #!/usr/bin/env python
1
2 class TimingScriptGenerator:
3 """Used to generate a bash script which will invoke the toy and time it"""
4 def __init__(self, scriptname, outputname):
5 self.shfile = open(scriptname, 'w')
6 self.timeFile = outputname
7 self.shfile.write("echo \"\" > %s\n" % self.timeFile)
8
9 def writeTimingCall(self, irname, callname):
10 """Echo some comments and invoke both versions of toy"""
11 rootname = irname
12 if '.' in irname:
13 rootname = irname[:irname.rfind('.')]
14 self.shfile.write("echo \"%s: Calls %s\" >> %s\n" % (callname, irname, self.timeFile))
15 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
16 self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile)
17 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
18 self.shfile.write(" -o %s -a " % self.timeFile)
19 self.shfile.write("./toy-mcjit -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname))
20 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
21 self.shfile.write("echo \"With MCJIT again\" >> %s\n" % self.timeFile)
22 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
23 self.shfile.write(" -o %s -a " % self.timeFile)
24 self.shfile.write("./toy-mcjit -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname))
25 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
26 self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile)
27 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
28 self.shfile.write(" -o %s -a " % self.timeFile)
29 self.shfile.write("./toy-jit -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname))
30 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
31 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
32
33 class LibScriptGenerator:
34 """Used to generate a bash script which will convert Kaleidoscope files to IR"""
35 def __init__(self, filename):
36 self.shfile = open(filename, 'w')
37
38 def writeLibGenCall(self, libname, irname):
39 self.shfile.write("./toy-ir-gen < %s 2> %s\n" % (libname, irname))
40
41 def splitScript(inputname, libGenScript, timingScript):
42 rootname = inputname[:-2]
43 libname = rootname + "-lib.k"
44 irname = rootname + "-lib.ir"
45 callname = rootname + "-call.k"
46 infile = open(inputname, "r")
47 libfile = open(libname, "w")
48 callfile = open(callname, "w")
49 print "Splitting %s into %s and %s" % (inputname, callname, libname)
50 for line in infile:
51 if not line.startswith("#"):
52 if line.startswith("print"):
53 callfile.write(line)
54 else:
55 libfile.write(line)
56 libGenScript.writeLibGenCall(libname, irname)
57 timingScript.writeTimingCall(irname, callname)
58
59 # Execution begins here
60 libGenScript = LibScriptGenerator("make-libs.sh")
61 timingScript = TimingScriptGenerator("time-lib.sh", "lib-timing.txt")
62
63 script_list = ["test-5000-3-50-50.k", "test-5000-10-100-10.k", "test-5000-10-5-10.k", "test-5000-10-1-0.k",
64 "test-1000-3-10-50.k", "test-1000-10-100-10.k", "test-1000-10-5-10.k", "test-1000-10-1-0.k",
65 "test-200-3-2-50.k", "test-200-10-40-10.k", "test-200-10-2-10.k", "test-200-10-1-0.k"]
66
67 for script in script_list:
68 splitScript(script, libGenScript, timingScript)
69 print "All done!"
0 #define MINIMAL_STDERR_OUTPUT
1
2 #include "llvm/Analysis/Passes.h"
3 #include "llvm/Analysis/Verifier.h"
4 #include "llvm/ExecutionEngine/ExecutionEngine.h"
5 #include "llvm/ExecutionEngine/JIT.h"
6 #include "llvm/IR/DataLayout.h"
7 #include "llvm/IR/DerivedTypes.h"
8 #include "llvm/IR/IRBuilder.h"
9 #include "llvm/IR/LLVMContext.h"
10 #include "llvm/IR/Module.h"
11 #include "llvm/IRReader/IRReader.h"
12 #include "llvm/PassManager.h"
13 #include "llvm/Support/CommandLine.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "llvm/Support/TargetSelect.h"
17 #include "llvm/Transforms/Scalar.h"
18 #include
19 #include
20 #include
21 #include
22
23 using namespace llvm;
24
25 //===----------------------------------------------------------------------===//
26 // Command-line options
27 //===----------------------------------------------------------------------===//
28
29 namespace {
30 cl::opt
31 InputIR("input-IR",
32 cl::desc("Specify the name of an IR file to load for function definitions"),
33 cl::value_desc("input IR file name"));
34 } // namespace
35
36 //===----------------------------------------------------------------------===//
37 // Lexer
38 //===----------------------------------------------------------------------===//
39
40 // The lexer returns tokens [0-255] if it is an unknown character, otherwise one
41 // of these for known things.
42 enum Token {
43 tok_eof = -1,
44
45 // commands
46 tok_def = -2, tok_extern = -3,
47
48 // primary
49 tok_identifier = -4, tok_number = -5,
50
51 // control
52 tok_if = -6, tok_then = -7, tok_else = -8,
53 tok_for = -9, tok_in = -10,
54
55 // operators
56 tok_binary = -11, tok_unary = -12,
57
58 // var definition
59 tok_var = -13
60 };
61
62 static std::string IdentifierStr; // Filled in if tok_identifier
63 static double NumVal; // Filled in if tok_number
64
65 /// gettok - Return the next token from standard input.
66 static int gettok() {
67 static int LastChar = ' ';
68
69 // Skip any whitespace.
70 while (isspace(LastChar))
71 LastChar = getchar();
72
73 if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
74 IdentifierStr = LastChar;
75 while (isalnum((LastChar = getchar())))
76 IdentifierStr += LastChar;
77
78 if (IdentifierStr == "def") return tok_def;
79 if (IdentifierStr == "extern") return tok_extern;
80 if (IdentifierStr == "if") return tok_if;
81 if (IdentifierStr == "then") return tok_then;
82 if (IdentifierStr == "else") return tok_else;
83 if (IdentifierStr == "for") return tok_for;
84 if (IdentifierStr == "in") return tok_in;
85 if (IdentifierStr == "binary") return tok_binary;
86 if (IdentifierStr == "unary") return tok_unary;
87 if (IdentifierStr == "var") return tok_var;
88 return tok_identifier;
89 }
90
91 if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+
92 std::string NumStr;
93 do {
94 NumStr += LastChar;
95 LastChar = getchar();
96 } while (isdigit(LastChar) || LastChar == '.');
97
98 NumVal = strtod(NumStr.c_str(), 0);
99 return tok_number;
100 }
101
102 if (LastChar == '#') {
103 // Comment until end of line.
104 do LastChar = getchar();
105 while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
106
107 if (LastChar != EOF)
108 return gettok();
109 }
110
111 // Check for end of file. Don't eat the EOF.
112 if (LastChar == EOF)
113 return tok_eof;
114
115 // Otherwise, just return the character as its ascii value.
116 int ThisChar = LastChar;
117 LastChar = getchar();
118 return ThisChar;
119 }
120
121 //===----------------------------------------------------------------------===//
122 // Abstract Syntax Tree (aka Parse Tree)
123 //===----------------------------------------------------------------------===//
124
125 /// ExprAST - Base class for all expression nodes.
126 class ExprAST {
127 public:
128 virtual ~ExprAST() {}
129 virtual Value *Codegen() = 0;
130 };
131
132 /// NumberExprAST - Expression class for numeric literals like "1.0".
133 class NumberExprAST : public ExprAST {
134 double Val;
135 public:
136 NumberExprAST(double val) : Val(val) {}
137 virtual Value *Codegen();
138 };
139
140 /// VariableExprAST - Expression class for referencing a variable, like "a".
141 class VariableExprAST : public ExprAST {
142 std::string Name;
143 public:
144 VariableExprAST(const std::string &name) : Name(name) {}
145 const std::string &getName() const { return Name; }
146 virtual Value *Codegen();
147 };
148
149 /// UnaryExprAST - Expression class for a unary operator.
150 class UnaryExprAST : public ExprAST {
151 char Opcode;
152 ExprAST *Operand;
153 public:
154 UnaryExprAST(char opcode, ExprAST *operand)
155 : Opcode(opcode), Operand(operand) {}
156 virtual Value *Codegen();
157 };
158
159 /// BinaryExprAST - Expression class for a binary operator.
160 class BinaryExprAST : public ExprAST {
161 char Op;
162 ExprAST *LHS, *RHS;
163 public:
164 BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs)
165 : Op(op), LHS(lhs), RHS(rhs) {}
166 virtual Value *Codegen();
167 };
168
169 /// CallExprAST - Expression class for function calls.
170 class CallExprAST : public ExprAST {
171 std::string Callee;
172 std::vector Args;
173 public:
174 CallExprAST(const std::string &callee, std::vector &args)
175 : Callee(callee), Args(args) {}
176 virtual Value *Codegen();
177 };
178
179 /// IfExprAST - Expression class for if/then/else.
180 class IfExprAST : public ExprAST {
181 ExprAST *Cond, *Then, *Else;
182 public:
183 IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
184 : Cond(cond), Then(then), Else(_else) {}
185 virtual Value *Codegen();
186 };
187
188 /// ForExprAST - Expression class for for/in.
189 class ForExprAST : public ExprAST {
190 std::string VarName;
191 ExprAST *Start, *End, *Step, *Body;
192 public:
193 ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
194 ExprAST *step, ExprAST *body)
195 : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
196 virtual Value *Codegen();
197 };
198
199 /// VarExprAST - Expression class for var/in
200 class VarExprAST : public ExprAST {
201 std::vector > VarNames;
202 ExprAST *Body;
203 public:
204 VarExprAST(const std::vector > &varnames,
205 ExprAST *body)
206 : VarNames(varnames), Body(body) {}
207
208 virtual Value *Codegen();
209 };
210
211 /// PrototypeAST - This class represents the "prototype" for a function,
212 /// which captures its argument names as well as if it is an operator.
213 class PrototypeAST {
214 std::string Name;
215 std::vector Args;
216 bool isOperator;
217 unsigned Precedence; // Precedence if a binary op.
218 public:
219 PrototypeAST(const std::string &name, const std::vector &args,
220 bool isoperator = false, unsigned prec = 0)
221 : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {}
222
223 bool isUnaryOp() const { return isOperator && Args.size() == 1; }
224 bool isBinaryOp() const { return isOperator && Args.size() == 2; }
225
226 char getOperatorName() const {
227 assert(isUnaryOp() || isBinaryOp());
228 return Name[Name.size()-1];
229 }
230
231 unsigned getBinaryPrecedence() const { return Precedence; }
232
233 Function *Codegen();
234
235 void CreateArgumentAllocas(Function *F);
236 };
237
238 /// FunctionAST - This class represents a function definition itself.
239 class FunctionAST {
240 PrototypeAST *Proto;
241 ExprAST *Body;
242 public:
243 FunctionAST(PrototypeAST *proto, ExprAST *body)
244 : Proto(proto), Body(body) {}
245
246 Function *Codegen();
247 };
248
249 //===----------------------------------------------------------------------===//
250 // Parser
251 //===----------------------------------------------------------------------===//
252
253 /// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
254 /// token the parser is looking at. getNextToken reads another token from the
255 /// lexer and updates CurTok with its results.
256 static int CurTok;
257 static int getNextToken() {
258 return CurTok = gettok();
259 }
260
261 /// BinopPrecedence - This holds the precedence for each binary operator that is
262 /// defined.
263 static std::map BinopPrecedence;
264
265 /// GetTokPrecedence - Get the precedence of the pending binary operator token.
266 static int GetTokPrecedence() {
267 if (!isascii(CurTok))
268 return -1;
269
270 // Make sure it's a declared binop.
271 int TokPrec = BinopPrecedence[CurTok];
272 if (TokPrec <= 0) return -1;
273 return TokPrec;
274 }
275
276 /// Error* - These are little helper functions for error handling.
277 ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
278 PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
279 FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
280
281 static ExprAST *ParseExpression();
282
283 /// identifierexpr
284 /// ::= identifier
285 /// ::= identifier '(' expression* ')'
286 static ExprAST *ParseIdentifierExpr() {
287 std::string IdName = IdentifierStr;
288
289 getNextToken(); // eat identifier.
290
291 if (CurTok != '(') // Simple variable ref.
292 return new VariableExprAST(IdName);
293
294 // Call.
295 getNextToken(); // eat (
296 std::vector Args;
297 if (CurTok != ')') {
298 while (1) {
299 ExprAST *Arg = ParseExpression();
300 if (!Arg) return 0;
301 Args.push_back(Arg);
302
303 if (CurTok == ')') break;
304
305 if (CurTok != ',')
306 return Error("Expected ')' or ',' in argument list");
307 getNextToken();
308 }
309 }
310
311 // Eat the ')'.
312 getNextToken();
313
314 return new CallExprAST(IdName, Args);
315 }
316
317 /// numberexpr ::= number
318 static ExprAST *ParseNumberExpr() {
319 ExprAST *Result = new NumberExprAST(NumVal);
320 getNextToken(); // consume the number
321 return Result;
322 }
323
324 /// parenexpr ::= '(' expression ')'
325 static ExprAST *ParseParenExpr() {
326 getNextToken(); // eat (.
327 ExprAST *V = ParseExpression();
328 if (!V) return 0;
329
330 if (CurTok != ')')
331 return Error("expected ')'");
332 getNextToken(); // eat ).
333 return V;
334 }
335
336 /// ifexpr ::= 'if' expression 'then' expression 'else' expression
337 static ExprAST *ParseIfExpr() {
338 getNextToken(); // eat the if.
339
340 // condition.
341 ExprAST *Cond = ParseExpression();
342 if (!Cond) return 0;
343
344 if (CurTok != tok_then)
345 return Error("expected then");
346 getNextToken(); // eat the then
347
348 ExprAST *Then = ParseExpression();
349 if (Then == 0) return 0;
350
351 if (CurTok != tok_else)
352 return Error("expected else");
353
354 getNextToken();
355
356 ExprAST *Else = ParseExpression();
357 if (!Else) return 0;
358
359 return new IfExprAST(Cond, Then, Else);
360 }
361
362 /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
363 static ExprAST *ParseForExpr() {
364 getNextToken(); // eat the for.
365
366 if (CurTok != tok_identifier)
367 return Error("expected identifier after for");
368
369 std::string IdName = IdentifierStr;
370 getNextToken(); // eat identifier.
371
372 if (CurTok != '=')
373 return Error("expected '=' after for");
374 getNextToken(); // eat '='.
375
376
377 ExprAST *Start = ParseExpression();
378 if (Start == 0) return 0;
379 if (CurTok != ',')
380 return Error("expected ',' after for start value");
381 getNextToken();
382
383 ExprAST *End = ParseExpression();
384 if (End == 0) return 0;
385
386 // The step value is optional.
387 ExprAST *Step = 0;
388 if (CurTok == ',') {
389 getNextToken();
390 Step = ParseExpression();
391 if (Step == 0) return 0;
392 }
393
394 if (CurTok != tok_in)
395 return Error("expected 'in' after for");
396 getNextToken(); // eat 'in'.
397
398 ExprAST *Body = ParseExpression();
399 if (Body == 0) return 0;
400
401 return new ForExprAST(IdName, Start, End, Step, Body);
402 }
403
404 /// varexpr ::= 'var' identifier ('=' expression)?
405 // (',' identifier ('=' expression)?)* 'in' expression
406 static ExprAST *ParseVarExpr() {
407 getNextToken(); // eat the var.
408
409 std::vector > VarNames;
410
411 // At least one variable name is required.
412 if (CurTok != tok_identifier)
413 return Error("expected identifier after var");
414
415 while (1) {
416 std::string Name = IdentifierStr;
417 getNextToken(); // eat identifier.
418
419 // Read the optional initializer.
420 ExprAST *Init = 0;
421 if (CurTok == '=') {
422 getNextToken(); // eat the '='.
423
424 Init = ParseExpression();
425 if (Init == 0) return 0;
426 }
427
428 VarNames.push_back(std::make_pair(Name, Init));
429
430 // End of var list, exit loop.
431 if (CurTok != ',') break;
432 getNextToken(); // eat the ','.
433
434 if (CurTok != tok_identifier)
435 return Error("expected identifier list after var");
436 }
437
438 // At this point, we have to have 'in'.
439 if (CurTok != tok_in)
440 return Error("expected 'in' keyword after 'var'");
441 getNextToken(); // eat 'in'.
442
443 ExprAST *Body = ParseExpression();
444 if (Body == 0) return 0;
445
446 return new VarExprAST(VarNames, Body);
447 }
448
449 /// primary
450 /// ::= identifierexpr
451 /// ::= numberexpr
452 /// ::= parenexpr
453 /// ::= ifexpr
454 /// ::= forexpr
455 /// ::= varexpr
456 static ExprAST *ParsePrimary() {
457 switch (CurTok) {
458 default: return Error("unknown token when expecting an expression");
459 case tok_identifier: return ParseIdentifierExpr();
460 case tok_number: return ParseNumberExpr();
461 case '(': return ParseParenExpr();
462 case tok_if: return ParseIfExpr();
463 case tok_for: return ParseForExpr();
464 case tok_var: return ParseVarExpr();
465 }
466 }
467
468 /// unary
469 /// ::= primary
470 /// ::= '!' unary
471 static ExprAST *ParseUnary() {
472 // If the current token is not an operator, it must be a primary expr.
473 if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
474 return ParsePrimary();
475
476 // If this is a unary operator, read it.
477 int Opc = CurTok;
478 getNextToken();
479 if (ExprAST *Operand = ParseUnary())
480 return new UnaryExprAST(Opc, Operand);
481 return 0;
482 }
483
484 /// binoprhs
485 /// ::= ('+' unary)*
486 static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
487 // If this is a binop, find its precedence.
488 while (1) {
489 int TokPrec = GetTokPrecedence();
490
491 // If this is a binop that binds at least as tightly as the current binop,
492 // consume it, otherwise we are done.
493 if (TokPrec < ExprPrec)
494 return LHS;
495
496 // Okay, we know this is a binop.
497 int BinOp = CurTok;
498 getNextToken(); // eat binop
499
500 // Parse the unary expression after the binary operator.
501 ExprAST *RHS = ParseUnary();
502 if (!RHS) return 0;
503
504 // If BinOp binds less tightly with RHS than the operator after RHS, let
505 // the pending operator take RHS as its LHS.
506 int NextPrec = GetTokPrecedence();
507 if (TokPrec < NextPrec) {
508 RHS = ParseBinOpRHS(TokPrec+1, RHS);
509 if (RHS == 0) return 0;
510 }
511
512 // Merge LHS/RHS.
513 LHS = new BinaryExprAST(BinOp, LHS, RHS);
514 }
515 }
516
517 /// expression
518 /// ::= unary binoprhs
519 ///
520 static ExprAST *ParseExpression() {
521 ExprAST *LHS = ParseUnary();
522 if (!LHS) return 0;
523
524 return ParseBinOpRHS(0, LHS);
525 }
526
527 /// prototype
528 /// ::= id '(' id* ')'
529 /// ::= binary LETTER number? (id, id)
530 /// ::= unary LETTER (id)
531 static PrototypeAST *ParsePrototype() {
532 std::string FnName;
533
534 unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
535 unsigned BinaryPrecedence = 30;
536
537 switch (CurTok) {
538 default:
539 return ErrorP("Expected function name in prototype");
540 case tok_identifier:
541 FnName = IdentifierStr;
542 Kind = 0;
543 getNextToken();
544 break;
545 case tok_unary:
546 getNextToken();
547 if (!isascii(CurTok))
548 return ErrorP("Expected unary operator");
549 FnName = "unary";
550 FnName += (char)CurTok;
551 Kind = 1;
552 getNextToken();
553 break;
554 case tok_binary:
555 getNextToken();
556 if (!isascii(CurTok))
557 return ErrorP("Expected binary operator");
558 FnName = "binary";
559 FnName += (char)CurTok;
560 Kind = 2;
561 getNextToken();
562
563 // Read the precedence if present.
564 if (CurTok == tok_number) {
565 if (NumVal < 1 || NumVal > 100)
566 return ErrorP("Invalid precedecnce: must be 1..100");
567 BinaryPrecedence = (unsigned)NumVal;
568 getNextToken();
569 }
570 break;
571 }
572
573 if (CurTok != '(')
574 return ErrorP("Expected '(' in prototype");
575
576 std::vector ArgNames;
577 while (getNextToken() == tok_identifier)
578 ArgNames.push_back(IdentifierStr);
579 if (CurTok != ')')
580 return ErrorP("Expected ')' in prototype");
581
582 // success.
583 getNextToken(); // eat ')'.
584
585 // Verify right number of names for operator.
586 if (Kind && ArgNames.size() != Kind)
587 return ErrorP("Invalid number of operands for operator");
588
589 return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence);
590 }
591
592 /// definition ::= 'def' prototype expression
593 static FunctionAST *ParseDefinition() {
594 getNextToken(); // eat def.
595 PrototypeAST *Proto = ParsePrototype();
596 if (Proto == 0) return 0;
597
598 if (ExprAST *E = ParseExpression())
599 return new FunctionAST(Proto, E);
600 return 0;
601 }
602
603 /// toplevelexpr ::= expression
604 static FunctionAST *ParseTopLevelExpr() {
605 if (ExprAST *E = ParseExpression()) {
606 // Make an anonymous proto.
607 PrototypeAST *Proto = new PrototypeAST("", std::vector());
608 return new FunctionAST(Proto, E);
609 }
610 return 0;
611 }
612
613 /// external ::= 'extern' prototype
614 static PrototypeAST *ParseExtern() {
615 getNextToken(); // eat extern.
616 return ParsePrototype();
617 }
618
619 //===----------------------------------------------------------------------===//
620 // Code Generation
621 //===----------------------------------------------------------------------===//
622
623 static Module *TheModule;
624 static FunctionPassManager *TheFPM;
625 static IRBuilder<> Builder(getGlobalContext());
626 static std::map NamedValues;
627
628 Value *ErrorV(const char *Str) { Error(Str); return 0; }
629
630 /// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of
631 /// the function. This is used for mutable variables etc.
632 static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
633 const std::string &VarName) {
634 IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
635 TheFunction->getEntryBlock().begin());
636 return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0,
637 VarName.c_str());
638 }
639
640 Value *NumberExprAST::Codegen() {
641 return ConstantFP::get(getGlobalContext(), APFloat(Val));
642 }
643
644 Value *VariableExprAST::Codegen() {
645 // Look this variable up in the function.
646 Value *V = NamedValues[Name];
647 if (V == 0) return ErrorV("Unknown variable name");
648
649 // Load the value.
650 return Builder.CreateLoad(V, Name.c_str());
651 }
652
653 Value *UnaryExprAST::Codegen() {
654 Value *OperandV = Operand->Codegen();
655 if (OperandV == 0) return 0;
656 #ifdef USE_MCJIT
657 Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode));
658 #else
659 Function *F = TheModule->getFunction(std::string("unary")+Opcode);
660 #endif
661 if (F == 0)
662 return ErrorV("Unknown unary operator");
663
664 return Builder.CreateCall(F, OperandV, "unop");
665 }
666
667 Value *BinaryExprAST::Codegen() {
668 // Special case '=' because we don't want to emit the LHS as an expression.
669 if (Op == '=') {
670 // Assignment requires the LHS to be an identifier.
671 // For now, I'm building without RTTI because LLVM builds that way by
672 // default and so we need to build that way to use the command line supprt.
673 // If you build LLVM with RTTI this can be changed back to a dynamic_cast.
674 VariableExprAST *LHSE = reinterpret_cast(LHS);
675 if (!LHSE)
676 return ErrorV("destination of '=' must be a variable");
677 // Codegen the RHS.
678 Value *Val = RHS->Codegen();
679 if (Val == 0) return 0;
680
681 // Look up the name.
682 Value *Variable = NamedValues[LHSE->getName()];
683 if (Variable == 0) return ErrorV("Unknown variable name");
684
685 Builder.CreateStore(Val, Variable);
686 return Val;
687 }
688
689 Value *L = LHS->Codegen();
690 Value *R = RHS->Codegen();
691 if (L == 0 || R == 0) return 0;
692
693 switch (Op) {
694 case '+': return Builder.CreateFAdd(L, R, "addtmp");
695 case '-': return Builder.CreateFSub(L, R, "subtmp");
696 case '*': return Builder.CreateFMul(L, R, "multmp");
697 case '/': return Builder.CreateFDiv(L, R, "divtmp");
698 case '<':
699 L = Builder.CreateFCmpULT(L, R, "cmptmp");
700 // Convert bool 0/1 to double 0.0 or 1.0
701 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
702 "booltmp");
703 default: break;
704 }
705
706 // If it wasn't a builtin binary operator, it must be a user defined one. Emit
707 // a call to it.
708 Function *F = TheModule->getFunction(std::string("binary")+Op);
709 assert(F && "binary operator not found!");
710
711 Value *Ops[] = { L, R };
712 return Builder.CreateCall(F, Ops, "binop");
713 }
714
715 Value *CallExprAST::Codegen() {
716 // Look up the name in the global module table.
717 Function *CalleeF = TheModule->getFunction(Callee);
718 if (CalleeF == 0) {
719 char error_str[64];
720 sprintf(error_str, "Unknown function referenced %s", Callee.c_str());
721 return ErrorV(error_str);
722 }
723
724 // If argument mismatch error.
725 if (CalleeF->arg_size() != Args.size())
726 return ErrorV("Incorrect # arguments passed");
727
728 std::vector ArgsV;
729 for (unsigned i = 0, e = Args.size(); i != e; ++i) {
730 ArgsV.push_back(Args[i]->Codegen());
731 if (ArgsV.back() == 0) return 0;
732 }
733
734 return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
735 }
736
737 Value *IfExprAST::Codegen() {
738 Value *CondV = Cond->Codegen();
739 if (CondV == 0) return 0;
740
741 // Convert condition to a bool by comparing equal to 0.0.
742 CondV = Builder.CreateFCmpONE(CondV,
743 ConstantFP::get(getGlobalContext(), APFloat(0.0)),
744 "ifcond");
745
746 Function *TheFunction = Builder.GetInsertBlock()->getParent();
747
748 // Create blocks for the then and else cases. Insert the 'then' block at the
749 // end of the function.
750 BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
751 BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
752 BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
753
754 Builder.CreateCondBr(CondV, ThenBB, ElseBB);
755
756 // Emit then value.
757 Builder.SetInsertPoint(ThenBB);
758
759 Value *ThenV = Then->Codegen();
760 if (ThenV == 0) return 0;
761
762 Builder.CreateBr(MergeBB);
763 // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
764 ThenBB = Builder.GetInsertBlock();
765
766 // Emit else block.
767 TheFunction->getBasicBlockList().push_back(ElseBB);
768 Builder.SetInsertPoint(ElseBB);
769
770 Value *ElseV = Else->Codegen();
771 if (ElseV == 0) return 0;
772
773 Builder.CreateBr(MergeBB);
774 // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
775 ElseBB = Builder.GetInsertBlock();
776
777 // Emit merge block.
778 TheFunction->getBasicBlockList().push_back(MergeBB);
779 Builder.SetInsertPoint(MergeBB);
780 PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2,
781 "iftmp");
782
783 PN->addIncoming(ThenV, ThenBB);
784 PN->addIncoming(ElseV, ElseBB);
785 return PN;
786 }
787
788 Value *ForExprAST::Codegen() {
789 // Output this as:
790 // var = alloca double
791 // ...
792 // start = startexpr
793 // store start -> var
794 // goto loop
795 // loop:
796 // ...
797 // bodyexpr
798 // ...
799 // loopend:
800 // step = stepexpr
801 // endcond = endexpr
802 //
803 // curvar = load var
804 // nextvar = curvar + step
805 // store nextvar -> var
806 // br endcond, loop, endloop
807 // outloop:
808
809 Function *TheFunction = Builder.GetInsertBlock()->getParent();
810
811 // Create an alloca for the variable in the entry block.
812 AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
813
814 // Emit the start code first, without 'variable' in scope.
815 Value *StartVal = Start->Codegen();
816 if (StartVal == 0) return 0;
817
818 // Store the value into the alloca.
819 Builder.CreateStore(StartVal, Alloca);
820
821 // Make the new basic block for the loop header, inserting after current
822 // block.
823 BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
824
825 // Insert an explicit fall through from the current block to the LoopBB.
826 Builder.CreateBr(LoopBB);
827
828 // Start insertion in LoopBB.
829 Builder.SetInsertPoint(LoopBB);
830
831 // Within the loop, the variable is defined equal to the PHI node. If it
832 // shadows an existing variable, we have to restore it, so save it now.
833 AllocaInst *OldVal = NamedValues[VarName];
834 NamedValues[VarName] = Alloca;
835
836 // Emit the body of the loop. This, like any other expr, can change the
837 // current BB. Note that we ignore the value computed by the body, but don't
838 // allow an error.
839 if (Body->Codegen() == 0)
840 return 0;
841
842 // Emit the step value.
843 Value *StepVal;
844 if (Step) {
845 StepVal = Step->Codegen();
846 if (StepVal == 0) return 0;
847 } else {
848 // If not specified, use 1.0.
849 StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
850 }
851
852 // Compute the end condition.
853 Value *EndCond = End->Codegen();
854 if (EndCond == 0) return EndCond;
855
856 // Reload, increment, and restore the alloca. This handles the case where
857 // the body of the loop mutates the variable.
858 Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str());
859 Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar");
860 Builder.CreateStore(NextVar, Alloca);
861
862 // Convert condition to a bool by comparing equal to 0.0.
863 EndCond = Builder.CreateFCmpONE(EndCond,
864 ConstantFP::get(getGlobalContext(), APFloat(0.0)),
865 "loopcond");
866
867 // Create the "after loop" block and insert it.
868 BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
869
870 // Insert the conditional branch into the end of LoopEndBB.
871 Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
872
873 // Any new code will be inserted in AfterBB.
874 Builder.SetInsertPoint(AfterBB);
875
876 // Restore the unshadowed variable.
877 if (OldVal)
878 NamedValues[VarName] = OldVal;
879 else
880 NamedValues.erase(VarName);
881
882
883 // for expr always returns 0.0.
884 return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
885 }
886
887 Value *VarExprAST::Codegen() {
888 std::vector OldBindings;
889
890 Function *TheFunction = Builder.GetInsertBlock()->getParent();
891
892 // Register all variables and emit their initializer.
893 for (unsigned i = 0, e = VarNames.size(); i != e; ++i) {
894 const std::string &VarName = VarNames[i].first;
895 ExprAST *Init = VarNames[i].second;
896
897 // Emit the initializer before adding the variable to scope, this prevents
898 // the initializer from referencing the variable itself, and permits stuff
899 // like this:
900 // var a = 1 in
901 // var a = a in ... # refers to outer 'a'.
902 Value *InitVal;
903 if (Init) {
904 InitVal = Init->Codegen();
905 if (InitVal == 0) return 0;
906 } else { // If not specified, use 0.0.
907 InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0));
908 }
909
910 AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
911 Builder.CreateStore(InitVal, Alloca);
912
913 // Remember the old variable binding so that we can restore the binding when
914 // we unrecurse.
915 OldBindings.push_back(NamedValues[VarName]);
916
917 // Remember this binding.
918 NamedValues[VarName] = Alloca;
919 }
920
921 // Codegen the body, now that all vars are in scope.
922 Value *BodyVal = Body->Codegen();
923 if (BodyVal == 0) return 0;
924
925 // Pop all our variables from scope.
926 for (unsigned i = 0, e = VarNames.size(); i != e; ++i)
927 NamedValues[VarNames[i].first] = OldBindings[i];
928
929 // Return the body computation.
930 return BodyVal;
931 }
932
933 Function *PrototypeAST::Codegen() {
934 // Make the function type: double(double,double) etc.
935 std::vector Doubles(Args.size(),
936 Type::getDoubleTy(getGlobalContext()));
937 FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
938 Doubles, false);
939
940 Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
941 // If F conflicted, there was already something named 'Name'. If it has a
942 // body, don't allow redefinition or reextern.
943 if (F->getName() != Name) {
944 // Delete the one we just made and get the existing one.
945 F->eraseFromParent();
946 F = TheModule->getFunction(Name);
947 // If F already has a body, reject this.
948 if (!F->empty()) {
949 ErrorF("redefinition of function");
950 return 0;
951 }
952 // If F took a different number of args, reject.
953 if (F->arg_size() != Args.size()) {
954 ErrorF("redefinition of function with different # args");
955 return 0;
956 }
957 }
958
959 // Set names for all arguments.
960 unsigned Idx = 0;
961 for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
962 ++AI, ++Idx)
963 AI->setName(Args[Idx]);
964
965 return F;
966 }
967
968 /// CreateArgumentAllocas - Create an alloca for each argument and register the
969 /// argument in the symbol table so that references to it will succeed.
970 void PrototypeAST::CreateArgumentAllocas(Function *F) {
971 Function::arg_iterator AI = F->arg_begin();
972 for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
973 // Create an alloca for this variable.
974 AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);
975
976 // Store the initial value into the alloca.
977 Builder.CreateStore(AI, Alloca);
978
979 // Add arguments to variable symbol table.
980 NamedValues[Args[Idx]] = Alloca;
981 }
982 }
983
984 Function *FunctionAST::Codegen() {
985 NamedValues.clear();
986
987 Function *TheFunction = Proto->Codegen();
988 if (TheFunction == 0)
989 return 0;
990
991 // If this is an operator, install it.
992 if (Proto->isBinaryOp())
993 BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
994
995 // Create a new basic block to start insertion into.
996 BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
997 Builder.SetInsertPoint(BB);
998
999 // Add all arguments to the symbol table and create their allocas.
1000 Proto->CreateArgumentAllocas(TheFunction);
1001
1002 if (Value *RetVal = Body->Codegen()) {
1003 // Finish off the function.
1004 Builder.CreateRet(RetVal);
1005
1006 // Validate the generated code, checking for consistency.
1007 verifyFunction(*TheFunction);
1008
1009 // Optimize the function.
1010 TheFPM->run(*TheFunction);
1011
1012 return TheFunction;
1013 }
1014
1015 // Error reading body, remove function.
1016 TheFunction->eraseFromParent();
1017
1018 if (Proto->isBinaryOp())
1019 BinopPrecedence.erase(Proto->getOperatorName());
1020 return 0;
1021 }
1022
1023 //===----------------------------------------------------------------------===//
1024 // Top-Level parsing and JIT Driver
1025 //===----------------------------------------------------------------------===//
1026
1027 static ExecutionEngine *TheExecutionEngine;
1028
1029 static void HandleDefinition() {
1030 if (FunctionAST *F = ParseDefinition()) {
1031 if (Function *LF = F->Codegen()) {
1032 #ifndef MINIMAL_STDERR_OUTPUT
1033 fprintf(stderr, "Read function definition:");
1034 LF->dump();
1035 #endif
1036 }
1037 } else {
1038 // Skip token for error recovery.
1039 getNextToken();
1040 }
1041 }
1042
1043 static void HandleExtern() {
1044 if (PrototypeAST *P = ParseExtern()) {
1045 if (Function *F = P->Codegen()) {
1046 #ifndef MINIMAL_STDERR_OUTPUT
1047 fprintf(stderr, "Read extern: ");
1048 F->dump();
1049 #endif
1050 }
1051 } else {
1052 // Skip token for error recovery.
1053 getNextToken();
1054 }
1055 }
1056
1057 static void HandleTopLevelExpression() {
1058 // Evaluate a top-level expression into an anonymous function.
1059 if (FunctionAST *F = ParseTopLevelExpr()) {
1060 if (Function *LF = F->Codegen()) {
1061 // JIT the function, returning a function pointer.
1062 void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
1063 // Cast it to the right type (takes no arguments, returns a double) so we
1064 // can call it as a native function.
1065 double (*FP)() = (double (*)())(intptr_t)FPtr;
1066 #ifdef MINIMAL_STDERR_OUTPUT
1067 FP();
1068 #else
1069 fprintf(stderr, "Evaluated to %f\n", FP());
1070 #endif
1071 }
1072 } else {
1073 // Skip token for error recovery.
1074 getNextToken();
1075 }
1076 }
1077
1078 /// top ::= definition | external | expression | ';'
1079 static void MainLoop() {
1080 while (1) {
1081 #ifndef MINIMAL_STDERR_OUTPUT
1082 fprintf(stderr, "ready> ");
1083 #endif
1084 switch (CurTok) {
1085 case tok_eof: return;
1086 case ';': getNextToken(); break; // ignore top-level semicolons.
1087 case tok_def: HandleDefinition(); break;
1088 case tok_extern: HandleExtern(); break;
1089 default: HandleTopLevelExpression(); break;
1090 }
1091 }
1092 }
1093
1094 //===----------------------------------------------------------------------===//
1095 // "Library" functions that can be "extern'd" from user code.
1096 //===----------------------------------------------------------------------===//
1097
1098 /// putchard - putchar that takes a double and returns 0.
1099 extern "C"
1100 double putchard(double X) {
1101 putchar((char)X);
1102 return 0;
1103 }
1104
1105 /// printd - printf that takes a double prints it as "%f\n", returning 0.
1106 extern "C"
1107 double printd(double X) {
1108 printf("%f", X);
1109 return 0;
1110 }
1111
1112 extern "C"
1113 double printlf() {
1114 printf("\n");
1115 return 0;
1116 }
1117
1118 //===----------------------------------------------------------------------===//
1119 // Command line input file handlers
1120 //===----------------------------------------------------------------------===//
1121
1122 Module* parseInputIR(std::string InputFile) {
1123 SMDiagnostic Err;
1124 Module *M = ParseIRFile(InputFile, Err, getGlobalContext());
1125 if (!M) {
1126 Err.print("IR parsing failed: ", errs());
1127 return NULL;
1128 }
1129
1130 return M;
1131 }
1132
1133 //===----------------------------------------------------------------------===//
1134 // Main driver code.
1135 //===----------------------------------------------------------------------===//
1136
1137 int main(int argc, char **argv) {
1138 InitializeNativeTarget();
1139 LLVMContext &Context = getGlobalContext();
1140
1141 cl::ParseCommandLineOptions(argc, argv,
1142 "Kaleidoscope example program\n");
1143
1144 // Install standard binary operators.
1145 // 1 is lowest precedence.
1146 BinopPrecedence['='] = 2;
1147 BinopPrecedence['<'] = 10;
1148 BinopPrecedence['+'] = 20;
1149 BinopPrecedence['-'] = 20;
1150 BinopPrecedence['/'] = 40;
1151 BinopPrecedence['*'] = 40; // highest.
1152
1153 // Make the module, which holds all the code.
1154 if (!InputIR.empty()) {
1155 TheModule = parseInputIR(InputIR);
1156 } else {
1157 TheModule = new Module("my cool jit", Context);
1158 }
1159
1160 // Create the JIT. This takes ownership of the module.
1161 std::string ErrStr;
1162 TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
1163 if (!TheExecutionEngine) {
1164 fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
1165 exit(1);
1166 }
1167
1168 FunctionPassManager OurFPM(TheModule);
1169
1170 // Set up the optimizer pipeline. Start with registering info about how the
1171 // target lays out data structures.
1172 OurFPM.add(new DataLayout(*TheExecutionEngine->getDataLayout()));
1173 // Provide basic AliasAnalysis support for GVN.
1174 OurFPM.add(createBasicAliasAnalysisPass());
1175 // Promote allocas to registers.
1176 OurFPM.add(createPromoteMemoryToRegisterPass());
1177 // Do simple "peephole" optimizations and bit-twiddling optzns.
1178 OurFPM.add(createInstructionCombiningPass());
1179 // Reassociate expressions.
1180 OurFPM.add(createReassociatePass());
1181 // Eliminate Common SubExpressions.
1182 OurFPM.add(createGVNPass());
1183 // Simplify the control flow graph (deleting unreachable blocks, etc).
1184 OurFPM.add(createCFGSimplificationPass());
1185
1186 OurFPM.doInitialization();
1187
1188 // Set the global so the code gen can use this.
1189 TheFPM = &OurFPM;
1190
1191 // Prime the first token.
1192 #ifndef MINIMAL_STDERR_OUTPUT
1193 fprintf(stderr, "ready> ");
1194 #endif
1195 getNextToken();
1196
1197 // Run the main "interpreter loop" now.
1198 MainLoop();
1199
1200 // Print out all of the generated code.
1201 TheFPM = 0;
1202 #if !defined(MINIMAL_STDERR_OUTPUT) || defined(DUMP_FINAL_MODULE)
1203 TheModule->dump();
1204 #endif
1205 return 0;
1206 }
0 #define MINIMAL_STDERR_OUTPUT
1
2 #include "llvm/Analysis/Passes.h"
3 #include "llvm/Analysis/Verifier.h"
4 #include "llvm/ExecutionEngine/ExecutionEngine.h"
5 #include "llvm/ExecutionEngine/MCJIT.h"
6 #include "llvm/ExecutionEngine/ObjectCache.h"
7 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
8 #include "llvm/IR/DataLayout.h"
9 #include "llvm/IR/DerivedTypes.h"
10 #include "llvm/IR/IRBuilder.h"
11 #include "llvm/IR/LLVMContext.h"
12 #include "llvm/IR/Module.h"
13 #include "llvm/IRReader/IRReader.h"
14 #include "llvm/PassManager.h"
15 #include "llvm/Support/CommandLine.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Path.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "llvm/Support/TargetSelect.h"
21 #include "llvm/Transforms/Scalar.h"
22 #include
23 #include
24 #include
25 #include
26 using namespace llvm;
27
28 //===----------------------------------------------------------------------===//
29 // Command-line options
30 //===----------------------------------------------------------------------===//
31
32 cl::opt
33 InputIR("input-IR",
34 cl::desc("Specify the name of an IR file to load for function definitions"),
35 cl::value_desc("input IR file name"));
36
37 cl::opt
38 UseObjectCache("use-object-cache",
39 cl::desc("Enable use of the MCJIT object caching"),
40 cl::init(false));
41
42 //===----------------------------------------------------------------------===//
43 // Lexer
44 //===----------------------------------------------------------------------===//
45
46 // The lexer returns tokens [0-255] if it is an unknown character, otherwise one
47 // of these for known things.
48 enum Token {
49 tok_eof = -1,
50
51 // commands
52 tok_def = -2, tok_extern = -3,
53
54 // primary
55 tok_identifier = -4, tok_number = -5,
56
57 // control
58 tok_if = -6, tok_then = -7, tok_else = -8,
59 tok_for = -9, tok_in = -10,
60
61 // operators
62 tok_binary = -11, tok_unary = -12,
63
64 // var definition
65 tok_var = -13
66 };
67
68 static std::string IdentifierStr; // Filled in if tok_identifier
69 static double NumVal; // Filled in if tok_number
70
71 /// gettok - Return the next token from standard input.
72 static int gettok() {
73 static int LastChar = ' ';
74
75 // Skip any whitespace.
76 while (isspace(LastChar))
77 LastChar = getchar();
78
79 if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
80 IdentifierStr = LastChar;
81 while (isalnum((LastChar = getchar())))
82 IdentifierStr += LastChar;
83
84 if (IdentifierStr == "def") return tok_def;
85 if (IdentifierStr == "extern") return tok_extern;
86 if (IdentifierStr == "if") return tok_if;
87 if (IdentifierStr == "then") return tok_then;
88 if (IdentifierStr == "else") return tok_else;
89 if (IdentifierStr == "for") return tok_for;
90 if (IdentifierStr == "in") return tok_in;
91 if (IdentifierStr == "binary") return tok_binary;
92 if (IdentifierStr == "unary") return tok_unary;
93 if (IdentifierStr == "var") return tok_var;
94 return tok_identifier;
95 }
96
97 if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+
98 std::string NumStr;
99 do {
100 NumStr += LastChar;
101 LastChar = getchar();
102 } while (isdigit(LastChar) || LastChar == '.');
103
104 NumVal = strtod(NumStr.c_str(), 0);
105 return tok_number;
106 }
107
108 if (LastChar == '#') {
109 // Comment until end of line.
110 do LastChar = getchar();
111 while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
112
113 if (LastChar != EOF)
114 return gettok();
115 }
116
117 // Check for end of file. Don't eat the EOF.
118 if (LastChar == EOF)
119 return tok_eof;
120
121 // Otherwise, just return the character as its ascii value.
122 int ThisChar = LastChar;
123 LastChar = getchar();
124 return ThisChar;
125 }
126
127 //===----------------------------------------------------------------------===//
128 // Abstract Syntax Tree (aka Parse Tree)
129 //===----------------------------------------------------------------------===//
130
131 /// ExprAST - Base class for all expression nodes.
132 class ExprAST {
133 public:
134 virtual ~ExprAST() {}
135 virtual Value *Codegen() = 0;
136 };
137
138 /// NumberExprAST - Expression class for numeric literals like "1.0".
139 class NumberExprAST : public ExprAST {
140 double Val;
141 public:
142 NumberExprAST(double val) : Val(val) {}
143 virtual Value *Codegen();
144 };
145
146 /// VariableExprAST - Expression class for referencing a variable, like "a".
147 class VariableExprAST : public ExprAST {
148 std::string Name;
149 public:
150 VariableExprAST(const std::string &name) : Name(name) {}
151 const std::string &getName() const { return Name; }
152 virtual Value *Codegen();
153 };
154
155 /// UnaryExprAST - Expression class for a unary operator.
156 class UnaryExprAST : public ExprAST {
157 char Opcode;
158 ExprAST *Operand;
159 public:
160 UnaryExprAST(char opcode, ExprAST *operand)
161 : Opcode(opcode), Operand(operand) {}
162 virtual Value *Codegen();
163 };
164
165 /// BinaryExprAST - Expression class for a binary operator.
166 class BinaryExprAST : public ExprAST {
167 char Op;
168 ExprAST *LHS, *RHS;
169 public:
170 BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs)
171 : Op(op), LHS(lhs), RHS(rhs) {}
172 virtual Value *Codegen();
173 };
174
175 /// CallExprAST - Expression class for function calls.
176 class CallExprAST : public ExprAST {
177 std::string Callee;
178 std::vector Args;
179 public:
180 CallExprAST(const std::string &callee, std::vector &args)
181 : Callee(callee), Args(args) {}
182 virtual Value *Codegen();
183 };
184
185 /// IfExprAST - Expression class for if/then/else.
186 class IfExprAST : public ExprAST {
187 ExprAST *Cond, *Then, *Else;
188 public:
189 IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
190 : Cond(cond), Then(then), Else(_else) {}
191 virtual Value *Codegen();
192 };
193
194 /// ForExprAST - Expression class for for/in.
195 class ForExprAST : public ExprAST {
196 std::string VarName;
197 ExprAST *Start, *End, *Step, *Body;
198 public:
199 ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
200 ExprAST *step, ExprAST *body)
201 : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
202 virtual Value *Codegen();
203 };
204
205 /// VarExprAST - Expression class for var/in
206 class VarExprAST : public ExprAST {
207 std::vector > VarNames;
208 ExprAST *Body;
209 public:
210 VarExprAST(const std::vector > &varnames,
211 ExprAST *body)
212 : VarNames(varnames), Body(body) {}
213
214 virtual Value *Codegen();
215 };
216
217 /// PrototypeAST - This class represents the "prototype" for a function,
218 /// which captures its argument names as well as if it is an operator.
219 class PrototypeAST {
220 std::string Name;
221 std::vector Args;
222 bool isOperator;
223 unsigned Precedence; // Precedence if a binary op.
224 public:
225 PrototypeAST(const std::string &name, const std::vector &args,
226 bool isoperator = false, unsigned prec = 0)
227 : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {}
228
229 bool isUnaryOp() const { return isOperator && Args.size() == 1; }
230 bool isBinaryOp() const { return isOperator && Args.size() == 2; }
231
232 char getOperatorName() const {
233 assert(isUnaryOp() || isBinaryOp());
234 return Name[Name.size()-1];
235 }
236
237 unsigned getBinaryPrecedence() const { return Precedence; }
238
239 Function *Codegen();
240
241 void CreateArgumentAllocas(Function *F);
242 };
243
244 /// FunctionAST - This class represents a function definition itself.
245 class FunctionAST {
246 PrototypeAST *Proto;
247 ExprAST *Body;
248 public:
249 FunctionAST(PrototypeAST *proto, ExprAST *body)
250 : Proto(proto), Body(body) {}
251
252 Function *Codegen();
253 };
254
255 //===----------------------------------------------------------------------===//
256 // Parser
257 //===----------------------------------------------------------------------===//
258
259 /// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
260 /// token the parser is looking at. getNextToken reads another token from the
261 /// lexer and updates CurTok with its results.
262 static int CurTok;
263 static int getNextToken() {
264 return CurTok = gettok();
265 }
266
267 /// BinopPrecedence - This holds the precedence for each binary operator that is
268 /// defined.
269 static std::map BinopPrecedence;
270
271 /// GetTokPrecedence - Get the precedence of the pending binary operator token.
272 static int GetTokPrecedence() {
273 if (!isascii(CurTok))
274 return -1;
275
276 // Make sure it's a declared binop.
277 int TokPrec = BinopPrecedence[CurTok];
278 if (TokPrec <= 0) return -1;
279 return TokPrec;
280 }
281
282 /// Error* - These are little helper functions for error handling.
283 ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
284 PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
285 FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
286
287 static ExprAST *ParseExpression();
288
289 /// identifierexpr
290 /// ::= identifier
291 /// ::= identifier '(' expression* ')'
292 static ExprAST *ParseIdentifierExpr() {
293 std::string IdName = IdentifierStr;
294
295 getNextToken(); // eat identifier.
296
297 if (CurTok != '(') // Simple variable ref.
298 return new VariableExprAST(IdName);
299
300 // Call.
301 getNextToken(); // eat (
302 std::vector Args;
303 if (CurTok != ')') {
304 while (1) {
305 ExprAST *Arg = ParseExpression();
306 if (!Arg) return 0;
307 Args.push_back(Arg);
308
309 if (CurTok == ')') break;
310
311 if (CurTok != ',')
312 return Error("Expected ')' or ',' in argument list");
313 getNextToken();
314 }
315 }
316
317 // Eat the ')'.
318 getNextToken();
319
320 return new CallExprAST(IdName, Args);
321 }
322
323 /// numberexpr ::= number
324 static ExprAST *ParseNumberExpr() {
325 ExprAST *Result = new NumberExprAST(NumVal);
326 getNextToken(); // consume the number
327 return Result;
328 }
329
330 /// parenexpr ::= '(' expression ')'
331 static ExprAST *ParseParenExpr() {
332 getNextToken(); // eat (.
333 ExprAST *V = ParseExpression();
334 if (!V) return 0;
335
336 if (CurTok != ')')
337 return Error("expected ')'");
338 getNextToken(); // eat ).
339 return V;
340 }
341
342 /// ifexpr ::= 'if' expression 'then' expression 'else' expression
343 static ExprAST *ParseIfExpr() {
344 getNextToken(); // eat the if.
345
346 // condition.
347 ExprAST *Cond = ParseExpression();
348 if (!Cond) return 0;
349
350 if (CurTok != tok_then)
351 return Error("expected then");
352 getNextToken(); // eat the then
353
354 ExprAST *Then = ParseExpression();
355 if (Then == 0) return 0;
356
357 if (CurTok != tok_else)
358 return Error("expected else");
359
360 getNextToken();
361
362 ExprAST *Else = ParseExpression();
363 if (!Else) return 0;
364
365 return new IfExprAST(Cond, Then, Else);
366 }
367
368 /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
369 static ExprAST *ParseForExpr() {
370 getNextToken(); // eat the for.
371
372 if (CurTok != tok_identifier)
373 return Error("expected identifier after for");
374
375 std::string IdName = IdentifierStr;
376 getNextToken(); // eat identifier.
377
378 if (CurTok != '=')
379 return Error("expected '=' after for");
380 getNextToken(); // eat '='.
381
382
383 ExprAST *Start = ParseExpression();
384 if (Start == 0) return 0;
385 if (CurTok != ',')
386 return Error("expected ',' after for start value");
387 getNextToken();
388
389 ExprAST *End = ParseExpression();
390 if (End == 0) return 0;
391
392 // The step value is optional.
393 ExprAST *Step = 0;
394 if (CurTok == ',') {
395 getNextToken();
396 Step = ParseExpression();
397 if (Step == 0) return 0;
398 }
399
400 if (CurTok != tok_in)
401 return Error("expected 'in' after for");
402 getNextToken(); // eat 'in'.
403
404 ExprAST *Body = ParseExpression();
405 if (Body == 0) return 0;
406
407 return new ForExprAST(IdName, Start, End, Step, Body);
408 }
409
410 /// varexpr ::= 'var' identifier ('=' expression)?
411 // (',' identifier ('=' expression)?)* 'in' expression
412 static ExprAST *ParseVarExpr() {
413 getNextToken(); // eat the var.
414
415 std::vector > VarNames;
416
417 // At least one variable name is required.
418 if (CurTok != tok_identifier)
419 return Error("expected identifier after var");
420
421 while (1) {
422 std::string Name = IdentifierStr;
423 getNextToken(); // eat identifier.
424
425 // Read the optional initializer.
426 ExprAST *Init = 0;
427 if (CurTok == '=') {
428 getNextToken(); // eat the '='.
429
430 Init = ParseExpression();
431 if (Init == 0) return 0;
432 }
433
434 VarNames.push_back(std::make_pair(Name, Init));
435
436 // End of var list, exit loop.
437 if (CurTok != ',') break;
438 getNextToken(); // eat the ','.
439
440 if (CurTok != tok_identifier)
441 return Error("expected identifier list after var");
442 }
443
444 // At this point, we have to have 'in'.
445 if (CurTok != tok_in)
446 return Error("expected 'in' keyword after 'var'");
447 getNextToken(); // eat 'in'.
448
449 ExprAST *Body = ParseExpression();
450 if (Body == 0) return 0;
451
452 return new VarExprAST(VarNames, Body);
453 }
454
455 /// primary
456 /// ::= identifierexpr
457 /// ::= numberexpr
458 /// ::= parenexpr
459 /// ::= ifexpr
460 /// ::= forexpr
461 /// ::= varexpr
462 static ExprAST *ParsePrimary() {
463 switch (CurTok) {
464 default: return Error("unknown token when expecting an expression");
465 case tok_identifier: return ParseIdentifierExpr();
466 case tok_number: return ParseNumberExpr();
467 case '(': return ParseParenExpr();
468 case tok_if: return ParseIfExpr();
469 case tok_for: return ParseForExpr();
470 case tok_var: return ParseVarExpr();
471 }
472 }
473
474 /// unary
475 /// ::= primary
476 /// ::= '!' unary
477 static ExprAST *ParseUnary() {
478 // If the current token is not an operator, it must be a primary expr.
479 if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
480 return ParsePrimary();
481
482 // If this is a unary operator, read it.
483 int Opc = CurTok;
484 getNextToken();
485 if (ExprAST *Operand = ParseUnary())
486 return new UnaryExprAST(Opc, Operand);
487 return 0;
488 }
489
490 /// binoprhs
491 /// ::= ('+' unary)*
492 static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
493 // If this is a binop, find its precedence.
494 while (1) {
495 int TokPrec = GetTokPrecedence();
496
497 // If this is a binop that binds at least as tightly as the current binop,
498 // consume it, otherwise we are done.
499 if (TokPrec < ExprPrec)
500 return LHS;
501
502 // Okay, we know this is a binop.
503 int BinOp = CurTok;
504 getNextToken(); // eat binop
505
506 // Parse the unary expression after the binary operator.
507 ExprAST *RHS = ParseUnary();
508 if (!RHS) return 0;
509
510 // If BinOp binds less tightly with RHS than the operator after RHS, let
511 // the pending operator take RHS as its LHS.
512 int NextPrec = GetTokPrecedence();
513 if (TokPrec < NextPrec) {
514 RHS = ParseBinOpRHS(TokPrec+1, RHS);
515 if (RHS == 0) return 0;
516 }
517
518 // Merge LHS/RHS.
519 LHS = new BinaryExprAST(BinOp, LHS, RHS);
520 }
521 }
522
523 /// expression
524 /// ::= unary binoprhs
525 ///
526 static ExprAST *ParseExpression() {
527 ExprAST *LHS = ParseUnary();
528 if (!LHS) return 0;
529
530 return ParseBinOpRHS(0, LHS);
531 }
532
533 /// prototype
534 /// ::= id '(' id* ')'
535 /// ::= binary LETTER number? (id, id)
536 /// ::= unary LETTER (id)
537 static PrototypeAST *ParsePrototype() {
538 std::string FnName;
539
540 unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
541 unsigned BinaryPrecedence = 30;
542
543 switch (CurTok) {
544 default:
545 return ErrorP("Expected function name in prototype");
546 case tok_identifier:
547 FnName = IdentifierStr;
548 Kind = 0;
549 getNextToken();
550 break;
551 case tok_unary:
552 getNextToken();
553 if (!isascii(CurTok))
554 return ErrorP("Expected unary operator");
555 FnName = "unary";
556 FnName += (char)CurTok;
557 Kind = 1;
558 getNextToken();
559 break;
560 case tok_binary:
561 getNextToken();
562 if (!isascii(CurTok))
563 return ErrorP("Expected binary operator");
564 FnName = "binary";
565 FnName += (char)CurTok;
566 Kind = 2;
567 getNextToken();
568
569 // Read the precedence if present.
570 if (CurTok == tok_number) {
571 if (NumVal < 1 || NumVal > 100)
572 return ErrorP("Invalid precedecnce: must be 1..100");
573 BinaryPrecedence = (unsigned)NumVal;
574 getNextToken();
575 }
576 break;
577 }
578
579 if (CurTok != '(')
580 return ErrorP("Expected '(' in prototype");
581
582 std::vector ArgNames;
583 while (getNextToken() == tok_identifier)
584 ArgNames.push_back(IdentifierStr);
585 if (CurTok != ')')
586 return ErrorP("Expected ')' in prototype");
587
588 // success.
589 getNextToken(); // eat ')'.
590
591 // Verify right number of names for operator.
592 if (Kind && ArgNames.size() != Kind)
593 return ErrorP("Invalid number of operands for operator");
594
595 return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence);
596 }
597
598 /// definition ::= 'def' prototype expression
599 static FunctionAST *ParseDefinition() {
600 getNextToken(); // eat def.
601 PrototypeAST *Proto = ParsePrototype();
602 if (Proto == 0) return 0;
603
604 if (ExprAST *E = ParseExpression())
605 return new FunctionAST(Proto, E);
606 return 0;
607 }
608
609 /// toplevelexpr ::= expression
610 static FunctionAST *ParseTopLevelExpr() {
611 if (ExprAST *E = ParseExpression()) {
612 // Make an anonymous proto.
613 PrototypeAST *Proto = new PrototypeAST("", std::vector());
614 return new FunctionAST(Proto, E);
615 }
616 return 0;
617 }
618
619 /// external ::= 'extern' prototype
620 static PrototypeAST *ParseExtern() {
621 getNextToken(); // eat extern.
622 return ParsePrototype();
623 }
624
625 //===----------------------------------------------------------------------===//
626 // Quick and dirty hack
627 //===----------------------------------------------------------------------===//
628
629 // FIXME: Obviously we can do better than this
630 std::string GenerateUniqueName(const char *root)
631 {
632 static int i = 0;
633 char s[16];
634 sprintf(s, "%s%d", root, i++);
635 std::string S = s;
636 return S;
637 }
638
639 std::string MakeLegalFunctionName(std::string Name)
640 {
641 std::string NewName;
642 if (!Name.length())
643 return GenerateUniqueName("anon_func_");
644
645 // Start with what we have
646 NewName = Name;
647
648 // Look for a numberic first character
649 if (NewName.find_first_of("0123456789") == 0) {
650 NewName.insert(0, 1, 'n');
651 }
652
653 // Replace illegal characters with their ASCII equivalent
654 std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
655 size_t pos;
656 while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) {
657 char old_c = NewName.at(pos);
658 char new_str[16];
659 sprintf(new_str, "%d", (int)old_c);
660 NewName = NewName.replace(pos, 1, new_str);
661 }
662
663 return NewName;
664 }
665
666 //===----------------------------------------------------------------------===//
667 // MCJIT object cache class
668 //===----------------------------------------------------------------------===//
669
670 class MCJITObjectCache : public ObjectCache {
671 public:
672 MCJITObjectCache() {
673 // Set IR cache directory
674 sys::fs::current_path(CacheDir);
675 sys::path::append(CacheDir, "toy_object_cache");
676 }
677
678 virtual ~MCJITObjectCache() {
679 }
680
681 virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) {
682 // Get the ModuleID
683 const std::string ModuleID = M->getModuleIdentifier();
684
685 // If we've flagged this as an IR file, cache it
686 if (0 == ModuleID.compare(0, 3, "IR:")) {
687 std::string IRFileName = ModuleID.substr(3);
688 SmallString<128>IRCacheFile = CacheDir;
689 sys::path::append(IRCacheFile, IRFileName);
690 if (!sys::fs::exists(CacheDir.str()) && sys::fs::create_directory(CacheDir.str())) {
691 fprintf(stderr, "Unable to create cache directory\n");
692 return;
693 }
694 std::string ErrStr;
695 raw_fd_ostream IRObjectFile(IRCacheFile.c_str(), ErrStr, raw_fd_ostream::F_Binary);
696 IRObjectFile << Obj->getBuffer();
697 }
698 }
699
700 // MCJIT will call this function before compiling any module
701 // MCJIT takes ownership of both the MemoryBuffer object and the memory
702 // to which it refers.
703 virtual MemoryBuffer* getObject(const Module* M) {
704 // Get the ModuleID
705 const std::string ModuleID = M->getModuleIdentifier();
706
707 // If we've flagged this as an IR file, cache it
708 if (0 == ModuleID.compare(0, 3, "IR:")) {
709 std::string IRFileName = ModuleID.substr(3);
710 SmallString<128> IRCacheFile = CacheDir;
711 sys::path::append(IRCacheFile, IRFileName);
712 if (!sys::fs::exists(IRCacheFile.str())) {
713 // This file isn't in our cache
714 return NULL;
715 }
716 OwningPtr IRObjectBuffer;
717 MemoryBuffer::getFile(IRCacheFile.c_str(), IRObjectBuffer, -1, false);
718 // MCJIT will want to write into this buffer, and we don't want that
719 // because the file has probably just been mmapped. Instead we make
720 // a copy. The filed-based buffer will be released when it goes
721 // out of scope.
722 return MemoryBuffer::getMemBufferCopy(IRObjectBuffer->getBuffer());
723 }
724
725 return NULL;
726 }
727
728 private:
729 SmallString<128> CacheDir;
730 };
731
732 //===----------------------------------------------------------------------===//
733 // MCJIT helper class
734 //===----------------------------------------------------------------------===//
735
736 class MCJITHelper
737 {
738 public:
739 MCJITHelper(LLVMContext& C) : Context(C), OpenModule(NULL) {}
740 ~MCJITHelper();
741
742 Function *getFunction(const std::string FnName);
743 Module *getModuleForNewFunction();
744 void *getPointerToFunction(Function* F);
745 void *getPointerToNamedFunction(const std::string &Name);
746 ExecutionEngine *compileModule(Module *M);
747 void closeCurrentModule();
748 void addModule(Module *M);
749 void dump();
750
751 private:
752 typedef std::vector ModuleVector;
753
754 LLVMContext &Context;
755 Module *OpenModule;
756 ModuleVector Modules;
757 std::map EngineMap;
758 MCJITObjectCache OurObjectCache;
759 };
760
761 class HelpingMemoryManager : public SectionMemoryManager
762 {
763 HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION;
764 void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION;
765
766 public:
767 HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {}
768 virtual ~HelpingMemoryManager() {}
769
770 /// This method returns the address of the specified function.
771 /// Our implementation will attempt to find functions in other
772 /// modules associated with the MCJITHelper to cross link functions
773 /// from one generated module to another.
774 ///
775 /// If \p AbortOnFailure is false and no function with the given name is
776 /// found, this function returns a null pointer. Otherwise, it prints a
777 /// message to stderr and aborts.
778 virtual void *getPointerToNamedFunction(const std::string &Name,
779 bool AbortOnFailure = true);
780 private:
781 MCJITHelper *MasterHelper;
782 };
783
784 void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name,
785 bool AbortOnFailure)
786 {
787 // Try the standard symbol resolution first, but ask it not to abort.
788 void *pfn = SectionMemoryManager::getPointerToNamedFunction(Name, false);
789 if (pfn)
790 return pfn;
791
792 pfn = MasterHelper->getPointerToNamedFunction(Name);
793 if (!pfn && AbortOnFailure)
794 report_fatal_error("Program used external function '" + Name +
795 "' which could not be resolved!");
796 return pfn;
797 }
798
799 MCJITHelper::~MCJITHelper()
800 {
801 // Walk the vector of modules.
802 ModuleVector::iterator it, end;
803 for (it = Modules.begin(), end = Modules.end();
804 it != end; ++it) {
805 // See if we have an execution engine for this module.
806 std::map::iterator mapIt = EngineMap.find(*it);
807 // If we have an EE, the EE owns the module so just delete the EE.
808 if (mapIt != EngineMap.end()) {
809 delete mapIt->second;
810 } else {
811 // Otherwise, we still own the module. Delete it now.
812 delete *it;
813 }
814 }
815 }
816
817 Function *MCJITHelper::getFunction(const std::string FnName) {
818 ModuleVector::iterator begin = Modules.begin();
819 ModuleVector::iterator end = Modules.end();
820 ModuleVector::iterator it;
821 for (it = begin; it != end; ++it) {
822 Function *F = (*it)->getFunction(FnName);
823 if (F) {
824 if (*it == OpenModule)
825 return F;
826
827 assert(OpenModule != NULL);
828
829 // This function is in a module that has already been JITed.
830 // We need to generate a new prototype for external linkage.
831 Function *PF = OpenModule->getFunction(FnName);
832 if (PF && !PF->empty()) {
833 ErrorF("redefinition of function across modules");
834 return 0;
835 }
836
837 // If we don't have a prototype yet, create one.
838 if (!PF)
839 PF = Function::Create(F->getFunctionType(),
840 Function::ExternalLinkage,
841 FnName,
842 OpenModule);
843 return PF;
844 }
845 }
846 return NULL;
847 }
848
849 Module *MCJITHelper::getModuleForNewFunction() {
850 // If we have a Module that hasn't been JITed, use that.
851 if (OpenModule)
852 return OpenModule;
853
854 // Otherwise create a new Module.
855 std::string ModName = GenerateUniqueName("mcjit_module_");
856 Module *M = new Module(ModName, Context);
857 Modules.push_back(M);
858 OpenModule = M;
859 return M;
860 }
861
862 void *MCJITHelper::getPointerToFunction(Function* F) {
863 // Look for this function in an existing module
864 ModuleVector::iterator begin = Modules.begin();
865 ModuleVector::iterator end = Modules.end();
866 ModuleVector::iterator it;
867 std::string FnName = F->getName();
868 for (it = begin; it != end; ++it) {
869 Function *MF = (*it)->getFunction(FnName);
870 if (MF == F) {
871 std::map::iterator eeIt = EngineMap.find(*it);
872 if (eeIt != EngineMap.end()) {
873 void *P = eeIt->second->getPointerToFunction(F);
874 if (P)
875 return P;
876 } else {
877 ExecutionEngine *EE = compileModule(*it);
878 void *P = EE->getPointerToFunction(F);
879 if (P)
880 return P;
881 }
882 }
883 }
884 return NULL;
885 }
886
887 void MCJITHelper::closeCurrentModule() {
888 OpenModule = NULL;
889 }
890
891 ExecutionEngine *MCJITHelper::compileModule(Module *M) {
892 if (M == OpenModule)
893 closeCurrentModule();
894
895 std::string ErrStr;
896 ExecutionEngine *NewEngine = EngineBuilder(M)
897 .setErrorStr(&ErrStr)
898 .setUseMCJIT(true)
899 .setMCJITMemoryManager(new HelpingMemoryManager(this))
900 .create();
901 if (!NewEngine) {
902 fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
903 exit(1);
904 }
905
906 if (UseObjectCache)
907 NewEngine->setObjectCache(&OurObjectCache);
908
909 // Get the ModuleID so we can identify IR input files
910 const std::string ModuleID = M->getModuleIdentifier();
911
912 // If we've flagged this as an IR file, it doesn't need function passes run.
913 if (0 != ModuleID.compare(0, 3, "IR:")) {
914 // Create a function pass manager for this engine
915 FunctionPassManager *FPM = new FunctionPassManager(M);
916
917 // Set up the optimizer pipeline. Start with registering info about how the
918 // target lays out data structures.
919 FPM->add(new DataLayout(*NewEngine->getDataLayout()));
920 // Provide basic AliasAnalysis support for GVN.
921 FPM->add(createBasicAliasAnalysisPass());
922 // Promote allocas to registers.
923 FPM->add(createPromoteMemoryToRegisterPass());
924 // Do simple "peephole" optimizations and bit-twiddling optzns.
925 FPM->add(createInstructionCombiningPass());
926 // Reassociate expressions.
927 FPM->add(createReassociatePass());
928 // Eliminate Common SubExpressions.
929 FPM->add(createGVNPass());
930 // Simplify the control flow graph (deleting unreachable blocks, etc).
931 FPM->add(createCFGSimplificationPass());
932 FPM->doInitialization();
933
934 // For each function in the module
935 Module::iterator it;
936 Module::iterator end = M->end();
937 for (it = M->begin(); it != end; ++it) {
938 // Run the FPM on this function
939 FPM->run(*it);
940 }
941
942 // We don't need this anymore
943 delete FPM;
944 }
945
946 // Store this engine
947 EngineMap[M] = NewEngine;
948 NewEngine->finalizeObject();
949
950 return NewEngine;
951 }
952
953 void *MCJITHelper::getPointerToNamedFunction(const std::string &Name)
954 {
955 // Look for the functions in our modules, compiling only as necessary
956 ModuleVector::iterator begin = Modules.begin();
957 ModuleVector::iterator end = Modules.end();
958 ModuleVector::iterator it;
959 for (it = begin; it != end; ++it) {
960 Function *F = (*it)->getFunction(Name);
961 if (F && !F->empty()) {
962 std::map::iterator eeIt = EngineMap.find(*it);
963 if (eeIt != EngineMap.end()) {
964 void *P = eeIt->second->getPointerToFunction(F);
965 if (P)
966 return P;
967 } else {
968 ExecutionEngine *EE = compileModule(*it);
969 void *P = EE->getPointerToFunction(F);
970 if (P)
971 return P;
972 }
973 }
974 }
975 return NULL;
976 }
977
978 void MCJITHelper::addModule(Module* M) {
979 Modules.push_back(M);
980 }
981
982 void MCJITHelper::dump()
983 {
984 ModuleVector::iterator begin = Modules.begin();
985 ModuleVector::iterator end = Modules.end();
986 ModuleVector::iterator it;
987 for (it = begin; it != end; ++it)
988 (*it)->dump();
989 }
990
991 //===----------------------------------------------------------------------===//
992 // Code Generation
993 //===----------------------------------------------------------------------===//
994
995 static MCJITHelper *TheHelper;
996 static IRBuilder<> Builder(getGlobalContext());
997 static std::map NamedValues;
998
999 Value *ErrorV(const char *Str) { Error(Str); return 0; }
1000
1001 /// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of
1002 /// the function. This is used for mutable variables etc.
1003 static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
1004 const std::string &VarName) {
1005 IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
1006 TheFunction->getEntryBlock().begin());
1007 return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0,
1008 VarName.c_str());
1009 }
1010
1011 Value *NumberExprAST::Codegen() {
1012 return ConstantFP::get(getGlobalContext(), APFloat(Val));
1013 }
1014
1015 Value *VariableExprAST::Codegen() {
1016 // Look this variable up in the function.
1017 Value *V = NamedValues[Name];
1018 char ErrStr[256];
1019 sprintf(ErrStr, "Unknown variable name %s", Name.c_str());
1020 if (V == 0) return ErrorV(ErrStr);
1021
1022 // Load the value.
1023 return Builder.CreateLoad(V, Name.c_str());
1024 }
1025
1026 Value *UnaryExprAST::Codegen() {
1027 Value *OperandV = Operand->Codegen();
1028 if (OperandV == 0) return 0;
1029
1030 Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode));
1031 if (F == 0)
1032 return ErrorV("Unknown unary operator");
1033
1034 return Builder.CreateCall(F, OperandV, "unop");
1035 }
1036
1037 Value *BinaryExprAST::Codegen() {
1038 // Special case '=' because we don't want to emit the LHS as an expression.
1039 if (Op == '=') {
1040 // Assignment requires the LHS to be an identifier.
1041 VariableExprAST *LHSE = reinterpret_cast(LHS);
1042 if (!LHSE)
1043 return ErrorV("destination of '=' must be a variable");
1044 // Codegen the RHS.
1045 Value *Val = RHS->Codegen();
1046 if (Val == 0) return 0;
1047
1048 // Look up the name.
1049 Value *Variable = NamedValues[LHSE->getName()];
1050 if (Variable == 0) return ErrorV("Unknown variable name");
1051
1052 Builder.CreateStore(Val, Variable);
1053 return Val;
1054 }
1055
1056 Value *L = LHS->Codegen();
1057 Value *R = RHS->Codegen();
1058 if (L == 0 || R == 0) return 0;
1059
1060 switch (Op) {
1061 case '+': return Builder.CreateFAdd(L, R, "addtmp");
1062 case '-': return Builder.CreateFSub(L, R, "subtmp");
1063 case '*': return Builder.CreateFMul(L, R, "multmp");
1064 case '/': return Builder.CreateFDiv(L, R, "divtmp");
1065 case '<':
1066 L = Builder.CreateFCmpULT(L, R, "cmptmp");
1067 // Convert bool 0/1 to double 0.0 or 1.0
1068 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
1069 "booltmp");
1070 default: break;
1071 }
1072
1073 // If it wasn't a builtin binary operator, it must be a user defined one. Emit
1074 // a call to it.
1075 Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op));
1076 assert(F && "binary operator not found!");
1077
1078 Value *Ops[] = { L, R };
1079 return Builder.CreateCall(F, Ops, "binop");
1080 }
1081
1082 Value *CallExprAST::Codegen() {
1083 // Look up the name in the global module table.
1084 Function *CalleeF = TheHelper->getFunction(Callee);
1085 if (CalleeF == 0)
1086 return ErrorV("Unknown function referenced");
1087
1088 // If argument mismatch error.
1089 if (CalleeF->arg_size() != Args.size())
1090 return ErrorV("Incorrect # arguments passed");
1091
1092 std::vector ArgsV;
1093 for (unsigned i = 0, e = Args.size(); i != e; ++i) {
1094 ArgsV.push_back(Args[i]->Codegen());
1095 if (ArgsV.back() == 0) return 0;
1096 }
1097
1098 return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
1099 }
1100
1101 Value *IfExprAST::Codegen() {
1102 Value *CondV = Cond->Codegen();
1103 if (CondV == 0) return 0;
1104
1105 // Convert condition to a bool by comparing equal to 0.0.
1106 CondV = Builder.CreateFCmpONE(CondV,
1107 ConstantFP::get(getGlobalContext(), APFloat(0.0)),
1108 "ifcond");
1109
1110 Function *TheFunction = Builder.GetInsertBlock()->getParent();
1111
1112 // Create blocks for the then and else cases. Insert the 'then' block at the
1113 // end of the function.
1114 BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
1115 BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
1116 BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
1117
1118 Builder.CreateCondBr(CondV, ThenBB, ElseBB);
1119
1120 // Emit then value.
1121 Builder.SetInsertPoint(ThenBB);
1122
1123 Value *ThenV = Then->Codegen();
1124 if (ThenV == 0) return 0;
1125
1126 Builder.CreateBr(MergeBB);
1127 // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
1128 ThenBB = Builder.GetInsertBlock();
1129
1130 // Emit else block.
1131 TheFunction->getBasicBlockList().push_back(ElseBB);
1132 Builder.SetInsertPoint(ElseBB);
1133
1134 Value *ElseV = Else->Codegen();
1135 if (ElseV == 0) return 0;
1136
1137 Builder.CreateBr(MergeBB);
1138 // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
1139 ElseBB = Builder.GetInsertBlock();
1140
1141 // Emit merge block.
1142 TheFunction->getBasicBlockList().push_back(MergeBB);
1143 Builder.SetInsertPoint(MergeBB);
1144 PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2,
1145 "iftmp");
1146
1147 PN->addIncoming(ThenV, ThenBB);
1148 PN->addIncoming(ElseV, ElseBB);
1149 return PN;
1150 }
1151
1152 Value *ForExprAST::Codegen() {
1153 // Output this as:
1154 // var = alloca double
1155 // ...
1156 // start = startexpr
1157 // store start -> var
1158 // goto loop
1159 // loop:
1160 // ...
1161 // bodyexpr
1162 // ...
1163 // loopend:
1164 // step = stepexpr
1165 // endcond = endexpr
1166 //
1167 // curvar = load var
1168 // nextvar = curvar + step
1169 // store nextvar -> var
1170 // br endcond, loop, endloop
1171 // outloop:
1172
1173 Function *TheFunction = Builder.GetInsertBlock()->getParent();
1174
1175 // Create an alloca for the variable in the entry block.
1176 AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
1177
1178 // Emit the start code first, without 'variable' in scope.
1179 Value *StartVal = Start->Codegen();
1180 if (StartVal == 0) return 0;
1181
1182 // Store the value into the alloca.
1183 Builder.CreateStore(StartVal, Alloca);
1184
1185 // Make the new basic block for the loop header, inserting after current
1186 // block.
1187 BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
1188
1189 // Insert an explicit fall through from the current block to the LoopBB.
1190 Builder.CreateBr(LoopBB);
1191
1192 // Start insertion in LoopBB.
1193 Builder.SetInsertPoint(LoopBB);
1194
1195 // Within the loop, the variable is defined equal to the PHI node. If it
1196 // shadows an existing variable, we have to restore it, so save it now.
1197 AllocaInst *OldVal = NamedValues[VarName];
1198 NamedValues[VarName] = Alloca;
1199
1200 // Emit the body of the loop. This, like any other expr, can change the
1201 // current BB. Note that we ignore the value computed by the body, but don't
1202 // allow an error.
1203 if (Body->Codegen() == 0)
1204 return 0;
1205
1206 // Emit the step value.
1207 Value *StepVal;
1208 if (Step) {
1209 StepVal = Step->Codegen();
1210 if (StepVal == 0) return 0;
1211 } else {
1212 // If not specified, use 1.0.
1213 StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
1214 }
1215
1216 // Compute the end condition.
1217 Value *EndCond = End->Codegen();
1218 if (EndCond == 0) return EndCond;
1219
1220 // Reload, increment, and restore the alloca. This handles the case where
1221 // the body of the loop mutates the variable.
1222 Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str());
1223 Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar");
1224 Builder.CreateStore(NextVar, Alloca);
1225
1226 // Convert condition to a bool by comparing equal to 0.0.
1227 EndCond = Builder.CreateFCmpONE(EndCond,
1228 ConstantFP::get(getGlobalContext(), APFloat(0.0)),
1229 "loopcond");
1230
1231 // Create the "after loop" block and insert it.
1232 BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
1233
1234 // Insert the conditional branch into the end of LoopEndBB.
1235 Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
1236
1237 // Any new code will be inserted in AfterBB.
1238 Builder.SetInsertPoint(AfterBB);
1239
1240 // Restore the unshadowed variable.
1241 if (OldVal)
1242 NamedValues[VarName] = OldVal;
1243 else
1244 NamedValues.erase(VarName);
1245
1246
1247 // for expr always returns 0.0.
1248 return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
1249 }
1250
1251 Value *VarExprAST::Codegen() {
1252 std::vector OldBindings;
1253
1254 Function *TheFunction = Builder.GetInsertBlock()->getParent();
1255
1256 // Register all variables and emit their initializer.
1257 for (unsigned i = 0, e = VarNames.size(); i != e; ++i) {
1258 const std::string &VarName = VarNames[i].first;
1259 ExprAST *Init = VarNames[i].second;
1260
1261 // Emit the initializer before adding the variable to scope, this prevents
1262 // the initializer from referencing the variable itself, and permits stuff
1263 // like this:
1264 // var a = 1 in
1265 // var a = a in ... # refers to outer 'a'.
1266 Value *InitVal;
1267 if (Init) {
1268 InitVal = Init->Codegen();
1269 if (InitVal == 0) return 0;
1270 } else { // If not specified, use 0.0.
1271 InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0));
1272 }
1273
1274 AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
1275 Builder.CreateStore(InitVal, Alloca);
1276
1277 // Remember the old variable binding so that we can restore the binding when
1278 // we unrecurse.
1279 OldBindings.push_back(NamedValues[VarName]);
1280
1281 // Remember this binding.
1282 NamedValues[VarName] = Alloca;
1283 }
1284
1285 // Codegen the body, now that all vars are in scope.
1286 Value *BodyVal = Body->Codegen();
1287 if (BodyVal == 0) return 0;
1288
1289 // Pop all our variables from scope.
1290 for (unsigned i = 0, e = VarNames.size(); i != e; ++i)
1291 NamedValues[VarNames[i].first] = OldBindings[i];
1292
1293 // Return the body computation.
1294 return BodyVal;
1295 }
1296
1297 Function *PrototypeAST::Codegen() {
1298 // Make the function type: double(double,double) etc.
1299 std::vector Doubles(Args.size(),
1300 Type::getDoubleTy(getGlobalContext()));
1301 FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
1302 Doubles, false);
1303
1304 std::string FnName = MakeLegalFunctionName(Name);
1305
1306 Module* M = TheHelper->getModuleForNewFunction();
1307
1308 Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M);
1309
1310 // If F conflicted, there was already something named 'FnName'. If it has a
1311 // body, don't allow redefinition or reextern.
1312 if (F->getName() != FnName) {
1313 // Delete the one we just made and get the existing one.
1314 F->eraseFromParent();
1315 F = M->getFunction(Name);
1316
1317 // If F already has a body, reject this.
1318 if (!F->empty()) {
1319 ErrorF("redefinition of function");
1320 return 0;
1321 }
1322
1323 // If F took a different number of args, reject.
1324 if (F->arg_size() != Args.size()) {
1325 ErrorF("redefinition of function with different # args");
1326 return 0;
1327 }
1328 }
1329
1330 // Set names for all arguments.
1331 unsigned Idx = 0;
1332 for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
1333 ++AI, ++Idx)
1334 AI->setName(Args[Idx]);
1335
1336 return F;
1337 }
1338
1339 /// CreateArgumentAllocas - Create an alloca for each argument and register the
1340 /// argument in the symbol table so that references to it will succeed.
1341 void PrototypeAST::CreateArgumentAllocas(Function *F) {
1342 Function::arg_iterator AI = F->arg_begin();
1343 for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
1344 // Create an alloca for this variable.
1345 AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);
1346
1347 // Store the initial value into the alloca.
1348 Builder.CreateStore(AI, Alloca);
1349
1350 // Add arguments to variable symbol table.
1351 NamedValues[Args[Idx]] = Alloca;
1352 }
1353 }
1354
1355 Function *FunctionAST::Codegen() {
1356 NamedValues.clear();
1357
1358 Function *TheFunction = Proto->Codegen();
1359 if (TheFunction == 0)
1360 return 0;
1361
1362 // If this is an operator, install it.
1363 if (Proto->isBinaryOp())
1364 BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
1365
1366 // Create a new basic block to start insertion into.
1367 BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
1368 Builder.SetInsertPoint(BB);
1369
1370 // Add all arguments to the symbol table and create their allocas.
1371 Proto->CreateArgumentAllocas(TheFunction);
1372
1373 if (Value *RetVal = Body->Codegen()) {
1374 // Finish off the function.
1375 Builder.CreateRet(RetVal);
1376
1377 // Validate the generated code, checking for consistency.
1378 verifyFunction(*TheFunction);
1379
1380 return TheFunction;
1381 }
1382
1383 // Error reading body, remove function.
1384 TheFunction->eraseFromParent();
1385
1386 if (Proto->isBinaryOp())
1387 BinopPrecedence.erase(Proto->getOperatorName());
1388 return 0;
1389 }
1390
1391 //===----------------------------------------------------------------------===//
1392 // Top-Level parsing and JIT Driver
1393 //===----------------------------------------------------------------------===//
1394
1395 static void HandleDefinition() {
1396 if (FunctionAST *F = ParseDefinition()) {
1397 TheHelper->closeCurrentModule();
1398 if (Function *LF = F->Codegen()) {
1399 #ifndef MINIMAL_STDERR_OUTPUT
1400 fprintf(stderr, "Read function definition:");
1401 LF->dump();
1402 #endif
1403 }
1404 } else {
1405 // Skip token for error recovery.
1406 getNextToken();
1407 }
1408 }
1409
1410 static void HandleExtern() {
1411 if (PrototypeAST *P = ParseExtern()) {
1412 if (Function *F = P->Codegen()) {
1413 #ifndef MINIMAL_STDERR_OUTPUT
1414 fprintf(stderr, "Read extern: ");
1415 F->dump();
1416 #endif
1417 }
1418 } else {
1419 // Skip token for error recovery.
1420 getNextToken();
1421 }
1422 }
1423
1424 static void HandleTopLevelExpression() {
1425 // Evaluate a top-level expression into an anonymous function.
1426 if (FunctionAST *F = ParseTopLevelExpr()) {
1427 if (Function *LF = F->Codegen()) {
1428 // JIT the function, returning a function pointer.
1429 void *FPtr = TheHelper->getPointerToFunction(LF);
1430
1431 // Cast it to the right type (takes no arguments, returns a double) so we
1432 // can call it as a native function.
1433 double (*FP)() = (double (*)())(intptr_t)FPtr;
1434 #ifdef MINIMAL_STDERR_OUTPUT
1435 FP();
1436 #else
1437 fprintf(stderr, "Evaluated to %f\n", FP());
1438 #endif
1439 }
1440 } else {
1441 // Skip token for error recovery.
1442 getNextToken();
1443 }
1444 }
1445
1446 /// top ::= definition | external | expression | ';'
1447 static void MainLoop() {
1448 while (1) {
1449 #ifndef MINIMAL_STDERR_OUTPUT
1450 fprintf(stderr, "ready> ");
1451 #endif
1452 switch (CurTok) {
1453 case tok_eof: return;
1454 case ';': getNextToken(); break; // ignore top-level semicolons.
1455 case tok_def: HandleDefinition(); break;
1456 case tok_extern: HandleExtern(); break;
1457 default: HandleTopLevelExpression(); break;
1458 }
1459 }
1460 }
1461
1462 //===----------------------------------------------------------------------===//
1463 // "Library" functions that can be "extern'd" from user code.
1464 //===----------------------------------------------------------------------===//
1465
1466 /// putchard - putchar that takes a double and returns 0.
1467 extern "C"
1468 double putchard(double X) {
1469 putchar((char)X);
1470 return 0;
1471 }
1472
1473 /// printd - printf that takes a double prints it as "%f\n", returning 0.
1474 extern "C"
1475 double printd(double X) {
1476 printf("%f", X);
1477 return 0;
1478 }
1479
1480 extern "C"
1481 double printlf() {
1482 printf("\n");
1483 return 0;
1484 }
1485
1486 //===----------------------------------------------------------------------===//
1487 // Command line input file handler
1488 //===----------------------------------------------------------------------===//
1489
1490 Module* parseInputIR(std::string InputFile) {
1491 SMDiagnostic Err;
1492 Module *M = ParseIRFile(InputFile, Err, getGlobalContext());
1493 if (!M) {
1494 Err.print("IR parsing failed: ", errs());
1495 return NULL;
1496 }
1497
1498 char ModID[256];
1499 sprintf(ModID, "IR:%s", InputFile.c_str());
1500 M->setModuleIdentifier(ModID);
1501
1502 TheHelper->addModule(M);
1503 return M;
1504 }
1505
1506 //===----------------------------------------------------------------------===//
1507 // Main driver code.
1508 //===----------------------------------------------------------------------===//
1509
1510 int main(int argc, char **argv) {
1511 InitializeNativeTarget();
1512 InitializeNativeTargetAsmPrinter();
1513 InitializeNativeTargetAsmParser();
1514 LLVMContext &Context = getGlobalContext();
1515
1516 cl::ParseCommandLineOptions(argc, argv,
1517 "Kaleidoscope example program\n");
1518
1519 // Install standard binary operators.
1520 // 1 is lowest precedence.
1521 BinopPrecedence['='] = 2;
1522 BinopPrecedence['<'] = 10;
1523 BinopPrecedence['+'] = 20;
1524 BinopPrecedence['-'] = 20;
1525 BinopPrecedence['/'] = 40;
1526 BinopPrecedence['*'] = 40; // highest.
1527
1528 // Prime the first token.
1529 #ifndef MINIMAL_STDERR_OUTPUT
1530 fprintf(stderr, "ready> ");
1531 #endif
1532 getNextToken();
1533
1534 // Make the helper, which holds all the code.
1535 TheHelper = new MCJITHelper(Context);
1536
1537 if (!InputIR.empty()) {
1538 parseInputIR(InputIR);
1539 }
1540
1541 // Run the main "interpreter loop" now.
1542 MainLoop();
1543
1544 #ifndef MINIMAL_STDERR_OUTPUT
1545 // Print out all of the generated code.
1546 TheHelper->dump();
1547 #endif
1548
1549 return 0;
1550 }
0 all: toy
1
2 toy : toy.cpp
3 clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core jit mcjit native irreader` -o toy
0 //===----------------------------------------------------------------------===/
1 // Kaleidoscope with MCJIT
2 //===----------------------------------------------------------------------===//
3
4 The files in this directory are meant to accompany the first in a series of
5 three blog posts that describe the process of porting the Kaleidoscope tutorial
6 to use the MCJIT execution engine instead of the older JIT engine.
7
8 When the blog post is ready this file will be updated with a link to the post.
9
10 The source code in this directory combines all previous versions, including the
11 old JIT-based implementation, into a single file for easy comparison with
12 command line options to select between the various possibilities.
13
14 This directory contain a Makefile that allow the code to be built in a
15 standalone manner, independent of the larger LLVM build infrastructure. To build
16 the program you will need to have 'clang++' and 'llvm-config' in your path. If
17 you attempt to build using the LLVM 3.3 release, some minor modifications will
18 be required.
19
20 This directory also contains a Python script that may be used to generate random
21 input for the program and test scripts to capture data for rough performance
22 comparisons. Another Python script will split generated input files into
23 definitions and function calls for the purpose of testing the IR input and
24 caching facilities.
0 #!/usr/bin/env python
1
2 import sys
3 import random
4
5 class TimingScriptGenerator:
6 """Used to generate a bash script which will invoke the toy and time it"""
7 def __init__(self, scriptname, outputname):
8 self.timeFile = outputname
9 self.shfile = open(scriptname, 'w')
10 self.shfile.write("echo \"\" > %s\n" % self.timeFile)
11
12 def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls):
13 """Echo some comments and invoke both versions of toy"""
14 rootname = filename
15 if '.' in filename:
16 rootname = filename[:filename.rfind('.')]
17 self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile))
18 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
19 self.shfile.write("echo \"With MCJIT (original)\" >> %s\n" % self.timeFile)
20 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
21 self.shfile.write(" -o %s -a " % self.timeFile)
22 self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=false < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname))
23 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
24 self.shfile.write("echo \"With MCJIT (lazy)\" >> %s\n" % self.timeFile)
25 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
26 self.shfile.write(" -o %s -a " % self.timeFile)
27 self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true < %s > %s-mcjit-lazy.out 2> %s-mcjit-lazy.err\n" % (filename, rootname, rootname))
28 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
29 self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile)
30 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
31 self.shfile.write(" -o %s -a " % self.timeFile)
32 self.shfile.write("./toy -suppress-prompts -use-mcjit=false < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname))
33 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
34 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
35
36 class KScriptGenerator:
37 """Used to generate random Kaleidoscope code"""
38 def __init__(self, filename):
39 self.kfile = open(filename, 'w')
40 self.nextFuncNum = 1
41 self.lastFuncNum = None
42 self.callWeighting = 0.1
43 # A mapping of calls within functions with no duplicates
44 self.calledFunctionTable = {}
45 # A list of function calls which will actually be executed
46 self.calledFunctions = []
47 # A comprehensive mapping of calls within functions
48 # used for computing the total number of calls
49 self.comprehensiveCalledFunctionTable = {}
50 self.totalCallsExecuted = 0
51
52 def updateTotalCallCount(self, callee):
53 # Count this call
54 self.totalCallsExecuted += 1
55 # Then count all the functions it calls
56 if callee in self.comprehensiveCalledFunctionTable:
57 for child in self.comprehensiveCalledFunctionTable[callee]:
58 self.updateTotalCallCount(child)
59
60 def updateFunctionCallMap(self, caller, callee):
61 """Maintains a map of functions that are called from other functions"""
62 if not caller in self.calledFunctionTable:
63 self.calledFunctionTable[caller] = []
64 if not callee in self.calledFunctionTable[caller]:
65 self.calledFunctionTable[caller].append(callee)
66 if not caller in self.comprehensiveCalledFunctionTable:
67 self.comprehensiveCalledFunctionTable[caller] = []
68 self.comprehensiveCalledFunctionTable[caller].append(callee)
69
70 def updateCalledFunctionList(self, callee):
71 """Maintains a list of functions that will actually be called"""
72 # Update the total call count
73 self.updateTotalCallCount(callee)
74 # If this function is already in the list, don't do anything else
75 if callee in self.calledFunctions:
76 return
77 # Add this function to the list of those that will be called.
78 self.calledFunctions.append(callee)
79 # If this function calls other functions, add them too
80 if callee in self.calledFunctionTable:
81 for subCallee in self.calledFunctionTable[callee]:
82 self.updateCalledFunctionList(subCallee)
83
84 def setCallWeighting(self, weight):
85 """ Sets the probably of generating a function call"""
86 self.callWeighting = weight
87
88 def writeln(self, line):
89 self.kfile.write(line + '\n')
90
91 def writeComment(self, comment):
92 self.writeln('# ' + comment)
93
94 def writeEmptyLine(self):
95 self.writeln("")
96
97 def writePredefinedFunctions(self):
98 self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands")
99 self.writeComment("and just returns the RHS.")
100 self.writeln("def binary : 1 (x y) y;")
101 self.writeEmptyLine()
102 self.writeComment("Helper functions defined within toy")
103 self.writeln("extern putchard(x);")
104 self.writeln("extern printd(d);")
105 self.writeln("extern printlf();")
106 self.writeEmptyLine()
107 self.writeComment("Print the result of a function call")
108 self.writeln("def printresult(N Result)")
109 self.writeln(" # 'result('")
110 self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :")
111 self.writeln(" printd(N) :");
112 self.writeln(" # ') = '")
113 self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :")
114 self.writeln(" printd(Result) :");
115 self.writeln(" printlf();")
116 self.writeEmptyLine()
117
118 def writeRandomOperation(self, LValue, LHS, RHS):
119 shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting)
120 if shouldCallFunc:
121 funcToCall = random.randrange(1, self.lastFuncNum - 1)
122 self.updateFunctionCallMap(self.lastFuncNum, funcToCall)
123 self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS))
124 else:
125 possibleOperations = ["+", "-", "*", "/"]
126 operation = random.choice(possibleOperations)
127 if operation == "-":
128 # Don't let our intermediate value become zero
129 # This is complicated by the fact that '<' is our only comparison operator
130 self.writeln(" if %s < %s then" % (LHS, RHS))
131 self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS))
132 self.writeln(" else if %s < %s then" % (RHS, LHS))
133 self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS))
134 self.writeln(" else")
135 self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100)))
136 else:
137 self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS))
138
139 def getNextFuncNum(self):
140 result = self.nextFuncNum
141 self.nextFuncNum += 1
142 self.lastFuncNum = result
143 return result
144
145 def writeFunction(self, elements):
146 funcNum = self.getNextFuncNum()
147 self.writeComment("Auto-generated function number %d" % funcNum)
148 self.writeln("def func%d(X Y)" % funcNum)
149 self.writeln(" var temp1 = X,")
150 self.writeln(" temp2 = Y,")
151 self.writeln(" temp3 in")
152 # Initialize the variable names to be rotated
153 first = "temp3"
154 second = "temp1"
155 third = "temp2"
156 # Write some random operations
157 for i in range(elements):
158 self.writeRandomOperation(first, second, third)
159 # Rotate the variables
160 temp = first
161 first = second
162 second = third
163 third = temp
164 self.writeln(" " + third + ";")
165 self.writeEmptyLine()
166
167 def writeFunctionCall(self):
168 self.writeComment("Call the last function")
169 arg1 = random.uniform(1, 100)
170 arg2 = random.uniform(1, 100)
171 self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2))
172 self.writeEmptyLine()
173 self.updateCalledFunctionList(self.lastFuncNum)
174
175 def writeFinalFunctionCounts(self):
176 self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum))
177
178 def generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript):
179 """ Generate a random Kaleidoscope script based on the given parameters """
180 print "Generating " + filename
181 print(" %d functions, %d elements per function, %d functions between execution" %
182 (numFuncs, elementsPerFunc, funcsBetweenExec))
183 print(" Call weighting = %f" % callWeighting)
184 script = KScriptGenerator(filename)
185 script.setCallWeighting(callWeighting)
186 script.writeComment("===========================================================================")
187 script.writeComment("Auto-generated script")
188 script.writeComment(" %d functions, %d elements per function, %d functions between execution"
189 % (numFuncs, elementsPerFunc, funcsBetweenExec))
190 script.writeComment(" call weighting = %f" % callWeighting)
191 script.writeComment("===========================================================================")
192 script.writeEmptyLine()
193 script.writePredefinedFunctions()
194 funcsSinceLastExec = 0
195 for i in range(numFuncs):
196 script.writeFunction(elementsPerFunc)
197 funcsSinceLastExec += 1
198 if funcsSinceLastExec == funcsBetweenExec:
199 script.writeFunctionCall()
200 funcsSinceLastExec = 0
201 # Always end with a function call
202 if funcsSinceLastExec > 0:
203 script.writeFunctionCall()
204 script.writeEmptyLine()
205 script.writeFinalFunctionCounts()
206 funcsCalled = len(script.calledFunctions)
207 print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted)
208 timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted)
209
210 # Execution begins here
211 random.seed()
212
213 timingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt")
214
215 dataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0),
216 (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0),
217 ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)]
218
219 # Generate the code
220 for (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets:
221 filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100))
222 generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript)
223 print "All done!"
0 #!/usr/bin/env python
1
2 class TimingScriptGenerator:
3 """Used to generate a bash script which will invoke the toy and time it"""
4 def __init__(self, scriptname, outputname):
5 self.shfile = open(scriptname, 'w')
6 self.timeFile = outputname
7 self.shfile.write("echo \"\" > %s\n" % self.timeFile)
8
9 def writeTimingCall(self, irname, callname):
10 """Echo some comments and invoke both versions of toy"""
11 rootname = irname
12 if '.' in irname:
13 rootname = irname[:irname.rfind('.')]
14 self.shfile.write("echo \"%s: Calls %s\" >> %s\n" % (callname, irname, self.timeFile))
15 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
16 self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile)
17 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
18 self.shfile.write(" -o %s -a " % self.timeFile)
19 self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname))
20 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
21 self.shfile.write("echo \"With MCJIT again\" >> %s\n" % self.timeFile)
22 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
23 self.shfile.write(" -o %s -a " % self.timeFile)
24 self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname))
25 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
26 self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile)
27 self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
28 self.shfile.write(" -o %s -a " % self.timeFile)
29 self.shfile.write("./toy -suppress-prompts -use-mcjit=false -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname))
30 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
31 self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
32
33 class LibScriptGenerator:
34 """Used to generate a bash script which will invoke the toy and time it"""
35 def __init__(self, filename):
36 self.shfile = open(filename, 'w')
37
38 def writeLibGenCall(self, libname, irname):
39 self.shfile.write("./toy -suppress-prompts -use-mcjit=false -dump-modules < %s 2> %s\n" % (libname, irname))
40
41 def splitScript(inputname, libGenScript, timingScript):
42 rootname = inputname[:-2]
43 libname = rootname + "-lib.k"
44 irname = rootname + "-lib.ir"
45 callname = rootname + "-call.k"
46 infile = open(inputname, "r")
47 libfile = open(libname, "w")
48 callfile = open(callname, "w")
49 print "Splitting %s into %s and %s" % (inputname, callname, libname)
50 for line in infile:
51 if not line.startswith("#"):
52 if line.startswith("print"):
53 callfile.write(line)
54 else:
55 libfile.write(line)
56 libGenScript.writeLibGenCall(libname, irname)
57 timingScript.writeTimingCall(irname, callname)
58
59 # Execution begins here
60 libGenScript = LibScriptGenerator("make-libs.sh")
61 timingScript = TimingScriptGenerator("time-lib.sh", "lib-timing.txt")
62
63 script_list = ["test-5000-3-50-50.k", "test-5000-10-100-10.k", "test-5000-10-5-10.k", "test-5000-10-1-0.k",
64 "test-1000-3-10-50.k", "test-1000-10-100-10.k", "test-1000-10-5-10.k", "test-1000-10-1-0.k",
65 "test-200-3-2-50.k", "test-200-10-40-10.k", "test-200-10-2-10.k", "test-200-10-1-0.k"]
66
67 for script in script_list:
68 splitScript(script, libGenScript, timingScript)
69 print "All done!"
0 #include "llvm/Analysis/Passes.h"
1 #include "llvm/Analysis/Verifier.h"
2 #include "llvm/ExecutionEngine/ExecutionEngine.h"
3 #include "llvm/ExecutionEngine/JIT.h"
4 #include "llvm/ExecutionEngine/MCJIT.h"
5 #include "llvm/ExecutionEngine/ObjectCache.h"
6 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
7 #include "llvm/IR/DataLayout.h"
8 #include "llvm/IR/DerivedTypes.h"
9 #include "llvm/IR/IRBuilder.h"
10 #include "llvm/IR/LLVMContext.h"
11 #include "llvm/IR/Module.h"
12 #include "llvm/IRReader/IRReader.h"
13 #include "llvm/PassManager.h"
14 #include "llvm/Support/CommandLine.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/Path.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "llvm/Transforms/Scalar.h"
21 #include
22 #include
23 #include
24 #include
25
26 using namespace llvm;
27
28 //===----------------------------------------------------------------------===//
29 // Command-line options
30 //===----------------------------------------------------------------------===//
31
32 namespace {
33 cl::opt
34 InputIR("input-IR",
35 cl::desc("Specify the name of an IR file to load for function definitions"),
36 cl::value_desc("input IR file name"));
37
38 cl::opt
39 VerboseOutput("verbose",
40 cl::desc("Enable verbose output (results, IR, etc.) to stderr"),
41 cl::init(false));
42
43 cl::opt
44 SuppressPrompts("suppress-prompts",
45 cl::desc("Disable printing the 'ready' prompt"),
46 cl::init(false));
47
48 cl::opt
49 DumpModulesOnExit("dump-modules",
50 cl::desc("Dump IR from modules to stderr on shutdown"),
51 cl::init(false));
52
53 cl::opt UseMCJIT(
54 "use-mcjit", cl::desc("Use the MCJIT execution engine"),
55 cl::init(true));
56
57 cl::opt EnableLazyCompilation(
58 "enable-lazy-compilation", cl::desc("Enable lazy compilation when using the MCJIT engine"),
59 cl::init(true));
60
61 cl::opt UseObjectCache(
62 "use-object-cache", cl::desc("Enable use of the MCJIT object caching"),
63 cl::init(false));
64 } // namespace
65
66 //===----------------------------------------------------------------------===//
67 // Lexer
68 //===----------------------------------------------------------------------===//
69
70 // The lexer returns tokens [0-255] if it is an unknown character, otherwise one
71 // of these for known things.
72 enum Token {
73 tok_eof = -1,
74
75 // commands
76 tok_def = -2, tok_extern = -3,
77
78 // primary
79 tok_identifier = -4, tok_number = -5,
80
81 // control
82