Commit 45fc5847 authored by Marius Wachtler's avatar Marius Wachtler

Merge branch 'master' of https://github.com/dropbox/pyston into generators

Conflicts:
	src/codegen/irgen/irgenerator.cpp
	src/codegen/runtime_hooks.h
parents bc512baf 07af2757
...@@ -59,7 +59,7 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>& ...@@ -59,7 +59,7 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>&
CFGBlock* block = q.top(); CFGBlock* block = q.top();
q.pop(); q.pop();
Map initial = states[block]; Map& initial = states[block];
if (VERBOSITY("analysis") >= 2) if (VERBOSITY("analysis") >= 2)
printf("fpc on block %d - %ld entries\n", block->idx, initial.size()); printf("fpc on block %d - %ld entries\n", block->idx, initial.size());
......
...@@ -95,6 +95,9 @@ public: ...@@ -95,6 +95,9 @@ public:
}; };
bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) { bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) {
if (name[0] != '#')
return true;
if (block->successors.size() == 0) if (block->successors.size() == 0)
return false; return false;
...@@ -292,19 +295,19 @@ DefinednessAnalysis::DefinednessAnalysis(const SourceInfo::ArgNames& arg_names, ...@@ -292,19 +295,19 @@ DefinednessAnalysis::DefinednessAnalysis(const SourceInfo::ArgNames& arg_names,
// printf("%d %s %d\n", p.first->idx, p2.first.c_str(), p2.second); // printf("%d %s %d\n", p.first->idx, p2.first.c_str(), p2.second);
required.insert(p2.first); required.insert(p2.first);
} }
defined.insert(make_pair(p.first, required)); defined_at_end.insert(make_pair(p.first, required));
} }
} }
DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAt(const std::string& name, CFGBlock* block) { DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(const std::string& name, CFGBlock* block) {
std::unordered_map<std::string, DefinitionLevel>& map = results[block]; std::unordered_map<std::string, DefinitionLevel>& map = results[block];
if (map.count(name) == 0) if (map.count(name) == 0)
return Undefined; return Undefined;
return map[name]; return map[name];
} }
const DefinednessAnalysis::RequiredSet& DefinednessAnalysis::getDefinedNamesAt(CFGBlock* block) { const DefinednessAnalysis::RequiredSet& DefinednessAnalysis::getDefinedNamesAtEnd(CFGBlock* block) {
return defined[block]; return defined_at_end[block];
} }
PhiAnalysis::PhiAnalysis(const SourceInfo::ArgNames& arg_names, CFG* cfg, LivenessAnalysis* liveness, PhiAnalysis::PhiAnalysis(const SourceInfo::ArgNames& arg_names, CFG* cfg, LivenessAnalysis* liveness,
...@@ -313,19 +316,21 @@ PhiAnalysis::PhiAnalysis(const SourceInfo::ArgNames& arg_names, CFG* cfg, Livene ...@@ -313,19 +316,21 @@ PhiAnalysis::PhiAnalysis(const SourceInfo::ArgNames& arg_names, CFG* cfg, Livene
for (CFGBlock* block : cfg->blocks) { for (CFGBlock* block : cfg->blocks) {
RequiredSet required; RequiredSet required;
if (block->predecessors.size() < 2)
continue;
const RequiredSet& defined = definedness.getDefinedNamesAt(block); if (block->predecessors.size() > 1) {
if (defined.size()) for (CFGBlock* pred : block->predecessors) {
assert(block->predecessors.size()); const RequiredSet& defined = definedness.getDefinedNamesAtEnd(pred);
for (const auto& s : defined) { for (const auto& s : defined) {
if (liveness->isLiveAtEnd(s, block->predecessors[0])) { if (required.count(s) == 0 && liveness->isLiveAtEnd(s, pred)) {
// printf("%d-%d %s\n", pred->idx, block->idx, s.c_str());
required.insert(s); required.insert(s);
} }
} }
}
}
required_phis.insert(make_pair(block, required)); required_phis.insert(make_pair(block, std::move(required)));
} }
} }
...@@ -336,8 +341,8 @@ const PhiAnalysis::RequiredSet& PhiAnalysis::getAllRequiredAfter(CFGBlock* block ...@@ -336,8 +341,8 @@ const PhiAnalysis::RequiredSet& PhiAnalysis::getAllRequiredAfter(CFGBlock* block
return required_phis[block->successors[0]]; return required_phis[block->successors[0]];
} }
const PhiAnalysis::RequiredSet& PhiAnalysis::getAllDefinedAt(CFGBlock* block) { const PhiAnalysis::RequiredSet& PhiAnalysis::getAllRequiredFor(CFGBlock* block) {
return definedness.getDefinedNamesAt(block); return required_phis[block];
} }
bool PhiAnalysis::isRequired(const std::string& name, CFGBlock* block) { bool PhiAnalysis::isRequired(const std::string& name, CFGBlock* block) {
...@@ -358,11 +363,16 @@ bool PhiAnalysis::isRequiredAfter(const std::string& name, CFGBlock* block) { ...@@ -358,11 +363,16 @@ bool PhiAnalysis::isRequiredAfter(const std::string& name, CFGBlock* block) {
bool PhiAnalysis::isPotentiallyUndefinedAfter(const std::string& name, CFGBlock* block) { bool PhiAnalysis::isPotentiallyUndefinedAfter(const std::string& name, CFGBlock* block) {
assert(!startswith(name, "!")); assert(!startswith(name, "!"));
assert(block->successors.size() > 0);
DefinednessAnalysis::DefinitionLevel dlevel = definedness.isDefinedAt(name, block->successors[0]);
ASSERT(dlevel != DefinednessAnalysis::Undefined, "%s %d", name.c_str(), block->idx);
return dlevel == DefinednessAnalysis::PotentiallyDefined; if (block->successors.size() != 1)
return false;
for (CFGBlock* pred : block->successors[0]->predecessors) {
DefinednessAnalysis::DefinitionLevel dlevel = definedness.isDefinedAtEnd(name, pred);
if (dlevel != DefinednessAnalysis::Defined)
return true;
}
return false;
} }
LivenessAnalysis* computeLivenessInfo(CFG*) { LivenessAnalysis* computeLivenessInfo(CFG*) {
......
...@@ -49,14 +49,14 @@ public: ...@@ -49,14 +49,14 @@ public:
private: private:
std::unordered_map<CFGBlock*, std::unordered_map<std::string, DefinitionLevel> > results; std::unordered_map<CFGBlock*, std::unordered_map<std::string, DefinitionLevel> > results;
std::unordered_map<CFGBlock*, const RequiredSet> defined; std::unordered_map<CFGBlock*, const RequiredSet> defined_at_end;
ScopeInfo* scope_info; ScopeInfo* scope_info;
public: public:
DefinednessAnalysis(const SourceInfo::ArgNames& args, CFG* cfg, ScopeInfo* scope_info); DefinednessAnalysis(const SourceInfo::ArgNames& args, CFG* cfg, ScopeInfo* scope_info);
DefinitionLevel isDefinedAt(const std::string& name, CFGBlock* block); DefinitionLevel isDefinedAtEnd(const std::string& name, CFGBlock* block);
const RequiredSet& getDefinedNamesAt(CFGBlock* block); const RequiredSet& getDefinedNamesAtEnd(CFGBlock* block);
}; };
class PhiAnalysis { class PhiAnalysis {
public: public:
...@@ -73,7 +73,7 @@ public: ...@@ -73,7 +73,7 @@ public:
bool isRequired(const std::string& name, CFGBlock* block); bool isRequired(const std::string& name, CFGBlock* block);
bool isRequiredAfter(const std::string& name, CFGBlock* block); bool isRequiredAfter(const std::string& name, CFGBlock* block);
const RequiredSet& getAllRequiredAfter(CFGBlock* block); const RequiredSet& getAllRequiredAfter(CFGBlock* block);
const RequiredSet& getAllDefinedAt(CFGBlock* block); const RequiredSet& getAllRequiredFor(CFGBlock* block);
bool isPotentiallyUndefinedAfter(const std::string& name, CFGBlock* block); bool isPotentiallyUndefinedAfter(const std::string& name, CFGBlock* block);
}; };
......
...@@ -61,6 +61,8 @@ public: ...@@ -61,6 +61,8 @@ public:
virtual bool takesClosure() { return false; } virtual bool takesClosure() { return false; }
bool passesThroughClosure() override { return false; }
virtual bool refersToGlobal(const std::string& name) { virtual bool refersToGlobal(const std::string& name) {
if (isCompilerCreatedName(name)) if (isCompilerCreatedName(name))
return false; return false;
...@@ -88,6 +90,7 @@ struct ScopingAnalysis::ScopeNameUsage { ...@@ -88,6 +90,7 @@ struct ScopingAnalysis::ScopeNameUsage {
// Properties determined by looking at other scopes as well: // Properties determined by looking at other scopes as well:
StrSet referenced_from_nested; StrSet referenced_from_nested;
StrSet got_from_closure; StrSet got_from_closure;
StrSet passthrough_accesses; // what names a child scope accesses a name from a parent scope
ScopeNameUsage(AST* node, ScopeNameUsage* parent) : node(node), parent(parent) { ScopeNameUsage(AST* node, ScopeNameUsage* parent) : node(node), parent(parent) {
if (node->type == AST_TYPE::ClassDef) { if (node->type == AST_TYPE::ClassDef) {
...@@ -123,7 +126,9 @@ public: ...@@ -123,7 +126,9 @@ public:
virtual bool createsClosure() { return usage->referenced_from_nested.size() > 0; } virtual bool createsClosure() { return usage->referenced_from_nested.size() > 0; }
virtual bool takesClosure() { return usage->got_from_closure.size() > 0; } virtual bool takesClosure() { return usage->got_from_closure.size() > 0 || usage->passthrough_accesses.size() > 0; }
bool passesThroughClosure() override { return usage->passthrough_accesses.size() > 0 && !createsClosure(); }
virtual bool refersToGlobal(const std::string& name) { virtual bool refersToGlobal(const std::string& name) {
// HAX // HAX
...@@ -235,6 +240,13 @@ public: ...@@ -235,6 +240,13 @@ public:
virtual bool visit_jump(AST_Jump* node) { return false; } virtual bool visit_jump(AST_Jump* node) { return false; }
virtual bool visit_delete(AST_Delete* node) {
for (auto t : node->targets) {
RELEASE_ASSERT(t->type != AST_TYPE::Name, "");
}
return false;
}
virtual bool visit_global(AST_Global* node) { virtual bool visit_global(AST_Global* node) {
for (int i = 0; i < node->names.size(); i++) { for (int i = 0; i < node->names.size(); i++) {
const std::string& name = node->names[i]; const std::string& name = node->names[i];
...@@ -364,6 +376,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) { ...@@ -364,6 +376,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
ScopeNameUsage* parent = usage->parent; ScopeNameUsage* parent = usage->parent;
while (parent) { while (parent) {
if (parent->node->type == AST_TYPE::ClassDef) { if (parent->node->type == AST_TYPE::ClassDef) {
intermediate_parents.push_back(parent);
parent = parent->parent; parent = parent->parent;
} else if (parent->forced_globals.count(name)) { } else if (parent->forced_globals.count(name)) {
break; break;
...@@ -372,8 +385,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) { ...@@ -372,8 +385,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
parent->referenced_from_nested.insert(name); parent->referenced_from_nested.insert(name);
for (ScopeNameUsage* iparent : intermediate_parents) { for (ScopeNameUsage* iparent : intermediate_parents) {
iparent->referenced_from_nested.insert(name); iparent->passthrough_accesses.insert(name);
iparent->got_from_closure.insert(name);
} }
break; break;
......
...@@ -30,6 +30,7 @@ public: ...@@ -30,6 +30,7 @@ public:
virtual bool createsClosure() = 0; virtual bool createsClosure() = 0;
virtual bool takesClosure() = 0; virtual bool takesClosure() = 0;
virtual bool passesThroughClosure() = 0;
virtual bool takesGenerator() { return isGeneratorValue; } virtual bool takesGenerator() { return isGeneratorValue; }
virtual void setTakesGenerator(bool b = true) { isGeneratorValue = b; } virtual void setTakesGenerator(bool b = true) { isGeneratorValue = b; }
......
...@@ -359,6 +359,8 @@ private: ...@@ -359,6 +359,8 @@ private:
return BOOL; return BOOL;
case AST_LangPrimitive::LANDINGPAD: case AST_LangPrimitive::LANDINGPAD:
return UNKNOWN; return UNKNOWN;
case AST_LangPrimitive::LOCALS:
return DICT;
default: default:
RELEASE_ASSERT(0, "%d", node->opcode); RELEASE_ASSERT(0, "%d", node->opcode);
} }
...@@ -384,6 +386,10 @@ private: ...@@ -384,6 +386,10 @@ private:
return UNKNOWN; return UNKNOWN;
} }
if (scope_info->refersToClosure(node->id)) {
return UNKNOWN;
}
CompilerType*& t = sym_table[node->id]; CompilerType*& t = sym_table[node->id];
if (t == NULL) { if (t == NULL) {
// if (VERBOSITY() >= 2) { // if (VERBOSITY() >= 2) {
......
This diff is collapsed.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <vector> #include <vector>
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "core/ast.h"
#include "core/types.h" #include "core/types.h"
namespace pyston { namespace pyston {
...@@ -47,6 +48,12 @@ public: ...@@ -47,6 +48,12 @@ public:
typedef std::unordered_map<CompilerVariable*, CompilerVariable*> DupCache; typedef std::unordered_map<CompilerVariable*, CompilerVariable*> DupCache;
enum BinExpType {
AugBinOp,
BinOp,
Compare,
};
template <class V> class _ValuedCompilerType : public CompilerType { template <class V> class _ValuedCompilerType : public CompilerType {
public: public:
typedef ValuedCompilerVariable<V> VAR; typedef ValuedCompilerVariable<V> VAR;
...@@ -63,11 +70,11 @@ public: ...@@ -63,11 +70,11 @@ public:
printf("getBoxType not defined for %s\n", debugName().c_str()); printf("getBoxType not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual void drop(IREmitter& emmitter, VAR* value) { virtual void drop(IREmitter& emmitter, VAR* var) {
printf("drop not defined for %s\n", debugName().c_str()); printf("drop not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual void grab(IREmitter& emmitter, VAR* value) { virtual void grab(IREmitter& emmitter, VAR* var) {
printf("grab not defined for %s\n", debugName().c_str()); printf("grab not defined for %s\n", debugName().c_str());
abort(); abort();
} }
...@@ -75,53 +82,58 @@ public: ...@@ -75,53 +82,58 @@ public:
printf("canConvertTo not defined for %s\n", debugName().c_str()); printf("canConvertTo not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* value, ConcreteCompilerType* other_type) { virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) {
printf("makeConverted not defined for %s\n", debugName().c_str()); printf("makeConverted not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, VAR* value) { virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("nonzero not defined for %s\n", debugName().c_str()); printf("nonzero not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, VAR* value, const std::string* attr, virtual CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, VAR* var, const std::string* attr,
bool cls_only) { bool cls_only) {
printf("getattr not defined for %s\n", debugName().c_str()); printf("getattr not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual void setattr(IREmitter& emitter, const OpInfo& info, VAR* value, const std::string* attr, virtual void setattr(IREmitter& emitter, const OpInfo& info, VAR* var, const std::string* attr,
CompilerVariable* v) { CompilerVariable* v) {
printf("setattr not defined for %s\n", debugName().c_str()); printf("setattr not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, VAR* value, const std::string* attr, virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, VAR* var, const std::string* attr,
bool clsonly, struct ArgPassSpec argspec, bool clsonly, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) { const std::vector<const std::string*>* keyword_names) {
printf("callattr not defined for %s\n", debugName().c_str()); printf("callattr not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, VAR* value, struct ArgPassSpec argspec, virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, VAR* var, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) { const std::vector<const std::string*>* keyword_names) {
printf("call not defined for %s\n", debugName().c_str()); printf("call not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual void print(IREmitter& emitter, const OpInfo& info, VAR* value) { virtual void print(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("print not defined for %s\n", debugName().c_str()); printf("print not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* value) { virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("len not defined for %s\n", debugName().c_str()); printf("len not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* value, CompilerVariable* v) { virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* v) {
// Can almost do this, except for error messages + types: // Can almost do this, except for error messages + types:
// static const std::string attr("__getitem__"); // static const std::string attr("__getitem__");
// return callattr(emitter, info, value, &attr, true, ArgPassSpec(1, 0, 0, 0), {v}, NULL); // return callattr(emitter, info, var, &attr, true, ArgPassSpec(1, 0, 0, 0), {v}, NULL);
printf("getitem not defined for %s\n", debugName().c_str()); printf("getitem not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual llvm::Value* makeClassCheck(IREmitter& emitter, VAR* value, BoxedClass* c) { virtual CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs,
AST_TYPE::AST_TYPE op_type, BinExpType exp_type) {
printf("binexp not defined for %s\n", debugName().c_str());
abort();
}
virtual llvm::Value* makeClassCheck(IREmitter& emitter, VAR* var, BoxedClass* c) {
printf("makeClassCheck not defined for %s\n", debugName().c_str()); printf("makeClassCheck not defined for %s\n", debugName().c_str());
abort(); abort();
} }
...@@ -189,7 +201,7 @@ public: ...@@ -189,7 +201,7 @@ public:
} }
} }
void decvref(IREmitter& emitter) { void decvref(IREmitter& emitter) {
assert(vrefs > 0 && vrefs < (1 << 20)); ASSERT(vrefs > 0 && vrefs < (1 << 20), "%d", vrefs);
// ASSERT(vrefs, "%s", getType()->debugName().c_str()); // ASSERT(vrefs, "%s", getType()->debugName().c_str());
vrefs--; vrefs--;
if (vrefs == 0) { if (vrefs == 0) {
...@@ -229,6 +241,8 @@ public: ...@@ -229,6 +241,8 @@ public:
virtual void print(IREmitter& emitter, const OpInfo& info) = 0; virtual void print(IREmitter& emitter, const OpInfo& info) = 0;
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) = 0; virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable*) = 0; virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable*) = 0;
virtual CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, CompilerVariable* rhs,
AST_TYPE::AST_TYPE op_type, BinExpType exp_type) = 0;
}; };
template <class V> class ValuedCompilerVariable : public CompilerVariable { template <class V> class ValuedCompilerVariable : public CompilerVariable {
...@@ -299,6 +313,12 @@ public: ...@@ -299,6 +313,12 @@ public:
CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable* slice) override { CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable* slice) override {
return type->getitem(emitter, info, this, slice); return type->getitem(emitter, info, this, slice);
} }
CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, CompilerVariable* rhs, AST_TYPE::AST_TYPE op_type,
BinExpType exp_type) override {
return type->binexp(emitter, info, this, rhs, op_type, exp_type);
}
llvm::Value* makeClassCheck(IREmitter& emitter, BoxedClass* cls) override { llvm::Value* makeClassCheck(IREmitter& emitter, BoxedClass* cls) override {
return type->makeClassCheck(emitter, this, cls); return type->makeClassCheck(emitter, this, cls);
} }
......
...@@ -337,13 +337,18 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -337,13 +337,18 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
arg_num++; arg_num++;
if (arg_num < 3) { if (arg_num < 3) {
from_arg = func_args[arg_num]; from_arg = func_args[arg_num];
assert(from_arg->getType() == p.second->llvmType());
} else { } else {
ASSERT(func_args.size() == 4, "%ld", func_args.size()); ASSERT(func_args.size() == 4, "%ld", func_args.size());
llvm::Value* ptr = entry_emitter->getBuilder()->CreateConstGEP1_32(func_args[3], arg_num - 3); llvm::Value* ptr = entry_emitter->getBuilder()->CreateConstGEP1_32(func_args[3], arg_num - 3);
if (p.second == INT) { if (p.second == INT) {
ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, g.i64->getPointerTo()); ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, g.i64->getPointerTo());
} else if (p.second == BOOL) {
ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, g.i1->getPointerTo());
} else if (p.second == FLOAT) { } else if (p.second == FLOAT) {
ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, g.double_->getPointerTo()); ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, g.double_->getPointerTo());
} else {
assert(p.second->llvmType() == g.llvm_value_type_ptr);
} }
from_arg = entry_emitter->getBuilder()->CreateLoad(ptr); from_arg = entry_emitter->getBuilder()->CreateLoad(ptr);
assert(from_arg->getType() == p.second->llvmType()); assert(from_arg->getType() == p.second->llvmType());
...@@ -599,12 +604,8 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -599,12 +604,8 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
into_hax.insert(b2); into_hax.insert(b2);
} }
const PhiAnalysis::RequiredSet& names = source->phis->getAllDefinedAt(block); const PhiAnalysis::RequiredSet& names = source->phis->getAllRequiredFor(block);
for (const auto& s : names) { for (const auto& s : names) {
// TODO the list from getAllDefinedAt should come filtered:
if (!source->liveness->isLiveAtEnd(s, block->predecessors[0]))
continue;
// printf("adding guessed phi for %s\n", s.c_str()); // printf("adding guessed phi for %s\n", s.c_str());
ConcreteCompilerType* type = types->getTypeAtBlockStart(s, block); ConcreteCompilerType* type = types->getTypeAtBlockStart(s, block);
llvm::PHINode* phi = emitter->getBuilder()->CreatePHI(type->llvmType(), block->predecessors.size(), s); llvm::PHINode* phi = emitter->getBuilder()->CreatePHI(type->llvmType(), block->predecessors.size(), s);
......
This diff is collapsed.
...@@ -102,6 +102,12 @@ Val fetch(llvm::Value* v, const llvm::DataLayout& dl, const SymMap& symbols) { ...@@ -102,6 +102,12 @@ Val fetch(llvm::Value* v, const llvm::DataLayout& dl, const SymMap& symbols) {
case llvm::Value::ConstantExprVal: { case llvm::Value::ConstantExprVal: {
llvm::ConstantExpr* ce = llvm::cast<llvm::ConstantExpr>(v); llvm::ConstantExpr* ce = llvm::cast<llvm::ConstantExpr>(v);
if (ce->isCast()) { if (ce->isCast()) {
if (ce->getOpcode() == llvm::Instruction::IntToPtr && ce->getOperand(0)->getType() == g.i1) {
// inttoptr is specified to zero-extend
Val o = fetch(ce->getOperand(0), dl, symbols);
return o.n & 0x1;
}
assert(width(ce->getOperand(0), dl) == 8 && width(ce, dl) == 8); assert(width(ce->getOperand(0), dl) == 8 && width(ce, dl) == 8);
Val o = fetch(ce->getOperand(0), dl, symbols); Val o = fetch(ce->getOperand(0), dl, symbols);
...@@ -283,7 +289,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -283,7 +289,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
int arg_num = -1; int arg_num = -1;
int closure_indicator = closure ? 1 : 0; int closure_indicator = closure ? 1 : 0;
int generator_indicator = generator ? 1 : 0; int generator_indicator = generator ? 1 : 0;
int argOffset = closure_indicator + generator_indicator; int arg_offset = closure_indicator + generator_indicator;
for (llvm::Argument& arg : f->args()) { for (llvm::Argument& arg : f->args()) {
arg_num++; arg_num++;
...@@ -291,15 +297,15 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -291,15 +297,15 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(closure))); symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(closure)));
else if ((arg_num == 0 || (arg_num == 1 && closure)) && generator) else if ((arg_num == 0 || (arg_num == 1 && closure)) && generator)
symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(generator))); symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(generator)));
else if (arg_num == 0 + argOffset) else if (arg_num == 0 + arg_offset)
symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg1))); symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg1)));
else if (arg_num == 1 + argOffset) else if (arg_num == 1 + arg_offset)
symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg2))); symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg2)));
else if (arg_num == 2 + argOffset) else if (arg_num == 2 + arg_offset)
symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg3))); symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg3)));
else { else {
assert(arg_num == 3 + argOffset); assert(arg_num == 3 + arg_offset);
assert(f->getArgumentList().size() == 4 + argOffset); assert(f->getArgumentList().size() == 4 + arg_offset);
assert(f->getArgumentList().back().getType() == g.llvm_value_type_ptr->getPointerTo()); assert(f->getArgumentList().back().getType() == g.llvm_value_type_ptr->getPointerTo());
symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val((int64_t)args))); symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val((int64_t)args)));
// printf("loading %%4 with %p\n", (void*)args); // printf("loading %%4 with %p\n", (void*)args);
...@@ -310,6 +316,14 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -310,6 +316,14 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
llvm::BasicBlock* prevblock = NULL; llvm::BasicBlock* prevblock = NULL;
llvm::BasicBlock* curblock = &f->getEntryBlock(); llvm::BasicBlock* curblock = &f->getEntryBlock();
// The symbol table at the end of the previous BB
// This is important for the following case:
// %a = phi [0, %l1], [1, %l2]
// %b = phi [0, %l1], [%a, %l2]
// The reference to %a in the definition of %b resolves to the *previous* value of %a,
// not the value of %a that we just set in the phi.
SymMap prev_symbols;
struct { struct {
Box* exc_obj; Box* exc_obj;
int64_t exc_selector; int64_t exc_selector;
...@@ -521,8 +535,12 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -521,8 +535,12 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
SET(fetch(bc->getOperand(0), dl, symbols)); SET(fetch(bc->getOperand(0), dl, symbols));
continue; continue;
} else if (llvm::IntToPtrInst* bc = llvm::dyn_cast<llvm::IntToPtrInst>(inst)) { } else if (llvm::IntToPtrInst* bc = llvm::dyn_cast<llvm::IntToPtrInst>(inst)) {
if (bc->getOperand(0)->getType() == g.i1) {
SET(fetch(bc->getOperand(0), dl, symbols).n & 0xff);
} else {
assert(width(bc->getOperand(0), dl) == 8); assert(width(bc->getOperand(0), dl) == 8);
SET(fetch(bc->getOperand(0), dl, symbols)); SET(fetch(bc->getOperand(0), dl, symbols));
}
continue; continue;
//} else if (llvm::CallInst* ci = llvm::dyn_cast<llvm::CallInst>(inst)) { //} else if (llvm::CallInst* ci = llvm::dyn_cast<llvm::CallInst>(inst)) {
} else if (llvm::isa<llvm::CallInst>(inst) || llvm::isa<llvm::InvokeInst>(inst)) { } else if (llvm::isa<llvm::CallInst>(inst) || llvm::isa<llvm::InvokeInst>(inst)) {
...@@ -615,14 +633,18 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -615,14 +633,18 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
r = reinterpret_cast<int64_t (*)(int64_t, double, double)>(f)(args[0].n, args[1].d, r = reinterpret_cast<int64_t (*)(int64_t, double, double)>(f)(args[0].n, args[1].d,
args[2].d); args[2].d);
break; break;
case 0b100000: case 0b100000: // 32
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t)>(f)( r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t)>(f)(
args[0].n, args[1].n, args[2].n, args[3].n); args[0].n, args[1].n, args[2].n, args[3].n);
break; break;
case 0b100001: case 0b100001: // 33
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, double)>(f)( r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, double)>(f)(
args[0].n, args[1].n, args[2].n, args[3].d); args[0].n, args[1].n, args[2].n, args[3].d);
break; break;
case 0b100010: // 34
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, double, int64_t)>(f)(
args[0].n, args[1].n, args[2].d, args[3].n);
break;
case 0b100110: case 0b100110:
r = reinterpret_cast<int64_t (*)(int64_t, double, double, int64_t)>(f)( r = reinterpret_cast<int64_t (*)(int64_t, double, double, int64_t)>(f)(
args[0].n, args[1].d, args[2].d, args[3].n); args[0].n, args[1].d, args[2].d, args[3].n);
...@@ -631,15 +653,15 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -631,15 +653,15 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
r = reinterpret_cast<int64_t (*)(double, int, double, int64_t)>(f)(args[0].d, args[1].n, r = reinterpret_cast<int64_t (*)(double, int, double, int64_t)>(f)(args[0].d, args[1].n,
args[2].d, args[3].n); args[2].d, args[3].n);
break; break;
case 0b1000000: case 0b1000000: // 64
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t)>(f)( r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t)>(f)(
args[0].n, args[1].n, args[2].n, args[3].n, args[4].n); args[0].n, args[1].n, args[2].n, args[3].n, args[4].n);
break; break;
case 0b10000000: case 0b10000000: // 128
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t)>(f)( r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t)>(f)(
args[0].n, args[1].n, args[2].n, args[3].n, args[4].n, args[5].n); args[0].n, args[1].n, args[2].n, args[3].n, args[4].n, args[5].n);
break; break;
case 0b100000000: case 0b100000000: // 256
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t,
int64_t)>(f)(args[0].n, args[1].n, args[2].n, args[3].n, int64_t)>(f)(args[0].n, args[1].n, args[2].n, args[3].n,
args[4].n, args[5].n, args[6].n); args[4].n, args[5].n, args[6].n);
...@@ -667,6 +689,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -667,6 +689,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
if (invoke != nullptr) { if (invoke != nullptr) {
prevblock = curblock; prevblock = curblock;
curblock = invoke->getNormalDest(); curblock = invoke->getNormalDest();
prev_symbols = symbols;
} }
} catch (Box* e) { } catch (Box* e) {
if (VERBOSITY("interpreter") >= 2) { if (VERBOSITY("interpreter") >= 2) {
...@@ -678,6 +701,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -678,6 +701,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
prevblock = curblock; prevblock = curblock;
curblock = invoke->getUnwindDest(); curblock = invoke->getUnwindDest();
prev_symbols = symbols;
landingpad_value.exc_obj = e; landingpad_value.exc_obj = e;
landingpad_value.exc_selector landingpad_value.exc_selector
...@@ -700,7 +724,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -700,7 +724,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
continue; continue;
} else if (llvm::PHINode* phi = llvm::dyn_cast<llvm::PHINode>(inst)) { } else if (llvm::PHINode* phi = llvm::dyn_cast<llvm::PHINode>(inst)) {
assert(prevblock); assert(prevblock);
SET(fetch(phi->getIncomingValueForBlock(prevblock), dl, symbols)); SET(fetch(phi->getIncomingValueForBlock(prevblock), dl, prev_symbols));
continue; continue;
} else if (llvm::BranchInst* br = llvm::dyn_cast<llvm::BranchInst>(inst)) { } else if (llvm::BranchInst* br = llvm::dyn_cast<llvm::BranchInst>(inst)) {
prevblock = curblock; prevblock = curblock;
...@@ -714,6 +738,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato ...@@ -714,6 +738,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
} else { } else {
curblock = br->getSuccessor(0); curblock = br->getSuccessor(0);
} }
prev_symbols = symbols;
// if (VERBOSITY()) { // if (VERBOSITY()) {
// printf("jumped to %s\n", curblock->getName().data()); // printf("jumped to %s\n", curblock->getName().data());
//} //}
......
...@@ -881,7 +881,7 @@ AST_Module* parse(const char* fn) { ...@@ -881,7 +881,7 @@ AST_Module* parse(const char* fn) {
#define MAGIC_STRING "a\nch" #define MAGIC_STRING "a\nch"
#define MAGIC_STRING_LENGTH 4 #define MAGIC_STRING_LENGTH 4
#define LENGTH_SUFFIX_LENGTH 4 #define CHECKSUM_LENGTH 4
static void _reparse(const char* fn, const std::string& cache_fn) { static void _reparse(const char* fn, const std::string& cache_fn) {
FILE* parser = popen(getParserCommandLine(fn).c_str(), "r"); FILE* parser = popen(getParserCommandLine(fn).c_str(), "r");
...@@ -890,7 +890,14 @@ static void _reparse(const char* fn, const std::string& cache_fn) { ...@@ -890,7 +890,14 @@ static void _reparse(const char* fn, const std::string& cache_fn) {
fwrite(MAGIC_STRING, 1, MAGIC_STRING_LENGTH, cache_fp); fwrite(MAGIC_STRING, 1, MAGIC_STRING_LENGTH, cache_fp);
int bytes_written = 0; int checksum_start = ftell(cache_fp);
int bytes_written = -1;
// Currently just use the length as the checksum
static_assert(sizeof(bytes_written) >= CHECKSUM_LENGTH, "");
fwrite(&bytes_written, 1, CHECKSUM_LENGTH, cache_fp);
bytes_written = 0;
char buf[80]; char buf[80];
while (true) { while (true) {
int nread = fread(buf, 1, 80, parser); int nread = fread(buf, 1, 80, parser);
...@@ -900,13 +907,12 @@ static void _reparse(const char* fn, const std::string& cache_fn) { ...@@ -900,13 +907,12 @@ static void _reparse(const char* fn, const std::string& cache_fn) {
fwrite(buf, 1, nread, cache_fp); fwrite(buf, 1, nread, cache_fp);
} }
// Ideally this should be a full checksum rather than just a length.
// And maybe it should be put at the beginning?
static_assert(sizeof(bytes_written) >= LENGTH_SUFFIX_LENGTH, "");
fwrite(&bytes_written, 1, LENGTH_SUFFIX_LENGTH, cache_fp);
int code = pclose(parser); int code = pclose(parser);
assert(code == 0); assert(code == 0);
fseek(cache_fp, checksum_start, SEEK_SET);
fwrite(&bytes_written, 1, CHECKSUM_LENGTH, cache_fp);
fclose(cache_fp); fclose(cache_fp);
} }
...@@ -940,20 +946,25 @@ AST_Module* caching_parse(const char* fn) { ...@@ -940,20 +946,25 @@ AST_Module* caching_parse(const char* fn) {
char buf[MAGIC_STRING_LENGTH]; char buf[MAGIC_STRING_LENGTH];
int read = fread(buf, 1, MAGIC_STRING_LENGTH, fp); int read = fread(buf, 1, MAGIC_STRING_LENGTH, fp);
if (read != MAGIC_STRING_LENGTH || strncmp(buf, MAGIC_STRING, MAGIC_STRING_LENGTH) != 0) { if (read != MAGIC_STRING_LENGTH || strncmp(buf, MAGIC_STRING, MAGIC_STRING_LENGTH) != 0) {
if (VERBOSITY()) {
printf("Warning: corrupt or non-Pyston .pyc file found; ignoring\n");
}
good = false; good = false;
} }
} }
if (good) { if (good) {
int length = 0; int length = 0;
fseek(fp, -LENGTH_SUFFIX_LENGTH, SEEK_END);
static_assert(sizeof(length) >= LENGTH_SUFFIX_LENGTH, "");
int read = fread(&length, 1, LENGTH_SUFFIX_LENGTH, fp);
fseek(fp, MAGIC_STRING_LENGTH, SEEK_SET); fseek(fp, MAGIC_STRING_LENGTH, SEEK_SET);
static_assert(sizeof(length) >= CHECKSUM_LENGTH, "");
int read = fread(&length, 1, CHECKSUM_LENGTH, fp);
int expected_length = MAGIC_STRING_LENGTH + LENGTH_SUFFIX_LENGTH + length; int expected_total_length = MAGIC_STRING_LENGTH + CHECKSUM_LENGTH + length;
if (read != LENGTH_SUFFIX_LENGTH || expected_length != cache_stat.st_size) { if (read != CHECKSUM_LENGTH || expected_total_length != cache_stat.st_size) {
if (VERBOSITY()) {
printf("Warning: truncated .pyc file found; ignoring\n");
}
good = false; good = false;
} }
} }
...@@ -974,7 +985,7 @@ AST_Module* caching_parse(const char* fn) { ...@@ -974,7 +985,7 @@ AST_Module* caching_parse(const char* fn) {
BufferedReader* reader = new BufferedReader(fp); BufferedReader* reader = new BufferedReader(fp);
AST* rtn = readASTMisc(reader); AST* rtn = readASTMisc(reader);
reader->fill(); reader->fill();
assert(reader->bytesBuffered() == LENGTH_SUFFIX_LENGTH); assert(reader->bytesBuffered() == 0);
delete reader; delete reader;
assert(rtn->type == AST_TYPE::Module); assert(rtn->type == AST_TYPE::Module);
......
...@@ -42,8 +42,6 @@ ...@@ -42,8 +42,6 @@
extern "C" void* __cxa_begin_catch(void*); extern "C" void* __cxa_begin_catch(void*);
extern "C" void __cxa_end_catch(); extern "C" void __cxa_end_catch();
extern "C" void* __cxa_allocate_exception(size_t);
extern "C" void __cxa_throw(void*, void*, void (*)(void*));
namespace pyston { namespace pyston {
...@@ -135,9 +133,11 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -135,9 +133,11 @@ void initGlobalFuncs(GlobalState& g) {
g.llvm_str_type_ptr = lookupFunction("boxStringPtr")->arg_begin()->getType(); g.llvm_str_type_ptr = lookupFunction("boxStringPtr")->arg_begin()->getType();
auto vector_type = g.stdlib_module->getTypeByName("class.std::vector"); // The LLVM vector type for the arguments that we pass to runtimeCall and related functions.
assert(vector_type); // It will be a pointer to a type named something like class.std::vector or
g.vector_ptr = vector_type->getPointerTo(); // class.std::vector.##. We can figure out exactly what it is by looking at the last
// argument of runtimeCall.
g.vector_ptr = (--lookupFunction("runtimeCall")->getArgumentList().end())->getType();
g.llvm_closure_type_ptr = g.stdlib_module->getTypeByName("class.pyston::BoxedClosure")->getPointerTo(); g.llvm_closure_type_ptr = g.stdlib_module->getTypeByName("class.pyston::BoxedClosure")->getPointerTo();
assert(g.llvm_closure_type_ptr); assert(g.llvm_closure_type_ptr);
...@@ -187,6 +187,7 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -187,6 +187,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(getclsattr); GET(getclsattr);
GET(unaryop); GET(unaryop);
GET(import); GET(import);
GET(importFrom);
GET(repr); GET(repr);
GET(isinstance); GET(isinstance);
GET(yield); GET(yield);
...@@ -225,8 +226,8 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -225,8 +226,8 @@ void initGlobalFuncs(GlobalState& g) {
GET(__cxa_begin_catch); GET(__cxa_begin_catch);
g.funcs.__cxa_end_catch = addFunc((void*)__cxa_end_catch, g.void_); g.funcs.__cxa_end_catch = addFunc((void*)__cxa_end_catch, g.void_);
g.funcs.__cxa_allocate_exception = addFunc((void*)__cxa_allocate_exception, g.i8_ptr, g.i64); GET(raise0);
g.funcs.__cxa_throw = addFunc((void*)__cxa_throw, g.void_, g.i8_ptr, g.i8_ptr, g.i8_ptr); GET(raise1);
g.funcs.div_i64_i64 = getFunc((void*)div_i64_i64, "div_i64_i64"); g.funcs.div_i64_i64 = getFunc((void*)div_i64_i64, "div_i64_i64");
g.funcs.mod_i64_i64 = getFunc((void*)mod_i64_i64, "mod_i64_i64"); g.funcs.mod_i64_i64 = getFunc((void*)mod_i64_i64, "mod_i64_i64");
......
...@@ -34,7 +34,7 @@ struct GlobalFuncs { ...@@ -34,7 +34,7 @@ struct GlobalFuncs {
*boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice,
*createUserClass, *createClosure, *createGenerator, *insideGenerator; *createUserClass, *createClosure, *createGenerator, *insideGenerator;
llvm::Value* getattr, *setattr, *print, *nonzero, *binop, *compare, *augbinop, *unboxedLen, *getitem, *getclsattr, llvm::Value* getattr, *setattr, *print, *nonzero, *binop, *compare, *augbinop, *unboxedLen, *getitem, *getclsattr,
*yield, *getGlobal, *setitem, *delitem, *unaryop, *import, *repr, *isinstance; *getGlobal, *setitem, *delitem, *unaryop, *import, *importFrom, *repr, *isinstance, *yield;
llvm::Value* checkUnpackingLength, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError, llvm::Value* checkUnpackingLength, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError,
*assertNameDefined, *assertFail; *assertNameDefined, *assertFail;
...@@ -43,7 +43,8 @@ struct GlobalFuncs { ...@@ -43,7 +43,8 @@ struct GlobalFuncs {
llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr; llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr;
llvm::Value* reoptCompiledFunc, *compilePartialFunc; llvm::Value* reoptCompiledFunc, *compilePartialFunc;
llvm::Value* __cxa_begin_catch, *__cxa_end_catch, *__cxa_allocate_exception, *__cxa_throw; llvm::Value* __cxa_begin_catch, *__cxa_end_catch;
llvm::Value* raise0, *raise1;
llvm::Value* div_i64_i64, *mod_i64_i64, *pow_i64_i64; llvm::Value* div_i64_i64, *mod_i64_i64, *pow_i64_i64;
llvm::Value* div_float_float, *mod_float_float, *pow_float_float; llvm::Value* div_float_float, *mod_float_float, *pow_float_float;
......
...@@ -1314,6 +1314,9 @@ bool PrintVisitor::visit_langprimitive(AST_LangPrimitive* node) { ...@@ -1314,6 +1314,9 @@ bool PrintVisitor::visit_langprimitive(AST_LangPrimitive* node) {
case AST_LangPrimitive::LANDINGPAD: case AST_LangPrimitive::LANDINGPAD:
printf("landingpad"); printf("landingpad");
break; break;
case AST_LangPrimitive::LOCALS:
printf("locals");
break;
default: default:
RELEASE_ASSERT(0, "%d", node->opcode); RELEASE_ASSERT(0, "%d", node->opcode);
} }
......
...@@ -879,6 +879,7 @@ public: ...@@ -879,6 +879,7 @@ public:
enum Opcodes { enum Opcodes {
ISINSTANCE, ISINSTANCE,
LANDINGPAD, LANDINGPAD,
LOCALS,
} opcode; } opcode;
std::vector<AST_expr*> args; std::vector<AST_expr*> args;
......
...@@ -379,6 +379,8 @@ private: ...@@ -379,6 +379,8 @@ private:
AST_expr* remapAttribute(AST_Attribute* node) { AST_expr* remapAttribute(AST_Attribute* node) {
AST_Attribute* rtn = new AST_Attribute(); AST_Attribute* rtn = new AST_Attribute();
rtn->col_offset = node->col_offset;
rtn->lineno = node->lineno;
rtn->ctx_type = node->ctx_type; rtn->ctx_type = node->ctx_type;
rtn->attr = node->attr; rtn->attr = node->attr;
rtn->value = remapExpr(node->value); rtn->value = remapExpr(node->value);
...@@ -483,6 +485,8 @@ private: ...@@ -483,6 +485,8 @@ private:
AST_expr* remapClsAttribute(AST_ClsAttribute* node) { AST_expr* remapClsAttribute(AST_ClsAttribute* node) {
AST_ClsAttribute* rtn = new AST_ClsAttribute(); AST_ClsAttribute* rtn = new AST_ClsAttribute();
rtn->col_offset = node->col_offset;
rtn->lineno = node->lineno;
rtn->attr = node->attr; rtn->attr = node->attr;
rtn->value = remapExpr(node->value); rtn->value = remapExpr(node->value);
return rtn; return rtn;
...@@ -622,28 +626,20 @@ private: ...@@ -622,28 +626,20 @@ private:
} }
AST_expr* remapLambda(AST_Lambda* node) { AST_expr* remapLambda(AST_Lambda* node) {
if (node->args->defaults.empty()) { // Remap in place: see note in visit_functiondef for why.
return node;
}
AST_Lambda* rtn = new AST_Lambda(); for (int i = 0; i < node->args->defaults.size(); i++) {
rtn->lineno = node->lineno; node->args->defaults[i] = remapExpr(node->args->defaults[i]);
rtn->col_offset = node->col_offset;
rtn->args = new AST_arguments();
rtn->args->args = node->args->args;
rtn->args->vararg = node->args->vararg;
rtn->args->kwarg = node->args->kwarg;
for (auto d : node->args->defaults) {
rtn->args->defaults.push_back(remapExpr(d));
} }
rtn->body = node->body; return node;
return rtn;
} }
AST_expr* remapLangPrimitive(AST_LangPrimitive* node) { AST_expr* remapLangPrimitive(AST_LangPrimitive* node) {
AST_LangPrimitive* rtn = new AST_LangPrimitive(node->opcode); AST_LangPrimitive* rtn = new AST_LangPrimitive(node->opcode);
rtn->col_offset = node->col_offset;
rtn->lineno = node->lineno;
for (AST_expr* arg : node->args) { for (AST_expr* arg : node->args) {
rtn->args.push_back(remapExpr(arg)); rtn->args.push_back(remapExpr(arg));
} }
...@@ -859,6 +855,8 @@ public: ...@@ -859,6 +855,8 @@ public:
AST_Invoke* invoke = new AST_Invoke(node); AST_Invoke* invoke = new AST_Invoke(node);
invoke->normal_dest = normal_dest; invoke->normal_dest = normal_dest;
invoke->exc_dest = exc_dest; invoke->exc_dest = exc_dest;
invoke->col_offset = node->col_offset;
invoke->lineno = node->lineno;
curblock->push_back(invoke); curblock->push_back(invoke);
curblock->connectTo(normal_dest); curblock->connectTo(normal_dest);
...@@ -878,36 +876,42 @@ public: ...@@ -878,36 +876,42 @@ public:
} }
virtual bool visit_classdef(AST_ClassDef* node) { virtual bool visit_classdef(AST_ClassDef* node) {
// Remap in place: see note in visit_functiondef for why.
// Decorators are evaluated before the defaults:
for (int i = 0; i < node->decorator_list.size(); i++) {
node->decorator_list[i] = remapExpr(node->decorator_list[i]);
}
for (int i = 0; i < node->bases.size(); i++) {
node->bases[i] = remapExpr(node->bases[i]);
}
push_back(node); push_back(node);
return true; return true;
} }
virtual bool visit_functiondef(AST_FunctionDef* node) { virtual bool visit_functiondef(AST_FunctionDef* node) {
if (node->args->defaults.size() == 0 && node->decorator_list.size() == 0) { // As much as I don't like it, for now we're remapping these in place.
push_back(node); // This is because we do certain analyses pre-remapping, and associate the
} else { // results with the node. We can either do some refactoring and have a way
AST_FunctionDef* remapped = new AST_FunctionDef(); // of associating the new node with the same results, or just do the remapping
// in-place.
remapped->name = node->name; // Doing it in-place seems ugly, but I can't think of anything it should break,
remapped->lineno = node->lineno; // so just do that for now.
remapped->col_offset = node->col_offset; // TODO If we remap these (functiondefs, lambdas, classdefs) in place, we should probably
remapped->args = new AST_arguments(); // remap everything in place?
remapped->body = node->body; // hmm shouldnt have to copy this
// Decorators are evaluated before the defaults: // Decorators are evaluated before the defaults:
for (auto d : node->decorator_list) { for (int i = 0; i < node->decorator_list.size(); i++) {
remapped->decorator_list.push_back(remapExpr(d)); node->decorator_list[i] = remapExpr(node->decorator_list[i]);
} }
remapped->args->args = node->args->args; for (int i = 0; i < node->args->defaults.size(); i++) {
remapped->args->vararg = node->args->vararg; node->args->defaults[i] = remapExpr(node->args->defaults[i]);
remapped->args->kwarg = node->args->kwarg;
for (auto d : node->args->defaults) {
remapped->args->defaults.push_back(remapExpr(d));
} }
push_back(remapped); push_back(node);
}
return true; return true;
} }
...@@ -1027,11 +1031,15 @@ public: ...@@ -1027,11 +1031,15 @@ public:
s_target->value = remapExpr(s->value); s_target->value = remapExpr(s->value);
s_target->slice = remapExpr(s->slice); s_target->slice = remapExpr(s->slice);
s_target->ctx_type = AST_TYPE::Store; s_target->ctx_type = AST_TYPE::Store;
s_target->col_offset = s->col_offset;
s_target->lineno = s->lineno;
remapped_target = s_target; remapped_target = s_target;
AST_Subscript* s_lhs = new AST_Subscript(); AST_Subscript* s_lhs = new AST_Subscript();
s_lhs->value = s_target->value; s_lhs->value = s_target->value;
s_lhs->slice = s_target->slice; s_lhs->slice = s_target->slice;
s_lhs->col_offset = s->col_offset;
s_lhs->lineno = s->lineno;
s_lhs->ctx_type = AST_TYPE::Load; s_lhs->ctx_type = AST_TYPE::Load;
remapped_lhs = remapExpr(s_lhs); remapped_lhs = remapExpr(s_lhs);
...@@ -1045,12 +1053,16 @@ public: ...@@ -1045,12 +1053,16 @@ public:
a_target->value = remapExpr(a->value); a_target->value = remapExpr(a->value);
a_target->attr = a->attr; a_target->attr = a->attr;
a_target->ctx_type = AST_TYPE::Store; a_target->ctx_type = AST_TYPE::Store;
a_target->col_offset = a->col_offset;
a_target->lineno = a->lineno;
remapped_target = a_target; remapped_target = a_target;
AST_Attribute* a_lhs = new AST_Attribute(); AST_Attribute* a_lhs = new AST_Attribute();
a_lhs->value = a_target->value; a_lhs->value = a_target->value;
a_lhs->attr = a->attr; a_lhs->attr = a->attr;
a_lhs->ctx_type = AST_TYPE::Load; a_lhs->ctx_type = AST_TYPE::Load;
a_lhs->col_offset = a->col_offset;
a_lhs->lineno = a->lineno;
remapped_lhs = remapExpr(a_lhs); remapped_lhs = remapExpr(a_lhs);
break; break;
...@@ -1063,6 +1075,8 @@ public: ...@@ -1063,6 +1075,8 @@ public:
binop->op_type = node->op_type; binop->op_type = node->op_type;
binop->left = remapped_lhs; binop->left = remapped_lhs;
binop->right = remapExpr(node->value); binop->right = remapExpr(node->value);
binop->col_offset = node->col_offset;
binop->lineno = node->lineno;
AST_stmt* assign = makeAssign(remapped_target, binop); AST_stmt* assign = makeAssign(remapped_target, binop);
push_back(assign); push_back(assign);
return true; return true;
...@@ -1109,6 +1123,7 @@ public: ...@@ -1109,6 +1123,7 @@ public:
int i = 0; int i = 0;
for (auto v : node->values) { for (auto v : node->values) {
AST_Print* remapped = new AST_Print(); AST_Print* remapped = new AST_Print();
remapped->col_offset = node->col_offset;
remapped->lineno = node->lineno; remapped->lineno = node->lineno;
// TODO not good to reuse 'dest' like this // TODO not good to reuse 'dest' like this
remapped->dest = dest; remapped->dest = dest;
...@@ -1128,6 +1143,8 @@ public: ...@@ -1128,6 +1143,8 @@ public:
assert(node->nl); assert(node->nl);
AST_Print* final = new AST_Print(); AST_Print* final = new AST_Print();
final->col_offset = node->col_offset;
final->lineno = node->lineno;
// TODO not good to reuse 'dest' like this // TODO not good to reuse 'dest' like this
final->dest = dest; final->dest = dest;
final->nl = node->nl; final->nl = node->nl;
...@@ -1417,6 +1434,9 @@ public: ...@@ -1417,6 +1434,9 @@ public:
bool visit_raise(AST_Raise* node) override { bool visit_raise(AST_Raise* node) override {
AST_Raise* remapped = new AST_Raise(); AST_Raise* remapped = new AST_Raise();
remapped->col_offset = node->col_offset;
remapped->lineno = node->lineno;
if (node->arg0) if (node->arg0)
remapped->arg0 = remapExpr(node->arg0); remapped->arg0 = remapExpr(node->arg0);
if (node->arg1) if (node->arg1)
...@@ -1425,6 +1445,9 @@ public: ...@@ -1425,6 +1445,9 @@ public:
remapped->arg2 = remapExpr(node->arg2); remapped->arg2 = remapExpr(node->arg2);
push_back(remapped); push_back(remapped);
if (!curblock)
return true;
curblock->push_back(new AST_Unreachable()); curblock->push_back(new AST_Unreachable());
curblock = NULL; curblock = NULL;
...@@ -1518,7 +1541,6 @@ public: ...@@ -1518,7 +1541,6 @@ public:
if (!caught_all) { if (!caught_all) {
AST_Raise* raise = new AST_Raise(); AST_Raise* raise = new AST_Raise();
raise->arg0 = exc_obj;
push_back(raise); push_back(raise);
curblock->push_back(new AST_Unreachable()); curblock->push_back(new AST_Unreachable());
curblock = NULL; curblock = NULL;
...@@ -1709,20 +1731,10 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) { ...@@ -1709,20 +1731,10 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) {
if (source->ast->type == AST_TYPE::ClassDef) { if (source->ast->type == AST_TYPE::ClassDef) {
ScopeInfo* scope_info = source->scoping->getScopeInfoForNode(source->ast); ScopeInfo* scope_info = source->scoping->getScopeInfoForNode(source->ast);
auto written_names = scope_info->getClassDefLocalNames(); AST_LangPrimitive* locals = new AST_LangPrimitive(AST_LangPrimitive::LOCALS);
AST_Dict* rtn_dict = new AST_Dict();
// Even if the user never explicitly wrote to __module__, there was an
// implicit write:
assert(written_names.count("__module__"));
for (auto s : written_names) {
rtn_dict->keys.push_back(new AST_Str(s));
rtn_dict->values.push_back(makeName(s, AST_TYPE::Load));
}
AST_Return* rtn = new AST_Return(); AST_Return* rtn = new AST_Return();
rtn->value = rtn_dict; rtn->value = locals;
visitor.push_back(rtn); visitor.push_back(rtn);
} else { } else {
// Put a fake "return" statement at the end of every function just to make sure they all have one; // Put a fake "return" statement at the end of every function just to make sure they all have one;
......
...@@ -42,6 +42,18 @@ void registerStaticRootObj(void* obj) { ...@@ -42,6 +42,18 @@ void registerStaticRootObj(void* obj) {
roots.push(obj); roots.push(obj);
} }
static std::unordered_set<StaticRootHandle*>* getRootHandles() {
static std::unordered_set<StaticRootHandle*> root_handles;
return &root_handles;
}
StaticRootHandle::StaticRootHandle() {
getRootHandles()->insert(this);
}
StaticRootHandle::~StaticRootHandle() {
getRootHandles()->erase(this);
}
bool TraceStackGCVisitor::isValid(void* p) { bool TraceStackGCVisitor::isValid(void* p) {
return global_heap.getAllocationFromInteriorPointer(p); return global_heap.getAllocationFromInteriorPointer(p);
} }
...@@ -105,6 +117,10 @@ static void markPhase() { ...@@ -105,6 +117,10 @@ static void markPhase() {
TraceStackGCVisitor visitor(&stack); TraceStackGCVisitor visitor(&stack);
for (auto h : *getRootHandles()) {
visitor.visitPotential(h->value);
}
// if (VERBOSITY()) printf("Found %d roots\n", stack.size()); // if (VERBOSITY()) printf("Found %d roots\n", stack.size());
while (void* p = stack.pop()) { while (void* p = stack.pop()) {
assert(((intptr_t)p) % 8 == 0); assert(((intptr_t)p) % 8 == 0);
......
...@@ -83,6 +83,19 @@ public: ...@@ -83,6 +83,19 @@ public:
// (that should be registerStaticRootPtr) // (that should be registerStaticRootPtr)
void registerStaticRootObj(void* root_obj); void registerStaticRootObj(void* root_obj);
void runCollection(); void runCollection();
// If you want to have a static root "location" where multiple values could be stored, use this:
class StaticRootHandle {
public:
Box* value;
StaticRootHandle();
~StaticRootHandle();
void operator=(Box* b) { value = b; }
operator Box*() { return value; }
};
} }
} }
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cmath>
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h"
#include "runtime/types.h"
#include "runtime/util.h"
namespace pyston {
BoxedModule* errno_module;
void setupErrno() {
errno_module = createModule("errno", "__builtin__");
}
}
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cmath>
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h"
#include "runtime/types.h"
#include "runtime/util.h"
namespace pyston {
BoxedModule* posix_module;
void setupPosix() {
posix_module = createModule("posix", "__builtin__");
}
}
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <algorithm>
#include <cmath> #include <cmath>
#include "core/types.h" #include "core/types.h"
...@@ -87,4 +88,16 @@ void setupSys() { ...@@ -87,4 +88,16 @@ void setupSys() {
sys_module->giveAttr("stdin", new BoxedFile(stdin)); sys_module->giveAttr("stdin", new BoxedFile(stdin));
sys_module->giveAttr("stderr", new BoxedFile(stderr)); sys_module->giveAttr("stderr", new BoxedFile(stderr));
} }
void setupSysEnd() {
BoxedTuple::GCVector builtin_module_names;
for (auto& p : sys_modules_dict->d) {
builtin_module_names.push_back(p.first);
}
std::sort<decltype(builtin_module_names)::iterator, PyLt>(builtin_module_names.begin(), builtin_module_names.end(),
PyLt());
sys_module->giveAttr("builtin_module_names", new BoxedTuple(std::move(builtin_module_names)));
}
} }
...@@ -76,6 +76,7 @@ void force() { ...@@ -76,6 +76,7 @@ void force() {
FORCE(delitem); FORCE(delitem);
FORCE(unaryop); FORCE(unaryop);
FORCE(import); FORCE(import);
FORCE(importFrom);
FORCE(repr); FORCE(repr);
FORCE(isinstance); FORCE(isinstance);
FORCE(yield); FORCE(yield);
...@@ -93,6 +94,9 @@ void force() { ...@@ -93,6 +94,9 @@ void force() {
FORCE(runtimeCall); FORCE(runtimeCall);
FORCE(callattr); FORCE(callattr);
FORCE(raise0);
FORCE(raise1);
FORCE(div_i64_i64); FORCE(div_i64_i64);
FORCE(mod_i64_i64); FORCE(mod_i64_i64);
FORCE(pow_i64_i64); FORCE(pow_i64_i64);
......
...@@ -545,6 +545,7 @@ void setupList() { ...@@ -545,6 +545,7 @@ void setupList() {
list_cls->giveAttr("pop", new BoxedFunction(boxRTFunction((void*)listPop, UNKNOWN, 2, 1, false, false), { None })); list_cls->giveAttr("pop", new BoxedFunction(boxRTFunction((void*)listPop, UNKNOWN, 2, 1, false, false), { None }));
list_cls->giveAttr("append", new BoxedFunction(boxRTFunction((void*)listAppend, NONE, 2))); list_cls->giveAttr("append", new BoxedFunction(boxRTFunction((void*)listAppend, NONE, 2)));
list_cls->giveAttr("extend", new BoxedFunction(boxRTFunction((void*)listIAdd, NONE, 2)));
CLFunction* setitem = createRTFunction(3, 0, false, false); CLFunction* setitem = createRTFunction(3, 0, false, false);
addRTFunction(setitem, (void*)listSetitemInt, NONE, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT, UNKNOWN }); addRTFunction(setitem, (void*)listSetitemInt, NONE, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT, UNKNOWN });
......
...@@ -1772,7 +1772,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -1772,7 +1772,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
rewrite_args->rewriter->loadConst(0, (intptr_t)closure); rewrite_args->rewriter->loadConst(0, (intptr_t)closure);
if (func->isGenerator) if (func->isGenerator)
rewrite_args->rewriter->loadConst(0, (intptr_t)0 /*generator*/); rewrite_args->rewriter->loadConst(0, (intptr_t)func->isGenerator);
// We might have trouble if we have more output args than input args, // We might have trouble if we have more output args than input args,
// such as if we need more space to pass defaults. // such as if we need more space to pass defaults.
...@@ -1963,7 +1963,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -1963,7 +1963,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
return createGenerator(func, oarg1, oarg2, oarg3, oargs); return createGenerator(func, oarg1, oarg2, oarg3, oargs);
} }
return callCLFunc(f, rewrite_args, num_output_args, closure, NULL, oarg1, oarg2, oarg3, oargs); return callCLFunc(f, rewrite_args, num_output_args, closure, (BoxedGenerator*)func->isGenerator, oarg1, oarg2, oarg3, oargs);
} }
Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure, Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure,
...@@ -2981,4 +2981,16 @@ extern "C" Box* import(const std::string* name) { ...@@ -2981,4 +2981,16 @@ extern "C" Box* import(const std::string* name) {
raiseExcHelper(ImportError, "No module named %s", name->c_str()); raiseExcHelper(ImportError, "No module named %s", name->c_str());
} }
extern "C" Box* importFrom(Box* _m, const std::string* name) {
assert(_m->cls == module_cls);
BoxedModule* m = static_cast<BoxedModule*>(_m);
Box* r = m->getattr(*name, NULL, NULL);
if (r)
return r;
raiseExcHelper(ImportError, "cannot import name %s", name->c_str());
}
} }
...@@ -29,7 +29,14 @@ class BoxedList; ...@@ -29,7 +29,14 @@ class BoxedList;
class BoxedString; class BoxedString;
class BoxedGenerator; class BoxedGenerator;
void raiseExc(Box*) __attribute__((__noreturn__)); // user-level raise functions that implement python-level semantics
extern "C" void raise0() __attribute__((__noreturn__));
extern "C" void raise1(Box*) __attribute__((__noreturn__));
extern "C" void raise2(Box*, Box*) __attribute__((__noreturn__));
extern "C" void raise3(Box*, Box*, Box*) __attribute__((__noreturn__));
void raiseExc(Box* exc_obj) __attribute__((__noreturn__));
// helper function for raising from the runtime:
void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__)); void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__));
extern "C" const std::string* getTypeName(Box* o); extern "C" const std::string* getTypeName(Box* o);
...@@ -37,6 +44,7 @@ extern "C" const std::string* getNameOfClass(BoxedClass* cls); ...@@ -37,6 +44,7 @@ extern "C" const std::string* getNameOfClass(BoxedClass* cls);
// TODO sort this // TODO sort this
extern "C" void my_assert(bool b); extern "C" void my_assert(bool b);
extern "C" Box* importFrom(Box* obj, const std::string* attr);
extern "C" Box* getattr(Box* obj, const char* attr); extern "C" Box* getattr(Box* obj, const char* attr);
extern "C" void setattr(Box* obj, const char* attr, Box* attr_val); extern "C" void setattr(Box* obj, const char* attr, Box* attr_val);
extern "C" bool nonzero(Box* obj); extern "C" bool nonzero(Box* obj);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/llvm_interpreter.h" #include "codegen/llvm_interpreter.h"
#include "core/options.h" #include "core/options.h"
#include "gc/collector.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -99,17 +100,27 @@ void unwindExc(Box* exc_obj) { ...@@ -99,17 +100,27 @@ void unwindExc(Box* exc_obj) {
abort(); abort();
} }
void raiseExc(Box* exc_obj) { static std::vector<const LineInfo*> getTracebackEntries();
static gc::StaticRootHandle last_exc;
static std::vector<const LineInfo*> last_tb;
void raiseRaw(Box* exc_obj) __attribute__((__noreturn__));
void raiseRaw(Box* exc_obj) {
// Using libgcc: // Using libgcc:
throw exc_obj; throw exc_obj;
// Using libunwind // Using libunwind
// unwindExc(exc_obj); // unwindExc(exc_obj);
}
abort(); void raiseExc(Box* exc_obj) {
auto entries = getTracebackEntries();
last_tb = std::move(entries);
last_exc = exc_obj;
raiseRaw(exc_obj);
} }
static std::vector<const LineInfo*> last_tb;
void printLastTraceback() { void printLastTraceback() {
fprintf(stderr, "Traceback (most recent call last):\n"); fprintf(stderr, "Traceback (most recent call last):\n");
...@@ -183,10 +194,28 @@ static std::vector<const LineInfo*> getTracebackEntries() { ...@@ -183,10 +194,28 @@ static std::vector<const LineInfo*> getTracebackEntries() {
return entries; return entries;
} }
void raiseExcHelper(BoxedClass* cls, const char* msg, ...) { void raise0() {
auto entries = getTracebackEntries(); raiseRaw(last_exc);
last_tb = std::move(entries); }
void raise1(Box* b) {
if (b->cls == type_cls) {
BoxedClass* c = static_cast<BoxedClass*>(b);
if (isSubclass(c, Exception)) {
auto exc_obj = exceptionNew1(c);
raiseExc(exc_obj);
} else {
raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s",
getTypeName(b)->c_str());
}
}
// TODO: should only allow throwing of old-style classes or things derived
// from BaseException:
raiseExc(b);
}
void raiseExcHelper(BoxedClass* cls, const char* msg, ...) {
if (msg != NULL) { if (msg != NULL) {
va_list ap; va_list ap;
va_start(ap, msg); va_start(ap, msg);
...@@ -223,6 +252,8 @@ std::string formatException(Box* b) { ...@@ -223,6 +252,8 @@ std::string formatException(Box* b) {
assert(r->cls == str_cls); assert(r->cls == str_cls);
const std::string* msg = &r->s; const std::string* msg = &r->s;
if (msg->size())
return *name + ": " + *msg; return *name + ": " + *msg;
return *name;
} }
} }
...@@ -191,6 +191,46 @@ extern "C" BoxedString* strMul(BoxedString* lhs, BoxedInt* rhs) { ...@@ -191,6 +191,46 @@ extern "C" BoxedString* strMul(BoxedString* lhs, BoxedInt* rhs) {
return new BoxedString(buf); return new BoxedString(buf);
} }
extern "C" Box* strLt(BoxedString* lhs, Box* rhs) {
assert(lhs->cls == str_cls);
if (rhs->cls != str_cls)
return NotImplemented;
BoxedString* srhs = static_cast<BoxedString*>(rhs);
return boxBool(lhs->s < srhs->s);
}
extern "C" Box* strLe(BoxedString* lhs, Box* rhs) {
assert(lhs->cls == str_cls);
if (rhs->cls != str_cls)
return NotImplemented;
BoxedString* srhs = static_cast<BoxedString*>(rhs);
return boxBool(lhs->s <= srhs->s);
}
extern "C" Box* strGt(BoxedString* lhs, Box* rhs) {
assert(lhs->cls == str_cls);
if (rhs->cls != str_cls)
return NotImplemented;
BoxedString* srhs = static_cast<BoxedString*>(rhs);
return boxBool(lhs->s > srhs->s);
}
extern "C" Box* strGe(BoxedString* lhs, Box* rhs) {
assert(lhs->cls == str_cls);
if (rhs->cls != str_cls)
return NotImplemented;
BoxedString* srhs = static_cast<BoxedString*>(rhs);
return boxBool(lhs->s >= srhs->s);
}
extern "C" Box* strEq(BoxedString* lhs, Box* rhs) { extern "C" Box* strEq(BoxedString* lhs, Box* rhs) {
assert(lhs->cls == str_cls); assert(lhs->cls == str_cls);
...@@ -201,6 +241,16 @@ extern "C" Box* strEq(BoxedString* lhs, Box* rhs) { ...@@ -201,6 +241,16 @@ extern "C" Box* strEq(BoxedString* lhs, Box* rhs) {
return boxBool(lhs->s == srhs->s); return boxBool(lhs->s == srhs->s);
} }
extern "C" Box* strNe(BoxedString* lhs, Box* rhs) {
assert(lhs->cls == str_cls);
if (rhs->cls != str_cls)
return boxBool(true);
BoxedString* srhs = static_cast<BoxedString*>(rhs);
return boxBool(lhs->s != srhs->s);
}
extern "C" Box* strLen(BoxedString* self) { extern "C" Box* strLen(BoxedString* self) {
assert(self->cls == str_cls); assert(self->cls == str_cls);
...@@ -572,7 +622,14 @@ void setupStr() { ...@@ -572,7 +622,14 @@ void setupStr() {
str_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)strAdd, UNKNOWN, 2))); str_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)strAdd, UNKNOWN, 2)));
str_cls->giveAttr("__mod__", new BoxedFunction(boxRTFunction((void*)strMod, STR, 2))); str_cls->giveAttr("__mod__", new BoxedFunction(boxRTFunction((void*)strMod, STR, 2)));
str_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)strMul, UNKNOWN, 2))); str_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)strMul, UNKNOWN, 2)));
str_cls->giveAttr("__lt__", new BoxedFunction(boxRTFunction((void*)strLt, UNKNOWN, 2)));
str_cls->giveAttr("__le__", new BoxedFunction(boxRTFunction((void*)strLe, UNKNOWN, 2)));
str_cls->giveAttr("__gt__", new BoxedFunction(boxRTFunction((void*)strGt, UNKNOWN, 2)));
str_cls->giveAttr("__ge__", new BoxedFunction(boxRTFunction((void*)strGe, UNKNOWN, 2)));
str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, UNKNOWN, 2))); str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, UNKNOWN, 2)));
str_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)strNe, UNKNOWN, 2)));
str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, STR, 2))); str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, STR, 2)));
str_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)strIter, typeFromClass(str_iterator_cls), 1))); str_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)strIter, typeFromClass(str_iterator_cls), 1)));
......
...@@ -652,9 +652,13 @@ void setupRuntime() { ...@@ -652,9 +652,13 @@ void setupRuntime() {
setupMath(); setupMath();
setupTime(); setupTime();
setupThread(); setupThread();
setupErrno();
setupPosix();
setupCAPI(); setupCAPI();
setupSysEnd();
TRACK_ALLOCATIONS = true; TRACK_ALLOCATIONS = true;
} }
......
...@@ -61,6 +61,9 @@ void setupBuiltins(); ...@@ -61,6 +61,9 @@ void setupBuiltins();
void setupMath(); void setupMath();
void setupTime(); void setupTime();
void setupThread(); void setupThread();
void setupErrno();
void setupPosix();
void setupSysEnd();
BoxedDict* getSysModulesDict(); BoxedDict* getSysModulesDict();
BoxedList* getSysPath(); BoxedList* getSysPath();
......
# expected: fail
# - WIP
X = 0 X = 0
Y = 0 Y = 0
Z = 0 Z = 0
...@@ -37,10 +34,10 @@ def wrapper(): ...@@ -37,10 +34,10 @@ def wrapper():
# The defaults for a and b should resolve to the classdef definitions, and the default # The defaults for a and b should resolve to the classdef definitions, and the default
# for c should resolve to the wrapper() definition # for c should resolve to the wrapper() definition
def f(self, a=X, b=Y, c=Z, d=W): def f(self, a=X, b=Y, c=Z, d=W):
print a, b, c, W # "2 2 0 1" print a, b, c, d # "2 2 0 1"
# These references should skip all of the classdef directives, # These references should skip all of the classdef directives,
# and hit the definitions in the wrapper() function # and hit the definitions in the wrapper() function
print X, Y # "1 1" print X, Y, Z, W # "1 1 1 1"
print "done with classdef" print "done with classdef"
print hasattr(C, 'X') print hasattr(C, 'X')
......
# expected: fail
# - decorators
def f(o, msg):
print msg
return o
@f(lambda c: f(c, "calling decorator"), "evaluating decorator object")
class C(f(object, "evaluating base")):
print "in classdef"
x3 = 0
def bad_addr3(_x):
if 0:
x3 = _
def g(y3):
return x3 + y3
return g
print bad_addr3(1)(2)
...@@ -43,11 +43,29 @@ def make_addr3(x3): ...@@ -43,11 +43,29 @@ def make_addr3(x3):
return g return g
print make_addr3(10)(2) print make_addr3(10)(2)
def bad_addr3(_x): def f4(args):
if 0: def inner():
x3 = _ for a in args:
print a
return inner
print f4([1, 2, 3])()
def g(y3): def f5():
return x3 + y3 x = 12039
return g def i1():
print bad_addr3(1)(2) def i2():
print x
i2()
i1()
f5()
def f6():
x = 131
# Regression test:
# default args shouldn't mess with closure analysis
def inner(a=1):
print x
inner()
print (lambda a=1: x)()
f6()
# expected: fail
# - deletes on names
x = 1
def f():
if 0:
# the del marks 'x' as a name written to in this scope
del x
print x
f()
...@@ -15,3 +15,12 @@ del a[:] ...@@ -15,3 +15,12 @@ del a[:]
print a print a
a.append(1) a.append(1)
print a print a
# Make sure that del's work correctly in sub-scopes:
x = 1
def f1():
x = range(5)
def f2():
del x[1]
return f2
f1()()
try:
import non_existent_module
assert 0, "shouldn't get here"
except ImportError:
pass
try:
from non_existent_module import a
assert 0, "shouldn't get here"
except ImportError:
pass
try:
from sys import non_existent_attribute
assert 0, "shouldn't get here"
except ImportError:
pass
...@@ -67,3 +67,7 @@ for i in xrange(100): ...@@ -67,3 +67,7 @@ for i in xrange(100):
l.append(i) l.append(i)
while l: while l:
del l[0] del l[0]
l = range(5)
l.extend(range(5))
print l
...@@ -39,3 +39,17 @@ for c in "hello world": ...@@ -39,3 +39,17 @@ for c in "hello world":
for i in xrange(1, 10): for i in xrange(1, 10):
for j in xrange(1, 4): for j in xrange(1, 4):
print ("a"*i).count("a"*j) print ("a"*i).count("a"*j)
def test_comparisons(a, b):
print "%s < %s = " % (a, b), a < b
print "%s <= %s = " % (a, b), a <= b
print "%s > %s = " % (a, b), a > b
print "%s >= %s = " % (a, b), a >= b
print "%s == %s = " % (a, b), a == b
print "%s != %s = " % (a, b), a != b
test_comparisons("a", "a")
test_comparisons("a", "A")
test_comparisons("a", "aa")
test_comparisons("ab", "aa")
print sorted([str(i) for i in xrange(25)])
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