Added support for fused math-assign ops (+=, etc).
2 * Copyright (C) 2012 David Anderson
4 * This file is part of JITCraft.
6 * JITCraft is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
11 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * JITCraft. If not, see http://www.gnu.org/licenses/.
18 #include "SemanticAnalysis.h"
21 #include "TypeManager.h"
27 IsPrimitiveType(Type *type, PrimitiveType primitive)
32 if (!type->isPrimitive())
35 return primitive == type->primitive();
39 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
44 *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
48 *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
56 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
58 switch (expression->kind()) {
59 case AstNode::kBinaryExpression:
63 BinaryExpression *b = expression->toBinaryExpression();
64 if (!EvaluateForConstant(b->left(), &left) ||
65 !EvaluateForConstant(b->right(), &right))
69 return EvaluateBinaryOperation(b->token(), left, right, out);
72 case AstNode::kNameProxy:
74 NameProxy *proxy = expression->toNameProxy();
75 if (proxy->binding()->kind() != BoundName::CONSTANT)
78 NamedConstant *c = proxy->binding()->toNamedConstant();
79 if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
86 case AstNode::kIntegerLiteral:
87 *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
95 SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
103 SemanticAnalysis::analyze()
105 for (size_t i = 0; i < tree_->statements()->length(); i++) {
106 Statement *statement = tree_->statements()->at(i);
107 statement->accept(this);
114 SemanticAnalysis::visit(NameProxy *name)
116 name->setType(name->binding()->type());
120 SemanticAnalysis::visitForLoad(Expression *expression)
122 expression->accept(this);
123 if (!expression->type())
127 Type *type = expression->type();
128 if (type->isReference()) {
129 expression->setType(type->contained());
130 } else if (expression->isIndexExpression()) {
132 expression->setType(type->contained());
134 return expression->type();
138 SemanticAnalysis::visitForRef(Expression *expression)
140 expression->accept(this);
141 return expression->type();
145 TypeCheck(Type *left, Type *right)
150 if (left->isPrimitive()) {
151 if (!right->isPrimitive())
153 return left->primitive() == right->primitive();
160 TypeCheckAssignment(Type *left, Type *right)
165 if (left->isPrimitive()) {
166 if (!right->isPrimitive())
168 return left->primitive() == right->primitive();
171 if (left->isArray() != right->isArray())
174 if (left->levels() != 1 || right->levels() != 1)
177 if (left->elements() == -1 || right->elements() == -1)
180 if (!TypeCheckAssignment(left->contained(), right->contained()))
183 if (left->elements() != right->elements()) {
184 if (left->isCharArray() && (left->elements() >= right->elements()))
193 TypeCheckBinary(TokenKind token, Type *left, Type *right)
198 if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
199 (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
201 // If either side is a float, the other side must be a float or int.
202 if (left->isFloat() || right->isFloat()) {
203 assert(left->isFloat() || left->isInt32());
204 assert(right->isFloat() || right->isInt32());
205 return left->isFloat() ? left : right;
209 assert(left->isInt32() && right->isInt32());
210 assert(!left->tag() && !right->tag());
215 SemanticAnalysis::visit(Assignment *node)
217 visitForLoad(node->expression());
219 if (node->lvalue()->isIndexExpression()) {
220 node->lvalue()->accept(this);
221 node->setType(node->lvalue()->type()->contained());
223 NameProxy *proxy = node->lvalue()->toNameProxy();
224 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
225 fprintf(stderr, "error\n");
229 Variable *var = proxy->binding()->toVariable();
233 if (var->type()->isReference())
234 node->setType(var->type()->contained());
236 node->setType(var->type());
239 if (node->token() != TOK_ASSIGN)
240 assert(TypeCheckBinary(node->token(), node->type(), node->expression()->type()));
242 assert(TypeCheckAssignment(node->type(), node->expression()->type()));
246 SemanticAnalysis::visit(BinaryExpression *node)
249 Type *left = visitForLoad(node->left());
250 Type *right = visitForLoad(node->right());
252 Type *result = TypeCheckBinary(node->token(), left, right);
253 node->setType(result);
257 SemanticAnalysis::visit(ReturnStatement *node)
259 visitForLoad(node->expression());
265 SemanticAnalysis::visit(ForStatement *node)
269 scope_ = node->scope();
270 if (node->initialization())
271 node->initialization()->accept(this);
272 if (node->condition())
273 visitForLoad(node->condition());
275 node->update()->accept(this);
276 node->body()->accept(this);
278 scope_ = scope_->enclosing();
283 SemanticAnalysis::visit(WhileStatement *node)
286 node->condition()->accept(this);
287 node->body()->accept(this);
292 SemanticAnalysis::visit(BlockStatement *node)
295 scope_ = node->scope();
296 for (size_t i = 0; i < node->statements()->length(); i++) {
297 Statement *statement = node->statements()->at(i);
298 statement->accept(this);
301 scope_ = scope_->enclosing();
305 SemanticAnalysis::visit(VariableDeclaration *node)
308 Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
312 if (node->postDimensions()) {
314 if (node->initialization()) {
315 node->initialization()->accept(this);
316 if ((init = node->initialization()->type()) == NULL)
320 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
325 // If we have an initializer, make sure it's the same type.
327 assert(init->levels() == node->postDimensions()->size());
331 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
332 Expression *expr = node->postDimensions()->at(i);
335 if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
336 typeError(expr, "integer");
341 if (expr->isIntegerLiteral()) {
342 size = expr->toIntegerLiteral()->value();
347 if (size >= INT_MAX / sizeof(int)) {
355 type = ZONE()->types()->unsafeArray(type, size);
358 assert(check->elements() != -1);
361 // If we're assigning a string, we're allowed to pad with
363 if (check->isCharArray()) {
364 assert(type->isCharArray());
365 assert(type->elements() >= check->elements());
372 check = check->contained();
375 // Right now, any array is allowed on the LIFO heap. In case the
376 // runtime actually decides to use the LIFO heap, we must reserve
377 // a slot so we can unwind the heap when the current scope leaves.
378 scope_->setUsesLifoHeap();
380 if (node->initialization()) {
381 Type *right = visitForLoad(node->initialization());
382 assert(TypeCheck(type, right));
384 if (type->primitive() == PrimitiveType_Char) {
390 node->variable()->setType(type);
394 SemanticAnalysis::visit(IntegerLiteral *node)
396 node->setType(ZONE()->types()->getPrimitive(PrimitiveType_Int32));
400 SemanticAnalysis::visit(ExpressionStatement *node)
402 node->expression()->accept(this);
406 SemanticAnalysis::preanalyze(FunctionStatement *node)
410 FixedArray *args = FixedArray::New(ZONE(), node->parameters()->size(), Heap::Tenure_Old);
414 // Apply types to arguments.
415 for (size_t i = 0; i < node->parameters()->size(); i++) {
416 Parameter *parameter = node->parameters()->at(i);
418 Type *type = ZONE()->types()->getPrimitiveForTag(parameter->tag());
422 if (parameter->reference()) {
423 type = ZONE()->types()->getReference(type);
428 args->set(ZONE(), i, type);
429 parameter->variable()->setType(type);
432 Type *returnType = ZONE()->types()->getPrimitive(PrimitiveType_Int32);
436 Type *funtype = ZONE()->types()->newFunction(returnType, args);
440 node->fun()->setType(funtype);
445 SemanticAnalysis::visit(FunctionStatement *node)
447 scope_ = node->scope();
449 // :TODO: call this ahead of time.
450 if (!preanalyze(node))
453 node->body()->accept(this);
457 // :TODO: use handles
459 TypeCheckParameter(Type *given, Type *actual)
461 if (actual->isReference()) {
462 if (given->isReference())
463 given = given->contained();
464 return TypeCheck(given, actual->contained());
467 return TypeCheck(given, actual);
471 SemanticAnalysis::visit(CallExpression *node)
473 visitForLoad(node->callee());
476 Type *type = node->callee()->type();
480 assert(type->isFunction());
481 assert(node->arguments()->size() == type->parameters()->length());
483 for (unsigned i = 0; i < node->arguments()->size(); i++) {
484 // Note: we don't compute references unless the callee needs a
486 Expression *expression = node->arguments()->at(i);
487 expression->accept(this);
489 Type *given = expression->type();
493 // If it's an IndexExpression, we special case the ability to compute
494 // a reference. Maybe we should compute actual Ref types for
496 if (expression->isIndexExpression())
497 given = given->contained();
499 Type *actual = Type::cast(type->parameters()->at(i));
500 assert(TypeCheckParameter(given, actual));
502 // If the actual is a reference, and the given is not, we'll need to
503 // compute a reference, which may be allocated on the stack.
504 if (actual->isReference() && !given->isReference())
505 scope_->setUsesLifoHeap();
510 SemanticAnalysis::visit(IfStatement *node)
512 visitForLoad(node->condition());
513 node->ifTrue()->accept(this);
515 node->ifFalse()->accept(this);
519 SemanticAnalysis::visit(IndexExpression *node)
522 Type *left = visitForRef(node->left());
523 Type *right = visitForLoad(node->right());
525 if (!right || !right->isInt32()) {
526 typeError(node->right(), "integer");
529 if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
530 typeError(node->left(), "array");
537 SemanticAnalysis::visit(EnumStatement *node)
539 // :TODO: test "enum Float { ..."
540 Name *tag = node->name();
542 Type *type = ZONE()->types()->getPrimitiveForTag(tag);
547 for (size_t i = 0; i < node->entries()->size(); i++) {
548 EnumStatement::Entry &entry = node->entries()->at(i);
550 BoxedPrimitive box = BoxedPrimitive::Int(value);
552 entry.expr->accept(this);
553 if (!EvaluateForConstant(entry.expr, &box))
554 fprintf(stderr, "expected constant integer expression\n");
556 assert(box.type() == PrimitiveType_Int32);
560 entry.name->set(type, box);
566 SemanticAnalysis::visit(StringLiteral *node)
568 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Char);
572 type = Type::NewArray(ZONE(), type, node->string()->length() + 1, true);
580 SemanticAnalysis::visit(FloatLiteral *node)
582 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
590 SemanticAnalysis::visit(BreakStatement *node)
592 assert(loopDepth_ > 0);
596 SemanticAnalysis::visit(ContinueStatement *node)
598 assert(loopDepth_ > 0);