Pegmatite
 All Classes Functions Variables Enumerations
compiler.cc
1 /*
2  * Copyright (c) 2014 David Chisnall
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy of
5  * this software and associated documentation files (the "Software"), to deal in
6  * the Software without restriction, including without limitation the rights to
7  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8  * the Software, and to permit persons to whom the Software is furnished to do so,
9  * subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  */
21 
22 #define LLVM_BEFORE(major,minor)\
23  ((LLVM_MAJOR < major) || ((LLVM_MAJOR == major) && (LLVM_MINOR < minor)))
24 #define LLVM_AFTER(major,minor)\
25  ((LLVM_MAJOR > major) || ((LLVM_MAJOR == major) && (LLVM_MINOR > minor)))
26 
27 #include <llvm/Analysis/Passes.h>
28 #include <llvm/Bitcode/ReaderWriter.h>
29 #include <llvm/ExecutionEngine/ExecutionEngine.h>
30 #include <llvm/ExecutionEngine/GenericValue.h>
31 #include <llvm/IR/Constants.h>
32 #include <llvm/IR/DataLayout.h>
33 #include <llvm/IR/DerivedTypes.h>
34 #include <llvm/IR/GlobalVariable.h>
35 #include <llvm/IR/IRBuilder.h>
36 #include <llvm/IR/LLVMContext.h>
37 #include <llvm/IR/Module.h>
38 #if LLVM_BEFORE(3,5)
39 #include <llvm/Support/system_error.h>
40 #include <llvm/Analysis/Verifier.h>
41 #include <llvm/Linker.h>
42 #else
43 #include <llvm/IR/Verifier.h>
44 #include <llvm/Linker/Linker.h>
45 #endif
46 #include <llvm/PassManager.h>
47 #include <llvm/Support/MemoryBuffer.h>
48 #include <llvm/Support/TargetSelect.h>
49 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
50 #include <llvm/Transforms/IPO.h>
51 
52 #include <iostream>
53 
54 #include "ast.hh"
55 
56 using namespace llvm;
57 
58 namespace Compiler
59 {
60 struct State
61 {
63  LLVMContext &C;
65  Module *Mod;
67  Function *F;
69  IRBuilder<> B;
71  Value *a[10];
73  Value *g[10];
75  Value *oldGrid;
77  Value *newGrid;
79  Value *width;
81  Value *height;
83  Value *x;
85  Value *y;
89  Value *v;
91  Type *regTy;
92 
98  State() : C(getGlobalContext()), B(C)
99  {
100  // Load the bitcode for the runtime helper code
101 #if LLVM_BEFORE(3,5)
102  OwningPtr<MemoryBuffer> buffer;
103  error_code ec = MemoryBuffer::getFile("runtime.bc", buffer);
104  if (ec)
105  {
106  std::cerr << "Failed to open runtime.bc: " << ec.message() << "\n";
107  exit(EXIT_FAILURE);
108  }
109  Mod = ParseBitcodeFile(buffer.get(), C);
110 #else
111  auto buffer = MemoryBuffer::getFile("runtime.bc");
112  std::error_code ec;
113  if ((ec = buffer.getError()))
114  {
115  std::cerr << "Failed to open runtime.bc: " << ec.message() << "\n";
116  exit(EXIT_FAILURE);
117  }
118  ErrorOr<Module*> e = parseBitcodeFile(buffer.get().get(), C);
119  if ((ec = e.getError()))
120  {
121  std::cerr << "Failed to parse runtime.bc: " << ec.message() << "\n";
122  exit(EXIT_FAILURE);
123  }
124  Mod = e.get();
125 #endif
126  // Get the stub (prototype) for the cell function
127  F = Mod->getFunction("cell");
128  // Set it to have private linkage, so that it can be removed after being
129  // inlined.
130  F->setLinkage(GlobalValue::PrivateLinkage);
131  // Add an entry basic block to this function and set it
132  BasicBlock *entry = BasicBlock::Create(C, "entry", F);
133  B.SetInsertPoint(entry);
134  // Cache the type of registers
135  regTy = Type::getInt16Ty(C);
136 
137  // Collect the function parameters
138  auto args = F->arg_begin();
139  oldGrid = args++;
140  newGrid = args++;
141  width = args++;
142  height = args++;
143  x = args++;
144  y = args++;
145 
146  // Create space on the stack for the local registers
147  for (int i=0 ; i<10 ; i++)
148  {
149  a[i] = B.CreateAlloca(regTy);
150  }
151  // Create a space on the stack for the current value. This can be
152  // assigned to, and will be returned at the end. Store the value passed
153  // as a parameter in this.
154  v = B.CreateAlloca(regTy);
155  B.CreateStore(args++, v);
156 
157  // Create a load of pointers to the global registers.
158  Value *gArg = args;
159  for (int i=0 ; i<10 ; i++)
160  {
161  B.CreateStore(ConstantInt::get(regTy, 0), a[i]);
162  g[i] = B.CreateConstGEP1_32(gArg, i);
163  }
164  }
165 
170  automaton getAutomaton(int optimiseLevel)
171  {
172  // We've finished generating code, so add a return statement - we're
173  // returning the value of the v register.
174  B.CreateRet(B.CreateLoad(v));
175 #ifdef DEBUG_CODEGEN
176  // If we're debugging, then print the module in human-readable form to
177  // the standard error and verify it.
178  Mod->dump();
179  verifyModule(*Mod);
180 #endif
181  // Now we need to construct the set of optimisations that we're going to
182  // run.
183  PassManagerBuilder PMBuilder;
184  // Set the optimisation level. This defines what optimisation passes
185  // will be added.
186  PMBuilder.OptLevel = optimiseLevel;
187  // Create a basic inliner. This will inline the cell function that we've
188  // just created into the automaton function that we're going to create.
189  PMBuilder.Inliner = createFunctionInliningPass(275);
190  // Now create a function pass manager that is responsible for running
191  // passes that optimise functions, and populate it.
192  FunctionPassManager *PerFunctionPasses= new FunctionPassManager(Mod);
193  PMBuilder.populateFunctionPassManager(*PerFunctionPasses);
194 
195  // Run all of the function passes on the functions in our module
196  for (auto &I : *Mod)
197  {
198  if (!I.isDeclaration())
199  {
200  PerFunctionPasses->run(I);
201  }
202  }
203  // Clean up
204  PerFunctionPasses->doFinalization();
205  delete PerFunctionPasses;
206  // Run the per-module passes
207  PassManager *PerModulePasses = new PassManager();
208  PMBuilder.populateModulePassManager(*PerModulePasses);
209  PerModulePasses->run(*Mod);
210  delete PerModulePasses;
211 
212  // Now we are ready to generate some code. First create the execution
213  // engine (JIT)
214  std::string error;
215  ExecutionEngine *EE = ExecutionEngine::create(Mod, false, &error);
216  if (!EE)
217  {
218  fprintf(stderr, "Error: %s\n", error.c_str());
219  exit(-1);
220  }
221  // Now tell it to compile
222  return (automaton)EE->getPointerToFunction(Mod->getFunction("automaton"));
223  }
224 
225 };
226 
227 automaton compile(AST::StatementList *ast, int optimiseLevel)
228 {
229  // These functions do nothing, they just ensure that the correct modules are
230  // not removed by the linker.
231  InitializeNativeTarget();
232  LLVMLinkInJIT();
233 
234  State s;
235  ast->compile(s);
236  // And then return the compiled version.
237  return s.getAutomaton(optimiseLevel);
238 }
239 
240 } // namespace Compiler
241 
242 namespace AST
243 {
244 
245 Value* Literal::compile(Compiler::State &s)
246 {
247  return ConstantInt::get(s.regTy, value);
248 }
249 Value* LocalRegister::compile(Compiler::State &s)
250 {
251  assert(registerNumber >= 0 && registerNumber < 10);
252  return s.B.CreateLoad(s.a[registerNumber]);
253 }
254 void LocalRegister::assign(Compiler::State &s, Value* val)
255 {
256  assert(registerNumber >= 0 && registerNumber < 10);
257  s.B.CreateStore(val, s.a[registerNumber]);
258 }
259 Value* GlobalRegister::compile(Compiler::State &s)
260 {
261  assert(registerNumber >= 0 && registerNumber < 10);
262  return s.B.CreateLoad(s.g[registerNumber]);
263 }
264 void GlobalRegister::assign(Compiler::State &s, Value* val)
265 {
266  assert(registerNumber >= 0 && registerNumber < 10);
267  s.B.CreateStore(val, s.g[registerNumber]);
268 }
269 Value* VRegister::compile(Compiler::State &s)
270 {
271  return s.B.CreateLoad(s.v);
272 }
273 void VRegister::assign(Compiler::State &s, Value* val)
274 {
275  s.B.CreateStore(val, s.v);
276 }
277 
278 Value* Arithmetic::compile(Compiler::State &s)
279 {
280  // Keep a reference to the builder so we don't have to type s.B everywhere
281  IRBuilder<> &B = s.B;
282  Value *v = value->compile(s);
283  Value *o = target->compile(s);
284  Value *result;
285  // For most operations, we can just create a single IR instruction and then
286  // store the result. For min and max, we create a comparison and a select
287  switch (op->op)
288  {
289  case Op::Add:
290  result = B.CreateAdd(v, o);
291  break;
292  case Op::Assign:
293  result = v;
294  break;
295  case Op::Sub:
296  result = B.CreateSub(o, v);
297  break;
298  case Op::Mul:
299  result = B.CreateMul(o, v);
300  break;
301  case Op::Div:
302  result = B.CreateSDiv(o, v);
303  break;
304  case Op::Min:
305  {
306  Value *gt = B.CreateICmpSGT(o, v);
307  result = B.CreateSelect(gt, v, o);
308  break;
309  }
310  case Op::Max:
311  {
312  Value *gt = B.CreateICmpSGT(o, v);
313  result = B.CreateSelect(gt, o, v);
314  break;
315  }
316  }
317  target->assign(s, result);
318  return target->compile(s);
319 }
320 
321 Value* RangeExpr::compile(Compiler::State &s)
322 {
323  // Keep a reference to the builder so we don't have to type s.B everywhere
324  IRBuilder<> &B = s.B;
325  LLVMContext &C = s.C;
326  Function *F = s.F;
327  // Load the register that we're mapping
328  Value *reg = value->compile(s);
329  // Now create a basic block for continuation. This is the block that
330  // will be reached after the range expression.
331  BasicBlock *cont = BasicBlock::Create(s.C, "range_continue", s.F);
332  // In this block, create a PHI node that contains the result.
333  PHINode *phi = PHINode::Create(s.regTy, ranges.objects().size(),
334  "range_result", cont);
335  // Now loop over all of the possible ranges and create a test for each one
336  BasicBlock *current = B.GetInsertBlock();
337  for (const auto &re : ranges.objects())
338  {
339  Value *match;
340  // If there is just one range value then we just need an
341  // equals-comparison
342  if (re->start.get() == nullptr)
343  {
344  Value *val = re->end->compile(s);
345  match = B.CreateICmpEQ(reg, val);
346  }
347  else
348  {
349  // Otherwise we need to emit both values and then compare if
350  // we're greater-than-or-equal-to the smaller, and
351  // less-than-or-equal-to the larger.
352  Value *min = re->start->compile(s);
353  Value *max = re->end->compile(s);
354  match = B.CreateAnd(B.CreateICmpSGE(reg, min),
355  B.CreateICmpSLE(reg, max));
356  }
357  // The match value is now a boolean (i1) indicating whether the
358  // value matches this range. Create a pair of basic blocks, one
359  // for the case where we did match the specified range, and one for
360  // the case where we didn't.
361  BasicBlock *expr = BasicBlock::Create(C, "range_result", F);
362  BasicBlock *next = BasicBlock::Create(C, "range_next", F);
363  // Branch to the correct block
364  B.CreateCondBr(match, expr, next);
365  // Now construct the block for the case where we matched a value
366  B.SetInsertPoint(expr);
367  // Compiling the statement may emit some complex code, so we need to
368  // leave everything set up for it to (potentially) write lots of
369  // instructions and create more basic blocks (imagine nested range
370  // expressions). If this is just a constant, then the next basic block
371  // will be empty, but the SimplifyCFG pass will remove it.
372  Value *output = re->value->compile(s);
373  phi->addIncoming(output, B.GetInsertBlock());
374  //phi->addIncoming(re->value->compile(s), B.GetInsertBlock());
375  // Now that we've generated the correct value, branch to the
376  // continuation block.
377  B.CreateBr(cont);
378  // ...and repeat
379  current = next;
380  B.SetInsertPoint(current);
381  }
382  // If we've fallen off the end, set the default value of zero and branch to
383  // the continuation point.
384  B.CreateBr(cont);
385  phi->addIncoming(ConstantInt::get(s.regTy, 0), B.GetInsertBlock());
386  B.SetInsertPoint(cont);
387  return phi;
388 }
389 
390 Value* Neighbours::compile(Compiler::State &s)
391 {
392  // Grab some local names for things in state
393  IRBuilder<> &B = s.B;
394  Value *x = s.x;
395  Value *y = s.y;
396  Value *width = s.width;
397  Value *height = s.height;
398  Type *regTy = s.regTy;
399  LLVMContext &C = s.C;
400  Function *F = s.F;
401  // Some useful constants.
402  Value *Zero = ConstantInt::get(regTy, 0);
403  Value *One = ConstantInt::get(regTy, 1);
404  // For each of the (valid) neighbours Start by identifying the bounds
405  Value *XMin = B.CreateSub(x, One);
406  Value *XMax = B.CreateAdd(x, One);
407  Value *YMin = B.CreateSub(y, One);
408  Value *YMax = B.CreateAdd(y, One);
409  // Now clamp them to the grid
410  XMin = B.CreateSelect(B.CreateICmpSLT(XMin, Zero), x, XMin);
411  YMin = B.CreateSelect(B.CreateICmpSLT(YMin, Zero), y, YMin);
412  XMax = B.CreateSelect(B.CreateICmpSGE(XMax, width), x, XMax);
413  YMax = B.CreateSelect(B.CreateICmpSGE(YMax, height), y, YMax);
414 
415  // Now create the loops. We're going to create two nested loops, an outer
416  // one for x and an inner one for y.
417  BasicBlock *start = B.GetInsertBlock();
418  // The entry basic blocks for the outer and inner loops.
419  BasicBlock *xLoopStart = BasicBlock::Create(C, "x_loop_start", F);
420  BasicBlock *yLoopStart = BasicBlock::Create(C, "y_loop_start", F);
421  // Branch to the start of the outer loop and start inserting instructions there
422  B.CreateBr(xLoopStart);
423  B.SetInsertPoint(xLoopStart);
424  // Create the Phi node representing the x index and fill in its value for
425  // the initial entry into the loop. We'll fill in its value for back
426  // branches later.
427  PHINode *XPhi = B.CreatePHI(regTy, 2);
428  XPhi->addIncoming(XMin, start);
429  // Branch to the inner loop and set up the y value in the same way.
430  B.CreateBr(yLoopStart);
431  B.SetInsertPoint(yLoopStart);
432  PHINode *YPhi = B.CreatePHI(regTy, 2);
433  YPhi->addIncoming(YMin, xLoopStart);
434 
435  // Create basic blocks for the end of the inner (y) loop and for the loop body
436  BasicBlock *endY = BasicBlock::Create(C, "y_loop_end", F);
437  BasicBlock *body = BasicBlock::Create(C, "body", F);
438 
439  // If we're in the (x,y) point, we're not in a neighbour, so skip the
440  // current loop iteration
441  B.CreateCondBr(B.CreateAnd(B.CreateICmpEQ(x, XPhi),
442  B.CreateICmpEQ(y, YPhi)),
443  endY, body);
444  // Now we start emitting the body of the loop
445  B.SetInsertPoint(body);
446 
447  // For larger grid sizes, we need to make sure that we're doing i32
448  // arithmetic, or we'll overflow
449  IntegerType *i32 = IntegerType::get(C, 32);
450  Value *x32 = B.CreateZExt(XPhi, i32);
451  Value *y32 = B.CreateZExt(YPhi, i32);
452  Value *height32 = B.CreateZExt(height, i32);
453  // Compute the address of the grid
454  Value *idx = B.CreateAdd(y32, B.CreateMul(x32, height32));
455 
456  // Load the value at the current grid point into a0
457  B.CreateStore(B.CreateLoad(B.CreateGEP(s.oldGrid, idx)), s.a[0]);
458 
459  // Compile each of the statements inside the loop
460  statements->compile(s);
461  // Branch to endY. This is needed if any of the statements have created
462  // basic blocks.
463  B.CreateBr(endY);
464  B.SetInsertPoint(endY);
465  BasicBlock *endX = BasicBlock::Create(C, "x_loop_end", F);
466  BasicBlock *cont = BasicBlock::Create(C, "continue", F);
467  // Increment the loop country for the next iteration
468  YPhi->addIncoming(B.CreateAdd(YPhi, ConstantInt::get(regTy, 1)), endY);
469  B.CreateCondBr(B.CreateICmpEQ(YPhi, YMax), endX, yLoopStart);
470 
471  B.SetInsertPoint(endX);
472  XPhi->addIncoming(B.CreateAdd(XPhi, ConstantInt::get(regTy, 1)), endX);
473  B.CreateCondBr(B.CreateICmpEQ(XPhi, XMax), cont, xLoopStart);
474  B.SetInsertPoint(cont);
475  return nullptr;
476 }
477 
478 Value* StatementList::compile(Compiler::State& state)
479 {
480  for (auto &s: statements.objects())
481  {
482  s->compile(state);
483  }
484  return nullptr;
485 }
486 
487 } // namespace AST
Value * height
The height of the grid (passed as an argument)
Definition: compiler.cc:81
Definition: ast.hh:67
LLVMContext & C
LLVM uses a context object to allow multiple threads.
Definition: compiler.cc:63
Value * oldGrid
The input grid (passed as an argument)
Definition: compiler.cc:75
Type * regTy
The type of our registers (currently i16)
Definition: compiler.cc:91
A list of statements that will be executed sequentially.
Definition: ast.hh:94
Function * F
The function representing the program.
Definition: compiler.cc:67
Value * x
The x coordinate of the current cell (passed as an argument)
Definition: compiler.cc:83
Value * a[10]
The 10 local registers in the source language.
Definition: compiler.cc:71
Definition: ast.hh:47
Value * width
The width of the grid (passed as an argument)
Definition: compiler.cc:79
Value * g[10]
The 10 global registers in the source language.
Definition: compiler.cc:73
IRBuilder B
A helper class for generating instructions.
Definition: compiler.cc:69
Value * y
The y coordinate of the current cell (passed as an argument)
Definition: compiler.cc:85
Value * newGrid
The output grid (passed as an argument)
Definition: compiler.cc:77
Definition: ast.hh:26
Value * v
The value of the current cell (passed as an argument, returned at the end)
Definition: compiler.cc:89
Module * Mod
The compilation unit that we are generating.
Definition: compiler.cc:65
automaton getAutomaton(int optimiseLevel)
Returns a function pointer for the automaton at the specified optimisation level. ...
Definition: compiler.cc:170
State()
Construct the compiler state object.
Definition: compiler.cc:98
virtual llvm::Value * compile(Compiler::State &) override
Compile this node, returning the LLVM value representing the result, if there is one.
Definition: compiler.cc:478