Added support for non-array references.
authorDavid Anderson <dvander@alliedmods.net>
Sat Jun 30 22:31:14 2012 -0700 (2012-06-30)
changeset 140784ac5cc347
parent 13 627b6b94e774
child 15 d8ed9b8f19ca
Added support for non-array references.
jitcraft/AST.h
jitcraft/BytecodeCompiler.cpp
jitcraft/BytecodeCompiler.h
jitcraft/BytecodeEmitter.h
jitcraft/Code.h
jitcraft/Heap.h
jitcraft/Interpreter.cpp
jitcraft/Modules.cpp
jitcraft/Modules.h
jitcraft/Opcodes.cpp
jitcraft/Opcodes.tbl
jitcraft/Parser.cpp
jitcraft/SemanticAnalysis.cpp
jitcraft/SemanticAnalysis.h
jitcraft/Stack.h
jitcraft/Token.h
jitcraft/TypeManager.cpp
jitcraft/TypeManager.h
jitcraft/Types.cpp
jitcraft/Types.h
jitcraft/Zone.cpp
jitcraft/jitcraft.vcxproj
jitcraft/main.cpp
     1.1 --- a/jitcraft/AST.h	Sat Jun 30 20:20:39 2012 -0700
     1.2 +++ b/jitcraft/AST.h	Sat Jun 30 22:31:14 2012 -0700
     1.3 @@ -176,6 +176,31 @@
     1.4      }
     1.5  };
     1.6  
     1.7 +class Parameter : public PoolObject
     1.8 +{
     1.9 +    Variable *variable_;
    1.10 +    Name *tag_;
    1.11 +    bool reference_;
    1.12 +
    1.13 +  public:
    1.14 +    Parameter(Variable *var, Name *tag, bool reference)
    1.15 +      : variable_(var),
    1.16 +        tag_(tag),
    1.17 +        reference_(reference)
    1.18 +    {
    1.19 +    }
    1.20 +
    1.21 +    Name *tag() const {
    1.22 +        return tag_;
    1.23 +    }
    1.24 +    Variable *variable() const {
    1.25 +        return variable_;
    1.26 +    }
    1.27 +    bool reference() const {
    1.28 +        return reference_;
    1.29 +    }
    1.30 +};
    1.31 +
    1.32  class NameProxy : public Expression
    1.33  {
    1.34      Name *name_;
    1.35 @@ -528,17 +553,21 @@
    1.36      }
    1.37  };
    1.38  
    1.39 +typedef std::vector<Parameter *> ParameterList;
    1.40 +
    1.41  class FunctionStatement : public Statement
    1.42  {
    1.43      Scope *scope_;
    1.44      NamedFunction *fun_;
    1.45      Statement *body_;
    1.46 +    ParameterList *parameters_;
    1.47  
    1.48    public:
    1.49 -    FunctionStatement(Scope *scope, NamedFunction *fun, Statement *body)
    1.50 +    FunctionStatement(Scope *scope, NamedFunction *fun, Statement *body, ParameterList *parameters)
    1.51        : scope_(scope),
    1.52          fun_(fun),
    1.53 -        body_(body)
    1.54 +        body_(body),
    1.55 +        parameters_(parameters)
    1.56      {
    1.57      }
    1.58  
    1.59 @@ -554,6 +583,9 @@
    1.60      Statement *body() const {
    1.61          return body_;
    1.62      }
    1.63 +    ParameterList *parameters() const {
    1.64 +        return parameters_;
    1.65 +    }
    1.66      void accept(AstVisitor *visitor) {
    1.67          visitor->visit(this);
    1.68      }
     2.1 --- a/jitcraft/BytecodeCompiler.cpp	Sat Jun 30 20:20:39 2012 -0700
     2.2 +++ b/jitcraft/BytecodeCompiler.cpp	Sat Jun 30 22:31:14 2012 -0700
     2.3 @@ -29,10 +29,11 @@
     2.4  
     2.5  #define __ emitter_.
     2.6  
     2.7 -BytecodeCompiler::BytecodeCompiler(ParseTree *tree)
     2.8 +BytecodeCompiler::BytecodeCompiler(ParseTree *tree, Module *module)
     2.9    : tree_(tree),
    2.10      scope_(NULL),
    2.11 -    loop_(NULL)
    2.12 +    loop_(NULL),
    2.13 +    module_(module)
    2.14  {
    2.15  }
    2.16  
    2.17 @@ -133,10 +134,22 @@
    2.18  
    2.19          if (var->location() == Variable::STACK) {
    2.20              __ getlocal(var->slot());
    2.21 +            assert(!name->type()->isReference());
    2.22          } else {
    2.23              assert(var->location() == Variable::PARAMETER);
    2.24              __ getarg(var->slot());
    2.25 +
    2.26 +            // If this argument is actually a reference, dereference it now.
    2.27 +            if (var->type()->isReference()) {
    2.28 +                if (var->type()->isFloat()) {
    2.29 +                    __ getref_f();
    2.30 +                } else {
    2.31 +                    assert(name->type()->isInt());
    2.32 +                    __ getref_i();
    2.33 +                }
    2.34 +            }
    2.35          }
    2.36 +
    2.37          break;
    2.38        }
    2.39  
    2.40 @@ -165,12 +178,32 @@
    2.41          NameProxy *proxy = node->lvalue()->toNameProxy();
    2.42          Variable *var = proxy->binding()->toVariable();
    2.43  
    2.44 +        // Make sure to bind the left-hand side first.
    2.45 +        if (var->type()->isReference()) {
    2.46 +            if (var->location() == Variable::STACK) {
    2.47 +                __ getlocal(var->slot());
    2.48 +            } else {
    2.49 +                assert(var->location() == Variable::PARAMETER);
    2.50 +                __ getarg(var->slot());
    2.51 +            }
    2.52 +        }
    2.53 +
    2.54          node->expression()->accept(this);
    2.55 -        if (var->location() == Variable::STACK) {
    2.56 -            __ setlocal(var->slot());
    2.57 +
    2.58 +        if (var->type()->isReference()) {
    2.59 +            if (var->type()->contained()->isFloat()) {
    2.60 +                __ setref_f();
    2.61 +            } else {
    2.62 +                assert(var->type()->contained()->isInt());
    2.63 +                __ setref_i();
    2.64 +            }
    2.65          } else {
    2.66 -            assert(var->location() == Variable::PARAMETER);
    2.67 -            __ setarg(var->slot());
    2.68 +            if (var->location() == Variable::STACK) {
    2.69 +                __ setlocal(var->slot());
    2.70 +            } else {
    2.71 +                assert(var->location() == Variable::PARAMETER);
    2.72 +                __ setarg(var->slot());
    2.73 +            }
    2.74          }
    2.75      } else if (node->lvalue()->isIndexExpression()) {
    2.76          IndexExpression *index = node->lvalue()->toIndexExpression();
    2.77 @@ -408,9 +441,33 @@
    2.78  {
    2.79      NameProxy *fun = node->callee()->toNameProxy();
    2.80  
    2.81 +    // :TODO: use Local
    2.82 +    Type *funType = node->callee()->type();
    2.83 +
    2.84      for (size_t i = 0; i < node->arguments()->size(); i++) {
    2.85          Expression *arg = node->arguments()->at(i);
    2.86 -        arg->accept(this);
    2.87 +
    2.88 +        Type *given = arg->type();
    2.89 +        Type *actual = Type::cast(funType->parameters()->at(i));
    2.90 +        if (actual->isReference()) {
    2.91 +            if (given->isReference()) {
    2.92 +                // The input type is already a reference, so we're just passing
    2.93 +                // it on to the callee.
    2.94 +                arg->accept(this);
    2.95 +            } else if (arg->isNameProxy()) {
    2.96 +                // :TODO: test with functions and globals
    2.97 +                // Compute a reference to the name.
    2.98 +                Variable *var = arg->toNameProxy()->binding()->toVariable();
    2.99 +                __ newref(var);
   2.100 +            } else {
   2.101 +                // We don't know how to, or can't, build a direct reference to
   2.102 +                // this type. Make an indirect one, by taking the top of the
   2.103 +                // stack and boxing it up.
   2.104 +                __ slotref_lifo();
   2.105 +            }
   2.106 +        } else {
   2.107 +            arg->accept(this);
   2.108 +        }
   2.109      }
   2.110  
   2.111      __ callglobal(node->arguments()->size(), 0);
   2.112 @@ -438,11 +495,11 @@
   2.113  void
   2.114  BytecodeCompiler::visit(FunctionStatement *node)
   2.115  {
   2.116 -    BytecodeCompiler child(tree_);
   2.117 +    BytecodeCompiler child(tree_, module_);
   2.118      Code *code = child.compileFunction(module_, node);
   2.119      
   2.120      assert(!module_->getFunction(node->fun()->slot()));
   2.121 -    module_->setFunction(node->fun()->slot(), code);
   2.122 +    module_->setFunction(ZONE(), node->fun()->slot(), code);
   2.123  }
   2.124  
   2.125  void
   2.126 @@ -497,10 +554,10 @@
   2.127  Module *
   2.128  BytecodeCompiler::compile()
   2.129  {
   2.130 -    Code **functions = new Code *[tree_->scope()->numFunctions()];
   2.131 -    memset(functions, 0, sizeof(Code *) * tree_->scope()->numFunctions());
   2.132 -
   2.133 -    module_ = new Module(functions, tree_->scope()->numFunctions());
   2.134 +    // :TODO: root
   2.135 +    module_ = Module::New(ZONE(), tree_->scope()->numFunctions());
   2.136 +    if (!module_)
   2.137 +        return NULL;
   2.138  
   2.139      for (size_t i = 0; i < tree_->statements()->length(); i++) {
   2.140          Statement *statement = tree_->statements()->at(i);
   2.141 @@ -509,7 +566,7 @@
   2.142  
   2.143  #ifndef NDEBUG
   2.144      for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
   2.145 -        assert(functions[i]);
   2.146 +        assert(module_->getFunction(i));
   2.147  #endif
   2.148  
   2.149      return module_;
     3.1 --- a/jitcraft/BytecodeCompiler.h	Sat Jun 30 20:20:39 2012 -0700
     3.2 +++ b/jitcraft/BytecodeCompiler.h	Sat Jun 30 22:31:14 2012 -0700
     3.3 @@ -99,7 +99,7 @@
     3.4      void visitForALU(Type *needed, Expression *node);
     3.5  
     3.6    public:
     3.7 -    BytecodeCompiler(ParseTree *tree);
     3.8 +    BytecodeCompiler(ParseTree *tree, Module *module);
     3.9  
    3.10      Module *compile();
    3.11  
     4.1 --- a/jitcraft/BytecodeEmitter.h	Sat Jun 30 20:20:39 2012 -0700
     4.2 +++ b/jitcraft/BytecodeEmitter.h	Sat Jun 30 22:31:14 2012 -0700
     4.3 @@ -22,6 +22,7 @@
     4.4  #include <limits.h>
     4.5  #include <vector>
     4.6  #include "Opcodes.h"
     4.7 +#include "NameBinding.h"
     4.8  
     4.9  namespace jc {
    4.10  
    4.11 @@ -308,6 +309,32 @@
    4.12          writeOp(OP_UNWINDLIFO);
    4.13          writeUint32(slot);
    4.14      }
    4.15 +    void newref(Variable *var) {
    4.16 +        if (var->location() == Variable::STACK) {
    4.17 +            ensure(OP_VARREF_LIFO_LENGTH);
    4.18 +            writeOp(OP_VARREF_LIFO);
    4.19 +        } else {
    4.20 +            assert(var->location() == Variable::PARAMETER);
    4.21 +            ensure(OP_ARGREF_LIFO_LENGTH);
    4.22 +            writeOp(OP_ARGREF_LIFO);
    4.23 +        }
    4.24 +        writeUint32(var->slot());
    4.25 +    }
    4.26 +    void slotref_lifo() {
    4.27 +        singleByteOp(OP_SLOTREF_LIFO);
    4.28 +    }
    4.29 +    void getref_i() {
    4.30 +        singleByteOp(OP_GETREF_I);
    4.31 +    }
    4.32 +    void setref_i() {
    4.33 +        singleByteOp(OP_SETREF_I);
    4.34 +    }
    4.35 +    void getref_f() {
    4.36 +        singleByteOp(OP_GETREF_F);
    4.37 +    }
    4.38 +    void setref_f() {
    4.39 +        singleByteOp(OP_SETREF_F);
    4.40 +    }
    4.41  };
    4.42  
    4.43  }
     5.1 --- a/jitcraft/Code.h	Sat Jun 30 20:20:39 2012 -0700
     5.2 +++ b/jitcraft/Code.h	Sat Jun 30 22:31:14 2012 -0700
     5.3 @@ -75,7 +75,7 @@
     5.4      }
     5.5  
     5.6      static Code *cast(Object *obj) {
     5.7 -        assert(obj->is(MapKind_Code));
     5.8 +        assert(!obj || obj->is(MapKind_Code));
     5.9          return reinterpret_cast<Code *>(obj);
    5.10      }
    5.11  };
     6.1 --- a/jitcraft/Heap.h	Sat Jun 30 20:20:39 2012 -0700
     6.2 +++ b/jitcraft/Heap.h	Sat Jun 30 22:31:14 2012 -0700
     6.3 @@ -57,13 +57,16 @@
     6.4      // Represents Type objects.
     6.5      MapKind_Type,
     6.6  
     6.7 -    // Represents basic data structures.
     6.8 +    // Represents basic data structures. When adding to this, don't forget
     6.9 +    // to update Zone::initialize(), or you'll get a NULL crash trying to
    6.10 +    // allocate, since these maps are cached.
    6.11      MapKind_FixedArray,
    6.12      MapKind_ByteArray,
    6.13      MapKind_Code,
    6.14 +    MapKind_Reference,
    6.15 +    MapKind_Module,
    6.16  
    6.17 -    // Used to represent Arrays. These two map kinds do not have canonical
    6.18 -    // maps.
    6.19 +    // Used to represent Arrays. This does not have a canonical map.
    6.20      MapKind_Array,
    6.21  
    6.22      // These represent special Map subclasses that require special tracing.
     7.1 --- a/jitcraft/Interpreter.cpp	Sat Jun 30 20:20:39 2012 -0700
     7.2 +++ b/jitcraft/Interpreter.cpp	Sat Jun 30 22:31:14 2012 -0700
     7.3 @@ -20,6 +20,7 @@
     7.4  #include "Zone.h"
     7.5  #include "Types.h"
     7.6  #include "Array.h"
     7.7 +#include "Reference.h"
     7.8  
     7.9  using namespace jc;
    7.10  
    7.11 @@ -52,6 +53,17 @@
    7.12  }
    7.13  
    7.14  static inline bool
    7.15 +PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
    7.16 +{
    7.17 +    Reference *ref = Reference::NewStack(zone, location, tenure);
    7.18 +    if (!ref)
    7.19 +        return false;
    7.20 +    top.sp->ref = ref;
    7.21 +    top.sp++;
    7.22 +    return true;
    7.23 +}
    7.24 +
    7.25 +static inline bool
    7.26  CheckDimensionSize(int size, unsigned width)
    7.27  {
    7.28      if (size <= 0) {
    7.29 @@ -453,6 +465,52 @@
    7.30      break;
    7.31  }
    7.32  
    7.33 +case OP_VARREF_LIFO:
    7.34 +{
    7.35 +    unsigned slot = READ_UINT32(top.pc);
    7.36 +    if (!PushNewRef(ZONE(), top, &locals[slot], Heap::Tenure_Stack)) {
    7.37 +        assert(false);
    7.38 +        return false;
    7.39 +    }
    7.40 +    break;
    7.41 +}
    7.42 +
    7.43 +case OP_ARGREF_LIFO:
    7.44 +{
    7.45 +    unsigned slot = READ_UINT32(top.pc);
    7.46 +    if (!PushNewRef(ZONE(), top, &frame->arg(slot), Heap::Tenure_Stack)) {
    7.47 +        assert(false);
    7.48 +        return false;
    7.49 +    }
    7.50 +    break;
    7.51 +}
    7.52 +
    7.53 +case OP_GETREF_I:
    7.54 +{
    7.55 +    top.sp[-1].i32 = top.sp[-1].ref->getInt();
    7.56 +    break;
    7.57 +}
    7.58 +
    7.59 +case OP_SETREF_I:
    7.60 +{
    7.61 +    top.sp[-2].ref->setInt(top.sp[-1].i32);
    7.62 +    top.sp[-2].i32 = top.sp[-1].i32;
    7.63 +    break;
    7.64 +}
    7.65 +
    7.66 +case OP_GETREF_F:
    7.67 +{
    7.68 +    top.sp[-1].f = top.sp[-1].ref->getFloat();
    7.69 +    break;
    7.70 +}
    7.71 +
    7.72 +case OP_SETREF_F:
    7.73 +{
    7.74 +    top.sp[-2].ref->setFloat(top.sp[-1].f);
    7.75 +    top.sp[-2].f = top.sp[-1].f;
    7.76 +    break;
    7.77 +}
    7.78 +
    7.79  default:
    7.80      assert(false);
    7.81      return false;
     8.1 --- a/jitcraft/Modules.cpp	Sat Jun 30 20:20:39 2012 -0700
     8.2 +++ b/jitcraft/Modules.cpp	Sat Jun 30 22:31:14 2012 -0700
     8.3 @@ -16,16 +16,24 @@
     8.4   * JITCraft. If not, see http://www.gnu.org/licenses/.
     8.5   */
     8.6  #include "Modules.h"
     8.7 +#include "Zone.h"
     8.8 +#include "Heap.h"
     8.9 +#include "Heap-inl.h"
    8.10  
    8.11  using namespace jc;
    8.12  
    8.13 -Module::Module(Code **functions, unsigned nfunctions)
    8.14 -  : functions_(functions),
    8.15 -    nfunctions_(nfunctions)
    8.16 +Module *
    8.17 +Module::New(Zone *zone, unsigned nfunctions)
    8.18  {
    8.19 +    // :TODO: use locals.
    8.20 +    Module *module = Module::cast(zone->allocate(MapKind_Module, sizeof(Module), Heap::Tenure_Old));
    8.21 +    if (!module)
    8.22 +        return NULL;
    8.23 +
    8.24 +    FixedArray *functions = FixedArray::New(zone, nfunctions, Heap::Tenure_Old);
    8.25 +    if (!functions)
    8.26 +        return NULL;
    8.27 +
    8.28 +    module->functions_ = functions;
    8.29 +    return module;
    8.30  }
    8.31 -
    8.32 -Module::~Module()
    8.33 -{
    8.34 -    delete [] functions_;
    8.35 -}
     9.1 --- a/jitcraft/Modules.h	Sat Jun 30 20:20:39 2012 -0700
     9.2 +++ b/jitcraft/Modules.h	Sat Jun 30 22:31:14 2012 -0700
     9.3 @@ -18,28 +18,30 @@
     9.4  #ifndef _include_jc_module_h_
     9.5  #define _include_jc_module_h_
     9.6  
     9.7 +#include "Heap.h"
     9.8  #include "Code.h"
     9.9  
    9.10  namespace jc {
    9.11  
    9.12 -class Module
    9.13 +class Module : public Object
    9.14  {
    9.15 -    Code **functions_;
    9.16 -    unsigned nfunctions_;
    9.17 +    Barriered<FixedArray> functions_;
    9.18  
    9.19    public:
    9.20 -    Module(Code **functions, unsigned nfunctions);
    9.21 -    ~Module();
    9.22 +    static Module *New(Zone *zone, unsigned nfunctions);
    9.23  
    9.24      Code *getFunction(size_t i) {
    9.25 -        assert(i < nfunctions_);
    9.26 -        return functions_[i];
    9.27 +        return Code::cast(functions_->at(i));
    9.28      }
    9.29 -    void setFunction(size_t i, Code *code) {
    9.30 -        assert(i < nfunctions_);
    9.31 -        assert(!functions_[i]);
    9.32 +    void setFunction(Zone *zone, size_t i, Code *code) {
    9.33 +        assert(!functions_->at(i));
    9.34          assert(code);
    9.35 -        functions_[i] = code;
    9.36 +        functions_->set(zone, i, code);
    9.37 +    }
    9.38 +
    9.39 +    static inline Module *cast(Object *obj) {
    9.40 +        assert(!obj || obj->is(MapKind_Module));
    9.41 +        return reinterpret_cast<Module *>(obj);
    9.42      }
    9.43  };
    9.44  
    10.1 --- a/jitcraft/Opcodes.cpp	Sat Jun 30 20:20:39 2012 -0700
    10.2 +++ b/jitcraft/Opcodes.cpp	Sat Jun 30 22:31:14 2012 -0700
    10.3 @@ -94,6 +94,10 @@
    10.4            case OP_BITAND:
    10.5            case OP_BITOR:
    10.6            case OP_BITXOR:
    10.7 +          case OP_GETREF_I:
    10.8 +          case OP_SETREF_I:
    10.9 +          case OP_GETREF_F:
   10.10 +          case OP_SETREF_F:
   10.11              break;
   10.12  
   10.13            case OP_STOP:
   10.14 @@ -141,6 +145,8 @@
   10.15            case OP_SAVELIFO:
   10.16            case OP_UNWINDLIFO:
   10.17            case OP_CALLGLOBAL:
   10.18 +          case OP_VARREF_LIFO:
   10.19 +          case OP_ARGREF_LIFO:
   10.20              fprintf(fp, "%u", READ_UINT32(pc));
   10.21              break;
   10.22  
    11.1 --- a/jitcraft/Opcodes.tbl	Sat Jun 30 20:20:39 2012 -0700
    11.2 +++ b/jitcraft/Opcodes.tbl	Sat Jun 30 22:31:14 2012 -0700
    11.3 @@ -133,4 +133,13 @@
    11.4  
    11.5  // Saves or restores the position of the LIFO heap to/from a local slot.
    11.6  OPDEF(OP_SAVELIFO,      42,         "savelifo",     5,      0,  0)
    11.7 -OPDEF(OP_UNWINDLIFO,    43,         "unwindlifo",   5,      0,  0)
    11.8 \ No newline at end of file
    11.9 +OPDEF(OP_UNWINDLIFO,    43,         "unwindlifo",   5,      0,  0)
   11.10 +
   11.11 +// Composes a variable reference to a stack slot or argument.
   11.12 +OPDEF(OP_VARREF_LIFO,   44,         "varref.lifo",  5,      0,  1)
   11.13 +OPDEF(OP_ARGREF_LIFO,   45,         "argref.lifo",  5,      0,  1)
   11.14 +OPDEF(OP_SLOTREF_LIFO,  46,         "slotref.lifo", 1,      1,  1)
   11.15 +OPDEF(OP_GETREF_I,      47,         "getref.i",     1,      1,  1)
   11.16 +OPDEF(OP_SETREF_I,      48,         "setref.i",     1,      2,  1)
   11.17 +OPDEF(OP_GETREF_F,      49,         "getref.f",     1,      1,  1)
   11.18 +OPDEF(OP_SETREF_F,      50,         "setref.f",     1,      2,  1)
    12.1 --- a/jitcraft/Parser.cpp	Sat Jun 30 20:20:39 2012 -0700
    12.2 +++ b/jitcraft/Parser.cpp	Sat Jun 30 22:31:14 2012 -0700
    12.3 @@ -732,10 +732,14 @@
    12.4      if (!scope)
    12.5          return NULL;
    12.6  
    12.7 +    ParameterList *parameters = new ParameterList();
    12.8 +
    12.9      if (!expect(TOK_LPAREN))
   12.10          return NULL;
   12.11      if (!match(TOK_RPAREN)) {
   12.12          while (true) {
   12.13 +            bool ref = match(TOK_AMPERSAND);
   12.14 +
   12.15              Name *name = expectName();
   12.16              if (!name)
   12.17                  return NULL;
   12.18 @@ -744,9 +748,13 @@
   12.19                  redeclarationError();
   12.20                  return NULL;
   12.21              }
   12.22 -            if (!scope_->declareArgument(name))
   12.23 +            Variable *arg = scope_->declareArgument(name);
   12.24 +            if (!arg)
   12.25                  return NULL;
   12.26  
   12.27 +            Parameter *parameter = new (pool_) Parameter(arg, NULL, ref);
   12.28 +            parameters->push_back(parameter);
   12.29 +
   12.30              if (!match(TOK_COMMA))
   12.31                  break;
   12.32          }
   12.33 @@ -759,7 +767,7 @@
   12.34          return NULL;
   12.35  
   12.36      scope_ = scope_->enclosing();
   12.37 -    return new (pool_) FunctionStatement(scope, fun, body);
   12.38 +    return new (pool_) FunctionStatement(scope, fun, body, parameters);
   12.39  }
   12.40  
   12.41  ParseTree *
    13.1 --- a/jitcraft/SemanticAnalysis.cpp	Sat Jun 30 20:20:39 2012 -0700
    13.2 +++ b/jitcraft/SemanticAnalysis.cpp	Sat Jun 30 22:31:14 2012 -0700
    13.3 @@ -120,8 +120,12 @@
    13.4  SemanticAnalysis::visitForLoad(Expression *expression)
    13.5  {
    13.6      expression->accept(this);
    13.7 -    if (expression->type() && expression->type()->isArray())
    13.8 -        expression->setType(expression->type()->contained());
    13.9 +    if (expression->type()) {
   13.10 +        // :TODO: use Local
   13.11 +        Type *type = expression->type();
   13.12 +        if (type->isArray() || type->isReference())
   13.13 +            expression->setType(type->contained());
   13.14 +    }
   13.15      return expression->type();
   13.16  }
   13.17  
   13.18 @@ -163,7 +167,10 @@
   13.19          }
   13.20  
   13.21          Variable *var = proxy->binding()->toVariable();
   13.22 -        node->setType(var->type());
   13.23 +        if  (var->type()->isReference())
   13.24 +            node->setType(var->type()->contained());
   13.25 +        else
   13.26 +            node->setType(var->type());
   13.27      }
   13.28  
   13.29      assert(TypeCheck(node->type(), node->expression()->type()));
   13.30 @@ -247,6 +254,7 @@
   13.31  void
   13.32  SemanticAnalysis::visit(VariableDeclaration *node)
   13.33  {
   13.34 +    // :TODO: use locals
   13.35      Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
   13.36      if (!type)
   13.37          return;
   13.38 @@ -308,17 +316,100 @@
   13.39      node->expression()->accept(this);
   13.40  }
   13.41  
   13.42 +bool
   13.43 +SemanticAnalysis::preanalyze(FunctionStatement *node)
   13.44 +{
   13.45 +    // :TODO: use Local
   13.46 +
   13.47 +    FixedArray *args = FixedArray::New(ZONE(), node->parameters()->size(), Heap::Tenure_Old);
   13.48 +    if (!args)
   13.49 +        return false;
   13.50 +
   13.51 +    // Apply types to arguments.
   13.52 +    for (size_t i = 0; i < node->parameters()->size(); i++) {
   13.53 +        Parameter *parameter = node->parameters()->at(i);
   13.54 +        
   13.55 +        Type *type = ZONE()->types()->getPrimitiveForTag(parameter->tag());
   13.56 +        if (!type)
   13.57 +            return false;
   13.58 +
   13.59 +        if (parameter->reference()) {
   13.60 +            type = ZONE()->types()->getReference(type);
   13.61 +            if (!type)
   13.62 +                return false;
   13.63 +        }
   13.64 +
   13.65 +        args->set(ZONE(), i, type);
   13.66 +        parameter->variable()->setType(type);
   13.67 +    }
   13.68 +
   13.69 +    Type *returnType = ZONE()->types()->getPrimitive(PrimitiveType_Int32);
   13.70 +    if (!returnType)
   13.71 +        return false;
   13.72 +
   13.73 +    Type *funtype = ZONE()->types()->newFunction(returnType, args);
   13.74 +    if (!funtype)
   13.75 +        return false;
   13.76 +
   13.77 +    node->fun()->setType(funtype);
   13.78 +    return true;
   13.79 +}
   13.80 +
   13.81  void
   13.82  SemanticAnalysis::visit(FunctionStatement *node)
   13.83  {
   13.84      scope_ = node->scope();
   13.85 +
   13.86 +    // :TODO: call this ahead of time.
   13.87 +    if (!preanalyze(node))
   13.88 +        return;
   13.89 +
   13.90      node->body()->accept(this);
   13.91      scope_ = NULL;
   13.92  }
   13.93  
   13.94 +// :TODO: use handles
   13.95 +static inline bool
   13.96 +TypeCheckParameter(Type *given, Type *actual)
   13.97 +{
   13.98 +    if (actual->isReference()) {
   13.99 +        if (given->isReference())
  13.100 +            given = given->contained();
  13.101 +        return TypeCheck(given, actual->contained());
  13.102 +    }
  13.103 +
  13.104 +    return TypeCheck(given, actual);
  13.105 +}
  13.106 +
  13.107  void
  13.108  SemanticAnalysis::visit(CallExpression *node)
  13.109  {
  13.110 +    visitForLoad(node->callee());
  13.111 +
  13.112 +    // :TODO: use locals
  13.113 +    Type *type = node->callee()->type();
  13.114 +    if (!type)
  13.115 +        return;
  13.116 +
  13.117 +    assert(type->isFunction());
  13.118 +    assert(node->arguments()->size() == type->parameters()->length());
  13.119 +
  13.120 +    for (unsigned i = 0; i < node->arguments()->size(); i++) {
  13.121 +        Expression *expression = node->arguments()->at(i);
  13.122 +        expression->accept(this);
  13.123 +
  13.124 +        Type *given = expression->type();
  13.125 +        if (!given)
  13.126 +            return;
  13.127 +
  13.128 +        Type *actual = Type::cast(type->parameters()->at(i));
  13.129 +        assert(TypeCheckParameter(given, actual));
  13.130 +
  13.131 +        // If the actual is a reference, and the given is not, we'll need to
  13.132 +        // compute a reference, which may be allocated on the stack.
  13.133 +        if (actual->isReference() && !given->isReference())
  13.134 +            scope_->setUsesLifoHeap();
  13.135 +    }
  13.136  }
  13.137  
  13.138  void
  13.139 @@ -333,6 +424,7 @@
  13.140  void
  13.141  SemanticAnalysis::visit(IndexExpression *node)
  13.142  {
  13.143 +    // :TODO: use locals
  13.144      Type *left = visitForRef(node->left());
  13.145      Type *right = visitForLoad(node->right());
  13.146  
    14.1 --- a/jitcraft/SemanticAnalysis.h	Sat Jun 30 20:20:39 2012 -0700
    14.2 +++ b/jitcraft/SemanticAnalysis.h	Sat Jun 30 22:31:14 2012 -0700
    14.3 @@ -38,6 +38,7 @@
    14.4      }
    14.5      Type *visitForLoad(Expression *expression);
    14.6      Type *visitForRef(Expression *expression);
    14.7 +    bool preanalyze(FunctionStatement *node);
    14.8  
    14.9    public:
   14.10      SemanticAnalysis(ParseTree *tree);
    15.1 --- a/jitcraft/Stack.h	Sat Jun 30 20:20:39 2012 -0700
    15.2 +++ b/jitcraft/Stack.h	Sat Jun 30 22:31:14 2012 -0700
    15.3 @@ -26,6 +26,7 @@
    15.4  
    15.5  class Object;
    15.6  class Array;
    15.7 +class Reference;
    15.8      
    15.9  union LocalSlot
   15.10  {
   15.11 @@ -34,6 +35,7 @@
   15.12      Address address;
   15.13      Object *obj;
   15.14      Array *array;
   15.15 +    Reference *ref;
   15.16  };
   15.17  
   15.18  struct Top
    16.1 --- a/jitcraft/Token.h	Sat Jun 30 20:20:39 2012 -0700
    16.2 +++ b/jitcraft/Token.h	Sat Jun 30 22:31:14 2012 -0700
    16.3 @@ -40,7 +40,7 @@
    16.4      _(MINUS,              "-")                          \
    16.5      _(STAR,               "*")                          \
    16.6      _(SLASH,              "/")                          \
    16.7 -    _(BITAND,             "&")                          \
    16.8 +    _(AMPERSAND,          "&")                          \
    16.9      _(BITOR,              "|")                          \
   16.10      _(BITXOR,             "^")                          \
   16.11      _(SHR,                ">>")                         \
   16.12 @@ -71,6 +71,7 @@
   16.13  #   define _(name, str) TOK_##name,
   16.14      TOKENMAP(_)
   16.15  #   undef _
   16.16 +    TOK_BITAND = TOK_AMPERSAND,
   16.17      TOKENS_TOTAL
   16.18  };
   16.19  
    17.1 --- a/jitcraft/TypeManager.cpp	Sat Jun 30 20:20:39 2012 -0700
    17.2 +++ b/jitcraft/TypeManager.cpp	Sat Jun 30 22:31:14 2012 -0700
    17.3 @@ -17,6 +17,7 @@
    17.4   */
    17.5  #include "Types.h"
    17.6  #include "TypeManager.h"
    17.7 +#include "Zone.h"
    17.8  
    17.9  using namespace jc;
   17.10  
   17.11 @@ -35,6 +36,12 @@
   17.12          return false;
   17.13      if ((primitiveTypes_[PrimitiveType_Native] = Type::NewPrimitive(zone_, PrimitiveType_Native)) == NULL)
   17.14          return false;
   17.15 +
   17.16 +    for (unsigned i = 0; i < PrimitiveTypes_Total; i++) {
   17.17 +        if ((referenceTypes_[i] = Type::NewReference(zone_, primitiveTypes_[i])) == NULL)
   17.18 +            return false;
   17.19 +    }
   17.20 +
   17.21      return true;
   17.22  }
   17.23  
   17.24 @@ -55,3 +62,20 @@
   17.25      // :TODO: cache this.
   17.26      return Type::NewUnsafeArray(zone_, contained, elements);
   17.27  }
   17.28 +
   17.29 +Type *
   17.30 +TypeManager::getReference(Type *type)
   17.31 +{
   17.32 +    if (type->isFloat() || (type->isInt() && !type->tag()))
   17.33 +        return referenceTypes_[type->primitive()];
   17.34 +
   17.35 +    // :TODO: cache this.
   17.36 +    return Type::NewReference(zone_, type);
   17.37 +}
   17.38 +
   17.39 +Type *
   17.40 +TypeManager::newFunction(Type *returnType, FixedArray *args)
   17.41 +{
   17.42 +    // :TODO: cache this.
   17.43 +    return Type::NewFunction(zone_, returnType, args);
   17.44 +}
    18.1 --- a/jitcraft/TypeManager.h	Sat Jun 30 20:20:39 2012 -0700
    18.2 +++ b/jitcraft/TypeManager.h	Sat Jun 30 22:31:14 2012 -0700
    18.3 @@ -29,6 +29,7 @@
    18.4  
    18.5      // Primitive type cache.
    18.6      Unbarriered<Type> primitiveTypes_[PrimitiveTypes_Total];
    18.7 +    Unbarriered<Type> referenceTypes_[PrimitiveTypes_Total];
    18.8  
    18.9    public:
   18.10      TypeManager(Zone *zone);
   18.11 @@ -39,7 +40,10 @@
   18.12      Type *getPrimitive(PrimitiveType type) {
   18.13          return primitiveTypes_[type];
   18.14      }
   18.15 +    // :TODO: use handle
   18.16 +    Type *getReference(Type *type);
   18.17      Type *unsafeArray(Type *contained, int elements);
   18.18 +    Type *newFunction(Type *returnType, FixedArray *args);
   18.19  };
   18.20  
   18.21  }
    19.1 --- a/jitcraft/Types.cpp	Sat Jun 30 20:20:39 2012 -0700
    19.2 +++ b/jitcraft/Types.cpp	Sat Jun 30 22:31:14 2012 -0700
    19.3 @@ -63,7 +63,7 @@
    19.4          return NULL;
    19.5  
    19.6      Type *type = Type::cast(obj);
    19.7 -    type->kind_ = UNSAFE_ARRAY;
    19.8 +    type->kind_ = ARRAY;
    19.9      type->tag_ = NULL;
   19.10      type->contained_ = contained;
   19.11      type->elements_ = elements;
   19.12 @@ -73,3 +73,31 @@
   19.13          type->levels_ = contained->levels() + 1;
   19.14      return type;
   19.15  }
   19.16 +
   19.17 +Type *
   19.18 +Type::NewReference(Zone *zone, Type *contained)
   19.19 +{
   19.20 +    Object *obj = zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old);
   19.21 +    if (!obj)
   19.22 +        return NULL;
   19.23 +
   19.24 +    Type *type = Type::cast(obj);
   19.25 +    type->kind_ = REFERENCE;
   19.26 +    type->tag_ = NULL;
   19.27 +    type->contained_ = contained;
   19.28 +    return type;
   19.29 +}
   19.30 +
   19.31 +Type *
   19.32 +Type::NewFunction(Zone *zone, Type *returnType, FixedArray *parameters)
   19.33 +{
   19.34 +    Object *obj = zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old);
   19.35 +    if (!obj)
   19.36 +        return NULL;
   19.37 +
   19.38 +    Type *type = Type::cast(obj);
   19.39 +    type->kind_ = FUNCTION;
   19.40 +    type->contained_ = returnType;
   19.41 +    type->parameters_ = parameters;
   19.42 +    return type;
   19.43 +}
    20.1 --- a/jitcraft/Types.h	Sat Jun 30 20:20:39 2012 -0700
    20.2 +++ b/jitcraft/Types.h	Sat Jun 30 22:31:14 2012 -0700
    20.3 @@ -21,6 +21,7 @@
    20.4  #include "StringPool.h"
    20.5  #include "Heap.h"
    20.6  #include "Barriers.h"
    20.7 +#include "FixedArray.h"
    20.8  
    20.9  namespace jc {
   20.10  
   20.11 @@ -36,7 +37,9 @@
   20.12  {
   20.13      enum Kind {
   20.14          PRIMITIVE,
   20.15 -        UNSAFE_ARRAY
   20.16 +        ARRAY,
   20.17 +        REFERENCE,
   20.18 +        FUNCTION
   20.19      };
   20.20  
   20.21    private:
   20.22 @@ -48,9 +51,12 @@
   20.23      static const int UNKNOWN_SIZE = -1;
   20.24      static const size_t MAX_UNSAFE_ARRAY_DEPTH = 5;
   20.25      
   20.26 +    // :TODO: use handles
   20.27      static Type *NewPrimitive(Zone *zone, Name *tag);
   20.28      static Type *NewPrimitive(Zone *zone, PrimitiveType type);
   20.29      static Type *NewUnsafeArray(Zone *zone, Type *contained, int elements);
   20.30 +    static Type *NewReference(Zone *zone, Type *contained);
   20.31 +    static Type *NewFunction(Zone *zone, Type *returnType, FixedArray *parameters);
   20.32  
   20.33      static Type *cast(Object *obj) {
   20.34          assert(obj->is(MapKind_Type));
   20.35 @@ -61,17 +67,20 @@
   20.36          return kind() == PRIMITIVE;
   20.37      }
   20.38      bool isArray() {
   20.39 -        return isUnsafeArray();
   20.40 +        return kind() == ARRAY;
   20.41      }
   20.42 -    bool isUnsafeArray() {
   20.43 -        return kind() == UNSAFE_ARRAY;
   20.44 +    bool isReference() {
   20.45 +        return kind() == REFERENCE;
   20.46 +    }
   20.47 +    bool isFunction() {
   20.48 +        return kind() == FUNCTION;
   20.49      }
   20.50      PrimitiveType primitive() {
   20.51          assert(isPrimitive());
   20.52          return primitive_;
   20.53      }
   20.54      Type *contained() {
   20.55 -        assert(isArray());
   20.56 +        assert(isArray() || isReference());
   20.57          return Type::cast(contained_);
   20.58      }
   20.59      int elements() {
   20.60 @@ -99,6 +108,14 @@
   20.61      bool isInt() {
   20.62          return isPrimitive() && primitive() == PrimitiveType_Int32;
   20.63      }
   20.64 +    Type *returnType() {
   20.65 +        assert(isFunction());
   20.66 +        return returnType_;
   20.67 +    }
   20.68 +    FixedArray *parameters() {
   20.69 +        assert(isFunction());
   20.70 +        return parameters_;
   20.71 +    }
   20.72  
   20.73    private:
   20.74      Kind kind_;
   20.75 @@ -108,7 +125,13 @@
   20.76      // Arrays only.
   20.77      int32 elements_;
   20.78      unsigned levels_;
   20.79 +
   20.80 +    // Arrays and references only.
   20.81      Barriered<Type> contained_;
   20.82 +
   20.83 +    // Functions only.
   20.84 +    Barriered<Type> returnType_;
   20.85 +    Barriered<FixedArray> parameters_;
   20.86  };
   20.87  
   20.88  class BoxedPrimitive
    21.1 --- a/jitcraft/Zone.cpp	Sat Jun 30 20:20:39 2012 -0700
    21.2 +++ b/jitcraft/Zone.cpp	Sat Jun 30 22:31:14 2012 -0700
    21.3 @@ -45,8 +45,12 @@
    21.4          return false;
    21.5      if ((maps_[MapKind_Code] = allocateMap(MapKind_Code, sizeof(Map))) == NULL)
    21.6          return false;
    21.7 +    if ((maps_[MapKind_Reference] = allocateMap(MapKind_Reference, sizeof(Map))) == NULL)
    21.8 +        return false;
    21.9      if ((maps_[MapKind_MetaArray] = allocateMap(MapKind_MetaArray, sizeof(Map))) == NULL)
   21.10          return false;
   21.11 +    if ((maps_[MapKind_Module] = allocateMap(MapKind_Module, sizeof(Map))) == NULL)
   21.12 +        return false;
   21.13  
   21.14      types_ = new TypeManager(this);
   21.15      if (!types_ || !types_->initialize())
    22.1 --- a/jitcraft/jitcraft.vcxproj	Sat Jun 30 20:20:39 2012 -0700
    22.2 +++ b/jitcraft/jitcraft.vcxproj	Sat Jun 30 22:31:14 2012 -0700
    22.3 @@ -87,6 +87,7 @@
    22.4      <ClCompile Include="Parser.cpp" />
    22.5      <ClCompile Include="Platform-Windows.cpp" />
    22.6      <ClCompile Include="PoolAllocator.cpp" />
    22.7 +    <ClCompile Include="Reference.cpp" />
    22.8      <ClCompile Include="Scanner.cpp" />
    22.9      <ClCompile Include="Scopes.cpp" />
   22.10      <ClCompile Include="SemanticAnalysis.cpp" />
   22.11 @@ -115,6 +116,7 @@
   22.12      <ClInclude Include="Platform.h" />
   22.13      <ClInclude Include="PoolAllocator.h" />
   22.14      <ClInclude Include="Handles.h" />
   22.15 +    <ClInclude Include="Reference.h" />
   22.16      <ClInclude Include="Scanner.h" />
   22.17      <ClInclude Include="Scopes.h" />
   22.18      <ClInclude Include="Code.h" />
    23.1 --- a/jitcraft/main.cpp	Sat Jun 30 20:20:39 2012 -0700
    23.2 +++ b/jitcraft/main.cpp	Sat Jun 30 22:31:14 2012 -0700
    23.3 @@ -73,19 +73,19 @@
    23.4  
    23.5      Scope::Allocate(tree);
    23.6  
    23.7 -    BytecodeCompiler compiler(tree);
    23.8 +    BytecodeCompiler compiler(tree, NULL);
    23.9      Module *module = compiler.compile();
   23.10      if (!module)
   23.11          return false;
   23.12  
   23.13      printf("\n ------------ \n\n");
   23.14  
   23.15 -    Disassemble(module->getFunction(0), stdout);
   23.16 +    Disassemble(module->getFunction(1), stdout);
   23.17      //Disassemble(module->getFunction(1), stdout);
   23.18  
   23.19      printf("\n ------------ \n\n");
   23.20  
   23.21 -    Code *main = module->getFunction(0);
   23.22 +    Code *main = module->getFunction(1);
   23.23  
   23.24      Top top = ZONE()->stack().begin();
   23.25      LocalTop localTop(top);