Added initial String: support.
Added initial String: support.
1.1 --- a/jitcraft/AST.h Sun Jul 01 11:25:36 2012 -0700
1.2 +++ b/jitcraft/AST.h Sun Jul 01 14:52:57 2012 -0700
1.3 @@ -31,6 +31,7 @@
1.4 _(ReturnStatement) \
1.5 _(IntegerLiteral) \
1.6 _(FloatLiteral) \
1.7 + _(StringLiteral) \
1.8 _(BinaryExpression) \
1.9 _(BlockStatement) \
1.10 _(Assignment) \
1.11 @@ -273,6 +274,27 @@
1.12 }
1.13 };
1.14
1.15 +class StringLiteral : public Expression
1.16 +{
1.17 + ByteArray *string_;
1.18 +
1.19 + public:
1.20 + StringLiteral(ByteArray *array)
1.21 + : string_(array)
1.22 + {
1.23 + }
1.24 +
1.25 + Kind kind() const {
1.26 + return kStringLiteral;
1.27 + }
1.28 + ByteArray *string() const {
1.29 + return string_;
1.30 + }
1.31 + void accept(AstVisitor *visitor) {
1.32 + visitor->visit(this);
1.33 + }
1.34 +};
1.35 +
1.36 class BinaryExpression : public Expression
1.37 {
1.38 Expression *left_;
2.1 --- a/jitcraft/Array.cpp Sun Jul 01 11:25:36 2012 -0700
2.2 +++ b/jitcraft/Array.cpp Sun Jul 01 14:52:57 2012 -0700
2.3 @@ -43,6 +43,8 @@
2.4 return sizeof(Array) + elements * sizeof(jc::Object *);
2.5 if (type->contained()->isInt32())
2.6 return sizeof(Array) + elements * sizeof(int);
2.7 + if (type->contained()->primitive() == PrimitiveType_Char)
2.8 + return sizeof(Array) + elements * sizeof(char);
2.9 assert(type->contained()->isFloat());
2.10 return sizeof(Array) + elements * sizeof(float);
2.11 }
3.1 --- a/jitcraft/Array.h Sun Jul 01 11:25:36 2012 -0700
3.2 +++ b/jitcraft/Array.h Sun Jul 01 14:52:57 2012 -0700
3.3 @@ -32,11 +32,6 @@
3.4 uint32 nelements_;
3.5 void *elements_;
3.6
3.7 - private:
3.8 - void *vec() {
3.9 - return elements_;
3.10 - }
3.11 -
3.12 public:
3.13 static Array *New(Zone *zone, ArrayMap *map, uint32 elements,
3.14 Heap::Tenure = Heap::Tenure_Default);
3.15 @@ -44,9 +39,17 @@
3.16 uint32 nelements() {
3.17 return nelements_;
3.18 }
3.19 + void *vec() {
3.20 + return elements_;
3.21 + }
3.22 +
3.23 inline int *int32Vec();
3.24 inline float *floatVec();
3.25 inline Object **objVec();
3.26 + inline char *chars();
3.27 +
3.28 + inline Type *type();
3.29 + inline size_t elementSize();
3.30
3.31 int readInt32(size_t index) {
3.32 assert(index < nelements());
3.33 @@ -56,6 +59,14 @@
3.34 assert(index < nelements());
3.35 int32Vec()[index] = i;
3.36 }
3.37 + char readChar(size_t index) {
3.38 + assert(index < nelements());
3.39 + return chars()[index];
3.40 + }
3.41 + void writeChar(size_t index, char c) {
3.42 + assert(index < nelements());
3.43 + chars()[index] = c;
3.44 + }
3.45 float readFloat(size_t index) {
3.46 assert(index < nelements());
3.47 return floatVec()[index];
3.48 @@ -104,35 +115,65 @@
3.49 inline int *
3.50 Array::int32Vec()
3.51 {
3.52 - assert(ArrayMap::cast(map())->type()->levels() == 1);
3.53 - assert(ArrayMap::cast(map())->type()->contained()->isInt32());
3.54 + assert(type()->levels() == 1);
3.55 + assert(type()->contained()->isInt32());
3.56 return reinterpret_cast<int *>(vec());
3.57 }
3.58
3.59 inline float *
3.60 Array::floatVec()
3.61 {
3.62 - assert(ArrayMap::cast(map())->type()->levels() == 1);
3.63 - assert(ArrayMap::cast(map())->type()->contained()->isFloat());
3.64 + assert(type()->levels() == 1);
3.65 + assert(type()->contained()->isFloat());
3.66 return reinterpret_cast<float *>(vec());
3.67 }
3.68
3.69 inline Object **
3.70 Array::objVec()
3.71 {
3.72 - assert(ArrayMap::cast(map())->type()->levels() > 1);
3.73 + assert(type()->levels() > 1);
3.74 return reinterpret_cast<Object **>(vec());
3.75 }
3.76
3.77 inline void *
3.78 Array::slotPtr(size_t index)
3.79 {
3.80 - assert(ArrayMap::cast(map())->type()->contained()->primitive() == PrimitiveType_Int32 ||
3.81 - ArrayMap::cast(map())->type()->contained()->primitive() == PrimitiveType_Float);
3.82 + assert(type()->contained()->primitive() == PrimitiveType_Int32 ||
3.83 + type()->contained()->primitive() == PrimitiveType_Float);
3.84 assert(index < nelements());
3.85 return reinterpret_cast<int *>(vec()) + index;
3.86 }
3.87
3.88 +inline char *
3.89 +Array::chars()
3.90 +{
3.91 + assert(type()->levels() == 1);
3.92 + assert(type()->contained()->primitive() == PrimitiveType_Char);
3.93 + return reinterpret_cast<char *>(vec());
3.94 +}
3.95 +
3.96 +inline Type *
3.97 +Array::type()
3.98 +{
3.99 + return ArrayMap::cast(map())->type();
3.100 +}
3.101 +
3.102 +inline size_t
3.103 +Array::elementSize()
3.104 +{
3.105 + if (type()->isArray())
3.106 + return sizeof(Object *);
3.107 + switch (type()->contained()->primitive()) {
3.108 + case PrimitiveType_Float:
3.109 + return sizeof(float);
3.110 + case PrimitiveType_Int32:
3.111 + return sizeof(int);
3.112 + default:
3.113 + assert(type()->contained()->primitive() == PrimitiveType_Char);
3.114 + return sizeof(char);
3.115 + }
3.116 +}
3.117 +
3.118 }
3.119
3.120 #endif // _include_jitcraft_array_h_
4.1 --- a/jitcraft/BytecodeCompiler.cpp Sun Jul 01 11:25:36 2012 -0700
4.2 +++ b/jitcraft/BytecodeCompiler.cpp Sun Jul 01 14:52:57 2012 -0700
4.3 @@ -173,15 +173,39 @@
4.4 void
4.5 BytecodeCompiler::visit(Assignment *node)
4.6 {
4.7 + // First compute the left-hand side.
4.8 if (node->lvalue()->isNameProxy()) {
4.9 NameProxy *proxy = node->lvalue()->toNameProxy();
4.10 Variable *var = proxy->binding()->toVariable();
4.11
4.12 // Make sure to bind the left-hand side first.
4.13 - if (var->type()->isReference())
4.14 + if (var->type()->isReference() || var->type()->isArray())
4.15 __ get(var);
4.16
4.17 node->expression()->accept(this);
4.18 + } else if (node->lvalue()->isIndexExpression()) {
4.19 + IndexExpression *index = node->lvalue()->toIndexExpression();
4.20 +
4.21 + // Note: Eventually, watch out for a whole here. An expression like:
4.22 + //
4.23 + // (a[4] = (5, a = []))
4.24 + //
4.25 + // Could shrink array, so we need to either bind a[i] to a Reference,
4.26 + // or keep the bounds check near the set. This is just a semantic
4.27 + // decision.
4.28 + index->left()->accept(this);
4.29 + index->right()->accept(this);
4.30 + node->expression()->accept(this);
4.31 + }
4.32 +
4.33 + // Emit the store.
4.34 + if (node->expression()->type()->isArray()) {
4.35 + // Unlike references, which can only be computed from a NamePRoxy,
4.36 + // arrays can be computed from multiple lvalue types.
4.37 + __ arraycopy();
4.38 + } else if (node->lvalue()->isNameProxy()) {
4.39 + NameProxy *proxy = node->lvalue()->toNameProxy();
4.40 + Variable *var = proxy->binding()->toVariable();
4.41
4.42 if (var->type()->isReference()) {
4.43 if (var->type()->contained()->isFloat()) {
4.44 @@ -193,19 +217,10 @@
4.45 } else {
4.46 __ set(var);
4.47 }
4.48 - } else if (node->lvalue()->isIndexExpression()) {
4.49 + } else {
4.50 IndexExpression *index = node->lvalue()->toIndexExpression();
4.51 -
4.52 - index->left()->accept(this);
4.53 - index->right()->accept(this);
4.54 __ bounds();
4.55 - node->expression()->accept(this);
4.56 - if (index->left()->type()->contained()->isFloat()) {
4.57 - __ setarray_f();
4.58 - } else {
4.59 - assert(index->left()->type()->contained()->isInt32());
4.60 - __ setarray_i();
4.61 - }
4.62 + __ setarray(index->left()->type()->contained()->primitive());
4.63 }
4.64 }
4.65
4.66 @@ -236,14 +251,10 @@
4.67 node->right()->accept(this);
4.68 __ bounds();
4.69
4.70 - if (node->type()->isArray()) {
4.71 + if (node->type()->isArray())
4.72 __ getarray_o();
4.73 - } else if (node->type()->isFloat()) {
4.74 - __ getarray_f();
4.75 - } else {
4.76 - __ getarray_i();
4.77 - assert(node->type()->isInt32());
4.78 - }
4.79 + else
4.80 + __ getarray(node->type()->primitive());
4.81 }
4.82
4.83 void
4.84 @@ -400,6 +411,24 @@
4.85 }
4.86
4.87 void
4.88 +BytecodeCompiler::visit(StringLiteral *node)
4.89 +{
4.90 + // :TODO: use Local
4.91 + ArrayMap *map = BuildArrayMap(ZONE(), node->type());
4.92 + if (!map)
4.93 + return;
4.94 +
4.95 + Array *array = Array::New(ZONE(), map, node->string()->length(), Heap::Tenure_Old);
4.96 + if (!array)
4.97 + return;
4.98 +
4.99 + assert(array->nelements() >= node->string()->length());
4.100 + memcpy(array->chars(), node->string()->raw(), node->string()->length() * sizeof(char));
4.101 +
4.102 + __ object(array);
4.103 +}
4.104 +
4.105 +void
4.106 BytecodeCompiler::visit(VariableDeclaration *node)
4.107 {
4.108 Variable *var = node->variable();
4.109 @@ -410,6 +439,11 @@
4.110 // :TODO: use Local
4.111 ArrayMap *map = BuildArrayMap(ZONE(), type);
4.112 __ newarray_lifo(map);
4.113 +
4.114 + if (node->initialization()) {
4.115 + node->initialization()->accept(this);
4.116 + __ arraycopy();
4.117 + }
4.118 } else {
4.119 if (node->initialization()) {
4.120 node->initialization()->accept(this);
4.121 @@ -535,14 +569,14 @@
4.122 for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
4.123 assert(locals_->at(i));
4.124
4.125 - FixedArray *maps = FixedArray::New(ZONE(), __ maps()->size(), Heap::Tenure_Old);
4.126 - if (!maps)
4.127 + FixedArray *objects = FixedArray::New(ZONE(), __ objects()->size(), Heap::Tenure_Old);
4.128 + if (!objects)
4.129 return NULL;
4.130
4.131 - for (size_t i = 0; i < __ maps()->size(); i++)
4.132 - maps->set(ZONE(), i, __ maps()->at(i));
4.133 + for (size_t i = 0; i < __ objects()->size(); i++)
4.134 + objects->set(ZONE(), i, __ objects()->at(i));
4.135
4.136 - Code *code = Code::New(ZONE(), bytes, locals_, args, maps, __ maxStackDepth(), module_);
4.137 + Code *code = Code::New(ZONE(), bytes, locals_, args, objects, __ maxStackDepth(), module_);
4.138 return code;
4.139 }
4.140
5.1 --- a/jitcraft/BytecodeCompiler.h Sun Jul 01 11:25:36 2012 -0700
5.2 +++ b/jitcraft/BytecodeCompiler.h Sun Jul 01 14:52:57 2012 -0700
5.3 @@ -113,6 +113,7 @@
5.4 void visit(VariableDeclaration *node);
5.5 void visit(IntegerLiteral *node);
5.6 void visit(FloatLiteral *node);
5.7 + void visit(StringLiteral *node);
5.8 void visit(ExpressionStatement *node);
5.9 void visit(FunctionStatement *node);
5.10 void visit(CallExpression *node);
6.1 --- a/jitcraft/BytecodeEmitter.h Sun Jul 01 11:25:36 2012 -0700
6.2 +++ b/jitcraft/BytecodeEmitter.h Sun Jul 01 14:52:57 2012 -0700
6.3 @@ -38,7 +38,7 @@
6.4 bool oom_;
6.5 unsigned maxStackDepth_;
6.6 unsigned stackDepth_;
6.7 - std::vector<Map *> maps_;
6.8 + std::vector<Object *> objects_;
6.9
6.10 private:
6.11 static const size_t MAX_LENGTH = INT_MAX / 2;
6.12 @@ -78,9 +78,9 @@
6.13 if (stackDepth_ > maxStackDepth_)
6.14 maxStackDepth_ = stackDepth_;
6.15 }
6.16 - void writeMap(Map *map) {
6.17 - writeUint32(maps_.size());
6.18 - maps_.push_back(map);
6.19 + void writeObject(Object *obj) {
6.20 + writeUint32(objects_.size());
6.21 + objects_.push_back(obj);
6.22 }
6.23
6.24 int position() const {
6.25 @@ -106,8 +106,8 @@
6.26 unsigned maxStackDepth() const {
6.27 return maxStackDepth_;
6.28 }
6.29 - const std::vector<Map *> *maps() const {
6.30 - return &maps_;
6.31 + const std::vector<Object *> *objects() const {
6.32 + return &objects_;
6.33 }
6.34
6.35 public:
6.36 @@ -268,17 +268,33 @@
6.37
6.38 stackDepth_ -= nargs;
6.39 }
6.40 - void getarray_i() {
6.41 - singleByteOp(OP_GETARRAY_I);
6.42 - }
6.43 - void setarray_i() {
6.44 - singleByteOp(OP_SETARRAY_I);
6.45 + void getarray(PrimitiveType type) {
6.46 + switch (type) {
6.47 + case PrimitiveType_Float:
6.48 + singleByteOp(OP_GETARRAY_F);
6.49 + break;
6.50 + case PrimitiveType_Int32:
6.51 + singleByteOp(OP_GETARRAY_I);
6.52 + break;
6.53 + default:
6.54 + assert(type == PrimitiveType_Char);
6.55 + singleByteOp(OP_GETARRAY_C);
6.56 + break;
6.57 + }
6.58 }
6.59 - void getarray_f() {
6.60 - singleByteOp(OP_GETARRAY_F);
6.61 - }
6.62 - void setarray_f() {
6.63 - singleByteOp(OP_SETARRAY_F);
6.64 + void setarray(PrimitiveType type) {
6.65 + switch (type) {
6.66 + case PrimitiveType_Float:
6.67 + singleByteOp(OP_SETARRAY_F);
6.68 + break;
6.69 + case PrimitiveType_Int32:
6.70 + singleByteOp(OP_SETARRAY_I);
6.71 + break;
6.72 + default:
6.73 + assert(type == PrimitiveType_Char);
6.74 + singleByteOp(OP_SETARRAY_C);
6.75 + break;
6.76 + }
6.77 }
6.78 void getarray_o() {
6.79 singleByteOp(OP_GETARRAY_O);
6.80 @@ -297,7 +313,7 @@
6.81 void newarray_lifo(Map *map) {
6.82 ensure(OP_NEWARRAY_LIFO_LENGTH);
6.83 writeOp(OP_NEWARRAY_LIFO);
6.84 - writeMap(map);
6.85 + writeObject(map);
6.86 }
6.87 void savelifo(unsigned slot) {
6.88 ensure(OP_SAVELIFO_LENGTH);
6.89 @@ -355,6 +371,14 @@
6.90 void setref_f() {
6.91 singleByteOp(OP_SETREF_F);
6.92 }
6.93 + void object(Object *obj) {
6.94 + ensure(OP_OBJECT_LENGTH);
6.95 + writeOp(OP_OBJECT);
6.96 + writeObject(obj);
6.97 + }
6.98 + void arraycopy() {
6.99 + singleByteOp(OP_ARRAYCOPY);
6.100 + }
6.101 };
6.102
6.103 }
7.1 --- a/jitcraft/Code.h Sun Jul 01 11:25:36 2012 -0700
7.2 +++ b/jitcraft/Code.h Sun Jul 01 14:52:57 2012 -0700
7.3 @@ -38,13 +38,13 @@
7.4 Unbarriered<ByteArray> bytecode_;
7.5 Unbarriered<FixedArray> locals_;
7.6 Unbarriered<FixedArray> args_;
7.7 - Unbarriered<FixedArray> maps_;
7.8 + Unbarriered<FixedArray> objects_;
7.9 unsigned maxStackDepth_;
7.10
7.11 public:
7.12 // :TODO: use handles
7.13 static Code *New(Zone *zone, ByteArray *bytecode, FixedArray *locals, FixedArray *args,
7.14 - FixedArray *maps, unsigned maxStackDepth, Module *module);
7.15 + FixedArray *objects, unsigned maxStackDepth, Module *module);
7.16
7.17 Module *module() {
7.18 return module_;
7.19 @@ -71,7 +71,10 @@
7.20 return maxStackDepth_;
7.21 }
7.22 Map *map(size_t index) {
7.23 - return Map::cast(maps_->at(index));
7.24 + return Map::cast(objects_->at(index));
7.25 + }
7.26 + Object *object(size_t index) {
7.27 + return objects_->at(index);
7.28 }
7.29
7.30 static Code *cast(Object *obj) {
8.1 --- a/jitcraft/FixedArray.h Sun Jul 01 11:25:36 2012 -0700
8.2 +++ b/jitcraft/FixedArray.h Sun Jul 01 14:52:57 2012 -0700
8.3 @@ -68,7 +68,7 @@
8.4 }
8.5
8.6 public:
8.7 - static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure);
8.8 + static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
8.9
8.10 unsigned length() {
8.11 return length_;
9.1 --- a/jitcraft/Interpreter.cpp Sun Jul 01 11:25:36 2012 -0700
9.2 +++ b/jitcraft/Interpreter.cpp Sun Jul 01 14:52:57 2012 -0700
9.3 @@ -102,6 +102,20 @@
9.4 return array;
9.5 }
9.6
9.7 +static bool
9.8 +CopyArray(Zone *zone, Array *source, Array *dest)
9.9 +{
9.10 + assert(source->type()->levels() == 1);
9.11 + assert(dest->type()->levels() == 1);
9.12 + assert(source->type()->contained()->primitive() ==
9.13 + dest->type()->contained()->primitive());
9.14 + assert(source->nelements() >= dest->nelements());
9.15 + assert(dest->elementSize() == source->elementSize());
9.16 +
9.17 + memcpy(source->vec(), dest->vec(), dest->nelements() * dest->elementSize());
9.18 + return true;
9.19 +}
9.20 +
9.21 bool
9.22 jc::Interpret(Frame *frame, LocalSlot *result)
9.23 {
9.24 @@ -400,6 +414,15 @@
9.25 break;
9.26 }
9.27
9.28 +case OP_GETARRAY_C:
9.29 +{
9.30 + Array *array = top.sp[-2].array;
9.31 + int index = top.sp[-1].i32;
9.32 + top.sp[-2].i32 = array->readChar(index);
9.33 + top.sp--;
9.34 + break;
9.35 +}
9.36 +
9.37 case OP_SETARRAY_I:
9.38 {
9.39 Array *array = top.sp[-3].array;
9.40 @@ -420,6 +443,16 @@
9.41 break;
9.42 }
9.43
9.44 +case OP_SETARRAY_C:
9.45 +{
9.46 + Array *array = top.sp[-3].array;
9.47 + int index = top.sp[-2].i32;
9.48 + array->writeChar(index, top.sp[-1].i32);
9.49 + top.sp[-3] = top.sp[-1];
9.50 + top.sp -= 2;
9.51 + break;
9.52 +}
9.53 +
9.54 case OP_GETARRAY_O:
9.55 {
9.56 Array *array = top.sp[-2].array;
9.57 @@ -534,6 +567,25 @@
9.58 break;
9.59 }
9.60
9.61 +case OP_OBJECT:
9.62 +{
9.63 + top.sp->obj = frame->code()->object(READ_UINT32(top.pc));
9.64 + top.sp++;
9.65 + break;
9.66 +}
9.67 +
9.68 +case OP_ARRAYCOPY:
9.69 +{
9.70 + // Note for this assignment opcode, we return the left-hand side, not the
9.71 + // right, since in this case the result of the expression could be different.
9.72 + if (!CopyArray(ZONE(), top.sp[-2].array, top.sp[-1].array)) {
9.73 + assert(false);
9.74 + return false;
9.75 + }
9.76 + top.sp--;
9.77 + break;
9.78 +}
9.79 +
9.80 default:
9.81 assert(false);
9.82 return false;
10.1 --- a/jitcraft/NameBinding.cpp Sun Jul 01 11:25:36 2012 -0700
10.2 +++ b/jitcraft/NameBinding.cpp Sun Jul 01 14:52:57 2012 -0700
10.3 @@ -21,7 +21,8 @@
10.4
10.5 BoundName::BoundName(Scope *scope, Name *name)
10.6 : scope_(scope),
10.7 - name_(name)
10.8 + name_(name),
10.9 + type_(NULL)
10.10 {
10.11 }
10.12
11.1 --- a/jitcraft/Opcodes.cpp Sun Jul 01 11:25:36 2012 -0700
11.2 +++ b/jitcraft/Opcodes.cpp Sun Jul 01 14:52:57 2012 -0700
11.3 @@ -34,7 +34,7 @@
11.4
11.5 Code *
11.6 Code::New(Zone *zone, ByteArray *bytecode, FixedArray *locals, FixedArray *args,
11.7 - FixedArray *maps, unsigned maxStackDepth, Module *module)
11.8 + FixedArray *objects, unsigned maxStackDepth, Module *module)
11.9 {
11.10 Object *obj = zone->allocate(MapKind_Code, sizeof(Code), Heap::Tenure_Old);
11.11 if (!obj)
11.12 @@ -44,7 +44,7 @@
11.13 code->bytecode_ = bytecode;
11.14 code->locals_ = locals;
11.15 code->args_ = args;
11.16 - code->maps_ = maps;
11.17 + code->objects_ = objects;
11.18 code->maxStackDepth_ = maxStackDepth;
11.19 code->module_ = module;
11.20 return code;
11.21 @@ -86,6 +86,8 @@
11.22 case OP_SETARRAY_I:
11.23 case OP_GETARRAY_F:
11.24 case OP_SETARRAY_F:
11.25 + case OP_GETARRAY_C:
11.26 + case OP_SETARRAY_C:
11.27 case OP_GETARRAY_O:
11.28 case OP_BOUNDS:
11.29 case OP_SHL:
11.30 @@ -100,6 +102,8 @@
11.31 case OP_SETREF_F:
11.32 case OP_SLOTREF_LIFO:
11.33 case OP_ARRAYREF_LIFO:
11.34 + case OP_OBJECT:
11.35 + case OP_ARRAYCOPY:
11.36 break;
11.37
11.38 case OP_STOP:
12.1 --- a/jitcraft/Opcodes.tbl Sun Jul 01 11:25:36 2012 -0700
12.2 +++ b/jitcraft/Opcodes.tbl Sun Jul 01 14:52:57 2012 -0700
12.3 @@ -92,14 +92,16 @@
12.4 OPDEF(OP_SETARRAY_I, 24, "setarray.i", 1, 3, 1)
12.5 OPDEF(OP_GETARRAY_F, 25, "getarray.f", 1, 2, 1)
12.6 OPDEF(OP_SETARRAY_F, 26, "setarray.f", 1, 3, 1)
12.7 -OPDEF(OP_GETARRAY_O, 27, "getarray.o", 1, 2, 1)
12.8 +OPDEF(OP_GETARRAY_C, 27, "getarray.c", 1, 2, 1)
12.9 +OPDEF(OP_SETARRAY_C, 28, "setarray.c", 1, 3, 1)
12.10 +OPDEF(OP_GETARRAY_O, 29, "getarray.o", 1, 2, 1)
12.11
12.12 // Allocate an array, info LIFO space if possible. The ArrayMap to use is
12.13 // specified as an index into the script's Map table.
12.14 //
12.15 // Format:
12.16 // [u8 op] [u32 index]
12.17 -OPDEF(OP_NEWARRAY_LIFO, 28, "newarray.lifo", 5, 0, 1)
12.18 +OPDEF(OP_NEWARRAY_LIFO, 30, "newarray.lifo", 5, 0, 1)
12.19
12.20 // Performs a bounds check on an unsafe array.
12.21 //
12.22 @@ -107,41 +109,51 @@
12.23 // array = pop()
12.24 // push(array)
12.25 // push(index)
12.26 -OPDEF(OP_BOUNDS, 29, "bounds", 1, 2, 2)
12.27 +OPDEF(OP_BOUNDS, 31, "bounds", 1, 2, 2)
12.28
12.29 // Pushes a 32-bit IEEE-754 floating point immediate onto the stack.
12.30 -OPDEF(OP_FLOAT, 30, "float", 5, 0, 1)
12.31 +OPDEF(OP_FLOAT, 32, "float", 5, 0, 1)
12.32
12.33 // Converts an integer to a 32-bit IEEE-754 floating point immediate.
12.34 -OPDEF(OP_CVT_I2F, 31, "cvt.i2f", 1, 1, 1)
12.35 +OPDEF(OP_CVT_I2F, 33, "cvt.i2f", 1, 1, 1)
12.36
12.37 // Stack transitions for these binary operators:
12.38 // rhs = pop()
12.39 // lhs = pop()
12.40 // push(lhs OP rhs)
12.41 -OPDEF(OP_ADD_F, 32, "add.f", 1, 2, 1)
12.42 -OPDEF(OP_SUB_F, 33, "sub.f", 1, 2, 1)
12.43 -OPDEF(OP_MUL_F, 34, "mul.f", 1, 2, 1)
12.44 -OPDEF(OP_DIV_F, 35, "div.f", 1, 2, 1)
12.45 +OPDEF(OP_ADD_F, 34, "add.f", 1, 2, 1)
12.46 +OPDEF(OP_SUB_F, 35, "sub.f", 1, 2, 1)
12.47 +OPDEF(OP_MUL_F, 36, "mul.f", 1, 2, 1)
12.48 +OPDEF(OP_DIV_F, 37, "div.f", 1, 2, 1)
12.49
12.50 // Bitwise operators.
12.51 -OPDEF(OP_SHL, 36, "shl", 1, 2, 1)
12.52 -OPDEF(OP_SHR, 37, "shr", 1, 2, 1)
12.53 -OPDEF(OP_USHR, 38, "ushr", 1, 2, 1)
12.54 -OPDEF(OP_BITAND, 39, "bitand", 1, 2, 1)
12.55 -OPDEF(OP_BITOR, 40, "bitor", 1, 2, 1)
12.56 -OPDEF(OP_BITXOR, 41, "bitxor", 1, 2, 1)
12.57 +OPDEF(OP_SHL, 38, "shl", 1, 2, 1)
12.58 +OPDEF(OP_SHR, 39, "shr", 1, 2, 1)
12.59 +OPDEF(OP_USHR, 40, "ushr", 1, 2, 1)
12.60 +OPDEF(OP_BITAND, 41, "bitand", 1, 2, 1)
12.61 +OPDEF(OP_BITOR, 42, "bitor", 1, 2, 1)
12.62 +OPDEF(OP_BITXOR, 43, "bitxor", 1, 2, 1)
12.63
12.64 // Saves or restores the position of the LIFO heap to/from a local slot.
12.65 -OPDEF(OP_SAVELIFO, 42, "savelifo", 5, 0, 0)
12.66 -OPDEF(OP_UNWINDLIFO, 43, "unwindlifo", 5, 0, 0)
12.67 +OPDEF(OP_SAVELIFO, 44, "savelifo", 5, 0, 0)
12.68 +OPDEF(OP_UNWINDLIFO, 45, "unwindlifo", 5, 0, 0)
12.69
12.70 // Composes a variable reference to a stack slot or argument.
12.71 -OPDEF(OP_VARREF_LIFO, 44, "varref.lifo", 5, 0, 1)
12.72 -OPDEF(OP_ARGREF_LIFO, 45, "argref.lifo", 5, 0, 1)
12.73 -OPDEF(OP_SLOTREF_LIFO, 46, "slotref.lifo", 1, 1, 1)
12.74 -OPDEF(OP_ARRAYREF_LIFO, 47, "arrayref.lifo",1, 2, 1)
12.75 -OPDEF(OP_GETREF_I, 48, "getref.i", 1, 1, 1)
12.76 -OPDEF(OP_SETREF_I, 49, "setref.i", 1, 2, 1)
12.77 -OPDEF(OP_GETREF_F, 50, "getref.f", 1, 1, 1)
12.78 -OPDEF(OP_SETREF_F, 51, "setref.f", 1, 2, 1)
12.79 +OPDEF(OP_VARREF_LIFO, 46, "varref.lifo", 5, 0, 1)
12.80 +OPDEF(OP_ARGREF_LIFO, 47, "argref.lifo", 5, 0, 1)
12.81 +OPDEF(OP_SLOTREF_LIFO, 48, "slotref.lifo", 1, 1, 1)
12.82 +OPDEF(OP_ARRAYREF_LIFO, 49, "arrayref.lifo",1, 2, 1)
12.83 +OPDEF(OP_GETREF_I, 50, "getref.i", 1, 1, 1)
12.84 +OPDEF(OP_SETREF_I, 51, "setref.i", 1, 2, 1)
12.85 +OPDEF(OP_GETREF_F, 52, "getref.f", 1, 1, 1)
12.86 +OPDEF(OP_SETREF_F, 53, "setref.f", 1, 2, 1)
12.87 +
12.88 +// Pushes an object reference onto the stack.
12.89 +OPDEF(OP_OBJECT, 54, "object", 5, 0, 1)
12.90 +
12.91 +// Performs an array-to-array assignment.
12.92 +// Left = pop()
12.93 +// Right = pop()
12.94 +// copy(Left, Right)
12.95 +// push(Left)
12.96 +OPDEF(OP_ARRAYCOPY, 55, "arraycopy", 1, 2, 1)
13.1 --- a/jitcraft/Parser.cpp Sun Jul 01 11:25:36 2012 -0700
13.2 +++ b/jitcraft/Parser.cpp Sun Jul 01 14:52:57 2012 -0700
13.3 @@ -17,6 +17,9 @@
13.4 */
13.5 #include "Zone.h"
13.6 #include "Parser.h"
13.7 +#include "FixedArray.h"
13.8 +#include "Heap.h"
13.9 +#include "Heap-inl.h"
13.10
13.11 using namespace jc;
13.12
13.13 @@ -112,6 +115,18 @@
13.14 return new (pool_) IntegerLiteral(value);
13.15 }
13.16
13.17 + case TOK_STRING_LITERAL:
13.18 + {
13.19 + // :TODO: Local
13.20 + scanner_.scan();
13.21 + ByteArray *array = ByteArray::New(ZONE(), scanner_.literal_length());
13.22 + if (!array)
13.23 + return NULL;
13.24 + memcpy(array->raw(), scanner_.literal(), scanner_.literal_length());
13.25 +
13.26 + return new (pool_) StringLiteral(array);
13.27 + }
13.28 +
13.29 default:
13.30 {
13.31 fprintf(stderr, "error: expected expression!\n");
13.32 @@ -497,10 +512,8 @@
13.33 Parser::expressionStatement()
13.34 {
13.35 Expression *left = primary();
13.36 - if (!left) {
13.37 - fprintf(stderr, "expected expression or statement\n");
13.38 + if (!left)
13.39 return NULL;
13.40 - }
13.41
13.42 if (match(TOK_ASSIGN)) {
13.43 Expression *expr = expression();
13.44 @@ -604,7 +617,8 @@
13.45
13.46 switch (scanner_.peek()) {
13.47 case TOK_NEW:
13.48 - statement = variableDeclaration();
13.49 + if ((statement = variableDeclaration()) == NULL)
13.50 + return NULL;
13.51 break;
13.52
13.53 case TOK_FOR:
13.54 @@ -629,11 +643,13 @@
13.55 break;
13.56
13.57 case TOK_RETURN:
13.58 - statement = returnStatement();
13.59 + if ((statement = returnStatement()) == NULL)
13.60 + return NULL;
13.61 break;
13.62
13.63 case TOK_ENUM:
13.64 - statement = enum_();
13.65 + if ((statement = enum_()) == NULL)
13.66 + return NULL;
13.67 break;
13.68
13.69 case TOK_IF:
13.70 @@ -979,6 +995,10 @@
13.71 prefix();
13.72 fprintf(fp_, "[ ContinueStatement\n");
13.73 }
13.74 + void visit(StringLiteral *node) {
13.75 + prefix();
13.76 + fprintf(fp_, "[ StringLiteral\n");
13.77 + }
13.78 };
13.79
13.80 void
14.1 --- a/jitcraft/Scanner.cpp Sun Jul 01 11:25:36 2012 -0700
14.2 +++ b/jitcraft/Scanner.cpp Sun Jul 01 14:52:57 2012 -0700
14.3 @@ -137,6 +137,114 @@
14.4 return number;
14.5 }
14.6
14.7 +static inline bool
14.8 +IsHexDigit(char c)
14.9 +{
14.10 + return IsDigit(c) ||
14.11 + (c >= 'a' && c <= 'f') ||
14.12 + (c >= 'A' && c <= 'F');
14.13 +}
14.14 +
14.15 +// Based on the logic for litchar() in sc2.c.
14.16 +int
14.17 +Scanner::readEscapeCode()
14.18 +{
14.19 + char c = getChar();
14.20 + if (c == '\\')
14.21 + return c;
14.22 +
14.23 + switch (c) {
14.24 + case 'a':
14.25 + return '\a';
14.26 + case 'b':
14.27 + return '\b';
14.28 + case 'e':
14.29 + return 27; // Apparently \e is non-standard.
14.30 + case 'f':
14.31 + return '\f';
14.32 + case 'n':
14.33 + return '\n';
14.34 + case 'r':
14.35 + return '\r';
14.36 + case 't':
14.37 + return '\t';
14.38 + case '\v':
14.39 + return '\v';
14.40 +
14.41 + case 'x':
14.42 + {
14.43 + unsigned digits = 0;
14.44 + char r = 0;
14.45 +
14.46 + c = getChar();
14.47 + while (IsHexDigit(c) && digits < 2) {
14.48 + if (IsDigit(c))
14.49 + c = (c << 4) + (c - '0');
14.50 + else
14.51 + c = (c << 4) + (tolower(c) - 'a' + 10);
14.52 + digits++;
14.53 + c = getChar();
14.54 + }
14.55 +
14.56 + // Swallow a trailing ';'
14.57 + if (c != ';')
14.58 + putChar(c);
14.59 +
14.60 + return r;
14.61 + }
14.62 +
14.63 + case '\'':
14.64 + case '\"':
14.65 + case '%':
14.66 + return c;
14.67 +
14.68 + default:
14.69 + {
14.70 + if (IsDigit(c)) {
14.71 + // \ddd
14.72 + char r = 0;
14.73 + while (IsDigit(c)) {
14.74 + r = r * 10 + (c - '0');
14.75 + c = getChar();
14.76 + }
14.77 +
14.78 + // Swallow a trailing ;
14.79 + if (c != ';')
14.80 + putChar(c);
14.81 +
14.82 + return r;
14.83 + }
14.84 + assert(false);
14.85 + return INT_MAX;
14.86 + }
14.87 + }
14.88 +}
14.89 +
14.90 +TokenKind
14.91 +Scanner::stringLiteral()
14.92 +{
14.93 + literal_.clear();
14.94 +
14.95 + for (;;) {
14.96 + char c = getChar();
14.97 + if (c == '\"')
14.98 + break;
14.99 + if (c == '\r' || c == '\n' || c == '\0') {
14.100 + assert(false);
14.101 + return TOK_ERROR;
14.102 + }
14.103 + if (c == '\\') {
14.104 + int code = readEscapeCode();
14.105 + if (code == INT_MAX)
14.106 + return TOK_ERROR;
14.107 + c = char(code);
14.108 + }
14.109 + literal_ += c;
14.110 + }
14.111 +
14.112 + return TOK_STRING_LITERAL;
14.113 +}
14.114 +
14.115 TokenKind
14.116 Scanner::numberLiteral(char first)
14.117 {
14.118 @@ -335,6 +443,9 @@
14.119 case '\n':
14.120 break;
14.121
14.122 + case '"':
14.123 + return stringLiteral();
14.124 +
14.125 default:
14.126 if (c >= '0' && c <= '9')
14.127 return numberLiteral(c);
15.1 --- a/jitcraft/Scanner.h Sun Jul 01 11:25:36 2012 -0700
15.2 +++ b/jitcraft/Scanner.h Sun Jul 01 14:52:57 2012 -0700
15.3 @@ -38,6 +38,8 @@
15.4 void putChar(char c);
15.5 void eatSingleLine();
15.6 bool eatComment();
15.7 + int readEscapeCode();
15.8 + TokenKind stringLiteral();
15.9 TokenKind numberLiteral(char first);
15.10 TokenKind identifier(char first);
15.11
15.12 @@ -54,9 +56,13 @@
15.13 return lastToken_;
15.14 }
15.15
15.16 + // Note: the literal may have embedded NUL characters.
15.17 const char *literal() const {
15.18 return literal_.c_str();
15.19 }
15.20 + size_t literal_length() const {
15.21 + return literal_.size() + 1;
15.22 + }
15.23 };
15.24
15.25 } // namespace jc
16.1 --- a/jitcraft/SemanticAnalysis.cpp Sun Jul 01 11:25:36 2012 -0700
16.2 +++ b/jitcraft/SemanticAnalysis.cpp Sun Jul 01 14:52:57 2012 -0700
16.3 @@ -120,10 +120,15 @@
16.4 SemanticAnalysis::visitForLoad(Expression *expression)
16.5 {
16.6 expression->accept(this);
16.7 - if (expression->type()) {
16.8 - // :TODO: use Local
16.9 - Type *type = expression->type();
16.10 - if (type->isArray() || type->isReference())
16.11 + if (!expression->type())
16.12 + return NULL;
16.13 +
16.14 + // :TODO: use Local
16.15 + Type *type = expression->type();
16.16 + if (type->isReference()) {
16.17 + expression->setType(type->contained());
16.18 + } else if (expression->isIndexExpression()) {
16.19 + if (type->isArray())
16.20 expression->setType(type->contained());
16.21 }
16.22 return expression->type();
16.23 @@ -151,6 +156,39 @@
16.24 return false;
16.25 }
16.26
16.27 +static inline bool
16.28 +TypeCheckAssignment(Type *left, Type *right)
16.29 +{
16.30 + if (!left || !right)
16.31 + return false;
16.32 +
16.33 + if (left->isPrimitive()) {
16.34 + if (!right->isPrimitive())
16.35 + return false;
16.36 + return left->primitive() == right->primitive();
16.37 + }
16.38 +
16.39 + if (left->isArray() != right->isArray())
16.40 + return false;
16.41 +
16.42 + if (left->levels() != 1 || right->levels() != 1)
16.43 + return false;
16.44 +
16.45 + if (left->elements() == -1 || right->elements() == -1)
16.46 + return false;
16.47 +
16.48 + if (!TypeCheckAssignment(left->contained(), right->contained()))
16.49 + return false;
16.50 +
16.51 + if (left->elements() != right->elements()) {
16.52 + if (left->isCharArray() && (left->elements() >= right->elements()))
16.53 + return true;
16.54 + return false;
16.55 + }
16.56 +
16.57 + return false;
16.58 +}
16.59 +
16.60 void
16.61 SemanticAnalysis::visit(Assignment *node)
16.62 {
16.63 @@ -167,13 +205,16 @@
16.64 }
16.65
16.66 Variable *var = proxy->binding()->toVariable();
16.67 + if (!var->type())
16.68 + return;
16.69 +
16.70 if (var->type()->isReference())
16.71 node->setType(var->type()->contained());
16.72 else
16.73 node->setType(var->type());
16.74 }
16.75
16.76 - assert(TypeCheck(node->type(), node->expression()->type()));
16.77 + assert(TypeCheckAssignment(node->type(), node->expression()->type()));
16.78 }
16.79
16.80
16.81 @@ -260,11 +301,24 @@
16.82 return;
16.83
16.84 if (node->postDimensions()) {
16.85 + Type *init = NULL;
16.86 + if (node->initialization()) {
16.87 + node->initialization()->accept(this);
16.88 + if ((init = node->initialization()->type()) == NULL)
16.89 + return;
16.90 + }
16.91 +
16.92 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
16.93 error();
16.94 return;
16.95 }
16.96
16.97 + // If we have an initializer, make sure it's the same type.
16.98 + if (init) {
16.99 + assert(init->levels() == node->postDimensions()->size());
16.100 + }
16.101 +
16.102 + Type *check = init;
16.103 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
16.104 Expression *expr = node->postDimensions()->at(i);
16.105 visitForLoad(expr);
16.106 @@ -285,9 +339,28 @@
16.107 error();
16.108 return;
16.109 }
16.110 + } else {
16.111 + assert(false);
16.112 }
16.113
16.114 type = ZONE()->types()->unsafeArray(type, size);
16.115 +
16.116 + if (check) {
16.117 + assert(check->elements() != -1);
16.118 + assert(size != -1);
16.119 +
16.120 + // If we're assigning a string, we're allowed to pad with
16.121 + // zeroes.
16.122 + if (check->isCharArray()) {
16.123 + assert(type->isCharArray());
16.124 + assert(type->elements() >= check->elements());
16.125 + } else {
16.126 + assert(false);
16.127 + }
16.128 + }
16.129 +
16.130 + if (check)
16.131 + check = check->contained();
16.132 }
16.133
16.134 // Right now, any array is allowed on the LIFO heap. In case the
16.135 @@ -299,6 +372,10 @@
16.136 Type *right = visitForLoad(node->initialization());
16.137 assert(TypeCheck(type, right));
16.138 }
16.139 + if (type->primitive() == PrimitiveType_Char) {
16.140 + assert(false);
16.141 + return;
16.142 + }
16.143 }
16.144
16.145 node->variable()->setType(type);
16.146 @@ -477,6 +554,20 @@
16.147 }
16.148
16.149 void
16.150 +SemanticAnalysis::visit(StringLiteral *node)
16.151 +{
16.152 + Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Char);
16.153 + if (!type)
16.154 + return;
16.155 +
16.156 + type = Type::NewArray(ZONE(), type, node->string()->length() + 1, true);
16.157 + if (!type)
16.158 + return;
16.159 +
16.160 + node->setType(type);
16.161 +}
16.162 +
16.163 +void
16.164 SemanticAnalysis::visit(FloatLiteral *node)
16.165 {
16.166 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
17.1 --- a/jitcraft/SemanticAnalysis.h Sun Jul 01 11:25:36 2012 -0700
17.2 +++ b/jitcraft/SemanticAnalysis.h Sun Jul 01 14:52:57 2012 -0700
17.3 @@ -63,6 +63,7 @@
17.4 void visit(WhileStatement *node);
17.5 void visit(BreakStatement *node);
17.6 void visit(ContinueStatement *node);
17.7 + void visit(StringLiteral *node);
17.8 };
17.9
17.10 } // namespace jc
18.1 --- a/jitcraft/Token.h Sun Jul 01 11:25:36 2012 -0700
18.2 +++ b/jitcraft/Token.h Sun Jul 01 14:52:57 2012 -0700
18.3 @@ -28,6 +28,7 @@
18.4 _(NAME, "<name>") \
18.5 _(INTEGER_LITERAL, "<integer>") \
18.6 _(FLOAT_LITERAL, "<float>") \
18.7 + _(STRING_LITERAL, "<string>") \
18.8 _(IF, "<if>") \
18.9 _(ELSE, "<else>") \
18.10 _(ENUM, "<enum>") \
19.1 --- a/jitcraft/TypeManager.cpp Sun Jul 01 11:25:36 2012 -0700
19.2 +++ b/jitcraft/TypeManager.cpp Sun Jul 01 14:52:57 2012 -0700
19.3 @@ -36,6 +36,8 @@
19.4 return false;
19.5 if ((primitiveTypes_[PrimitiveType_Native] = Type::NewPrimitive(zone_, PrimitiveType_Native)) == NULL)
19.6 return false;
19.7 + if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, "String")) == NULL)
19.8 + return false;
19.9
19.10 for (unsigned i = 0; i < PrimitiveTypes_Total; i++) {
19.11 if ((referenceTypes_[i] = Type::NewReference(zone_, primitiveTypes_[i])) == NULL)
19.12 @@ -52,7 +54,8 @@
19.13 return getPrimitive(PrimitiveType_Int32);
19.14 if (strcmp(tag, "Float") == 0)
19.15 return getPrimitive(PrimitiveType_Float);
19.16 - assert(!"tag cache");
19.17 + if (strcmp(tag, "String") == 0)
19.18 + return getPrimitive(PrimitiveType_Char);
19.19 return NULL;
19.20 }
19.21
19.22 @@ -60,7 +63,7 @@
19.23 TypeManager::unsafeArray(Type *contained, int elements)
19.24 {
19.25 // :TODO: cache this.
19.26 - return Type::NewUnsafeArray(zone_, contained, elements);
19.27 + return Type::NewArray(zone_, contained, elements, false);
19.28 }
19.29
19.30 Type *
20.1 --- a/jitcraft/Types.cpp Sun Jul 01 11:25:36 2012 -0700
20.2 +++ b/jitcraft/Types.cpp Sun Jul 01 14:52:57 2012 -0700
20.3 @@ -35,6 +35,8 @@
20.4
20.5 if (tag && strcmp(tag, "Float") == 0)
20.6 type->primitive_ = PrimitiveType_Float;
20.7 + else if (tag && strcmp(tag, "String") == 0)
20.8 + type->primitive_ = PrimitiveType_Char;
20.9 else
20.10 type->primitive_ = PrimitiveType_Int32;
20.11 return type;
20.12 @@ -56,7 +58,7 @@
20.13 }
20.14
20.15 Type *
20.16 -Type::NewUnsafeArray(Zone *zone, Type *contained, int elements)
20.17 +Type::NewArray(Zone *zone, Type *contained, int elements, bool isConst)
20.18 {
20.19 Object *obj = zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old);
20.20 if (!obj)
20.21 @@ -71,6 +73,7 @@
20.22 type->levels_ = 1;
20.23 else
20.24 type->levels_ = contained->levels() + 1;
20.25 + type->const_ = isConst;
20.26 return type;
20.27 }
20.28
21.1 --- a/jitcraft/Types.h Sun Jul 01 11:25:36 2012 -0700
21.2 +++ b/jitcraft/Types.h Sun Jul 01 14:52:57 2012 -0700
21.3 @@ -27,7 +27,7 @@
21.4
21.5 enum PrimitiveType
21.6 {
21.7 - PrimitiveType_Int8, // signed, 8-bit character
21.8 + PrimitiveType_Char, // signed, 8-bit character
21.9 PrimitiveType_Int32, // signed, 32-bit integer
21.10 PrimitiveType_Float, // 32-bit IEEE-754 float
21.11 PrimitiveType_Native, // native-sized word
21.12 @@ -40,8 +40,7 @@
21.13 PRIMITIVE,
21.14 ARRAY,
21.15 REFERENCE,
21.16 - FUNCTION,
21.17 - CHAR
21.18 + FUNCTION
21.19 };
21.20
21.21 private:
21.22 @@ -56,7 +55,7 @@
21.23 // :TODO: use handles
21.24 static Type *NewPrimitive(Zone *zone, Name *tag);
21.25 static Type *NewPrimitive(Zone *zone, PrimitiveType type);
21.26 - static Type *NewUnsafeArray(Zone *zone, Type *contained, int elements);
21.27 + static Type *NewArray(Zone *zone, Type *contained, int elements, bool isConst);
21.28 static Type *NewReference(Zone *zone, Type *contained);
21.29 static Type *NewFunction(Zone *zone, Type *returnType, FixedArray *parameters);
21.30
21.31 @@ -110,6 +109,15 @@
21.32 bool isInt32() {
21.33 return isPrimitive() && primitive() == PrimitiveType_Int32;
21.34 }
21.35 + bool isCharArray() {
21.36 + return isArray() &&
21.37 + contained()->isPrimitive() &&
21.38 + contained()->primitive() == PrimitiveType_Char;
21.39 + }
21.40 + bool isConst() {
21.41 + assert(isArray());
21.42 + return const_;
21.43 + }
21.44 Type *returnType() {
21.45 assert(isFunction());
21.46 return returnType_;
21.47 @@ -127,6 +135,7 @@
21.48 // Arrays only.
21.49 int32 elements_;
21.50 unsigned levels_;
21.51 + bool const_;
21.52
21.53 // Arrays and references only.
21.54 Barriered<Type> contained_;
22.1 --- a/jitcraft/main.cpp Sun Jul 01 11:25:36 2012 -0700
22.2 +++ b/jitcraft/main.cpp Sun Jul 01 14:52:57 2012 -0700
22.3 @@ -80,12 +80,12 @@
22.4
22.5 printf("\n ------------ \n\n");
22.6
22.7 - Disassemble(module->getFunction(1), stdout);
22.8 + Disassemble(module->getFunction(0), stdout);
22.9 //Disassemble(module->getFunction(1), stdout);
22.10
22.11 printf("\n ------------ \n\n");
22.12
22.13 - Code *main = module->getFunction(1);
22.14 + Code *main = module->getFunction(0);
22.15
22.16 Top top = ZONE()->stack().begin();
22.17 LocalTop localTop(top);
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/tests/prototype/string-1.sp Sun Jul 01 14:52:57 2012 -0700
23.3 @@ -0,0 +1,6 @@
23.4 +main()
23.5 +{
23.6 + new String:buffer[100] = "clam";
23.7 + buffer = "hedgehog";
23.8 + return buffer[3];
23.9 +}