jitcraft/BytecodeCompiler.cpp
changeset 14 0784ac5cc347
parent 12 75e385f68b7e
child 15 d8ed9b8f19ca
     1.1 --- a/jitcraft/BytecodeCompiler.cpp	Sat Jun 30 20:20:39 2012 -0700
     1.2 +++ b/jitcraft/BytecodeCompiler.cpp	Sat Jun 30 22:31:14 2012 -0700
     1.3 @@ -29,10 +29,11 @@
     1.4  
     1.5  #define __ emitter_.
     1.6  
     1.7 -BytecodeCompiler::BytecodeCompiler(ParseTree *tree)
     1.8 +BytecodeCompiler::BytecodeCompiler(ParseTree *tree, Module *module)
     1.9    : tree_(tree),
    1.10      scope_(NULL),
    1.11 -    loop_(NULL)
    1.12 +    loop_(NULL),
    1.13 +    module_(module)
    1.14  {
    1.15  }
    1.16  
    1.17 @@ -133,10 +134,22 @@
    1.18  
    1.19          if (var->location() == Variable::STACK) {
    1.20              __ getlocal(var->slot());
    1.21 +            assert(!name->type()->isReference());
    1.22          } else {
    1.23              assert(var->location() == Variable::PARAMETER);
    1.24              __ getarg(var->slot());
    1.25 +
    1.26 +            // If this argument is actually a reference, dereference it now.
    1.27 +            if (var->type()->isReference()) {
    1.28 +                if (var->type()->isFloat()) {
    1.29 +                    __ getref_f();
    1.30 +                } else {
    1.31 +                    assert(name->type()->isInt());
    1.32 +                    __ getref_i();
    1.33 +                }
    1.34 +            }
    1.35          }
    1.36 +
    1.37          break;
    1.38        }
    1.39  
    1.40 @@ -165,12 +178,32 @@
    1.41          NameProxy *proxy = node->lvalue()->toNameProxy();
    1.42          Variable *var = proxy->binding()->toVariable();
    1.43  
    1.44 +        // Make sure to bind the left-hand side first.
    1.45 +        if (var->type()->isReference()) {
    1.46 +            if (var->location() == Variable::STACK) {
    1.47 +                __ getlocal(var->slot());
    1.48 +            } else {
    1.49 +                assert(var->location() == Variable::PARAMETER);
    1.50 +                __ getarg(var->slot());
    1.51 +            }
    1.52 +        }
    1.53 +
    1.54          node->expression()->accept(this);
    1.55 -        if (var->location() == Variable::STACK) {
    1.56 -            __ setlocal(var->slot());
    1.57 +
    1.58 +        if (var->type()->isReference()) {
    1.59 +            if (var->type()->contained()->isFloat()) {
    1.60 +                __ setref_f();
    1.61 +            } else {
    1.62 +                assert(var->type()->contained()->isInt());
    1.63 +                __ setref_i();
    1.64 +            }
    1.65          } else {
    1.66 -            assert(var->location() == Variable::PARAMETER);
    1.67 -            __ setarg(var->slot());
    1.68 +            if (var->location() == Variable::STACK) {
    1.69 +                __ setlocal(var->slot());
    1.70 +            } else {
    1.71 +                assert(var->location() == Variable::PARAMETER);
    1.72 +                __ setarg(var->slot());
    1.73 +            }
    1.74          }
    1.75      } else if (node->lvalue()->isIndexExpression()) {
    1.76          IndexExpression *index = node->lvalue()->toIndexExpression();
    1.77 @@ -408,9 +441,33 @@
    1.78  {
    1.79      NameProxy *fun = node->callee()->toNameProxy();
    1.80  
    1.81 +    // :TODO: use Local
    1.82 +    Type *funType = node->callee()->type();
    1.83 +
    1.84      for (size_t i = 0; i < node->arguments()->size(); i++) {
    1.85          Expression *arg = node->arguments()->at(i);
    1.86 -        arg->accept(this);
    1.87 +
    1.88 +        Type *given = arg->type();
    1.89 +        Type *actual = Type::cast(funType->parameters()->at(i));
    1.90 +        if (actual->isReference()) {
    1.91 +            if (given->isReference()) {
    1.92 +                // The input type is already a reference, so we're just passing
    1.93 +                // it on to the callee.
    1.94 +                arg->accept(this);
    1.95 +            } else if (arg->isNameProxy()) {
    1.96 +                // :TODO: test with functions and globals
    1.97 +                // Compute a reference to the name.
    1.98 +                Variable *var = arg->toNameProxy()->binding()->toVariable();
    1.99 +                __ newref(var);
   1.100 +            } else {
   1.101 +                // We don't know how to, or can't, build a direct reference to
   1.102 +                // this type. Make an indirect one, by taking the top of the
   1.103 +                // stack and boxing it up.
   1.104 +                __ slotref_lifo();
   1.105 +            }
   1.106 +        } else {
   1.107 +            arg->accept(this);
   1.108 +        }
   1.109      }
   1.110  
   1.111      __ callglobal(node->arguments()->size(), 0);
   1.112 @@ -438,11 +495,11 @@
   1.113  void
   1.114  BytecodeCompiler::visit(FunctionStatement *node)
   1.115  {
   1.116 -    BytecodeCompiler child(tree_);
   1.117 +    BytecodeCompiler child(tree_, module_);
   1.118      Code *code = child.compileFunction(module_, node);
   1.119      
   1.120      assert(!module_->getFunction(node->fun()->slot()));
   1.121 -    module_->setFunction(node->fun()->slot(), code);
   1.122 +    module_->setFunction(ZONE(), node->fun()->slot(), code);
   1.123  }
   1.124  
   1.125  void
   1.126 @@ -497,10 +554,10 @@
   1.127  Module *
   1.128  BytecodeCompiler::compile()
   1.129  {
   1.130 -    Code **functions = new Code *[tree_->scope()->numFunctions()];
   1.131 -    memset(functions, 0, sizeof(Code *) * tree_->scope()->numFunctions());
   1.132 -
   1.133 -    module_ = new Module(functions, tree_->scope()->numFunctions());
   1.134 +    // :TODO: root
   1.135 +    module_ = Module::New(ZONE(), tree_->scope()->numFunctions());
   1.136 +    if (!module_)
   1.137 +        return NULL;
   1.138  
   1.139      for (size_t i = 0; i < tree_->statements()->length(); i++) {
   1.140          Statement *statement = tree_->statements()->at(i);
   1.141 @@ -509,7 +566,7 @@
   1.142  
   1.143  #ifndef NDEBUG
   1.144      for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
   1.145 -        assert(functions[i]);
   1.146 +        assert(module_->getFunction(i));
   1.147  #endif
   1.148  
   1.149      return module_;