Implemented gcmaps and stack frame tracing.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
7 * JITCraft is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * JITCraft. If not, see http://www.gnu.org/licenses/.
19 #include "SemanticAnalysis.h"
22 #include "TypeManager.h"
29 IsPrimitiveType(Type *type, PrimitiveType primitive)
34 if (!type->isPrimitive())
37 return primitive == type->primitive();
41 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
46 *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
50 *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
59 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
61 switch (expression->kind()) {
62 case AstNode::kBinaryExpression:
66 BinaryExpression *b = expression->toBinaryExpression();
67 if (!EvaluateForConstant(b->left(), &left) ||
68 !EvaluateForConstant(b->right(), &right))
72 return EvaluateBinaryOperation(b->token(), left, right, out);
75 case AstNode::kNameProxy:
77 NameProxy *proxy = expression->toNameProxy();
78 if (proxy->binding()->kind() != BoundName::CONSTANT)
81 NamedConstant *c = proxy->binding()->toNamedConstant();
82 if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
89 case AstNode::kIntegerLiteral:
90 *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
98 SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
108 SemanticAnalysis::analyze()
113 for (size_t i = 0; i < tree_->statements()->length(); i++) {
114 Statement *statement = tree_->statements()->at(i);
115 if (statement->isFunctionStatement()) {
116 FunctionStatement *funstmt = statement->toFunctionStatement();
117 if (!preanalyze(funstmt))
122 for (size_t i = 0; i < tree_->statements()->length(); i++) {
123 Statement *statement = tree_->statements()->at(i);
124 statement->accept(this);
127 return !cc_.failures();
131 SemanticAnalysis::visitAndApplyType(Expression *expression)
133 expression->accept(this);
134 return expression->type();
138 SemanticAnalysis::visitForLoad(Expression *expression)
140 Local<Type> type(zone_, visitAndApplyType(expression));
144 if (type->isReference()) {
145 expression->setType(type->contained());
146 } else if (expression->isIndexExpression()) {
148 expression->setType(type->contained());
151 return expression->type();
155 SemanticAnalysis::visitForRef(Expression *expression)
157 expression->accept(this);
158 return expression->type();
161 static inline const char *
162 GetTypeName(Type *type)
166 if (type->isFunction())
168 if (type->isReference())
169 type = type->contained();
176 SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
178 const char *op = TokenNames[token];
179 const char *name = GetTypeName(type);
181 cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
185 SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
187 const char *op = TokenNames[token];
188 const char *leftName = GetTypeName(left);
189 const char *rightName = GetTypeName(right);
191 cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
195 SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
197 if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
198 (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
200 // If either side is a float, the other side must be a float or int.
201 if (left->isFloat() || right->isFloat()) {
202 Type *floatType = left->isFloat() ? left : right;
203 Type *other = left->isFloat() ? right : left;
204 if (other->isFloat() || (other->isInt32() && !other->tag()))
209 if ((!left->isInt32() || left->tag()) ||
210 (!right->isInt32() || right->tag()))
212 binaryTypeError(node, token, left, right);
220 SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
222 if (type->isArray()) {
223 cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
230 SemanticAnalysis::visitForLValue(Expression *expression)
232 if (expression->isIndexExpression()) {
233 Type *type = visitAndApplyType(expression);
237 return type->contained();
240 if (!expression->isNameProxy()) {
241 cc_.reportError(expression->pos(), Message_ExpectedLValue);
245 NameProxy *proxy = expression->toNameProxy();
246 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
247 cc_.reportError(expression->pos(), Message_ExpectedLValue);
251 Variable *var = proxy->binding()->toVariable();
255 if (var->type()->isReference())
256 return var->type()->contained();
261 SemanticAnalysis::visit(NameProxy *name)
263 name->setType(name->binding()->type());
267 SemanticAnalysis::visit(Assignment *node)
269 Local<Type> exprType(zone_, visitForLoad(node->expression()));
273 Local<Type> type(zone_, visitForLValue(node->lvalue()));
277 if (node->token() != TOK_ASSIGN) {
278 if (!typeCheckBinary(node, node->token(), type, exprType))
282 if (!typeCheckAssignment(node, exprType, type, true))
289 SemanticAnalysis::visit(IncDecExpression *node)
291 Local<Type> type(zone_, visitForLValue(node->expression()));
295 assert(!type->isReference());
297 if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
298 unaryTypeError(node, node->token(), type);
306 SemanticAnalysis::visit(BinaryExpression *node)
308 Local<Type> left(zone_, visitForLoad(node->left()));
309 Local<Type> right(zone_, visitForLoad(node->right()));
313 Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
317 node->setType(result);
321 SemanticAnalysis::visit(ReturnStatement *node)
323 Local<Type> type(zone_, visitForLoad(node->expression()));
327 Local<Type> returnType(zone_, function_->returnType());
328 if (!typeCheckAssignment(node, type, returnType, true))
333 SemanticAnalysis::visit(ForStatement *node)
337 scope_ = node->scope();
339 if (node->initialization())
340 node->initialization()->accept(this);
342 if (node->condition()) {
343 Local<Type> type(zone_, visitForLoad(node->condition()));
344 if (!type || !canTest(node->condition(), type)) {
351 node->update()->accept(this);
353 node->body()->accept(this);
356 scope_ = scope_->enclosing();
361 SemanticAnalysis::visit(WhileStatement *node)
365 Local<Type> type(zone_, visitForLoad(node->condition()));
366 if (!type || !canTest(node->condition(), type)) {
371 node->body()->accept(this);
376 SemanticAnalysis::visit(BlockStatement *node)
379 scope_ = node->scope();
380 for (size_t i = 0; i < node->statements()->length(); i++) {
381 Statement *statement = node->statements()->at(i);
382 statement->accept(this);
385 scope_ = scope_->enclosing();
389 SemanticAnalysis::visit(VariableDeclaration *node)
391 Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(node->tag()));
395 if (node->postDimensions()) {
396 Local<Type> init(zone_);
397 if (node->initialization()) {
398 if ((init = visitAndApplyType(node->initialization())) == NULL)
402 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
403 cc_.reportError(node->pos(), Message_MaximumArrayDepth);
407 // If we have an initializer, make sure it's the same type.
408 if (init && node->postDimensions()->size() != init->levels()) {
409 cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
413 Local<Type> check(zone_, init);
414 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
415 Expression *expr = node->postDimensions()->at(i);
419 Local<Type> exprType(zone_, visitForLoad(expr));
423 if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
424 cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
429 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
432 cc_.reportError(expr->pos(), Message_BadArraySize);
435 if (size >= INT_MAX / sizeof(int)) {
436 cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
441 if (check->elements() == -1) {
442 cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
446 if (check->isCharArray()) {
447 if (check->elements() > size) {
448 cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
451 } else if (check->elements() != size) {
452 cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
458 cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
462 // here until we get dynamic array support.
463 cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
467 // Infer the size from the initializer.
469 cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
472 if (init->elements() == -1) {
473 cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
476 size = init->elements();
479 type = zone_->types()->unsafeArray(type, size);
484 check = check->contained();
487 // Right now, any array is allowed on the LIFO heap. In case the
488 // runtime actually decides to use the LIFO heap, we must reserve
489 // a slot so we can unwind the heap when the current scope leaves.
490 scope_->setUsesLifoHeap();
492 if (node->initialization()) {
493 Local<Type> right(zone_, visitForLoad(node->initialization()));
496 if (!typeCheckAssignment(node, type, right, true))
499 if (type->primitive() == PrimitiveType_Char) {
500 cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
505 node->variable()->setType(type);
509 SemanticAnalysis::visit(IntegerLiteral *node)
511 node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
515 SemanticAnalysis::visit(ExpressionStatement *node)
517 node->expression()->accept(this);
521 SemanticAnalysis::preanalyze(FunctionStatement *node)
523 Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->size(), Heap::Tenure_Old));
527 // Apply types to arguments.
528 for (size_t i = 0; i < node->parameters()->size(); i++) {
529 Parameter *parameter = node->parameters()->at(i);
531 Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(parameter->tag()));
535 if (type->primitive() == PrimitiveType_Char) {
536 cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
540 if (parameter->reference()) {
541 type = zone_->types()->getReference(type);
546 args->set(zone_, i, type);
547 parameter->variable()->setType(type);
550 Local<Type> returnType(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
554 Local<Type> funtype(zone_, zone_->types()->newFunction(returnType, args));
558 node->fun()->setType(funtype);
563 SemanticAnalysis::visit(FunctionStatement *node)
565 function_ = node->fun()->type();
566 scope_ = node->scope();
567 node->body()->accept(this);
573 SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
575 Local<Type> actual(zone_, argActual);
576 Local<Type> given(zone_, argGiven);
578 if (!given->isArray()) {
579 cc_.reportError(node->pos(), Message_ExpectedArray);
582 if (given->levels() != actual->levels()) {
583 cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
588 while (given->isArray()) {
589 if (actual->elements() != -1) {
591 if (given->elements() == -1 || actual->elements() == -1) {
592 cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
596 if (actual->isCharArray()) {
597 // String assignment can have a truncated |given|.
598 if (given->elements() > actual->elements()) {
599 cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
603 if (given->elements() != actual->elements()) {
604 cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
609 if (actual->elements() != -1 && given->elements() != actual->elements()) {
610 cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
615 given = given->contained();
616 actual = actual->contained();
619 if (given->primitive() != actual->primitive()) {
620 const char *givenTag = given->tag() ? given->tag() : "_";
621 const char *actualTag = given->tag() ? given->tag() : "_";
622 cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
630 SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
632 Local<Type> actual(zone_, argActual);
633 Local<Type> given(zone_, argGiven);
635 if (actual->isArray())
636 return typeCheckArrayAssignment(node, given, actual, forAssign);
638 if (given->isArray()) {
639 cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
643 // The given type may not have been dereferenced.
644 if (given->isReference())
645 given = given->contained();
646 if (actual->isReference())
647 actual = actual->contained();
649 if (!given->isPrimitive() || !actual->isPrimitive()) {
650 cc_.reportError(node->pos(), Message_UnsupportedType);
654 if (given->primitive() != actual->primitive()) {
655 const char *givenTag = given->tag() ? given->tag() : "_";
656 const char *actualTag = given->tag() ? given->tag() : "_";
657 cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
665 SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
667 return typeCheckAssignment(node, given, actual, false);
671 SemanticAnalysis::visit(CallExpression *node)
673 Local<Type> type(zone_, visitForLoad(node->callee()));
677 if (!type->isFunction()) {
678 cc_.reportError(node->pos(), Message_CalleeNotFunction);
681 if (node->arguments()->size() != type->parameters()->length()) {
682 cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
686 for (unsigned i = 0; i < node->arguments()->size(); i++) {
687 // Note: we don't compute references unless the callee needs a
689 Expression *expression = node->arguments()->at(i);
690 Local<Type> given(zone_, visitAndApplyType(expression));
694 // If it's an IndexExpression, we special case the ability to compute
696 if (expression->isIndexExpression())
697 given = given->contained();
699 Local<Type> actual(zone_, type->parameterAt(i));
700 if (!typeCheckParameter(expression, given, actual))
703 // If the actual is a reference, and the given is not, we'll need to
704 // compute a reference, which may be allocated on the stack.
705 if (actual->isReference() && !given->isReference())
706 scope_->setUsesLifoHeap();
711 SemanticAnalysis::visit(IfStatement *node)
713 Local<Type> type(zone_, visitForLoad(node->condition()));
717 if (!canTest(node, type))
720 node->ifTrue()->accept(this);
722 node->ifFalse()->accept(this);
726 SemanticAnalysis::visit(IndexExpression *node)
728 Local<Type> left(zone_, visitForRef(node->left()));
729 Local<Type> right(zone_, visitForLoad(node->right()));
734 if (!right->isInt32()) {
735 cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
738 if (!left->isArray()) {
739 cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
746 SemanticAnalysis::visit(EnumStatement *node)
748 // Forbid the blessed types.
749 Name *tag = node->name();
750 if (!strcmp(tag, "Float") ||
751 !strcmp(tag, "String") ||
752 !strcmp(tag, "any") ||
753 !strcmp(tag, "bool"))
755 cc_.reportError(node->pos(), Message_InvalidEnumName);
759 Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
764 for (size_t i = 0; i < node->entries()->size(); i++) {
765 EnumStatement::Entry &entry = node->entries()->at(i);
767 BoxedPrimitive box = BoxedPrimitive::Int(value);
769 entry.expr->accept(this);
770 if (!EvaluateForConstant(entry.expr, &box)) {
771 cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
775 assert(box.type() == PrimitiveType_Int32);
779 entry.name->set(type, box);
785 SemanticAnalysis::visit(StringLiteral *node)
787 Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
791 type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
799 SemanticAnalysis::visit(FloatLiteral *node)
801 Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
809 SemanticAnalysis::visit(BreakStatement *node)
812 cc_.reportError(node->pos(), Message_BreakOutsideLoop);
816 SemanticAnalysis::visit(ContinueStatement *node)
819 cc_.reportError(node->pos(), Message_ContinueOutsideLoop);