1.1 --- a/jitcraft/SemanticAnalysis.cpp Thu Jul 12 00:38:00 2012 -0700
1.2 +++ b/jitcraft/SemanticAnalysis.cpp Sat Jul 14 18:43:34 2012 -0700
1.3 @@ -100,8 +100,8 @@
1.4 : zone_(zone),
1.5 cc_(cc),
1.6 tree_(tree),
1.7 - loopDepth_(0),
1.8 - scope_(NULL)
1.9 + scope_(NULL),
1.10 + loop_(NULL)
1.11 {
1.12 }
1.13
1.14 @@ -147,18 +147,17 @@
1.15 } else if (expression->isIndexExpression()) {
1.16 if (type->isArray())
1.17 expression->setType(type->contained());
1.18 + } else if (expression->isCallExpression()) {
1.19 + if (type->isVoid()) {
1.20 + CallExpression *call = expression->toCallExpression();
1.21 + cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
1.22 + return NULL;
1.23 + }
1.24 }
1.25
1.26 return expression->type();
1.27 }
1.28
1.29 -Type *
1.30 -SemanticAnalysis::visitForRef(Expression *expression)
1.31 -{
1.32 - expression->accept(this);
1.33 - return expression->type();
1.34 -}
1.35 -
1.36 // :TODO: this leaks an interior pointer.
1.37 static inline const char *
1.38 GetTypeName(Type *type)
1.39 @@ -269,6 +268,14 @@
1.40 return var->type();
1.41 }
1.42
1.43 +SemanticAnalysis::ControlStatus
1.44 +SemanticAnalysis::visitForControl(Statement *statement)
1.45 +{
1.46 + ControlScope scope(&control_);
1.47 + statement->accept(this);
1.48 + return scope.status();
1.49 +}
1.50 +
1.51 void
1.52 SemanticAnalysis::visit(NameProxy *name)
1.53 {
1.54 @@ -332,6 +339,9 @@
1.55 void
1.56 SemanticAnalysis::visit(ReturnStatement *node)
1.57 {
1.58 + // Set this early, so if we error we don't get more errors.
1.59 + control_->returns(Returns_Always);
1.60 +
1.61 Local<Type> type(zone_, visitForLoad(node->expression()));
1.62 if (!type)
1.63 return;
1.64 @@ -344,7 +354,8 @@
1.65 void
1.66 SemanticAnalysis::visit(ForStatement *node)
1.67 {
1.68 - loopDepth_++;
1.69 + LoopScope loop(&loop_);
1.70 +
1.71 if (node->scope())
1.72 scope_ = node->scope();
1.73
1.74 @@ -354,7 +365,6 @@
1.75 if (node->condition()) {
1.76 Local<Type> type(zone_, visitForLoad(node->condition()));
1.77 if (!type || !canTest(node->condition(), type)) {
1.78 - loopDepth_--;
1.79 return;
1.80 }
1.81 }
1.82 @@ -362,26 +372,48 @@
1.83 if (node->update())
1.84 node->update()->accept(this);
1.85
1.86 - node->body()->accept(this);
1.87 + ControlStatus status = visitForControl(node->body());
1.88 +
1.89 + // If there is a condition, we treat this like a while loop. Otherwise,
1.90 + // join point is only reachable if the loop contains a break. The
1.91 + // termination status doesn't tell us anything yet.
1.92 + if (node->condition() || loop.breaks())
1.93 + control_->merge(status, ControlStatus(false, Returns_Never));
1.94 + else
1.95 + control_->terminate(status.returns());
1.96
1.97 if (node->scope())
1.98 scope_ = scope_->enclosing();
1.99 - loopDepth_--;
1.100 }
1.101
1.102 void
1.103 SemanticAnalysis::visit(WhileStatement *node)
1.104 {
1.105 - loopDepth_++;
1.106 + LoopScope loop(&loop_);
1.107
1.108 Local<Type> type(zone_, visitForLoad(node->condition()));
1.109 if (!type || !canTest(node->condition(), type)) {
1.110 - loopDepth_--;
1.111 return;
1.112 }
1.113
1.114 - node->body()->accept(this);
1.115 - loopDepth_--;
1.116 + ControlStatus status = visitForControl(node->body());
1.117 +
1.118 + // Detect loops that will always have a fork in the control-flow graph.
1.119 + // This will be a |while| loop, or a |do-while| loop whose body does
1.120 + // not terminate.
1.121 + //
1.122 + // For now, we treat these as an |if| regardless of the direction the
1.123 + // branch can take. That means the control-flow is always conditional.
1.124 + if (node->token() == TOK_WHILE ||
1.125 + !status.terminates() ||
1.126 + loop.breaks())
1.127 + {
1.128 + control_->merge(status, ControlStatus(false, Returns_Never));
1.129 + } else {
1.130 + // At this point, we've got a do-while loop with a |return| or
1.131 + // |continue|, meaning that the rest of the block is unreachable.
1.132 + control_->terminate(status.returns());
1.133 + }
1.134 }
1.135
1.136 void
1.137 @@ -408,7 +440,7 @@
1.138 if (node->postDimensions()) {
1.139 Local<Type> init(zone_);
1.140 if (node->initialization()) {
1.141 - if ((init = visitAndApplyType(node->initialization())) == NULL)
1.142 + if ((init = visitForLoad(node->initialization())) == NULL)
1.143 return;
1.144 }
1.145
1.146 @@ -527,7 +559,7 @@
1.147 void
1.148 SemanticAnalysis::visit(ExpressionStatement *node)
1.149 {
1.150 - node->expression()->accept(this);
1.151 + visitAndApplyType(node->expression());
1.152 }
1.153
1.154 bool
1.155 @@ -597,7 +629,11 @@
1.156 parameter->variable()->setType(type);
1.157 }
1.158
1.159 - Local<Type> returnType(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
1.160 + Local<Type> returnType(zone_);
1.161 + if (node->hasExplicitReturn())
1.162 + returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
1.163 + else
1.164 + returnType = zone_->types()->getVoid();
1.165 if (!returnType)
1.166 return false;
1.167
1.168 @@ -630,8 +666,20 @@
1.169 {
1.170 function_ = node->fun()->type();
1.171 scope_ = node->scope();
1.172 - if (node->body())
1.173 +
1.174 + ControlScope control(&control_);
1.175 + if (node->body()) {
1.176 node->body()->accept(this);
1.177 +
1.178 + ControlStatus status = control.status();
1.179 + if (status.returns() == Returns_Sometimes) {
1.180 + cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
1.181 + } else if (status.returns() == Returns_Never) {
1.182 + if (!function_->returnType()->isVoid())
1.183 + cc_.reportError(node->pos(), Message_MissingReturnValue);
1.184 + }
1.185 + }
1.186 +
1.187 scope_ = NULL;
1.188 function_ = NULL;
1.189 }
1.190 @@ -772,6 +820,14 @@
1.191 if (!given)
1.192 return;
1.193
1.194 + // Since we skip a load, check for a call expression that returns void.
1.195 + if (given->isVoid()) {
1.196 + assert(expression->isCallExpression());
1.197 + CallExpression *call = expression->toCallExpression();
1.198 + cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
1.199 + return;
1.200 + }
1.201 +
1.202 // If it's an IndexExpression, we special case the ability to compute
1.203 // a reference.
1.204 if (expression->isIndexExpression())
1.205 @@ -801,6 +857,25 @@
1.206 }
1.207
1.208 void
1.209 +SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
1.210 +{
1.211 + // If both sides terminate in a return, we consider this a return as well.
1.212 + if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
1.213 + terminate(Returns_Always);
1.214 + return;
1.215 + }
1.216 +
1.217 + ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
1.218 + ? Returns_Never
1.219 + : Returns_Sometimes;
1.220 +
1.221 + if (left.terminates() && right.terminates())
1.222 + terminate(status);
1.223 + else
1.224 + returns(status);
1.225 +}
1.226 +
1.227 +void
1.228 SemanticAnalysis::visit(IfStatement *node)
1.229 {
1.230 Local<Type> type(zone_, visitForLoad(node->condition()));
1.231 @@ -810,15 +885,19 @@
1.232 if (!canTest(node, type))
1.233 return;
1.234
1.235 - node->ifTrue()->accept(this);
1.236 + ControlStatus trueBranch = visitForControl(node->ifTrue());
1.237 + ControlStatus falseBranch = ControlStatus(false, Returns_Never);
1.238 +
1.239 if (node->ifFalse())
1.240 - node->ifFalse()->accept(this);
1.241 + falseBranch = visitForControl(node->ifFalse());
1.242 +
1.243 + control_->merge(trueBranch, falseBranch);
1.244 }
1.245
1.246 void
1.247 SemanticAnalysis::visit(IndexExpression *node)
1.248 {
1.249 - Local<Type> left(zone_, visitForRef(node->left()));
1.250 + Local<Type> left(zone_, visitForLoad(node->left()));
1.251 Local<Type> right(zone_, visitForLoad(node->right()));
1.252
1.253 if (!left || !right)
1.254 @@ -901,13 +980,29 @@
1.255 void
1.256 SemanticAnalysis::visit(BreakStatement *node)
1.257 {
1.258 - if (loopDepth_ == 0)
1.259 + if (!loop_) {
1.260 cc_.reportError(node->pos(), Message_BreakOutsideLoop);
1.261 + return;
1.262 + }
1.263 +
1.264 + // Note: ignore breaks that occur in unreachable control-flow.
1.265 + if (!control_->status().terminates())
1.266 + loop_->addBreak();
1.267 +
1.268 + control_->terminate(Returns_Never);
1.269 }
1.270
1.271 void
1.272 SemanticAnalysis::visit(ContinueStatement *node)
1.273 {
1.274 - if (loopDepth_ == 0)
1.275 + if (!loop_) {
1.276 cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
1.277 + return;
1.278 + }
1.279 +
1.280 + // Note: ignore continues that occur in unreachable control-flow.
1.281 + if (!control_->status().terminates())
1.282 + loop_->addContinue();
1.283 +
1.284 + control_->terminate(Returns_Never);
1.285 }