MysoreScript
compiler.cc
Go to the documentation of this file.
1 #include <functional>
2 #include "interpreter.hh"
3 #include "compiler.hh"
4 #include "ast.hh"
5 #include <llvm/ExecutionEngine/ExecutionEngine.h>
6 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
7 #include <llvm/IR/LegacyPassManager.h>
8 #include <llvm/Support/TargetSelect.h>
9 
10 using namespace llvm;
11 using llvm::legacy::PassManager;
12 using namespace MysoreScript;
13 using namespace AST;
14 
15 namespace {
25 template<typename T>
26 Value *staticAddress(Compiler::Context &c, T *ptr, Type *ty)
27 {
28  return c.B.CreateIntToPtr(
29  ConstantInt::get(c.ObjIntTy, reinterpret_cast<uintptr_t>(ptr)), ty);
30 }
34 Value *compileSmallInt(Compiler::Context &c, Value *i)
35 {
36  i = c.B.CreateShl(i, ConstantInt::get(c.ObjIntTy, 3));
37  return c.B.CreateOr(i, ConstantInt::get(c.ObjIntTy, 1));
38 }
42 Value *compileSmallInt(Compiler::Context &c, intptr_t i)
43 {
44  return ConstantInt::get(c.ObjIntTy, (i << 3) | 1);
45 }
50 Value *getAsObject(Compiler::Context &c, Value *i)
51 {
52  if (i->getType()->isPointerTy())
53  {
54  return c.B.CreateBitCast(i, c.ObjPtrTy);
55  }
56  return c.B.CreateIntToPtr(i, c.ObjPtrTy);
57 }
63 Value *getAsSmallInt(Compiler::Context &c, Value *i)
64 {
65  if (i->getType()->isPointerTy())
66  {
67  return c.B.CreatePtrToInt(i, c.ObjIntTy);
68  }
69  return c.B.CreateBitCast(i, c.ObjIntTy);
70 }
71 }
72 
74  globalSymbols(g),
75  M(new Module("MysoreScript", C)),
76  B(C),
77  ObjPtrTy(Type::getInt8PtrTy(C)),
78  ObjIntTy(Type::getInt64Ty(C)),
79  SelTy(Type::getInt32Ty(C))
80 {
81  // These functions do nothing, they just ensure that the correct modules
82  // are not removed by the linker.
83  LLVMInitializeNativeTarget();
84  InitializeNativeTargetAsmPrinter();
85  LLVMLinkInMCJIT();
86 
87 }
88 
89 Value *Compiler::Context::lookupSymbolAddr(const std::string &str)
90 {
91  // If the value is in the compiler's symbol table, then it's stored as an
92  // LLVM `Value` representing the address of the variable, so just return it.
93  if (Value *addr = symbols[str])
94  {
95  return addr;
96  }
97  // If it's in the global symbol table that we inherited from the interpreter
98  // then it's a pointer, so construct an LLVM `Value` of the correct type and
99  // value.
100  if (Obj *global = globalSymbols[str])
101  {
102  return staticAddress(*this, global, ObjPtrTy->getPointerTo());
103  }
104  llvm_unreachable("Symbol not found");
105 }
106 
108 {
109  // Construct a couple of pass managers to run the optimisations.
110  llvm::legacy::FunctionPassManager FPM(M.get());
111  PassManager MPM;
112  PassManagerBuilder Builder;
113  Builder.OptLevel = 2;
114  Builder.populateFunctionPassManager(FPM);
115  Builder.populateModulePassManager(MPM);
116 
117  // If you want to see the LLVM IR before optimisation, uncomment the
118  // following line:
119  //M->dump();
120 
121  // Run the passes to optimise the function / module.
122  FPM.run(*F);
123  MPM.run(*M);
124 
125  // If you want to see the LLVM IR before optimisation, uncomment the
126  // following line:
127  //M->dump();
128 
129  std::string FunctionName = F->getName();
130  std::string err;
131  EngineBuilder EB(std::move(M));
132  // Construct an execution engine (JIT)
133  ExecutionEngine *EE = EB.setEngineKind(EngineKind::JIT)
134  .setErrorStr(&err)
135  .create();
136  if (!EE)
137  {
138  fprintf(stderr, "Failed to construct Execution Engine: %s\n",
139  err.c_str());
140  return nullptr;
141  }
142  // Use the execution engine to compile the code. Note that we leave the
143  // ExecutionEngine live here because it owns the memory for the function.
144  // It would be better to provide our own JIT memory manager to manage the
145  // memory (and allow us to GC the functions if their addresses don't exist
146  // on the stack and they're replaced by specialised versions, but for now
147  // it's fine to just leak)
148  return reinterpret_cast<ClosureInvoke>(EE->getFunctionAddress(FunctionName));
149 }
150 
151 llvm::FunctionType *Compiler::Context::getMethodType(int ivars, int args)
152 {
153  PointerType *ObjTy = ObjPtrTy;
154  if (ivars)
155  {
156  // The fields in a class are the class pointer and the array of instance
157  // variables
158  Type* fields[2];
159  // isa (actually a class pointer not an object pointer)
160  fields[0] = ObjPtrTy;
161  fields[1] = ArrayType::get(ObjPtrTy, ivars);
162  ObjTy = StructType::create(fields)->getPointerTo();
163  }
164  // Set up the argument types for the closure invoke function.
165  SmallVector<Type*, 10> paramTypes;
166  // First two parameters are the implicit receiver and selector parameters.
167  paramTypes.push_back(ObjTy);
168  paramTypes.push_back(SelTy);
169  // All parameters are objects.
170  paramTypes.insert(paramTypes.end(), args, ObjPtrTy);
171  return FunctionType::get(ObjPtrTy, paramTypes, false);
172 }
173 
174 llvm::FunctionType *Compiler::Context::getClosureType(int bound, int args)
175 {
176  PointerType *ClosureTy = ObjPtrTy;
177  if (bound)
178  {
179  SmallVector<Type*, 6> fields;
180  // isa (actually a class pointer not an object pointer)
181  fields.push_back(ObjPtrTy);
182  // Number of parameters
183  fields.push_back(ObjPtrTy);
184  // Invoke function. We insert an explicit cast before we use this
185  // field, so we don't need to worry about it.
186  fields.push_back(ObjPtrTy);
187  // AST pointer
188  fields.push_back(ObjPtrTy);
189  // The array of bound variables.
190  fields.push_back(ArrayType::get(ObjPtrTy, bound));
191  ClosureTy = StructType::create(fields)->getPointerTo();
192  }
193  // Set up the argument types for the closure invoke function.
194  SmallVector<Type*, 10> paramTypes;
195  paramTypes.push_back(ClosureTy);
196  // All parameters are objects.
197  paramTypes.insert(paramTypes.end(), args, ObjPtrTy);
198  return FunctionType::get(ObjPtrTy, paramTypes, false);
199 }
200 
201 CompiledMethod ClosureDecl::compileMethod(Class *cls,
202  Interpreter::SymbolTable &globalSymbols)
203 {
204  auto &params = parameters->arguments;
205  Compiler::Context c(globalSymbols);
206  // Get the type of the method as an LLVM type
207  FunctionType *ClosureInvokeTy = c.getMethodType(cls->indexedIVarCount,
208  params.size());
209  // Create the LLVM function
210  c.F = Function::Create(ClosureInvokeTy, GlobalValue::ExternalLinkage,
211  "invoke", c.M.get());
212  // Insert the first basic block and store all of the parameters.
213  BasicBlock *entry = BasicBlock::Create(c.C, "entry", c.F);
214  c.B.SetInsertPoint(entry);
215  // We'll store the arguments into stack allocations so that they can be
216  // written to.
217  auto AI = c.F->arg_begin();
218  // The first two arguments are the two implicit parameters, self and cmd
219  auto selfPtr = c.B.CreateAlloca(c.ObjPtrTy);
220  auto cmdPtr = c.B.CreateAlloca(c.ObjPtrTy);
221  // Add these two stack locations to the symbol table.
222  c.symbols["self"] = selfPtr;
223  c.symbols["cmd"] = cmdPtr;
224  // We're now going to create stack allocations for all of the parameters and
225  // all of the locals. We do this *before* we initialise any of them because
226  // that makes life easier for the LLVM pass that generates SSA form, which
227  // only guarantees to promote allocas that occur before any other
228  // instructions to SSA registers.
229  SmallVector<Value*, 10> paramAllocas;
230  SmallVector<Value*, 10> localAllocas;
231 
232  // Create a stack allocation for each explicit parameter
233  for (size_t i=0 ; i<params.size() ; i++)
234  {
235  paramAllocas.push_back(c.B.CreateAlloca(c.ObjPtrTy));
236  }
237  // Create a stack allocation for each local variable
238  for (size_t i=0 ; i<decls.size() ; i++)
239  {
240  localAllocas.push_back(c.B.CreateAlloca(c.ObjPtrTy));
241  }
242  // Now we'll initialise the parameter allocations
243  auto alloca = paramAllocas.begin();
244  // First store the self pointer in its slot (which is already in the symbol
245  // table)
246  c.B.CreateStore(c.B.CreateBitCast(&*(AI++), c.ObjPtrTy), selfPtr);
247  // The selector is a 32-bit integer, promote it to an object and store it.
248  c.B.CreateStore(getAsObject(c, compileSmallInt(c, c.B.CreateZExt(&*(AI++),
249  c.ObjIntTy))), cmdPtr);
250  for (auto &arg : params)
251  {
252  // Set the name of the stack slot. This isn't necessary, but makes
253  // reading the generated IR a bit easier.
254  (*alloca)->setName(*arg.get());
255  // Store the argument in the stack slot.
256  c.B.CreateStore(&*(AI++), *alloca);
257  // Set this slot (specifically, the address of this stack allocation) to
258  // the address used when looking up the name of the argument.
259  c.symbols[*arg.get()] = *(alloca++);
260  }
261  alloca = localAllocas.begin();
262  // Now do almost the same thing for locals
263  for (auto &local : decls)
264  {
265  (*alloca)->setName(local);
266  // Initialise all local variables with null.
267  c.B.CreateStore(ConstantPointerNull::get(c.ObjPtrTy), *alloca);
268  c.symbols[local] = *(alloca++);
269  }
270  // Next we need to add the instance variables to the symbol table.
271  if (cls->indexedIVarCount)
272  {
273  // The type of the object pointer argument
274  PointerType *ArgTy = cast<PointerType>(ClosureInvokeTy->params()[0]);
275  // The type of the object
276  StructType *ObjTy =
277  cast<StructType>(cast<PointerType>(ArgTy)->getElementType());
278  // This does pointer arithmetic on the first argument to get the address
279  // of the array of instance variables.
280  Value *iVarsArray = c.B.CreateStructGEP(ObjTy, &*c.F->arg_begin(), 1);
281  // The type of the instance variables array
282  Type *iVarsArrayTy = ObjTy->elements()[1];
283  // The type of the arguments array
284  for (int i=0 ; i<cls->indexedIVarCount ; i++)
285  {
286  const char *name = cls->indexedIVarNames[i];
287  // Now we do similar arithmetic on the array to get the address of
288  // each instance variable.
289  c.symbols[name] =
290  c.B.CreateStructGEP(iVarsArrayTy, iVarsArray, i, name);
291  }
292  }
293  // Compile the statements in the method.
294  body->compile(c);
295  // If we hit a return statement, it will clear the insert block, so if there
296  // is still a valid insert block then the function ends with an unterminated
297  // basic block.
298  if (c.B.GetInsertBlock() != nullptr)
299  {
300  // Return null if there's no explicit return
301  c.B.CreateRet(ConstantPointerNull::get(c.ObjPtrTy));
302  }
303  // Generate the compiled code.
304  return reinterpret_cast<CompiledMethod>(c.compile());
305 }
306 
307 ClosureInvoke ClosureDecl::compileClosure(Interpreter::SymbolTable &globalSymbols)
308 {
309  auto &params = parameters->arguments;
310  Compiler::Context c(globalSymbols);
311  // Get the LLVM type of the closure invoke function
312  FunctionType *ClosureInvokeTy = c.getClosureType(boundVars.size(),
313  params.size());
314  // Create the LLVM function
315  c.F = Function::Create(ClosureInvokeTy, GlobalValue::ExternalLinkage, "invoke", c.M.get());
316  // Insert the first basic block and store all of the parameters.
317  BasicBlock *entry = BasicBlock::Create(c.C, "entry", c.F);
318  c.B.SetInsertPoint(entry);
319  auto AI = c.F->arg_begin();
320  auto selfPtr = c.B.CreateAlloca(c.ObjPtrTy);
321  c.symbols["self"] = selfPtr;
322  SmallVector<Value*, 10> paramAllocas;
323  SmallVector<Value*, 10> localAllocas;
324 
325  for (size_t i=0 ; i<params.size() ; i++)
326  {
327  paramAllocas.push_back(c.B.CreateAlloca(c.ObjPtrTy));
328  }
329  for (size_t i=0 ; i<decls.size() ; i++)
330  {
331  localAllocas.push_back(c.B.CreateAlloca(c.ObjPtrTy));
332  }
333  auto alloca = paramAllocas.begin();
334 
335  c.B.CreateStore(c.B.CreateBitCast(&*(AI++), c.ObjPtrTy), selfPtr);
336  for (auto &arg : params)
337  {
338  (*alloca)->setName(*arg.get());
339  c.B.CreateStore(&*(AI++), *alloca);
340  c.symbols[*arg.get()] = *(alloca++);
341  }
342  alloca = localAllocas.begin();
343  for (auto &local : decls)
344  {
345  (*alloca)->setName(local);
346  c.B.CreateStore(ConstantPointerNull::get(c.ObjPtrTy), *alloca);
347  c.symbols[local] = *(alloca++);
348  }
349  // If this closure refers to external variables then they'll have been
350  // copied into the closure structure. Add those to the symbol table in the
351  // same way that we added instance variables for methods.
352  if (!boundVars.empty())
353  {
354  // The type of the closure pointer argument
355  PointerType *ArgTy = cast<PointerType>(ClosureInvokeTy->params()[0]);
356  // The type of the closure object
357  StructType *ObjTy =
358  cast<StructType>(cast<PointerType>(ArgTy)->getElementType());
359  // The type of the instance variables array
360  Type *boundVarsArrayTy = ObjTy->elements()[4];
361 
362  Value *boundVarsArray = c.B.CreateStructGEP(ObjTy, &*c.F->arg_begin(), 4);
363  int i=0;
364  for (auto &bound : boundVars)
365  {
366  c.symbols[bound] = c.B.CreateStructGEP(boundVarsArrayTy, boundVarsArray, i++, bound);
367  }
368  }
369  body->compile(c);
370  if (c.B.GetInsertBlock() != nullptr)
371  {
372  c.B.CreateRet(ConstantPointerNull::get(c.ObjPtrTy));
373  }
374  return c.compile();
375 }
376 
377 Value *ClosureDecl::compileExpression(Compiler::Context &c)
378 {
379  // Make sure that we know what the bound variables are.
380  check();
381  auto &params = parameters->arguments;
382  // Get the type of the invoke function
383  FunctionType *invokeTy = c.getClosureType(boundVars.size(), params.size());
384  // Get the type of the first parameter (a pointer to the closure structure)
385  PointerType *closurePtrTy = cast<PointerType>(invokeTy->getParamType(0));
386  // The type of the closure.
387  StructType *closureTy = cast<StructType>(closurePtrTy->getElementType());
388  // The size of the closure is the size of `Closure`, which contains all of
389  // the fields shared by all closures, and then space for all of the bound
390  // variables.
391  size_t closureSize = sizeof(struct Closure) + boundVars.size() * sizeof(Obj);
392  // Insert the `GC_malloc` function (provided by libgc) into the module,
393  // bitcast to return a pointer to our closure type.
394  Constant *allocFn = c.M->getOrInsertFunction("GC_malloc", closurePtrTy,
395  c.ObjIntTy, nullptr);
396  // Allocate GC'd memory for the closure. Note that it would often be more
397  // efficient to do this on the stack, but only if we can either statically
398  // prove that the closure is not captured by anything that is called or if
399  // we can promote it to the heap if it is.
400  Value *closure = c.B.CreateCall(allocFn, ConstantInt::get(c.ObjIntTy,
401  closureSize));
402  // Set the isa pointer to the closure class.
403  c.B.CreateStore(staticAddress(c, &ClosureClass, c.ObjPtrTy),
404  c.B.CreateStructGEP(closureTy, closure, 0));
405  // Set the parameters pointer to the number of parameters.
406  c.B.CreateStore(getAsObject(c, compileSmallInt(c, params.size())),
407  c.B.CreateStructGEP(closureTy, closure, 1));
408  // If we've already compiled the function for this closure, then insert a
409  // pointer to it into the closure, otherwise use the trampoline that calls
410  // back into the interpreter.
411  // Note: This means that if we later compile this closure we should
412  // recompile the enclosing function or the invocation of the closure will be
413  // expensive.
414  ClosureInvoke closureFn = compiledClosure ? compiledClosure :
415  Interpreter::closureTrampolines[params.size()];
416  c.B.CreateStore(staticAddress(c, closureFn, c.ObjPtrTy),
417  c.B.CreateStructGEP(closureTy, closure, 2));
418  // Set the AST pointer
419  c.B.CreateStore(staticAddress(c, this, c.ObjPtrTy),
420  c.B.CreateStructGEP(closureTy, closure, 3));
421  // Get a pointer to the array of bound variables
422  Value *boundVarsArray = c.B.CreateStructGEP(closureTy, closure, 4);
423  Type *boundVarsArrayTy = closureTy->elements()[4];
424  int i=0;
425  for (auto &var : boundVars)
426  {
427  // Load each bound variable and then insert it into the closure at the
428  // correct index.
429  c.B.CreateStore(c.B.CreateLoad(c.lookupSymbolAddr(var)),
430  c.B.CreateStructGEP(boundVarsArrayTy, boundVarsArray, i++, var));
431  }
432  // Add this closure to our symbol table.
433  c.B.CreateStore(c.B.CreateBitCast(closure, c.ObjPtrTy), c.symbols[name]);
434  return closure;
435 }
436 Value *Call::compileExpression(Compiler::Context &c)
437 {
438  SmallVector<Value*, 10> args;
439  // Compile the expression that evaluates to the object being called.
440  Value *obj = getAsObject(c, callee->compileExpression(c));
441  assert(obj);
442  // For both closure and method invocations, the object being invoked is the
443  // first argument
444  args.push_back(obj);
445  // If this is a method invocation, then the next argument is the selector.
446  if (method)
447  {
448  Selector sel = lookupSelector(*method.get());
449  args.push_back(ConstantInt::get(c.SelTy, sel));
450  }
451  // Now add each of the explicit arguments.
452  auto &argsAST = arguments->arguments;
453  for (auto &arg : argsAST)
454  {
455  args.push_back(getAsObject(c, arg->compileExpression(c)));
456  }
457  // If there's no method, then we're trying to invoke a closure.
458  if (!method)
459  {
460  // Get the closure invoke type.
461  FunctionType *invokeFnTy = c.getClosureType(0, args.size() - 1);
462  // The only field we care about in the closure is the invoke pointer,
463  // so define enough of the structure to get that (two pointers before
464  // it)
465  Type *Fields[3] =
466  { c.ObjPtrTy, c.ObjPtrTy, invokeFnTy->getPointerTo() };
467  // Get the type of a pointer to the closure object
468  Type *closureTy = StructType::create(Fields);
469  Type *closurePtrTy = closureTy->getPointerTo();
470  // Cast the called object to a closure
471  Value *closure = c.B.CreateBitCast(obj, closurePtrTy);
472  // Compute the address of the pointer to the closure invoke function
473  Value *invokeFn = c.B.CreateStructGEP(closureTy, closure, 2);
474  // Load the address of the invoke function
475  invokeFn = c.B.CreateLoad(invokeFn);
476  // Insert the call
477  return c.B.CreateCall(invokeFn, args, "call_closure");
478  }
479  // If we are invoking a method, then we must first look up the method, then
480  // call it.
481  FunctionType *methodType = c.getMethodType(0, args.size() - 2);
482  // Get the lookup function
483  Constant *lookupFn = c.M->getOrInsertFunction("compiledMethodForSelector",
484  methodType->getPointerTo(), obj->getType(), c.SelTy, nullptr);
485  // Insert the call to the function that performs the lookup. This will
486  // always return *something* that we can call, even if it's just a function
487  // that reports an error.
488  Value *methodFn = c.B.CreateCall(lookupFn, {obj, args[1]});
489  // Call the method
490  return c.B.CreateCall(methodFn, args, "call_method");
491 }
492 
493 void Statements::compile(Compiler::Context &c)
494 {
495  for (auto &s : statements)
496  {
497  // If we've hit a return statement then any subsequent statements in
498  // this block are dead so just return.
499  if (c.B.GetInsertBlock() == nullptr)
500  {
501  return;
502  }
503  s->compile(c);
504  }
505 }
506 
507 
508 
509 void Return::compile(Compiler::Context &c)
510 {
511  // Insert a return instruction with the correct value
512  Value *ret = expr->compileExpression(c);
513  c.B.CreateRet(getAsObject(c, ret));
514  // Clear the insert point so nothing else tries to insert instructions after
515  // the basic block terminator
516  c.B.ClearInsertionPoint();
517 }
518 
519 void IfStatement::compile(Compiler::Context &c)
520 {
521  // Compute the condition
522  Value *cond = condition->compileExpression(c);
523  // Create the basic block that we'll branch to if the condition is false and
524  // after executing if the condition is true.
525  BasicBlock *cont = BasicBlock::Create(c.C, "if.cont", c.F);
526  // Create the block that contains the body of the if statement
527  BasicBlock *ifBody = BasicBlock::Create(c.C, "if.body", c.F);
528  // Cast the condition to a small int. We aren't unconditionally
529  // interpreting it as a small int, we just want to be able to do some
530  // arithmetic on it...
531  cond = getAsSmallInt(c, cond);
532  // Now right shift it by 3. If it is an object pointer, it will now be 0 if
533  // it were a null pointer before the shift. If it is a small integer, then
534  // it will now contain its numeric value. Either way, a value of 0 means
535  // either a zero integer or null, and a value of anything else means a valid
536  // object or non-zero integer.
537  cond = c.B.CreateLShr(cond, ConstantInt::get(c.ObjIntTy, 3));
538  // Create a comparison with 0 that we can then branch on
539  cond = c.B.CreateIsNotNull(cond);
540  // Branch to the body if it's not 0, to the continuation block if it is
541  c.B.CreateCondBr(cond, ifBody, cont);
542  // Compile the body of the if statement.
543  c.B.SetInsertPoint(ifBody);
544  body->compile(c);
545  // If the if statement didn't end with a return, then return control flow to
546  // the block after the if statement.
547  if (c.B.GetInsertBlock() != nullptr)
548  {
549  c.B.CreateBr(cont);
550  }
551  // Continue from the end
552  c.B.SetInsertPoint(cont);
553 }
554 void WhileLoop::compile(Compiler::Context &c)
555 {
556  // Create three blocks, one for the body of the test (which we will
557  // unconditionally branch back to at the end of the body), one for the loop
558  // body (which we will skip if the condition is false) and one for the end,
559  // which we will branch to after the loop has finished.
560  BasicBlock *condBlock = BasicBlock::Create(c.C, "while.cond", c.F);
561  BasicBlock *cont = BasicBlock::Create(c.C, "while.cont", c.F);
562  BasicBlock *whileBody = BasicBlock::Create(c.C, "while.body", c.F);
563  // Unconditionally branch to the block for the condition and compile it
564  c.B.CreateBr(condBlock);
565  c.B.SetInsertPoint(condBlock);
566  // Compile the condition expression
567  Value *cond = condition->compileExpression(c);
568  // Convert it to an integer and test that it isn't null
569  cond = getAsSmallInt(c, cond);
570  cond = c.B.CreateLShr(cond, ConstantInt::get(c.ObjIntTy, 3));
571  cond = c.B.CreateIsNotNull(cond);
572  // Branch into the loop body or past it, depending on the condition value.
573  c.B.CreateCondBr(cond, whileBody, cont);
574  c.B.SetInsertPoint(whileBody);
575  // Compile the body of the loop.
576  body->compile(c);
577  // Unconditionally branch back to the condition to check it again.
578  c.B.CreateBr(condBlock);
579  // Set the insert point to the block after the loop.
580  c.B.SetInsertPoint(cont);
581 }
582 
584 {
585  // If we don't have a cached string object for this literal, then poke the
586  // interpreter to generate one.
587  if (!static_cast<Obj>(cache))
588  {
590  cache = evaluateExpr(ic);
591  }
592  // Return a constant pointer to the cached value.
593  return staticAddress(c, static_cast<Obj>(cache), c.ObjPtrTy);
594 }
595 Value *Number::compileExpression(Compiler::Context &c)
596 {
597  // Construct a constant small integer value
598  return compileSmallInt(c, value);
599 }
600 
601 void Decl::compile(Compiler::Context &c)
602 {
603  // Decls are collected and stack space allocated for them when we compile a
604  // closure, but we still want to initialise them at their first use.
605  if (init)
606  {
607  assert(c.symbols[name]);
608  c.B.CreateStore(getAsObject(c, init->compileExpression(c)),
609  c.symbols[name]);
610  }
611 }
612 void Assignment::compile(Compiler::Context &c)
613 {
614  assert(c.symbols[target->name]);
615  // Store the result of the expression in the address of the named variable.
616  c.B.CreateStore(getAsObject(c, expr->compileExpression(c)),
617  c.symbols[target->name]);
618 }
619 
620 Value *VarRef::compileExpression(Compiler::Context &c)
621 {
622  return c.B.CreateLoad(c.lookupSymbolAddr(name));
623 }
624 Value *NewExpr::compileExpression(Compiler::Context &c)
625 {
626  // Look up the class statically
627  Class *cls = lookupClass(className);
628  // Create a value corresponding to the class pointer
629  Value *clsPtr = staticAddress(c, cls, c.ObjPtrTy);
630  // Look up the function that creates instances of objects
631  Constant *newFn = c.M->getOrInsertFunction("newObject", c.ObjPtrTy,
632  c.ObjPtrTy, nullptr);
633  // Call the function with the class pointer as the argument
634  return c.B.CreateCall(newFn, clsPtr, "new");
635 }
636 
637 namespace {
644 typedef std::function<Value*(Compiler::Context &c, Value*, Value*)> BinOpFn;
645 
650 Value *compileCompare(Compiler::Context &c, CmpInst::Predicate Op,
651  Value *LHS, Value *RHS)
652 {
653  // Comparisons work on small integers or pointers, so just insert the
654  // relevant compare instruction.
655  Value *cmp = c.B.CreateICmp(Op, getAsSmallInt(c, LHS),
656  getAsSmallInt(c, RHS), "cmp");
657  // The result is an i1 (one-bit integer), so zero-extend it to the size of a
658  // small integer
659  cmp = c.B.CreateZExt(cmp, c.ObjIntTy, "cmp_object");
660  // Then set the low bit to make it an object.
661  return compileSmallInt(c, cmp);
662 
663 }
664 
672 Value *compileBinaryOp(Compiler::Context &c, Value *LHS, Value *RHS,
673  Instruction::BinaryOps Op, const char *slowCallFnName)
674 {
675  // Get the two operands as integer values
676  Value *LHSInt = getAsSmallInt(c, LHS);
677  Value *RHSInt = getAsSmallInt(c, RHS);
678  // And them together. If they are both small ints, then the low bits of the
679  // result will be 001.
680  Value *isSmallInt = c.B.CreateAnd(LHSInt, RHSInt);
681  // Now mask off the low 3 bits.
682  isSmallInt = c.B.CreateAnd(isSmallInt, ConstantInt::get(c.ObjIntTy, 7));
683  // If the low three bits are 001, then it is a small integer
684  isSmallInt = c.B.CreateICmpEQ(isSmallInt, ConstantInt::get(c.ObjIntTy, 1));
685  // Create three basic blocks, one for the small int case, one for the real
686  // object case, and one for when the two join together again.
687  BasicBlock *cont = BasicBlock::Create(c.C, "cont", c.F);
688  BasicBlock *small = BasicBlock::Create(c.C, "int", c.F);
689  BasicBlock *obj = BasicBlock::Create(c.C, "obj", c.F);
690  // If both arguments are small integers, jump to the small int block,
691  // otherwise fall back to the other case.
692  c.B.CreateCondBr(isSmallInt, small, obj);
693 
694  // Now emit the small int code:
695  c.B.SetInsertPoint(small);
696  // Shift both values right by 3 to give primitive integer values
697  LHSInt = c.B.CreateAShr(LHSInt, ConstantInt::get(c.ObjIntTy, 3));
698  RHSInt = c.B.CreateAShr(RHSInt, ConstantInt::get(c.ObjIntTy, 3));
699  // Invoke the function passed by the caller to insert the correct operation.
700  Value *intResult = c.B.CreateBinOp(Op, LHSInt, RHSInt);
701  // Now cast the result to an object and branch to the continue block
702  intResult = getAsObject(c, compileSmallInt(c, intResult));
703  c.B.CreateBr(cont);
704 
705  // Next we'll handle the real object case.
706  c.B.SetInsertPoint(obj);
707  // Call the function that handles the object case
708  Value *objResult = c.B.CreateCall(c.M->getOrInsertFunction(slowCallFnName,
709  c.ObjPtrTy, LHS->getType(), RHS->getType(), nullptr),
710  {LHS, RHS});
711  // And branch to the continuation block
712  c.B.CreateBr(cont);
713 
714  // Now that we've handled both cases, we need to unify the flow control and
715  // provide a single value
716  c.B.SetInsertPoint(cont);
717  // Construct a PHI node to hold the result.
718  PHINode *result = c.B.CreatePHI(intResult->getType(), 2, "sub");
719  // Set its value to the result of whichever basic block we arrived from
720  result->addIncoming(intResult, small);
721  result->addIncoming(objResult, obj);
722  // Return the result
723  return result;
724 }
725 } // End anonymous namespace
726 
727 Value *CmpNe::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
728 {
729  return compileCompare(c, CmpInst::Predicate::ICMP_NE, LHS, RHS);
730 }
731 Value *CmpEq::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
732 {
733  return compileCompare(c, CmpInst::Predicate::ICMP_EQ, LHS, RHS);
734 }
735 Value *CmpGt::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
736 {
737  return compileCompare(c, CmpInst::Predicate::ICMP_SGT, LHS, RHS);
738 }
739 Value *CmpLt::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
740 {
741  return compileCompare(c, CmpInst::Predicate::ICMP_SLT, LHS, RHS);
742 }
743 Value *CmpGE::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
744 {
745  return compileCompare(c, CmpInst::Predicate::ICMP_SGE, LHS, RHS);
746 }
747 Value *CmpLE::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
748 {
749  return compileCompare(c, CmpInst::Predicate::ICMP_SLE, LHS, RHS);
750 }
751 Value *Subtract::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
752 {
753  return compileBinaryOp(c, LHS, RHS, Instruction::Sub, "mysoreScriptAdd");
754 }
755 Value *Add::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
756 {
757  return compileBinaryOp(c, LHS, RHS, Instruction::Add, "mysoreScriptSub");
758 }
759 Value *Multiply::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
760 {
761  return compileBinaryOp(c, LHS, RHS, Instruction::Mul, "mysoreScriptMul");
762 }
763 Value *Divide::compileBinOp(Compiler::Context &c, Value *LHS, Value *RHS)
764 {
765  return compileBinaryOp(c, LHS, RHS, Instruction::SDiv, "mysoreScriptDiv");
766 }
Value * getAsObject(Compiler::Context &c, Value *i)
Get the specified value as the LLVM type used for object pointers.
Definition: compiler.cc:50
Object *(* CompiledMethod)(Object *, Selector,...)
A compiled method is a function that takes an object (the receiver) and the selector as implicit argu...
Definition: runtime.hh:75
Definition: ast.hh:12
Object * Obj
Object pointer.
Definition: runtime.hh:33
uint32_t Selector
Selectors are unique identifiers for methods.
Definition: runtime.hh:70
std::unique_ptr< llvm::Module > M
The current module.
Definition: compiler.hh:33
const char ** indexedIVarNames
The names of the instance variables.
Definition: runtime.hh:136
llvm::IRBuilder B
The IR builder, always set to the current insert point.
Definition: compiler.hh:41
std::unordered_map< std::string, llvm::Value * > symbols
Symbols within this compilation context.
Definition: compiler.hh:47
llvm::Value * lookupSymbolAddr(const std::string &str)
Returns the address of the specified symbol.
Definition: compiler.cc:89
std::unordered_map< std::string, Obj * > SymbolTable
A symbol table stores the address of each allocation.
Definition: interpreter.hh:103
llvm::FunctionType * getClosureType(int bound, int args)
Get the type of a closure invoke function, for a closure with the specified number of instance variab...
Definition: compiler.cc:174
Selector lookupSelector(const std::string &str)
Looks up the selector for a specified string value, registering a new value if this is the first time...
Definition: runtime.cc:553
The compiler context.
Definition: compiler.hh:16
Object *(* ClosureInvoke)(Closure *,...)
A compiled closure invoke function.
Definition: runtime.hh:80
struct Class * lookupClass(const std::string &name)
Look up an existing class.
Definition: runtime.cc:601
llvm::Value * compileExpression(Compiler::Context &c) override
Compile the string.
Definition: compiler.cc:583
A generic MysoreScript object.
Definition: runtime.hh:144
Value * compileSmallInt(Compiler::Context &c, intptr_t i)
Generate a small integer object from an integer constant.
Definition: compiler.cc:42
struct Class ClosureClass
The Closure class structure.
Definition: runtime.cc:543
ClosureInvoke closureTrampolines[]
Array of trampolines, indexed by number or arguments.
Definition: interpreter.cc:277
Value * compileBinaryOp(Compiler::Context &c, Value *LHS, Value *RHS, Instruction::BinaryOps Op, const char *slowCallFnName)
Helper function that inserts all of the code required for small integer operations, either calling the relevant method or doing the arithmetic.
Definition: compiler.cc:672
llvm::Type * ObjIntTy
The type of an integer the same size as an object pointer.
Definition: compiler.hh:55
Value * getAsSmallInt(Compiler::Context &c, Value *i)
Get the specified value as the LLVM type used for small integer objects.
Definition: compiler.cc:63
std::function< Value *(Compiler::Context &c, Value *, Value *)> BinOpFn
A function type that is used by the compileBinaryOp function.
Definition: compiler.cc:644
llvm::Type * SelTy
The type used for selectors.
Definition: compiler.hh:59
llvm::Function * F
The function being compiled.
Definition: compiler.hh:37
llvm::PointerType * ObjPtrTy
The type of a pointer to a MysoreScript object.
Definition: compiler.hh:51
int32_t indexedIVarCount
The number of indexed instance variables that this class has.
Definition: runtime.hh:127
Value * compileCompare(Compiler::Context &c, CmpInst::Predicate Op, Value *LHS, Value *RHS)
Helper function that inserts all of the code required for comparison operations.
Definition: compiler.cc:650
Definition: ast.hh:17
Value * staticAddress(Compiler::Context &c, T *ptr, Type *ty)
Helper function that turns a pointer that is known at compile time into a constant in the code...
Definition: compiler.cc:26
llvm::LLVMContext C
The LLVM context.
Definition: compiler.hh:29
Struct holding metadata about a class.
Definition: runtime.hh:109
llvm::FunctionType * getMethodType(int ivars, int args)
Get the type of a method with the specified number of arguments, for an object with the specified num...
Definition: compiler.cc:151
MysoreScript::ClosureInvoke compile()
At the end of compilation, generate code and return a function pointer.
Definition: compiler.cc:107
Context(Interpreter::SymbolTable &g)
Construct a context, given a global symbol table from the interpreter.
Definition: compiler.cc:73
The layout of all closures in MysoreScript.
Definition: runtime.hh:199