Commit e4d91e36 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Fix a type analysis bug

A discrepancy between irgen and type_analysis was causing an assertion.  The
difference was that irgen will do full type inference for things that get put
into closures (ie in the parent scope), but type_analysis was bailing and
just saying that it was unknown.
parent fd4737aa
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include "runtime/types.h" #include "runtime/types.h"
//#undef VERBOSITY //#undef VERBOSITY
//#define VERBOSITY(x) 2 //#define VERBOSITY(x) 4
namespace pyston { namespace pyston {
...@@ -116,9 +116,11 @@ private: ...@@ -116,9 +116,11 @@ private:
if (speculated_cls != NULL && speculated_cls->is_constant) { if (speculated_cls != NULL && speculated_cls->is_constant) {
ConcreteCompilerType* speculated_type = unboxedType(typeFromClass(speculated_cls)); ConcreteCompilerType* speculated_type = unboxedType(typeFromClass(speculated_cls));
if (VERBOSITY() >= 2) { if (VERBOSITY() >= 2) {
printf("in propagator, speculating that %s would actually be %s, at:\n", old_type->debugName().c_str(), printf("in propagator, speculating that %s would actually be %s, at ", old_type->debugName().c_str(),
speculated_type->debugName().c_str()); speculated_type->debugName().c_str());
fflush(stdout);
print_ast(node); print_ast(node);
llvm::outs().flush();
printf("\n"); printf("\n");
} }
...@@ -152,8 +154,9 @@ private: ...@@ -152,8 +154,9 @@ private:
CompilerType* rtn = static_cast<CompilerType*>(raw_rtn); CompilerType* rtn = static_cast<CompilerType*>(raw_rtn);
if (VERBOSITY() >= 3) { if (VERBOSITY() >= 3) {
printf("Type of ");
print_ast(node); print_ast(node);
printf(" %s\n", rtn->debugName().c_str()); printf(" is %s\n", rtn->debugName().c_str());
} }
expr_types[node] = rtn; expr_types[node] = rtn;
...@@ -428,10 +431,6 @@ private: ...@@ -428,10 +431,6 @@ private:
return UNKNOWN; return UNKNOWN;
} }
if (name_scope == ScopeInfo::VarScopeType::CLOSURE) {
return UNKNOWN;
}
if (name_scope == ScopeInfo::VarScopeType::NAME) { if (name_scope == ScopeInfo::VarScopeType::NAME) {
return UNKNOWN; return UNKNOWN;
} }
...@@ -440,7 +439,7 @@ private: ...@@ -440,7 +439,7 @@ private:
return UNKNOWN; return UNKNOWN;
} }
if (name_scope == ScopeInfo::VarScopeType::FAST) { if (name_scope == ScopeInfo::VarScopeType::FAST || name_scope == ScopeInfo::VarScopeType::CLOSURE) {
CompilerType*& t = sym_table[node->id]; CompilerType*& t = sym_table[node->id];
if (t == NULL) { if (t == NULL) {
// if (VERBOSITY() >= 2) { // if (VERBOSITY() >= 2) {
......
...@@ -1170,7 +1170,7 @@ private: ...@@ -1170,7 +1170,7 @@ private:
llvm::Value* r = emitter.createCall3(unw_info, g.funcs.boxedLocalsGet, boxedLocals, attr, module); llvm::Value* r = emitter.createCall3(unw_info, g.funcs.boxedLocalsGet, boxedLocals, attr, module);
return new ConcreteCompilerVariable(UNKNOWN, r, true); return new ConcreteCompilerVariable(UNKNOWN, r, true);
} else { } else {
// vst is one of {FAST, CLOSURE, NAME} // vst is one of {FAST, CLOSURE}
if (symbol_table.find(node->id) == symbol_table.end()) { if (symbol_table.find(node->id) == symbol_table.end()) {
// TODO should mark as DEAD here, though we won't end up setting all the names appropriately // TODO should mark as DEAD here, though we won't end up setting all the names appropriately
// state = DEAD; // state = DEAD;
...@@ -1541,14 +1541,24 @@ private: ...@@ -1541,14 +1541,24 @@ private:
if (VERBOSITY("irgen") >= 2) { if (VERBOSITY("irgen") >= 2) {
printf("Speculating that %s is actually %s, at ", rtn->getConcreteType()->debugName().c_str(), printf("Speculating that %s is actually %s, at ", rtn->getConcreteType()->debugName().c_str(),
speculated_type->debugName().c_str()); speculated_type->debugName().c_str());
PrintVisitor printer; fflush(stdout);
node->accept(&printer); print_ast(node);
llvm::outs().flush();
printf("\n"); printf("\n");
} }
#ifndef NDEBUG
// That's not really a speculation.... could potentially handle this here, but // That's not really a speculation.... could potentially handle this here, but
// I think it's better to just not generate bad speculations: // I think it's better to just not generate bad speculations:
assert(!rtn->canConvertTo(speculated_type)); if (rtn->canConvertTo(speculated_type)) {
auto source = irstate->getSourceInfo();
printf("On %s:%d, function %s:\n", source->getFn()->c_str(), source->body[0]->lineno,
source->getName()->c_str());
irstate->getSourceInfo()->cfg->print();
}
RELEASE_ASSERT(!rtn->canConvertTo(speculated_type), "%s %s", rtn->getType()->debugName().c_str(),
speculated_type->debugName().c_str());
#endif
ConcreteCompilerVariable* old_rtn = rtn->makeConverted(emitter, UNKNOWN); ConcreteCompilerVariable* old_rtn = rtn->makeConverted(emitter, UNKNOWN);
rtn->decvref(emitter); rtn->decvref(emitter);
......
...@@ -243,7 +243,7 @@ public: ...@@ -243,7 +243,7 @@ public:
if (!lookup_success) { if (!lookup_success) {
llvm::Constant* int_val llvm::Constant* int_val
= llvm::ConstantInt::get(g.i64, reinterpret_cast<uintptr_t>(addr), false); = llvm::ConstantInt::get(g.i64, reinterpret_cast<uintptr_t>(addr), false);
llvm::Constant* ptr_val = llvm::ConstantExpr::getIntToPtr(int_val, g.i8); llvm::Constant* ptr_val = llvm::ConstantExpr::getIntToPtr(int_val, g.i8_ptr);
ii->setArgOperand(i, ptr_val); ii->setArgOperand(i, ptr_val);
continue; continue;
} else { } else {
......
...@@ -1056,6 +1056,7 @@ void* AST_MakeClass::accept_expr(ExprVisitor* v) { ...@@ -1056,6 +1056,7 @@ void* AST_MakeClass::accept_expr(ExprVisitor* v) {
void print_ast(AST* ast) { void print_ast(AST* ast) {
PrintVisitor v; PrintVisitor v;
ast->accept(&v); ast->accept(&v);
v.flush();
} }
void PrintVisitor::printIndent() { void PrintVisitor::printIndent() {
......
...@@ -1338,6 +1338,9 @@ private: ...@@ -1338,6 +1338,9 @@ private:
public: public:
PrintVisitor(int indent = 0, llvm::raw_ostream& stream = llvm::outs()) : stream(stream), indent(indent) {} PrintVisitor(int indent = 0, llvm::raw_ostream& stream = llvm::outs()) : stream(stream), indent(indent) {}
virtual ~PrintVisitor() {} virtual ~PrintVisitor() {}
void flush() {
stream.flush();
}
virtual bool visit_alias(AST_alias* node); virtual bool visit_alias(AST_alias* node);
virtual bool visit_arguments(AST_arguments* node); virtual bool visit_arguments(AST_arguments* node);
......
...@@ -82,3 +82,15 @@ def f7(n): ...@@ -82,3 +82,15 @@ def f7(n):
c = f7(5)() c = f7(5)()
print c.foo() print c.foo()
# Regression test: being included in a closure (ie in the parent scope) shouldn't ruin type analysis.
def f8():
l = []
def g():
print l
l.append(1)
for i in xrange(11000):
f8()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment