Added support for non-array references.
Added support for non-array references.
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);