Commit 40cb8002 authored by Marius Wachtler's avatar Marius Wachtler

BST: switch to a gapless bytecode

- all instructions of the CFG are directly emitted a single memory region
- all instructions are packed and follow each other directly
- the CFGBlock just stores the offset into the bytecode where the first instruction of the block is located
- invokes are only a bit in the opcode field which when set means that the pointers to the normal and exc CFGBlocks* directly follow the normal instruction
parent 138433d8
...@@ -102,7 +102,7 @@ LivenessAnalysis::LivenessAnalysis(CFG* cfg, const CodeConstants& code_constants ...@@ -102,7 +102,7 @@ LivenessAnalysis::LivenessAnalysis(CFG* cfg, const CodeConstants& code_constants
for (CFGBlock* b : cfg->blocks) { for (CFGBlock* b : cfg->blocks) {
auto visitor = new LivenessBBVisitor(this); // livenessCache unique_ptr will delete it. auto visitor = new LivenessBBVisitor(this); // livenessCache unique_ptr will delete it.
for (BST_stmt* stmt : b->body) { for (BST_stmt* stmt : *b) {
stmt->accept(visitor); stmt->accept(visitor);
} }
liveness_cache.insert(std::make_pair(b, std::unique_ptr<LivenessBBVisitor>(visitor))); liveness_cache.insert(std::make_pair(b, std::unique_ptr<LivenessBBVisitor>(visitor)));
...@@ -257,8 +257,8 @@ public: ...@@ -257,8 +257,8 @@ public:
void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const { void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
DefinednessVisitor visitor(code_constants, starting); DefinednessVisitor visitor(code_constants, starting);
for (int i = 0; i < block->body.size(); i++) { for (BST_stmt* stmt : *block) {
block->body[i]->accept(&visitor); stmt->accept(&visitor);
} }
if (VERBOSITY("analysis") >= 3) { if (VERBOSITY("analysis") >= 3) {
......
...@@ -101,8 +101,8 @@ private: ...@@ -101,8 +101,8 @@ private:
speculation(speculation) {} speculation(speculation) {}
void run() { void run() {
for (int i = 0; i < block->body.size(); i++) { for (BST_stmt* stmt : *block) {
block->body[i]->accept_stmt(this); stmt->accept_stmt(this);
} }
} }
...@@ -526,8 +526,6 @@ private: ...@@ -526,8 +526,6 @@ private:
getType(node->vreg_locals); getType(node->vreg_locals);
} }
void visit_invoke(BST_Invoke* node) override { node->stmt->accept_stmt(this); }
void visit_jump(BST_Jump* node) override {} void visit_jump(BST_Jump* node) override {}
void visit_print(BST_Print* node) override { void visit_print(BST_Print* node) override {
......
...@@ -74,6 +74,8 @@ public: ...@@ -74,6 +74,8 @@ public:
static Box* executeInner(ASTInterpreter& interpreter, CFGBlock* start_block, BST_stmt* start_at); static Box* executeInner(ASTInterpreter& interpreter, CFGBlock* start_block, BST_stmt* start_at);
private: private:
Value executeStmt(BST_stmt* node);
Value createFunction(BST_FunctionDef* node, BoxedCode* node_code); Value createFunction(BST_FunctionDef* node, BoxedCode* node_code);
Value doBinOp(BST_stmt* node, Value left, Value right, int op, BinExpType exp_type); Value doBinOp(BST_stmt* node, Value left, Value right, int op, BinExpType exp_type);
void doStore(int vreg, STOLEN(Value) value); void doStore(int vreg, STOLEN(Value) value);
...@@ -95,7 +97,6 @@ private: ...@@ -95,7 +97,6 @@ private:
Value visit_importfrom(BST_ImportFrom* node); Value visit_importfrom(BST_ImportFrom* node);
Value visit_importname(BST_ImportName* node); Value visit_importname(BST_ImportName* node);
Value visit_importstar(BST_ImportStar* node); Value visit_importstar(BST_ImportStar* node);
Value visit_invoke(BST_Invoke* node);
Value visit_jump(BST_Jump* node); Value visit_jump(BST_Jump* node);
Value visit_landingpad(BST_Landingpad* node); Value visit_landingpad(BST_Landingpad* node);
Value visit_list(BST_List* node); Value visit_list(BST_List* node);
...@@ -362,7 +363,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) { ...@@ -362,7 +363,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
} catch (ExcInfo e) { } catch (ExcInfo e) {
--num_inside; --num_inside;
BST_stmt* stmt = getCurrentStatement(); BST_stmt* stmt = getCurrentStatement();
if (stmt->type != BST_TYPE::Invoke) if (!stmt->is_invoke())
throw e; throw e;
assert(getPythonFrameInfo(0) == getFrameInfo()); assert(getPythonFrameInfo(0) == getFrameInfo());
...@@ -370,7 +371,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) { ...@@ -370,7 +371,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
++getCode()->cxx_exception_count[stmt]; ++getCode()->cxx_exception_count[stmt];
caughtCxxException(&e); caughtCxxException(&e);
next_block = ((BST_Invoke*)stmt)->exc_dest; next_block = stmt->get_exc_block();
last_exception = e; last_exception = e;
} }
return nullptr; return nullptr;
...@@ -384,7 +385,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b ...@@ -384,7 +385,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
assert((start_block == NULL) == (start_at == NULL)); assert((start_block == NULL) == (start_at == NULL));
if (start_block == NULL) { if (start_block == NULL) {
start_block = interpreter.source_info->cfg->getStartingBlock(); start_block = interpreter.source_info->cfg->getStartingBlock();
start_at = start_block->body[0]; start_at = start_block->body();
} }
// Important that this happens after RegisterHelper: // Important that this happens after RegisterHelper:
...@@ -395,7 +396,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b ...@@ -395,7 +396,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
if (!from_start) { if (!from_start) {
interpreter.current_block = start_block; interpreter.current_block = start_block;
bool started = false; bool started = false;
for (auto s : start_block->body) { for (auto s : *start_block) {
if (!started) { if (!started) {
if (s != start_at) if (s != start_at)
continue; continue;
...@@ -404,7 +405,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b ...@@ -404,7 +405,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
interpreter.setCurrentStatement(s); interpreter.setCurrentStatement(s);
Py_XDECREF(v.o); Py_XDECREF(v.o);
v = interpreter.visit_stmt(s); v = interpreter.executeStmt(s);
} }
} else { } else {
interpreter.next_block = start_block; interpreter.next_block = start_block;
...@@ -427,7 +428,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b ...@@ -427,7 +428,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
// check if we returned from the baseline JIT because we should do a OSR. // check if we returned from the baseline JIT because we should do a OSR.
if (unlikely(rtn == (Box*)ASTInterpreterJitInterface::osr_dummy_value)) { if (unlikely(rtn == (Box*)ASTInterpreterJitInterface::osr_dummy_value)) {
BST_Jump* cur_stmt = (BST_Jump*)interpreter.getCurrentStatement(); BST_Jump* cur_stmt = (BST_Jump*)interpreter.getCurrentStatement();
RELEASE_ASSERT(cur_stmt->type == BST_TYPE::Jump, ""); RELEASE_ASSERT(cur_stmt->type() == BST_TYPE::Jump, "");
// WARNING: do not put a try catch + rethrow block around this code here. // WARNING: do not put a try catch + rethrow block around this code here.
// it will confuse our unwinder! // it will confuse our unwinder!
rtn = interpreter.doOSR(cur_stmt); rtn = interpreter.doOSR(cur_stmt);
...@@ -449,14 +450,14 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b ...@@ -449,14 +450,14 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
interpreter.startJITing(interpreter.current_block); interpreter.startJITing(interpreter.current_block);
} }
for (BST_stmt* s : interpreter.current_block->body) { for (BST_stmt* s : *interpreter.current_block) {
interpreter.setCurrentStatement(s); interpreter.setCurrentStatement(s);
if (interpreter.jit) if (interpreter.jit)
interpreter.jit->emitSetCurrentInst(s); interpreter.jit->emitSetCurrentInst(s);
if (v.o) { if (v.o) {
Py_DECREF(v.o); Py_DECREF(v.o);
} }
v = interpreter.visit_stmt(s); v = interpreter.executeStmt(s);
} }
} }
return v.o; return v.o;
...@@ -759,11 +760,14 @@ Box* ASTInterpreter::doOSR(BST_Jump* node) { ...@@ -759,11 +760,14 @@ Box* ASTInterpreter::doOSR(BST_Jump* node) {
} }
} }
Value ASTInterpreter::visit_invoke(BST_Invoke* node) { Value ASTInterpreter::executeStmt(BST_stmt* node) {
if (!node->is_invoke())
return visit_stmt(node);
Value v; Value v;
try { try {
v = visit_stmt(node->stmt); v = visit_stmt(node);
next_block = node->normal_dest; next_block = node->get_normal_block();
if (jit) { if (jit) {
jit->emitJump(next_block); jit->emitJump(next_block);
...@@ -778,7 +782,7 @@ Value ASTInterpreter::visit_invoke(BST_Invoke* node) { ...@@ -778,7 +782,7 @@ Value ASTInterpreter::visit_invoke(BST_Invoke* node) {
++getCode()->cxx_exception_count[node]; ++getCode()->cxx_exception_count[node];
caughtCxxException(&e); caughtCxxException(&e);
next_block = node->exc_dest; next_block = node->get_exc_block();
last_exception = e; last_exception = e;
} }
...@@ -909,7 +913,7 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) { ...@@ -909,7 +913,7 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) {
// to be careful to wrap pendingCallsCheckHelper, and it can signal that it was careful // to be careful to wrap pendingCallsCheckHelper, and it can signal that it was careful
// by returning from the function instead of breaking. // by returning from the function instead of breaking.
switch (node->type) { switch (node->type()) {
case BST_TYPE::Assert: case BST_TYPE::Assert:
visit_assert((BST_Assert*)node); visit_assert((BST_Assert*)node);
ASTInterpreterJitInterface::pendingCallsCheckHelper(); ASTInterpreterJitInterface::pendingCallsCheckHelper();
...@@ -977,9 +981,6 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) { ...@@ -977,9 +981,6 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) {
break; break;
case BST_TYPE::Jump: case BST_TYPE::Jump:
return visit_jump((BST_Jump*)node); return visit_jump((BST_Jump*)node);
case BST_TYPE::Invoke:
visit_invoke((BST_Invoke*)node);
break;
case BST_TYPE::SetExcInfo: case BST_TYPE::SetExcInfo:
visit_setexcinfo((BST_SetExcInfo*)node); visit_setexcinfo((BST_SetExcInfo*)node);
ASTInterpreterJitInterface::pendingCallsCheckHelper(); ASTInterpreterJitInterface::pendingCallsCheckHelper();
...@@ -996,7 +997,7 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) { ...@@ -996,7 +997,7 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) {
// Handle all cases which are derived from BST_stmt_with_dest // Handle all cases which are derived from BST_stmt_with_dest
default: { default: {
Value v; Value v;
switch (node->type) { switch (node->type()) {
case BST_TYPE::CopyVReg: case BST_TYPE::CopyVReg:
v = visit_copyvreg((BST_CopyVReg*)node); v = visit_copyvreg((BST_CopyVReg*)node);
break; break;
...@@ -1084,7 +1085,7 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) { ...@@ -1084,7 +1085,7 @@ Value ASTInterpreter::visit_stmt(BST_stmt* node) {
v = visit_makeslice((BST_MakeSlice*)node); v = visit_makeslice((BST_MakeSlice*)node);
break; break;
default: default:
RELEASE_ASSERT(0, "not implemented %d", node->type); RELEASE_ASSERT(0, "not implemented %d", node->type());
}; };
doStore(((BST_stmt_with_dest*)node)->vreg_dst, v); doStore(((BST_stmt_with_dest*)node)->vreg_dst, v);
ASTInterpreterJitInterface::pendingCallsCheckHelper(); ASTInterpreterJitInterface::pendingCallsCheckHelper();
...@@ -1425,14 +1426,14 @@ Value ASTInterpreter::visit_call(BST_Call* node) { ...@@ -1425,14 +1426,14 @@ Value ASTInterpreter::visit_call(BST_Call* node) {
bool is_callattr = false; bool is_callattr = false;
bool callattr_clsonly = false; bool callattr_clsonly = false;
int* vreg_elts = NULL; int* vreg_elts = NULL;
if (node->type == BST_TYPE::CallAttr) { if (node->type() == BST_TYPE::CallAttr) {
is_callattr = true; is_callattr = true;
callattr_clsonly = false; callattr_clsonly = false;
auto* attr_ast = bst_cast<BST_CallAttr>(node); auto* attr_ast = bst_cast<BST_CallAttr>(node);
func = getVReg(attr_ast->vreg_value); func = getVReg(attr_ast->vreg_value);
attr = getCodeConstants().getInternedString(attr_ast->index_attr); attr = getCodeConstants().getInternedString(attr_ast->index_attr);
vreg_elts = bst_cast<BST_CallAttr>(node)->elts; vreg_elts = bst_cast<BST_CallAttr>(node)->elts;
} else if (node->type == BST_TYPE::CallClsAttr) { } else if (node->type() == BST_TYPE::CallClsAttr) {
is_callattr = true; is_callattr = true;
callattr_clsonly = true; callattr_clsonly = true;
auto* attr_ast = bst_cast<BST_CallClsAttr>(node); auto* attr_ast = bst_cast<BST_CallClsAttr>(node);
...@@ -2109,30 +2110,28 @@ extern "C" Box* astInterpretDeoptFromASM(BoxedCode* code, BST_stmt* enclosing_st ...@@ -2109,30 +2110,28 @@ extern "C" Box* astInterpretDeoptFromASM(BoxedCode* code, BST_stmt* enclosing_st
CFGBlock* start_block = NULL; CFGBlock* start_block = NULL;
BST_stmt* starting_statement = NULL; BST_stmt* starting_statement = NULL;
while (true) { while (true) {
if (enclosing_stmt->type == BST_TYPE::Invoke) { if (enclosing_stmt->is_invoke()) {
auto invoke = bst_cast<BST_Invoke>(enclosing_stmt); start_block = enclosing_stmt->get_normal_block();
start_block = invoke->normal_dest; starting_statement = start_block->body();
starting_statement = start_block->body[0]; }
enclosing_stmt = invoke->stmt; if (enclosing_stmt->has_dest_vreg()) {
} else if (enclosing_stmt->has_dest_vreg()) {
int vreg_dst = ((BST_stmt_with_dest*)enclosing_stmt)->vreg_dst; int vreg_dst = ((BST_stmt_with_dest*)enclosing_stmt)->vreg_dst;
if (vreg_dst != VREG_UNDEFINED) if (vreg_dst != VREG_UNDEFINED)
interpreter.addSymbol(vreg_dst, expr_val, true); interpreter.addSymbol(vreg_dst, expr_val, true);
break; break;
} else { } else {
RELEASE_ASSERT(0, "encountered an yet unimplemented opcode (got %d)", enclosing_stmt->type); RELEASE_ASSERT(0, "encountered an yet unimplemented opcode (got %d)", enclosing_stmt->type());
} }
} }
if (start_block == NULL) { if (start_block == NULL) {
// TODO innefficient // TODO innefficient
for (auto block : code->source->cfg->blocks) { for (auto block : code->source->cfg->blocks) {
int n = block->body.size(); for (auto it = block->begin(), it_end = block->end(); it != it_end; ++it) {
for (int i = 0; i < n; i++) { if (*it == enclosing_stmt) {
if (block->body[i] == enclosing_stmt) { ASSERT(!(*it)->is_terminator(), "how could we deopt from a non-invoke terminator?");
ASSERT(i + 1 < n, "how could we deopt from a non-invoke terminator?");
start_block = block; start_block = block;
starting_statement = block->body[i + 1]; starting_statement = *(++it);
break; break;
} }
} }
......
...@@ -69,7 +69,7 @@ SourceInfo::SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags futur ...@@ -69,7 +69,7 @@ SourceInfo::SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags futur
} }
SourceInfo::~SourceInfo() { SourceInfo::~SourceInfo() {
// TODO: release memory.. delete cfg;
} }
void FunctionAddressRegistry::registerFunction(const std::string& name, void* addr, int length, void FunctionAddressRegistry::registerFunction(const std::string& name, void* addr, int length,
......
...@@ -371,7 +371,7 @@ protected: ...@@ -371,7 +371,7 @@ protected:
public: public:
static std::pair<SymbolTable*, bool /* created_new_sym_table */> static std::pair<SymbolTable*, bool /* created_new_sym_table */>
removeDestVRegsFromSymTable(const CodeConstants& code_constants, SymbolTable* sym_table, BST_Invoke* stmt) { removeDestVRegsFromSymTable(const CodeConstants& code_constants, SymbolTable* sym_table, BST_stmt* stmt) {
SymTableDstVRegDeleter visitor(code_constants, sym_table); SymTableDstVRegDeleter visitor(code_constants, sym_table);
stmt->accept(&visitor); stmt->accept(&visitor);
return std::make_pair(visitor.sym_table, visitor.created_new_sym_table); return std::make_pair(visitor.sym_table, visitor.created_new_sym_table);
...@@ -649,7 +649,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -649,7 +649,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// Function-entry safepoint: // Function-entry safepoint:
// TODO might be more efficient to do post-call safepoints? // TODO might be more efficient to do post-call safepoints?
generator->doSafePoint(block->body[0]); generator->doSafePoint(block->body());
} else if (entry_descriptor && block == entry_descriptor->backedge->target) { } else if (entry_descriptor && block == entry_descriptor->backedge->target) {
assert(block->predecessors.size() > 1); assert(block->predecessors.size() > 1);
assert(osr_entry_block); assert(osr_entry_block);
...@@ -742,13 +742,13 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -742,13 +742,13 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// are disallowed // are disallowed
auto pred = block->predecessors[0]; auto pred = block->predecessors[0];
auto last_inst = pred->body.back(); auto last_inst = pred->getLastStmt();
SymbolTable* sym_table = ending_symbol_tables[pred]; SymbolTable* sym_table = ending_symbol_tables[pred];
bool created_new_sym_table = false; bool created_new_sym_table = false;
if (last_inst->type == BST_TYPE::Invoke && bst_cast<BST_Invoke>(last_inst)->exc_dest == block) if (last_inst->is_invoke() && last_inst->get_exc_block() == block)
std::tie(sym_table, created_new_sym_table) = SymTableDstVRegDeleter::removeDestVRegsFromSymTable( std::tie(sym_table, created_new_sym_table) = SymTableDstVRegDeleter::removeDestVRegsFromSymTable(
irstate->getCodeConstants(), sym_table, bst_cast<BST_Invoke>(last_inst)); irstate->getCodeConstants(), sym_table, last_inst);
generator->copySymbolsFrom(sym_table); generator->copySymbolsFrom(sym_table);
for (auto&& p : *definedness_tables[pred]) { for (auto&& p : *definedness_tables[pred]) {
...@@ -809,7 +809,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -809,7 +809,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
if (predecessor->idx > block->idx) { if (predecessor->idx > block->idx) {
// Loop safepoint: // Loop safepoint:
// TODO does it matter which side of the backedge these are on? // TODO does it matter which side of the backedge these are on?
generator->doSafePoint(block->body[0]); generator->doSafePoint(block->body());
break; break;
} }
} }
...@@ -824,9 +824,9 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -824,9 +824,9 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
llvm_exit_blocks[block] = ending_st.ending_block; llvm_exit_blocks[block] = ending_st.ending_block;
if (ending_st.exception_state.size()) { if (ending_st.exception_state.size()) {
BST_stmt* last_stmt = block->body.back(); BST_stmt* last_stmt = block->getLastStmt();
assert(last_stmt->type == BST_TYPE::Invoke); assert(last_stmt->is_invoke());
CFGBlock* exc_block = bst_cast<BST_Invoke>(last_stmt)->exc_dest; CFGBlock* exc_block = last_stmt->get_exc_block();
assert(!incoming_exception_state.count(exc_block)); assert(!incoming_exception_state.count(exc_block));
incoming_exception_state.insert(std::make_pair(exc_block, ending_st.exception_state)); incoming_exception_state.insert(std::make_pair(exc_block, ending_st.exception_state));
......
...@@ -1098,14 +1098,14 @@ private: ...@@ -1098,14 +1098,14 @@ private:
InternedString attr; InternedString attr;
CompilerVariable* func; CompilerVariable* func;
int* vreg_elts = NULL; int* vreg_elts = NULL;
if (node->type == BST_TYPE::CallAttr) { if (node->type() == BST_TYPE::CallAttr) {
is_callattr = true; is_callattr = true;
callattr_clsonly = false; callattr_clsonly = false;
auto* attr_ast = bst_cast<BST_CallAttr>(node); auto* attr_ast = bst_cast<BST_CallAttr>(node);
vreg_elts = bst_cast<BST_CallAttr>(node)->elts; vreg_elts = bst_cast<BST_CallAttr>(node)->elts;
func = evalVReg(attr_ast->vreg_value); func = evalVReg(attr_ast->vreg_value);
attr = irstate->getCodeConstants().getInternedString(attr_ast->index_attr); attr = irstate->getCodeConstants().getInternedString(attr_ast->index_attr);
} else if (node->type == BST_TYPE::CallClsAttr) { } else if (node->type() == BST_TYPE::CallClsAttr) {
is_callattr = true; is_callattr = true;
callattr_clsonly = true; callattr_clsonly = true;
auto* attr_ast = bst_cast<BST_CallClsAttr>(node); auto* attr_ast = bst_cast<BST_CallClsAttr>(node);
...@@ -2406,7 +2406,7 @@ private: ...@@ -2406,7 +2406,7 @@ private:
llvm::DebugLoc::get(node->lineno, 0, irstate->getFuncDbgInfo())); llvm::DebugLoc::get(node->lineno, 0, irstate->getFuncDbgInfo()));
} }
switch (node->type) { switch (node->type()) {
case BST_TYPE::Assert: case BST_TYPE::Assert:
doAssert(bst_cast<BST_Assert>(node), unw_info); doAssert(bst_cast<BST_Assert>(node), unw_info);
break; break;
...@@ -2455,20 +2455,6 @@ private: ...@@ -2455,20 +2455,6 @@ private:
assert(!unw_info.hasHandler()); assert(!unw_info.hasHandler());
doJump(bst_cast<BST_Jump>(node), unw_info); doJump(bst_cast<BST_Jump>(node), unw_info);
break; break;
case BST_TYPE::Invoke: {
assert(!unw_info.hasHandler());
BST_Invoke* invoke = bst_cast<BST_Invoke>(node);
doStmt(invoke->stmt, UnwindInfo(irstate->getCode(), node, entry_blocks[invoke->exc_dest]));
assert(state == RUNNING || state == DEAD);
if (state == RUNNING) {
emitter.getBuilder()->CreateBr(entry_blocks[invoke->normal_dest]);
endBlock(FINISHED);
}
break;
}
case BST_TYPE::Raise: case BST_TYPE::Raise:
doRaise(bst_cast<BST_Raise>(node), unw_info); doRaise(bst_cast<BST_Raise>(node), unw_info);
break; break;
...@@ -2485,7 +2471,7 @@ private: ...@@ -2485,7 +2471,7 @@ private:
// Handle all cases which are derived from BST_stmt_with_dest // Handle all cases which are derived from BST_stmt_with_dest
default: { default: {
CompilerVariable* rtn = NULL; CompilerVariable* rtn = NULL;
switch (node->type) { switch (node->type()) {
case BST_TYPE::CopyVReg: case BST_TYPE::CopyVReg:
rtn = evalAssign(bst_cast<BST_CopyVReg>(node), unw_info); rtn = evalAssign(bst_cast<BST_CopyVReg>(node), unw_info);
break; break;
...@@ -2573,7 +2559,7 @@ private: ...@@ -2573,7 +2559,7 @@ private:
rtn = evalMakeSlice(bst_cast<BST_MakeSlice>(node), unw_info); rtn = evalMakeSlice(bst_cast<BST_MakeSlice>(node), unw_info);
break; break;
default: default:
printf("Unhandled stmt type at " __FILE__ ":" STRINGIFY(__LINE__) ": %d\n", node->type); printf("Unhandled stmt type at " __FILE__ ":" STRINGIFY(__LINE__) ": %d\n", node->type());
exit(1); exit(1);
} }
rtn = evalSliceExprPost((BST_stmt_with_dest*)node, unw_info, rtn); rtn = evalSliceExprPost((BST_stmt_with_dest*)node, unw_info, rtn);
...@@ -2951,18 +2937,25 @@ public: ...@@ -2951,18 +2937,25 @@ public:
} }
printf("\n"); printf("\n");
} }
for (int i = 0; i < block->body.size(); i++) { for (BST_stmt* stmt : *block) {
if (state == DEAD) if (state == DEAD)
break; break;
assert(state != FINISHED); assert(state != FINISHED);
#if ENABLE_SAMPLING_PROFILER #if ENABLE_SAMPLING_PROFILER
auto stmt = block->body[i];
if (stmt->type != BST_TYPE::Landigpad && stmt->lineno > 0) if (stmt->type != BST_TYPE::Landigpad && stmt->lineno > 0)
doSafePoint(block->body[i]); doSafePoint(stmt);
#endif #endif
if (stmt->is_invoke()) {
doStmt(stmt, UnwindInfo(irstate->getCode(), stmt, entry_blocks[stmt->get_exc_block()]));
doStmt(block->body[i], UnwindInfo(irstate->getCode(), block->body[i], NULL)); assert(state == RUNNING || state == DEAD);
if (state == RUNNING) {
emitter.getBuilder()->CreateBr(entry_blocks[stmt->get_normal_block()]);
endBlock(FINISHED);
}
} else
doStmt(stmt, UnwindInfo(irstate->getCode(), stmt, NULL));
} }
if (VERBOSITY("irgenerator") >= 2) { // print ending symbol table if (VERBOSITY("irgenerator") >= 2) { // print ending symbol table
printf(" %d fini:", block->idx); printf(" %d fini:", block->idx);
......
...@@ -35,7 +35,6 @@ class MDNode; ...@@ -35,7 +35,6 @@ class MDNode;
namespace pyston { namespace pyston {
class BST_Invoke;
class CFGBlock; class CFGBlock;
class GCBuilder; class GCBuilder;
struct PatchpointInfo; struct PatchpointInfo;
......
...@@ -43,6 +43,25 @@ template <class T> static void visitVector(const std::vector<T*>& vec, BSTVisito ...@@ -43,6 +43,25 @@ template <class T> static void visitVector(const std::vector<T*>& vec, BSTVisito
} }
} }
void BST_stmt::accept(BSTVisitor* v) {
switch (type()) {
#define DISPATCH_ACCEPT(x, y) \
case BST_TYPE::x: \
return bst_cast<BST_##x>(this)->accept(v);
FOREACH_TYPE(DISPATCH_ACCEPT)
};
}
void BST_stmt::accept_stmt(StmtVisitor* v) {
switch (type()) {
#define DISPATCH_ACCEPT_STMT(x, y) \
case BST_TYPE::x: \
return bst_cast<BST_##x>(this)->accept_stmt(v);
FOREACH_TYPE(DISPATCH_ACCEPT_STMT)
};
}
void BST_Assert::accept(BSTVisitor* v) { void BST_Assert::accept(BSTVisitor* v) {
bool skip = v->visit_assert(this); bool skip = v->visit_assert(this);
if (skip) if (skip)
...@@ -272,18 +291,6 @@ void BST_FunctionDef::accept_stmt(StmtVisitor* v) { ...@@ -272,18 +291,6 @@ void BST_FunctionDef::accept_stmt(StmtVisitor* v) {
v->visit_functiondef(this); v->visit_functiondef(this);
} }
void BST_Invoke::accept(BSTVisitor* v) {
bool skip = v->visit_invoke(this);
if (skip)
return;
this->stmt->accept(v);
}
void BST_Invoke::accept_stmt(StmtVisitor* v) {
return v->visit_invoke(this);
}
void BST_Landingpad::accept(BSTVisitor* v) { void BST_Landingpad::accept(BSTVisitor* v) {
bool skip = v->visit_landingpad(this); bool skip = v->visit_landingpad(this);
if (skip) if (skip)
...@@ -773,7 +780,15 @@ bool PrintVisitor::visit_vreg(int* vreg, bool is_dst) { ...@@ -773,7 +780,15 @@ bool PrintVisitor::visit_vreg(int* vreg, bool is_dst) {
return true; return true;
} }
bool PrintVisitor::check_if_invoke(BST_stmt* node) {
if (node->is_invoke())
stream << "invoke " << node->get_normal_block()->idx << " " << node->get_exc_block()->idx << ": ";
return false;
}
bool PrintVisitor::visit_assert(BST_Assert* node) { bool PrintVisitor::visit_assert(BST_Assert* node) {
check_if_invoke(node);
stream << "assert 0"; stream << "assert 0";
if (node->vreg_msg != VREG_UNDEFINED) { if (node->vreg_msg != VREG_UNDEFINED) {
stream << ", "; stream << ", ";
...@@ -783,6 +798,8 @@ bool PrintVisitor::visit_assert(BST_Assert* node) { ...@@ -783,6 +798,8 @@ bool PrintVisitor::visit_assert(BST_Assert* node) {
} }
bool PrintVisitor::visit_copyvreg(BST_CopyVReg* node) { bool PrintVisitor::visit_copyvreg(BST_CopyVReg* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "nokill "; stream << "nokill ";
visit_vreg(&node->vreg_src); visit_vreg(&node->vreg_src);
...@@ -790,6 +807,8 @@ bool PrintVisitor::visit_copyvreg(BST_CopyVReg* node) { ...@@ -790,6 +807,8 @@ bool PrintVisitor::visit_copyvreg(BST_CopyVReg* node) {
} }
bool PrintVisitor::visit_augbinop(BST_AugBinOp* node) { bool PrintVisitor::visit_augbinop(BST_AugBinOp* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_left); visit_vreg(&node->vreg_left);
stream << " =" << getOpSymbol(node->op_type) << " "; stream << " =" << getOpSymbol(node->op_type) << " ";
...@@ -798,6 +817,8 @@ bool PrintVisitor::visit_augbinop(BST_AugBinOp* node) { ...@@ -798,6 +817,8 @@ bool PrintVisitor::visit_augbinop(BST_AugBinOp* node) {
} }
bool PrintVisitor::visit_binop(BST_BinOp* node) { bool PrintVisitor::visit_binop(BST_BinOp* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_left); visit_vreg(&node->vreg_left);
stream << " " << getOpSymbol(node->op_type) << " "; stream << " " << getOpSymbol(node->op_type) << " ";
...@@ -806,6 +827,8 @@ bool PrintVisitor::visit_binop(BST_BinOp* node) { ...@@ -806,6 +827,8 @@ bool PrintVisitor::visit_binop(BST_BinOp* node) {
} }
bool PrintVisitor::visit_callfunc(BST_CallFunc* node) { bool PrintVisitor::visit_callfunc(BST_CallFunc* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_func); visit_vreg(&node->vreg_func);
stream << "("; stream << "(";
...@@ -834,6 +857,8 @@ bool PrintVisitor::visit_callfunc(BST_CallFunc* node) { ...@@ -834,6 +857,8 @@ bool PrintVisitor::visit_callfunc(BST_CallFunc* node) {
} }
bool PrintVisitor::visit_callattr(BST_CallAttr* node) { bool PrintVisitor::visit_callattr(BST_CallAttr* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << "."; stream << ".";
...@@ -864,6 +889,8 @@ bool PrintVisitor::visit_callattr(BST_CallAttr* node) { ...@@ -864,6 +889,8 @@ bool PrintVisitor::visit_callattr(BST_CallAttr* node) {
} }
bool PrintVisitor::visit_callclsattr(BST_CallClsAttr* node) { bool PrintVisitor::visit_callclsattr(BST_CallClsAttr* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << ":"; stream << ":";
...@@ -894,6 +921,8 @@ bool PrintVisitor::visit_callclsattr(BST_CallClsAttr* node) { ...@@ -894,6 +921,8 @@ bool PrintVisitor::visit_callclsattr(BST_CallClsAttr* node) {
} }
bool PrintVisitor::visit_compare(BST_Compare* node) { bool PrintVisitor::visit_compare(BST_Compare* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_left); visit_vreg(&node->vreg_left);
stream << " " << getOpSymbol(node->op) << " "; stream << " " << getOpSymbol(node->op) << " ";
...@@ -903,6 +932,8 @@ bool PrintVisitor::visit_compare(BST_Compare* node) { ...@@ -903,6 +932,8 @@ bool PrintVisitor::visit_compare(BST_Compare* node) {
} }
bool PrintVisitor::visit_classdef(BST_ClassDef* node) { bool PrintVisitor::visit_classdef(BST_ClassDef* node) {
check_if_invoke(node);
for (int i = 0, n = node->num_decorator; i < n; i++) { for (int i = 0, n = node->num_decorator; i < n; i++) {
stream << "@"; stream << "@";
visit_vreg(&node->decorator[i]); visit_vreg(&node->decorator[i]);
...@@ -930,6 +961,8 @@ bool PrintVisitor::visit_classdef(BST_ClassDef* node) { ...@@ -930,6 +961,8 @@ bool PrintVisitor::visit_classdef(BST_ClassDef* node) {
} }
bool PrintVisitor::visit_deletesub(BST_DeleteSub* node) { bool PrintVisitor::visit_deletesub(BST_DeleteSub* node) {
check_if_invoke(node);
stream << "del "; stream << "del ";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << "["; stream << "[";
...@@ -938,6 +971,8 @@ bool PrintVisitor::visit_deletesub(BST_DeleteSub* node) { ...@@ -938,6 +971,8 @@ bool PrintVisitor::visit_deletesub(BST_DeleteSub* node) {
return true; return true;
} }
bool PrintVisitor::visit_deletesubslice(BST_DeleteSubSlice* node) { bool PrintVisitor::visit_deletesubslice(BST_DeleteSubSlice* node) {
check_if_invoke(node);
stream << "del "; stream << "del ";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << "["; stream << "[";
...@@ -951,6 +986,8 @@ bool PrintVisitor::visit_deletesubslice(BST_DeleteSubSlice* node) { ...@@ -951,6 +986,8 @@ bool PrintVisitor::visit_deletesubslice(BST_DeleteSubSlice* node) {
return true; return true;
} }
bool PrintVisitor::visit_deleteattr(BST_DeleteAttr* node) { bool PrintVisitor::visit_deleteattr(BST_DeleteAttr* node) {
check_if_invoke(node);
stream << "del "; stream << "del ";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << '.'; stream << '.';
...@@ -958,6 +995,8 @@ bool PrintVisitor::visit_deleteattr(BST_DeleteAttr* node) { ...@@ -958,6 +995,8 @@ bool PrintVisitor::visit_deleteattr(BST_DeleteAttr* node) {
return true; return true;
} }
bool PrintVisitor::visit_deletename(BST_DeleteName* node) { bool PrintVisitor::visit_deletename(BST_DeleteName* node) {
check_if_invoke(node);
stream << "del "; stream << "del ";
if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) { if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) {
visit_vreg(&node->vreg); visit_vreg(&node->vreg);
...@@ -968,12 +1007,16 @@ bool PrintVisitor::visit_deletename(BST_DeleteName* node) { ...@@ -968,12 +1007,16 @@ bool PrintVisitor::visit_deletename(BST_DeleteName* node) {
} }
bool PrintVisitor::visit_dict(BST_Dict* node) { bool PrintVisitor::visit_dict(BST_Dict* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "{}"; stream << "{}";
return true; return true;
} }
bool PrintVisitor::visit_exec(BST_Exec* node) { bool PrintVisitor::visit_exec(BST_Exec* node) {
check_if_invoke(node);
stream << "exec "; stream << "exec ";
visit_vreg(&node->vreg_body); visit_vreg(&node->vreg_body);
...@@ -991,6 +1034,8 @@ bool PrintVisitor::visit_exec(BST_Exec* node) { ...@@ -991,6 +1034,8 @@ bool PrintVisitor::visit_exec(BST_Exec* node) {
} }
bool PrintVisitor::visit_functiondef(BST_FunctionDef* node) { bool PrintVisitor::visit_functiondef(BST_FunctionDef* node) {
check_if_invoke(node);
for (int i = 0; i < node->num_decorator; ++i) { for (int i = 0; i < node->num_decorator; ++i) {
stream << "@"; stream << "@";
visit_vreg(&node->elts[i]); visit_vreg(&node->elts[i]);
...@@ -1030,23 +1075,23 @@ bool PrintVisitor::visit_functiondef(BST_FunctionDef* node) { ...@@ -1030,23 +1075,23 @@ bool PrintVisitor::visit_functiondef(BST_FunctionDef* node) {
return true; return true;
} }
bool PrintVisitor::visit_invoke(BST_Invoke* node) {
stream << "invoke " << node->normal_dest->idx << " " << node->exc_dest->idx << ": ";
node->stmt->accept(this);
return true;
}
bool PrintVisitor::visit_landingpad(BST_Landingpad* node) { bool PrintVisitor::visit_landingpad(BST_Landingpad* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":LANDINGPAD()"; stream << ":LANDINGPAD()";
return true; return true;
} }
bool PrintVisitor::visit_locals(BST_Locals* node) { bool PrintVisitor::visit_locals(BST_Locals* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":LOCALS()"; stream << ":LOCALS()";
return true; return true;
} }
bool PrintVisitor::visit_getiter(BST_GetIter* node) { bool PrintVisitor::visit_getiter(BST_GetIter* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":GET_ITER("; stream << ":GET_ITER(";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
...@@ -1054,6 +1099,8 @@ bool PrintVisitor::visit_getiter(BST_GetIter* node) { ...@@ -1054,6 +1099,8 @@ bool PrintVisitor::visit_getiter(BST_GetIter* node) {
return true; return true;
} }
bool PrintVisitor::visit_importfrom(BST_ImportFrom* node) { bool PrintVisitor::visit_importfrom(BST_ImportFrom* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":IMPORT_FROM("; stream << ":IMPORT_FROM(";
visit_vreg(&node->vreg_module); visit_vreg(&node->vreg_module);
...@@ -1063,6 +1110,8 @@ bool PrintVisitor::visit_importfrom(BST_ImportFrom* node) { ...@@ -1063,6 +1110,8 @@ bool PrintVisitor::visit_importfrom(BST_ImportFrom* node) {
return true; return true;
} }
bool PrintVisitor::visit_importname(BST_ImportName* node) { bool PrintVisitor::visit_importname(BST_ImportName* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":IMPORT_NAME("; stream << ":IMPORT_NAME(";
visit_vreg(&node->vreg_from); visit_vreg(&node->vreg_from);
...@@ -1072,6 +1121,8 @@ bool PrintVisitor::visit_importname(BST_ImportName* node) { ...@@ -1072,6 +1121,8 @@ bool PrintVisitor::visit_importname(BST_ImportName* node) {
return true; return true;
} }
bool PrintVisitor::visit_importstar(BST_ImportStar* node) { bool PrintVisitor::visit_importstar(BST_ImportStar* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":IMPORT_STAR("; stream << ":IMPORT_STAR(";
visit_vreg(&node->vreg_name); visit_vreg(&node->vreg_name);
...@@ -1079,6 +1130,8 @@ bool PrintVisitor::visit_importstar(BST_ImportStar* node) { ...@@ -1079,6 +1130,8 @@ bool PrintVisitor::visit_importstar(BST_ImportStar* node) {
return true; return true;
} }
bool PrintVisitor::visit_nonzero(BST_Nonzero* node) { bool PrintVisitor::visit_nonzero(BST_Nonzero* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":NONZERO("; stream << ":NONZERO(";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
...@@ -1086,6 +1139,8 @@ bool PrintVisitor::visit_nonzero(BST_Nonzero* node) { ...@@ -1086,6 +1139,8 @@ bool PrintVisitor::visit_nonzero(BST_Nonzero* node) {
return true; return true;
} }
bool PrintVisitor::visit_checkexcmatch(BST_CheckExcMatch* node) { bool PrintVisitor::visit_checkexcmatch(BST_CheckExcMatch* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":CHECK_EXC_MATCH("; stream << ":CHECK_EXC_MATCH(";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
...@@ -1095,6 +1150,8 @@ bool PrintVisitor::visit_checkexcmatch(BST_CheckExcMatch* node) { ...@@ -1095,6 +1150,8 @@ bool PrintVisitor::visit_checkexcmatch(BST_CheckExcMatch* node) {
return true; return true;
} }
bool PrintVisitor::visit_setexcinfo(BST_SetExcInfo* node) { bool PrintVisitor::visit_setexcinfo(BST_SetExcInfo* node) {
check_if_invoke(node);
stream << ":SET_EXC_INFO("; stream << ":SET_EXC_INFO(";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << ", "; stream << ", ";
...@@ -1105,10 +1162,14 @@ bool PrintVisitor::visit_setexcinfo(BST_SetExcInfo* node) { ...@@ -1105,10 +1162,14 @@ bool PrintVisitor::visit_setexcinfo(BST_SetExcInfo* node) {
return true; return true;
} }
bool PrintVisitor::visit_uncacheexcinfo(BST_UncacheExcInfo* node) { bool PrintVisitor::visit_uncacheexcinfo(BST_UncacheExcInfo* node) {
check_if_invoke(node);
stream << ":UNCACHE_EXC_INFO()"; stream << ":UNCACHE_EXC_INFO()";
return true; return true;
} }
bool PrintVisitor::visit_hasnext(BST_HasNext* node) { bool PrintVisitor::visit_hasnext(BST_HasNext* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << ":HAS_NEXT("; stream << ":HAS_NEXT(";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
...@@ -1116,6 +1177,8 @@ bool PrintVisitor::visit_hasnext(BST_HasNext* node) { ...@@ -1116,6 +1177,8 @@ bool PrintVisitor::visit_hasnext(BST_HasNext* node) {
return true; return true;
} }
bool PrintVisitor::visit_printexpr(BST_PrintExpr* node) { bool PrintVisitor::visit_printexpr(BST_PrintExpr* node) {
check_if_invoke(node);
stream << ":PRINT_EXPR("; stream << ":PRINT_EXPR(";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << ")"; stream << ")";
...@@ -1123,6 +1186,8 @@ bool PrintVisitor::visit_printexpr(BST_PrintExpr* node) { ...@@ -1123,6 +1186,8 @@ bool PrintVisitor::visit_printexpr(BST_PrintExpr* node) {
} }
bool PrintVisitor::visit_list(BST_List* node) { bool PrintVisitor::visit_list(BST_List* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "["; stream << "[";
for (int i = 0, n = node->num_elts; i < n; ++i) { for (int i = 0, n = node->num_elts; i < n; ++i) {
...@@ -1135,6 +1200,8 @@ bool PrintVisitor::visit_list(BST_List* node) { ...@@ -1135,6 +1200,8 @@ bool PrintVisitor::visit_list(BST_List* node) {
} }
bool PrintVisitor::visit_print(BST_Print* node) { bool PrintVisitor::visit_print(BST_Print* node) {
check_if_invoke(node);
stream << "print "; stream << "print ";
if (node->vreg_dest != VREG_UNDEFINED) { if (node->vreg_dest != VREG_UNDEFINED) {
stream << ">>"; stream << ">>";
...@@ -1149,6 +1216,8 @@ bool PrintVisitor::visit_print(BST_Print* node) { ...@@ -1149,6 +1216,8 @@ bool PrintVisitor::visit_print(BST_Print* node) {
} }
bool PrintVisitor::visit_raise(BST_Raise* node) { bool PrintVisitor::visit_raise(BST_Raise* node) {
check_if_invoke(node);
stream << "raise"; stream << "raise";
if (node->vreg_arg0 != VREG_UNDEFINED) { if (node->vreg_arg0 != VREG_UNDEFINED) {
stream << " "; stream << " ";
...@@ -1166,6 +1235,8 @@ bool PrintVisitor::visit_raise(BST_Raise* node) { ...@@ -1166,6 +1235,8 @@ bool PrintVisitor::visit_raise(BST_Raise* node) {
} }
bool PrintVisitor::visit_repr(BST_Repr* node) { bool PrintVisitor::visit_repr(BST_Repr* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "`"; stream << "`";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
...@@ -1174,6 +1245,8 @@ bool PrintVisitor::visit_repr(BST_Repr* node) { ...@@ -1174,6 +1245,8 @@ bool PrintVisitor::visit_repr(BST_Repr* node) {
} }
bool PrintVisitor::visit_return(BST_Return* node) { bool PrintVisitor::visit_return(BST_Return* node) {
check_if_invoke(node);
stream << "return "; stream << "return ";
if (node->vreg_value != VREG_UNDEFINED) if (node->vreg_value != VREG_UNDEFINED)
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
...@@ -1181,6 +1254,8 @@ bool PrintVisitor::visit_return(BST_Return* node) { ...@@ -1181,6 +1254,8 @@ bool PrintVisitor::visit_return(BST_Return* node) {
} }
bool PrintVisitor::visit_set(BST_Set* node) { bool PrintVisitor::visit_set(BST_Set* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
// An empty set literal is not writeable in Python (it's a dictionary), // An empty set literal is not writeable in Python (it's a dictionary),
// but we sometimes generate it (ex in set comprehension lowering). // but we sometimes generate it (ex in set comprehension lowering).
...@@ -1204,6 +1279,8 @@ bool PrintVisitor::visit_set(BST_Set* node) { ...@@ -1204,6 +1279,8 @@ bool PrintVisitor::visit_set(BST_Set* node) {
} }
bool PrintVisitor::visit_makeslice(BST_MakeSlice* node) { bool PrintVisitor::visit_makeslice(BST_MakeSlice* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "<slice>("; stream << "<slice>(";
if (node->vreg_lower != VREG_UNDEFINED) if (node->vreg_lower != VREG_UNDEFINED)
...@@ -1221,6 +1298,8 @@ bool PrintVisitor::visit_makeslice(BST_MakeSlice* node) { ...@@ -1221,6 +1298,8 @@ bool PrintVisitor::visit_makeslice(BST_MakeSlice* node) {
} }
bool PrintVisitor::visit_loadname(BST_LoadName* node) { bool PrintVisitor::visit_loadname(BST_LoadName* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) { if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) {
visit_vreg(&node->vreg); visit_vreg(&node->vreg);
...@@ -1231,6 +1310,8 @@ bool PrintVisitor::visit_loadname(BST_LoadName* node) { ...@@ -1231,6 +1310,8 @@ bool PrintVisitor::visit_loadname(BST_LoadName* node) {
} }
bool PrintVisitor::visit_loadattr(BST_LoadAttr* node) { bool PrintVisitor::visit_loadattr(BST_LoadAttr* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << (node->clsonly ? ':' : '.') << code_constants.getInternedString(node->index_attr).s(); stream << (node->clsonly ? ':' : '.') << code_constants.getInternedString(node->index_attr).s();
...@@ -1238,6 +1319,8 @@ bool PrintVisitor::visit_loadattr(BST_LoadAttr* node) { ...@@ -1238,6 +1319,8 @@ bool PrintVisitor::visit_loadattr(BST_LoadAttr* node) {
} }
bool PrintVisitor::visit_loadsub(BST_LoadSub* node) { bool PrintVisitor::visit_loadsub(BST_LoadSub* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << "["; stream << "[";
...@@ -1247,6 +1330,8 @@ bool PrintVisitor::visit_loadsub(BST_LoadSub* node) { ...@@ -1247,6 +1330,8 @@ bool PrintVisitor::visit_loadsub(BST_LoadSub* node) {
} }
bool PrintVisitor::visit_loadsubslice(BST_LoadSubSlice* node) { bool PrintVisitor::visit_loadsubslice(BST_LoadSubSlice* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
stream << "["; stream << "[";
...@@ -1261,6 +1346,8 @@ bool PrintVisitor::visit_loadsubslice(BST_LoadSubSlice* node) { ...@@ -1261,6 +1346,8 @@ bool PrintVisitor::visit_loadsubslice(BST_LoadSubSlice* node) {
} }
bool PrintVisitor::visit_storename(BST_StoreName* node) { bool PrintVisitor::visit_storename(BST_StoreName* node) {
check_if_invoke(node);
if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) { if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) {
visit_vreg(&node->vreg); visit_vreg(&node->vreg);
stream << " "; stream << " ";
...@@ -1272,6 +1359,8 @@ bool PrintVisitor::visit_storename(BST_StoreName* node) { ...@@ -1272,6 +1359,8 @@ bool PrintVisitor::visit_storename(BST_StoreName* node) {
} }
bool PrintVisitor::visit_storeattr(BST_StoreAttr* node) { bool PrintVisitor::visit_storeattr(BST_StoreAttr* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_target); visit_vreg(&node->vreg_target);
stream << "." << code_constants.getInternedString(node->index_attr).s() << " = "; stream << "." << code_constants.getInternedString(node->index_attr).s() << " = ";
visit_vreg(&node->vreg_value); visit_vreg(&node->vreg_value);
...@@ -1279,6 +1368,8 @@ bool PrintVisitor::visit_storeattr(BST_StoreAttr* node) { ...@@ -1279,6 +1368,8 @@ bool PrintVisitor::visit_storeattr(BST_StoreAttr* node) {
} }
bool PrintVisitor::visit_storesub(BST_StoreSub* node) { bool PrintVisitor::visit_storesub(BST_StoreSub* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_target); visit_vreg(&node->vreg_target);
stream << "["; stream << "[";
visit_vreg(&node->vreg_slice); visit_vreg(&node->vreg_slice);
...@@ -1288,6 +1379,8 @@ bool PrintVisitor::visit_storesub(BST_StoreSub* node) { ...@@ -1288,6 +1379,8 @@ bool PrintVisitor::visit_storesub(BST_StoreSub* node) {
} }
bool PrintVisitor::visit_storesubslice(BST_StoreSubSlice* node) { bool PrintVisitor::visit_storesubslice(BST_StoreSubSlice* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_target); visit_vreg(&node->vreg_target);
stream << "["; stream << "[";
if (node->vreg_lower != VREG_UNDEFINED) if (node->vreg_lower != VREG_UNDEFINED)
...@@ -1302,6 +1395,8 @@ bool PrintVisitor::visit_storesubslice(BST_StoreSubSlice* node) { ...@@ -1302,6 +1395,8 @@ bool PrintVisitor::visit_storesubslice(BST_StoreSubSlice* node) {
} }
bool PrintVisitor::visit_tuple(BST_Tuple* node) { bool PrintVisitor::visit_tuple(BST_Tuple* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "("; stream << "(";
int n = node->num_elts; int n = node->num_elts;
...@@ -1317,6 +1412,8 @@ bool PrintVisitor::visit_tuple(BST_Tuple* node) { ...@@ -1317,6 +1412,8 @@ bool PrintVisitor::visit_tuple(BST_Tuple* node) {
} }
bool PrintVisitor::visit_unaryop(BST_UnaryOp* node) { bool PrintVisitor::visit_unaryop(BST_UnaryOp* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
switch (node->op_type) { switch (node->op_type) {
case AST_TYPE::Invert: case AST_TYPE::Invert:
...@@ -1342,6 +1439,8 @@ bool PrintVisitor::visit_unaryop(BST_UnaryOp* node) { ...@@ -1342,6 +1439,8 @@ bool PrintVisitor::visit_unaryop(BST_UnaryOp* node) {
} }
bool PrintVisitor::visit_unpackintoarray(BST_UnpackIntoArray* node) { bool PrintVisitor::visit_unpackintoarray(BST_UnpackIntoArray* node) {
check_if_invoke(node);
stream << "("; stream << "(";
for (int i = 0; i < node->num_elts; ++i) { for (int i = 0; i < node->num_elts; ++i) {
visit_vreg(&node->vreg_dst[i]); visit_vreg(&node->vreg_dst[i]);
...@@ -1355,6 +1454,8 @@ bool PrintVisitor::visit_unpackintoarray(BST_UnpackIntoArray* node) { ...@@ -1355,6 +1454,8 @@ bool PrintVisitor::visit_unpackintoarray(BST_UnpackIntoArray* node) {
} }
bool PrintVisitor::visit_yield(BST_Yield* node) { bool PrintVisitor::visit_yield(BST_Yield* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "yield "; stream << "yield ";
if (node->vreg_value != VREG_UNDEFINED) if (node->vreg_value != VREG_UNDEFINED)
...@@ -1363,6 +1464,8 @@ bool PrintVisitor::visit_yield(BST_Yield* node) { ...@@ -1363,6 +1464,8 @@ bool PrintVisitor::visit_yield(BST_Yield* node) {
} }
bool PrintVisitor::visit_branch(BST_Branch* node) { bool PrintVisitor::visit_branch(BST_Branch* node) {
check_if_invoke(node);
stream << "if "; stream << "if ";
visit_vreg(&node->vreg_test); visit_vreg(&node->vreg_test);
stream << " goto " << node->iftrue->idx << " else goto " << node->iffalse->idx; stream << " goto " << node->iftrue->idx << " else goto " << node->iffalse->idx;
...@@ -1370,17 +1473,23 @@ bool PrintVisitor::visit_branch(BST_Branch* node) { ...@@ -1370,17 +1473,23 @@ bool PrintVisitor::visit_branch(BST_Branch* node) {
} }
bool PrintVisitor::visit_jump(BST_Jump* node) { bool PrintVisitor::visit_jump(BST_Jump* node) {
check_if_invoke(node);
stream << "goto " << node->target->idx; stream << "goto " << node->target->idx;
return true; return true;
} }
bool PrintVisitor::visit_makefunction(BST_MakeFunction* node) { bool PrintVisitor::visit_makefunction(BST_MakeFunction* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "make_"; stream << "make_";
return false; return false;
} }
bool PrintVisitor::visit_makeclass(BST_MakeClass* node) { bool PrintVisitor::visit_makeclass(BST_MakeClass* node) {
check_if_invoke(node);
visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_dst, true);
stream << "make_"; stream << "make_";
return false; return false;
......
...@@ -58,35 +58,34 @@ namespace BST_TYPE { ...@@ -58,35 +58,34 @@ namespace BST_TYPE {
X(ImportFrom, 21) \ X(ImportFrom, 21) \
X(ImportName, 22) \ X(ImportName, 22) \
X(ImportStar, 23) \ X(ImportStar, 23) \
X(Invoke, 24) \ X(Jump, 24) \
X(Jump, 25) \ X(Landingpad, 25) \
X(Landingpad, 26) \ X(List, 26) \
X(List, 27) \ X(LoadAttr, 27) \
X(LoadAttr, 28) \ X(LoadName, 28) \
X(LoadName, 29) \ X(LoadSub, 29) \
X(LoadSub, 30) \ X(LoadSubSlice, 30) \
X(LoadSubSlice, 31) \ X(Locals, 31) \
X(Locals, 32) \ X(MakeClass, 32) \
X(MakeClass, 33) \ X(MakeFunction, 33) \
X(MakeFunction, 34) \ X(MakeSlice, 34) \
X(MakeSlice, 35) \ X(Nonzero, 35) \
X(Nonzero, 36) \ X(Print, 36) \
X(Print, 37) \ X(PrintExpr, 37) \
X(PrintExpr, 38) \ X(Raise, 38) \
X(Raise, 39) \ X(Repr, 39) \
X(Repr, 40) \ X(Return, 40) \
X(Return, 41) \ X(Set, 41) \
X(Set, 42) \ X(SetExcInfo, 42) \
X(SetExcInfo, 43) \ X(StoreAttr, 43) \
X(StoreAttr, 44) \ X(StoreName, 44) \
X(StoreName, 45) \ X(StoreSub, 45) \
X(StoreSub, 46) \ X(StoreSubSlice, 46) \
X(StoreSubSlice, 47) \ X(Tuple, 47) \
X(Tuple, 48) \ X(UnaryOp, 48) \
X(UnaryOp, 49) \ X(UncacheExcInfo, 49) \
X(UncacheExcInfo, 50) \ X(UnpackIntoArray, 50) \
X(UnpackIntoArray, 51) \ X(Yield, 51)
X(Yield, 52)
#define GENERATE_ENUM(ENUM, N) ENUM = N, #define GENERATE_ENUM(ENUM, N) ENUM = N,
#define GENERATE_STRING(STRING, N) m[N] = #STRING; #define GENERATE_STRING(STRING, N) m[N] = #STRING;
...@@ -99,7 +98,6 @@ static const char* stringify(int n) { ...@@ -99,7 +98,6 @@ static const char* stringify(int n) {
return m[n]; return m[n];
} }
#undef FOREACH_TYPE
#undef GENERATE_ENUM #undef GENERATE_ENUM
#undef GENERATE_STRING #undef GENERATE_STRING
}; };
...@@ -128,17 +126,78 @@ static constexpr int VREG_UNDEFINED = std::numeric_limits<int>::min(); ...@@ -128,17 +126,78 @@ static constexpr int VREG_UNDEFINED = std::numeric_limits<int>::min();
// in order to make it easier for a human to understand we print the actual value of the constant between | characters. // in order to make it easier for a human to understand we print the actual value of the constant between | characters.
#define PACKED __attribute__((packed)) __attribute__((__aligned__(1)))
class BSTAllocator {
public:
BSTAllocator() = default;
BSTAllocator(BSTAllocator&) = delete;
void* allocate(int num_bytes) {
mem.resize(mem.size() + num_bytes, 0);
return &mem[mem.size() - num_bytes];
}
template <typename T> T* allocate() { return (T*)allocate(sizeof(T)); }
void reserve(int num_bytes) { mem.reserve(num_bytes); }
int getOffset(void* ptr) const {
auto offset = (unsigned char*)ptr - mem.data();
// assert(offset >= 0);
return offset;
}
int getSize() const { return mem.size(); }
void optimizeSize() { mem.shrink_to_fit(); }
unsigned char* getData() { return mem.data(); }
bool isInside(void* ptr) const { return ptr >= mem.data() && ptr <= &mem.back(); }
private:
std::vector<unsigned char> mem;
};
class BST_stmt { class BST_stmt {
public: public:
virtual ~BST_stmt() {} static constexpr unsigned char invoke_flag = 64;
// contains the opcode which can have the invoke bit set which signals that this stmt is inside a invoke and that a
// pointer to the normal CFGBlock and the exception block follow directly after the last field in the instruction.
unsigned char type_and_flags;
const BST_TYPE::BST_TYPE type;
uint32_t lineno; uint32_t lineno;
virtual void accept(BSTVisitor* v) = 0;
virtual void accept_stmt(StmtVisitor* v) = 0;
virtual bool has_dest_vreg() const { return false; } BST_TYPE::BST_TYPE type() const { return (BST_TYPE::BST_TYPE)(type_and_flags & (~invoke_flag)); }
bool is_invoke() const { return type_and_flags & invoke_flag; }
CFGBlock* get_normal_block() const {
assert(is_invoke());
return ((CFGBlock * const*)&((const unsigned char*)this)[size_in_bytes()])[-2];
}
CFGBlock* get_exc_block() const {
assert(is_invoke());
return ((CFGBlock * const*)&((const unsigned char*)this)[size_in_bytes()])[-1];
}
// if this instruction is inside a invoke it will return the size including the two CFGBlock* it contains
inline int size_in_bytes() const __attribute__((always_inline));
inline bool has_dest_vreg() const __attribute__((always_inline));
bool is_terminator() const __attribute__((always_inline)) {
if (is_invoke())
return true;
switch (type_and_flags) {
case BST_TYPE::Assert:
case BST_TYPE::Branch:
case BST_TYPE::Jump:
case BST_TYPE::Raise:
case BST_TYPE::Return:
return true;
default:
return false;
}
}
void accept(BSTVisitor* v);
void accept_stmt(StmtVisitor* v);
// #define DEBUG_LINE_NUMBERS 1 // #define DEBUG_LINE_NUMBERS 1
#ifdef DEBUG_LINE_NUMBERS #ifdef DEBUG_LINE_NUMBERS
...@@ -150,10 +209,10 @@ private: ...@@ -150,10 +209,10 @@ private:
public: public:
BST_stmt(BST_TYPE::BST_TYPE type); BST_stmt(BST_TYPE::BST_TYPE type);
#else #else
BST_stmt(BST_TYPE::BST_TYPE type) : type(type), lineno(0) {} BST_stmt(BST_TYPE::BST_TYPE type) : type_and_flags(type), lineno(0) {}
#endif #endif
BST_stmt(BST_TYPE::BST_TYPE type, uint32_t lineno) : type(type), lineno(lineno) {} BST_stmt(BST_TYPE::BST_TYPE type, uint32_t lineno) : type_and_flags(type), lineno(lineno) {}
}; } PACKED;
// base class of all nodes which have a single destination vreg // base class of all nodes which have a single destination vreg
class BST_stmt_with_dest : public BST_stmt { class BST_stmt_with_dest : public BST_stmt {
...@@ -161,28 +220,33 @@ public: ...@@ -161,28 +220,33 @@ public:
int vreg_dst = VREG_UNDEFINED; int vreg_dst = VREG_UNDEFINED;
BST_stmt_with_dest(BST_TYPE::BST_TYPE type) : BST_stmt(type) {} BST_stmt_with_dest(BST_TYPE::BST_TYPE type) : BST_stmt(type) {}
BST_stmt_with_dest(BST_TYPE::BST_TYPE type, int lineno) : BST_stmt(type, lineno) {} BST_stmt_with_dest(BST_TYPE::BST_TYPE type, int lineno) : BST_stmt(type, lineno) {}
} PACKED;
bool has_dest_vreg() const override { return true; }
};
#define BSTNODE(opcode) \ #define BSTNODE(opcode) \
virtual void accept(BSTVisitor* v); \ void accept(BSTVisitor* v); \
virtual void accept_stmt(StmtVisitor* v); \ void accept_stmt(StmtVisitor* v); \
static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::opcode; static const BST_TYPE::BST_TYPE TYPE = BST_TYPE::opcode;
#define BSTFIXEDVREGS(opcode, base_class) \ #define BSTFIXEDVREGS(opcode, base_class) \
BSTNODE(opcode) \ BSTNODE(opcode) \
BST_##opcode() : base_class(BST_TYPE::opcode) {} static BST_##opcode* create(BSTAllocator& alloc) { return new (alloc) BST_##opcode(); } \
BST_##opcode() : base_class(BST_TYPE::opcode) {} \
int size_in_bytes() const { return sizeof(*this); } \
static void* operator new(size_t s, BSTAllocator & alloc) { return alloc.allocate(s); } \
static void operator delete(void* ptr) { RELEASE_ASSERT(0, ""); }
#define BSTVARVREGS(opcode, base_class, num_elts, vreg_dst) \ #define BSTVARVREGS(opcode, base_class, num_elts, vreg_dst) \
public: \ public: \
BSTNODE(opcode) \ BSTNODE(opcode) \
static BST_##opcode* create(int num_elts) { return new (num_elts) BST_##opcode(num_elts); } \ static BST_##opcode* create(BSTAllocator& alloc, int num_elts) { \
static void operator delete(void* ptr) { ::operator delete[](ptr); } \ return new (alloc, num_elts) BST_##opcode(num_elts); \
} \
static void operator delete(void* ptr) { RELEASE_ASSERT(0, ""); } \
int size_in_bytes() const { return offsetof(BST_##opcode, vreg_dst) + num_elts * sizeof(int); } \
\ \
private: \ private: \
static void* operator new(size_t, int num_elts) { \ static void* operator new(size_t, BSTAllocator & alloc, int num_elts) { \
return ::new char[offsetof(BST_##opcode, vreg_dst) + num_elts * sizeof(int)]; \ return alloc.allocate(offsetof(BST_##opcode, vreg_dst) + num_elts * sizeof(int)); \
} \ } \
BST_##opcode(int num_elts) : base_class(BST_TYPE::opcode), num_elts(num_elts) { \ BST_##opcode(int num_elts) : base_class(BST_TYPE::opcode), num_elts(num_elts) { \
for (int i = 0; i < num_elts; ++i) { \ for (int i = 0; i < num_elts; ++i) { \
...@@ -193,14 +257,15 @@ private: ...@@ -193,14 +257,15 @@ private:
#define BSTVARVREGS2(opcode, base_class, num_elts, num_elts2, vreg_dst) \ #define BSTVARVREGS2(opcode, base_class, num_elts, num_elts2, vreg_dst) \
public: \ public: \
BSTNODE(opcode) \ BSTNODE(opcode) \
static BST_##opcode* create(int num_elts, int num_elts2) { \ static BST_##opcode* create(BSTAllocator& alloc, int num_elts, int num_elts2) { \
return new (num_elts + num_elts2) BST_##opcode(num_elts, num_elts2); \ return new (alloc, num_elts + num_elts2) BST_##opcode(num_elts, num_elts2); \
} \ } \
static void operator delete(void* ptr) { ::operator delete[](ptr); } \ static void operator delete(void* ptr) { ::operator delete[](ptr); } \
int size_in_bytes() const { return offsetof(BST_##opcode, vreg_dst) + (num_elts + num_elts2) * sizeof(int); } \
\ \
private: \ private: \
static void* operator new(size_t, int num_elts_total) { \ static void* operator new(size_t, BSTAllocator & alloc, int num_elts_total) { \
return ::new char[offsetof(BST_##opcode, vreg_dst) + num_elts_total * sizeof(int)]; \ return alloc.allocate(offsetof(BST_##opcode, vreg_dst) + num_elts_total * sizeof(int)); \
} \ } \
BST_##opcode(int num_elts, int num_elts2) \ BST_##opcode(int num_elts, int num_elts2) \
: base_class(BST_TYPE::opcode), num_elts(num_elts), num_elts2(num_elts2) { \ : base_class(BST_TYPE::opcode), num_elts(num_elts), num_elts2(num_elts2) { \
...@@ -212,14 +277,15 @@ private: ...@@ -212,14 +277,15 @@ private:
#define BSTVARVREGS2CALL(opcode, num_elts, num_elts2, vreg_dst) \ #define BSTVARVREGS2CALL(opcode, num_elts, num_elts2, vreg_dst) \
public: \ public: \
BSTNODE(opcode) \ BSTNODE(opcode) \
static BST_##opcode* create(int num_elts, int num_elts2) { \ static BST_##opcode* create(BSTAllocator& alloc, int num_elts, int num_elts2) { \
return new (num_elts + num_elts2) BST_##opcode(num_elts, num_elts2); \ return new (alloc, num_elts + num_elts2) BST_##opcode(num_elts, num_elts2); \
} \ } \
static void operator delete(void* ptr) { ::operator delete[](ptr); } \ static void operator delete(void* ptr) { RELEASE_ASSERT(0, ""); } \
int size_in_bytes() const { return offsetof(BST_##opcode, vreg_dst) + (num_elts + num_elts2) * sizeof(int); } \
\ \
private: \ private: \
static void* operator new(size_t, int num_elts_total) { \ static void* operator new(size_t, BSTAllocator & alloc, int num_elts_total) { \
return ::new char[offsetof(BST_##opcode, vreg_dst) + num_elts_total * sizeof(int)]; \ return alloc.allocate(offsetof(BST_##opcode, vreg_dst) + num_elts_total * sizeof(int)); \
} \ } \
BST_##opcode(int num_elts, int num_elts2) : BST_Call(BST_TYPE::opcode, num_elts, num_elts2) { \ BST_##opcode(int num_elts, int num_elts2) : BST_Call(BST_TYPE::opcode, num_elts, num_elts2) { \
for (int i = 0; i < num_elts + num_elts2; ++i) { \ for (int i = 0; i < num_elts + num_elts2; ++i) { \
...@@ -232,7 +298,7 @@ public: ...@@ -232,7 +298,7 @@ public:
int vreg_msg = VREG_UNDEFINED; int vreg_msg = VREG_UNDEFINED;
BSTFIXEDVREGS(Assert, BST_stmt) BSTFIXEDVREGS(Assert, BST_stmt)
}; } PACKED;
class BST_UnpackIntoArray : public BST_stmt { class BST_UnpackIntoArray : public BST_stmt {
public: public:
...@@ -241,7 +307,7 @@ public: ...@@ -241,7 +307,7 @@ public:
int vreg_dst[1]; int vreg_dst[1];
BSTVARVREGS(UnpackIntoArray, BST_stmt, num_elts, vreg_dst) BSTVARVREGS(UnpackIntoArray, BST_stmt, num_elts, vreg_dst)
}; } PACKED;
// This is a special instruction which copies a vreg without destroying the source. // This is a special instruction which copies a vreg without destroying the source.
// All other instructions always kill the operands (except if they are a constant) so if one needs the operand to stay // All other instructions always kill the operands (except if they are a constant) so if one needs the operand to stay
...@@ -251,7 +317,7 @@ public: ...@@ -251,7 +317,7 @@ public:
int vreg_src = VREG_UNDEFINED; // this vreg will not get killed! int vreg_src = VREG_UNDEFINED; // this vreg will not get killed!
BSTFIXEDVREGS(CopyVReg, BST_stmt_with_dest) BSTFIXEDVREGS(CopyVReg, BST_stmt_with_dest)
}; } PACKED;
class BST_StoreName : public BST_stmt { class BST_StoreName : public BST_stmt {
...@@ -268,7 +334,7 @@ public: ...@@ -268,7 +334,7 @@ public:
int closure_offset = -1; int closure_offset = -1;
BSTFIXEDVREGS(StoreName, BST_stmt) BSTFIXEDVREGS(StoreName, BST_stmt)
}; } PACKED;
class BST_StoreAttr : public BST_stmt { class BST_StoreAttr : public BST_stmt {
public: public:
...@@ -277,7 +343,7 @@ public: ...@@ -277,7 +343,7 @@ public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(StoreAttr, BST_stmt) BSTFIXEDVREGS(StoreAttr, BST_stmt)
}; } PACKED;
class BST_StoreSub : public BST_stmt { class BST_StoreSub : public BST_stmt {
public: public:
...@@ -286,7 +352,7 @@ public: ...@@ -286,7 +352,7 @@ public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(StoreSub, BST_stmt) BSTFIXEDVREGS(StoreSub, BST_stmt)
}; } PACKED;
class BST_StoreSubSlice : public BST_stmt { class BST_StoreSubSlice : public BST_stmt {
public: public:
...@@ -295,7 +361,7 @@ public: ...@@ -295,7 +361,7 @@ public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(StoreSubSlice, BST_stmt) BSTFIXEDVREGS(StoreSubSlice, BST_stmt)
}; } PACKED;
class BST_LoadName : public BST_stmt_with_dest { class BST_LoadName : public BST_stmt_with_dest {
public: public:
...@@ -310,7 +376,7 @@ public: ...@@ -310,7 +376,7 @@ public:
int closure_offset = -1; int closure_offset = -1;
BSTFIXEDVREGS(LoadName, BST_stmt_with_dest) BSTFIXEDVREGS(LoadName, BST_stmt_with_dest)
}; } PACKED;
class BST_LoadAttr : public BST_stmt_with_dest { class BST_LoadAttr : public BST_stmt_with_dest {
public: public:
...@@ -319,7 +385,7 @@ public: ...@@ -319,7 +385,7 @@ public:
bool clsonly = false; bool clsonly = false;
BSTFIXEDVREGS(LoadAttr, BST_stmt_with_dest) BSTFIXEDVREGS(LoadAttr, BST_stmt_with_dest)
}; } PACKED;
class BST_LoadSub : public BST_stmt_with_dest { class BST_LoadSub : public BST_stmt_with_dest {
public: public:
...@@ -327,7 +393,7 @@ public: ...@@ -327,7 +393,7 @@ public:
int vreg_slice = VREG_UNDEFINED; int vreg_slice = VREG_UNDEFINED;
BSTFIXEDVREGS(LoadSub, BST_stmt_with_dest) BSTFIXEDVREGS(LoadSub, BST_stmt_with_dest)
}; } PACKED;
class BST_LoadSubSlice : public BST_stmt_with_dest { class BST_LoadSubSlice : public BST_stmt_with_dest {
public: public:
...@@ -335,7 +401,7 @@ public: ...@@ -335,7 +401,7 @@ public:
int vreg_lower = VREG_UNDEFINED, vreg_upper = VREG_UNDEFINED; int vreg_lower = VREG_UNDEFINED, vreg_upper = VREG_UNDEFINED;
BSTFIXEDVREGS(LoadSubSlice, BST_stmt_with_dest) BSTFIXEDVREGS(LoadSubSlice, BST_stmt_with_dest)
}; } PACKED;
class BST_AugBinOp : public BST_stmt_with_dest { class BST_AugBinOp : public BST_stmt_with_dest {
public: public:
...@@ -343,7 +409,7 @@ public: ...@@ -343,7 +409,7 @@ public:
int vreg_left = VREG_UNDEFINED, vreg_right = VREG_UNDEFINED; int vreg_left = VREG_UNDEFINED, vreg_right = VREG_UNDEFINED;
BSTFIXEDVREGS(AugBinOp, BST_stmt_with_dest) BSTFIXEDVREGS(AugBinOp, BST_stmt_with_dest)
}; } PACKED;
class BST_BinOp : public BST_stmt_with_dest { class BST_BinOp : public BST_stmt_with_dest {
public: public:
...@@ -351,7 +417,7 @@ public: ...@@ -351,7 +417,7 @@ public:
int vreg_left = VREG_UNDEFINED, vreg_right = VREG_UNDEFINED; int vreg_left = VREG_UNDEFINED, vreg_right = VREG_UNDEFINED;
BSTFIXEDVREGS(BinOp, BST_stmt_with_dest) BSTFIXEDVREGS(BinOp, BST_stmt_with_dest)
}; } PACKED;
class BST_Call : public BST_stmt_with_dest { class BST_Call : public BST_stmt_with_dest {
public: public:
...@@ -363,7 +429,7 @@ public: ...@@ -363,7 +429,7 @@ public:
BST_Call(BST_TYPE::BST_TYPE type, int num_args, int num_keywords) BST_Call(BST_TYPE::BST_TYPE type, int num_args, int num_keywords)
: BST_stmt_with_dest(type), num_args(num_args), num_keywords(num_keywords) {} : BST_stmt_with_dest(type), num_args(num_args), num_keywords(num_keywords) {}
}; } PACKED;
class BST_CallFunc : public BST_Call { class BST_CallFunc : public BST_Call {
public: public:
...@@ -371,7 +437,7 @@ public: ...@@ -371,7 +437,7 @@ public:
int elts[1]; int elts[1];
BSTVARVREGS2CALL(CallFunc, num_args, num_keywords, elts) BSTVARVREGS2CALL(CallFunc, num_args, num_keywords, elts)
}; } PACKED;
class BST_CallAttr : public BST_Call { class BST_CallAttr : public BST_Call {
public: public:
...@@ -380,7 +446,7 @@ public: ...@@ -380,7 +446,7 @@ public:
int elts[1]; int elts[1];
BSTVARVREGS2CALL(CallAttr, num_args, num_keywords, elts) BSTVARVREGS2CALL(CallAttr, num_args, num_keywords, elts)
}; } PACKED;
class BST_CallClsAttr : public BST_Call { class BST_CallClsAttr : public BST_Call {
public: public:
...@@ -389,7 +455,7 @@ public: ...@@ -389,7 +455,7 @@ public:
int elts[1]; int elts[1];
BSTVARVREGS2CALL(CallClsAttr, num_args, num_keywords, elts) BSTVARVREGS2CALL(CallClsAttr, num_args, num_keywords, elts)
}; } PACKED;
class BST_Compare : public BST_stmt_with_dest { class BST_Compare : public BST_stmt_with_dest {
...@@ -399,7 +465,7 @@ public: ...@@ -399,7 +465,7 @@ public:
int vreg_left = VREG_UNDEFINED; int vreg_left = VREG_UNDEFINED;
BSTFIXEDVREGS(Compare, BST_stmt_with_dest) BSTFIXEDVREGS(Compare, BST_stmt_with_dest)
}; } PACKED;
class BST_ClassDef : public BST_stmt { class BST_ClassDef : public BST_stmt {
public: public:
...@@ -408,13 +474,18 @@ public: ...@@ -408,13 +474,18 @@ public:
const int num_decorator; const int num_decorator;
int decorator[1]; int decorator[1];
static BST_ClassDef* create(int num_decorator) { return new (num_decorator) BST_ClassDef(num_decorator); }
static void* operator new(size_t, int num_decorator) {
return ::new unsigned char[offsetof(BST_ClassDef, decorator) + num_decorator * sizeof(int)];
}
BSTVARVREGS(ClassDef, BST_stmt, num_decorator, decorator) BSTVARVREGS(ClassDef, BST_stmt, num_decorator, decorator)
}; } PACKED;
class BST_Dict : public BST_stmt_with_dest { class BST_Dict : public BST_stmt_with_dest {
public: public:
BSTFIXEDVREGS(Dict, BST_stmt_with_dest) BSTFIXEDVREGS(Dict, BST_stmt_with_dest)
}; } PACKED;
class BST_DeleteAttr : public BST_stmt { class BST_DeleteAttr : public BST_stmt {
public: public:
...@@ -422,7 +493,7 @@ public: ...@@ -422,7 +493,7 @@ public:
int index_attr = VREG_UNDEFINED; int index_attr = VREG_UNDEFINED;
BSTFIXEDVREGS(DeleteAttr, BST_stmt) BSTFIXEDVREGS(DeleteAttr, BST_stmt)
}; } PACKED;
class BST_DeleteName : public BST_stmt { class BST_DeleteName : public BST_stmt {
public: public:
...@@ -436,7 +507,7 @@ public: ...@@ -436,7 +507,7 @@ public:
int closure_offset = -1; int closure_offset = -1;
BSTFIXEDVREGS(DeleteName, BST_stmt) BSTFIXEDVREGS(DeleteName, BST_stmt)
}; } PACKED;
class BST_DeleteSub : public BST_stmt { class BST_DeleteSub : public BST_stmt {
public: public:
...@@ -444,7 +515,7 @@ public: ...@@ -444,7 +515,7 @@ public:
int vreg_slice = VREG_UNDEFINED; int vreg_slice = VREG_UNDEFINED;
BSTFIXEDVREGS(DeleteSub, BST_stmt) BSTFIXEDVREGS(DeleteSub, BST_stmt)
}; } PACKED;
class BST_DeleteSubSlice : public BST_stmt { class BST_DeleteSubSlice : public BST_stmt {
public: public:
...@@ -453,7 +524,7 @@ public: ...@@ -453,7 +524,7 @@ public:
int vreg_upper = VREG_UNDEFINED; int vreg_upper = VREG_UNDEFINED;
BSTFIXEDVREGS(DeleteSubSlice, BST_stmt) BSTFIXEDVREGS(DeleteSubSlice, BST_stmt)
}; } PACKED;
class BST_Exec : public BST_stmt { class BST_Exec : public BST_stmt {
public: public:
...@@ -462,7 +533,7 @@ public: ...@@ -462,7 +533,7 @@ public:
int vreg_locals = VREG_UNDEFINED; int vreg_locals = VREG_UNDEFINED;
BSTFIXEDVREGS(Exec, BST_stmt) BSTFIXEDVREGS(Exec, BST_stmt)
}; } PACKED;
class BST_FunctionDef : public BST_stmt { class BST_FunctionDef : public BST_stmt {
public: public:
...@@ -473,8 +544,15 @@ public: ...@@ -473,8 +544,15 @@ public:
int elts[1]; // decorators followed by defaults int elts[1]; // decorators followed by defaults
static BST_FunctionDef* create(int num_decorator, int num_defaults) {
return new (num_decorator + num_defaults) BST_FunctionDef(num_decorator, num_defaults);
}
static void* operator new(size_t, int num_elts) {
return ::new unsigned char[offsetof(BST_FunctionDef, elts) + num_elts * sizeof(int)];
}
BSTVARVREGS2(FunctionDef, BST_stmt, num_decorator, num_defaults, elts) BSTVARVREGS2(FunctionDef, BST_stmt, num_decorator, num_defaults, elts)
}; } PACKED;
class BST_List : public BST_stmt_with_dest { class BST_List : public BST_stmt_with_dest {
public: public:
...@@ -482,14 +560,14 @@ public: ...@@ -482,14 +560,14 @@ public:
int elts[1]; int elts[1];
BSTVARVREGS(List, BST_stmt_with_dest, num_elts, elts) BSTVARVREGS(List, BST_stmt_with_dest, num_elts, elts)
}; } PACKED;
class BST_Repr : public BST_stmt_with_dest { class BST_Repr : public BST_stmt_with_dest {
public: public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(Repr, BST_stmt_with_dest) BSTFIXEDVREGS(Repr, BST_stmt_with_dest)
}; } PACKED;
class BST_Print : public BST_stmt { class BST_Print : public BST_stmt {
public: public:
...@@ -498,7 +576,7 @@ public: ...@@ -498,7 +576,7 @@ public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(Print, BST_stmt) BSTFIXEDVREGS(Print, BST_stmt)
}; } PACKED;
class BST_Raise : public BST_stmt { class BST_Raise : public BST_stmt {
public: public:
...@@ -509,14 +587,14 @@ public: ...@@ -509,14 +587,14 @@ public:
int vreg_arg0 = VREG_UNDEFINED, vreg_arg1 = VREG_UNDEFINED, vreg_arg2 = VREG_UNDEFINED; int vreg_arg0 = VREG_UNDEFINED, vreg_arg1 = VREG_UNDEFINED, vreg_arg2 = VREG_UNDEFINED;
BSTFIXEDVREGS(Raise, BST_stmt) BSTFIXEDVREGS(Raise, BST_stmt)
}; } PACKED;
class BST_Return : public BST_stmt { class BST_Return : public BST_stmt {
public: public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(Return, BST_stmt) BSTFIXEDVREGS(Return, BST_stmt)
}; } PACKED;
class BST_Set : public BST_stmt_with_dest { class BST_Set : public BST_stmt_with_dest {
public: public:
...@@ -524,14 +602,14 @@ public: ...@@ -524,14 +602,14 @@ public:
int elts[1]; int elts[1];
BSTVARVREGS(Set, BST_stmt_with_dest, num_elts, elts) BSTVARVREGS(Set, BST_stmt_with_dest, num_elts, elts)
}; } PACKED;
class BST_MakeSlice : public BST_stmt_with_dest { class BST_MakeSlice : public BST_stmt_with_dest {
public: public:
int vreg_lower = VREG_UNDEFINED, vreg_upper = VREG_UNDEFINED, vreg_step = VREG_UNDEFINED; int vreg_lower = VREG_UNDEFINED, vreg_upper = VREG_UNDEFINED, vreg_step = VREG_UNDEFINED;
BSTFIXEDVREGS(MakeSlice, BST_stmt_with_dest) BSTFIXEDVREGS(MakeSlice, BST_stmt_with_dest)
}; } PACKED;
class BST_Tuple : public BST_stmt_with_dest { class BST_Tuple : public BST_stmt_with_dest {
public: public:
...@@ -539,7 +617,7 @@ public: ...@@ -539,7 +617,7 @@ public:
int elts[1]; int elts[1];
BSTVARVREGS(Tuple, BST_stmt_with_dest, num_elts, elts) BSTVARVREGS(Tuple, BST_stmt_with_dest, num_elts, elts)
}; } PACKED;
class BST_UnaryOp : public BST_stmt_with_dest { class BST_UnaryOp : public BST_stmt_with_dest {
public: public:
...@@ -547,14 +625,14 @@ public: ...@@ -547,14 +625,14 @@ public:
AST_TYPE::AST_TYPE op_type; AST_TYPE::AST_TYPE op_type;
BSTFIXEDVREGS(UnaryOp, BST_stmt_with_dest) BSTFIXEDVREGS(UnaryOp, BST_stmt_with_dest)
}; } PACKED;
class BST_Yield : public BST_stmt_with_dest { class BST_Yield : public BST_stmt_with_dest {
public: public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(Yield, BST_stmt_with_dest) BSTFIXEDVREGS(Yield, BST_stmt_with_dest)
}; } PACKED;
class BST_MakeFunction : public BST_stmt_with_dest { class BST_MakeFunction : public BST_stmt_with_dest {
public: public:
...@@ -562,9 +640,17 @@ public: ...@@ -562,9 +640,17 @@ public:
BST_MakeFunction(BST_FunctionDef* fd, int index_func_def) BST_MakeFunction(BST_FunctionDef* fd, int index_func_def)
: BST_stmt_with_dest(BST_TYPE::MakeFunction, fd->lineno), index_func_def(index_func_def) {} : BST_stmt_with_dest(BST_TYPE::MakeFunction, fd->lineno), index_func_def(index_func_def) {}
int size_in_bytes() const { return sizeof(*this); }
static BST_MakeFunction* create(BSTAllocator& alloc, BST_FunctionDef* fd, int index_func_def) {
return new (alloc) BST_MakeFunction(fd, index_func_def);
}
static void* operator new(size_t s, BSTAllocator& alloc) { return alloc.allocate(s); }
static void operator delete(void* ptr) { RELEASE_ASSERT(0, ""); }
BSTNODE(MakeFunction) BSTNODE(MakeFunction)
}; } PACKED;
class BST_MakeClass : public BST_stmt_with_dest { class BST_MakeClass : public BST_stmt_with_dest {
public: public:
...@@ -572,9 +658,17 @@ public: ...@@ -572,9 +658,17 @@ public:
BST_MakeClass(BST_ClassDef* cd, int index_class_def) BST_MakeClass(BST_ClassDef* cd, int index_class_def)
: BST_stmt_with_dest(BST_TYPE::MakeClass, cd->lineno), index_class_def(index_class_def) {} : BST_stmt_with_dest(BST_TYPE::MakeClass, cd->lineno), index_class_def(index_class_def) {}
int size_in_bytes() const { return sizeof(*this); }
static BST_MakeClass* create(BSTAllocator& alloc, BST_ClassDef* cd, int index_class_def) {
return new (alloc) BST_MakeClass(cd, index_class_def);
}
static void* operator new(size_t s, BSTAllocator& alloc) { return alloc.allocate(s); }
static void operator delete(void* ptr) { RELEASE_ASSERT(0, ""); }
BSTNODE(MakeClass) BSTNODE(MakeClass)
}; } PACKED;
class CFGBlock; class CFGBlock;
...@@ -584,44 +678,32 @@ public: ...@@ -584,44 +678,32 @@ public:
CFGBlock* iftrue, *iffalse; CFGBlock* iftrue, *iffalse;
BSTFIXEDVREGS(Branch, BST_stmt) BSTFIXEDVREGS(Branch, BST_stmt)
}; } PACKED;
class BST_Jump : public BST_stmt { class BST_Jump : public BST_stmt {
public: public:
CFGBlock* target; CFGBlock* target;
BSTFIXEDVREGS(Jump, BST_stmt) BSTFIXEDVREGS(Jump, BST_stmt)
}; } PACKED;
class BST_Invoke : public BST_stmt {
public:
BST_stmt* stmt;
CFGBlock* normal_dest, *exc_dest;
BST_Invoke(BST_stmt* stmt) : BST_stmt(BST_TYPE::Invoke), stmt(stmt) {}
BSTNODE(Invoke)
};
// grabs the info about the last raised exception // grabs the info about the last raised exception
class BST_Landingpad : public BST_stmt_with_dest { class BST_Landingpad : public BST_stmt_with_dest {
public: public:
BSTFIXEDVREGS(Landingpad, BST_stmt_with_dest) BSTFIXEDVREGS(Landingpad, BST_stmt_with_dest)
}; } PACKED;
class BST_Locals : public BST_stmt_with_dest { class BST_Locals : public BST_stmt_with_dest {
public: public:
BSTFIXEDVREGS(Locals, BST_stmt_with_dest) BSTFIXEDVREGS(Locals, BST_stmt_with_dest)
}; } PACKED;
class BST_GetIter : public BST_stmt_with_dest { class BST_GetIter : public BST_stmt_with_dest {
public: public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(GetIter, BST_stmt_with_dest) BSTFIXEDVREGS(GetIter, BST_stmt_with_dest)
}; } PACKED;
class BST_ImportFrom : public BST_stmt_with_dest { class BST_ImportFrom : public BST_stmt_with_dest {
public: public:
...@@ -629,7 +711,7 @@ public: ...@@ -629,7 +711,7 @@ public:
int vreg_name = VREG_UNDEFINED; int vreg_name = VREG_UNDEFINED;
BSTFIXEDVREGS(ImportFrom, BST_stmt_with_dest) BSTFIXEDVREGS(ImportFrom, BST_stmt_with_dest)
}; } PACKED;
class BST_ImportName : public BST_stmt_with_dest { class BST_ImportName : public BST_stmt_with_dest {
public: public:
...@@ -638,14 +720,14 @@ public: ...@@ -638,14 +720,14 @@ public:
int vreg_name = VREG_UNDEFINED; int vreg_name = VREG_UNDEFINED;
BSTFIXEDVREGS(ImportName, BST_stmt_with_dest) BSTFIXEDVREGS(ImportName, BST_stmt_with_dest)
}; } PACKED;
class BST_ImportStar : public BST_stmt_with_dest { class BST_ImportStar : public BST_stmt_with_dest {
public: public:
int vreg_name = VREG_UNDEFINED; int vreg_name = VREG_UNDEFINED;
BSTFIXEDVREGS(ImportStar, BST_stmt_with_dest) BSTFIXEDVREGS(ImportStar, BST_stmt_with_dest)
}; } PACKED;
// determines whether something is "true" for purposes of `if' and so forth // determines whether something is "true" for purposes of `if' and so forth
class BST_Nonzero : public BST_stmt_with_dest { class BST_Nonzero : public BST_stmt_with_dest {
...@@ -653,7 +735,7 @@ public: ...@@ -653,7 +735,7 @@ public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(Nonzero, BST_stmt_with_dest) BSTFIXEDVREGS(Nonzero, BST_stmt_with_dest)
}; } PACKED;
class BST_CheckExcMatch : public BST_stmt_with_dest { class BST_CheckExcMatch : public BST_stmt_with_dest {
public: public:
...@@ -661,7 +743,7 @@ public: ...@@ -661,7 +743,7 @@ public:
int vreg_cls = VREG_UNDEFINED; int vreg_cls = VREG_UNDEFINED;
BSTFIXEDVREGS(CheckExcMatch, BST_stmt_with_dest) BSTFIXEDVREGS(CheckExcMatch, BST_stmt_with_dest)
}; } PACKED;
class BST_SetExcInfo : public BST_stmt { class BST_SetExcInfo : public BST_stmt {
public: public:
...@@ -670,27 +752,57 @@ public: ...@@ -670,27 +752,57 @@ public:
int vreg_traceback = VREG_UNDEFINED; int vreg_traceback = VREG_UNDEFINED;
BSTFIXEDVREGS(SetExcInfo, BST_stmt) BSTFIXEDVREGS(SetExcInfo, BST_stmt)
}; } PACKED;
class BST_UncacheExcInfo : public BST_stmt { class BST_UncacheExcInfo : public BST_stmt {
public: public:
BSTFIXEDVREGS(UncacheExcInfo, BST_stmt) BSTFIXEDVREGS(UncacheExcInfo, BST_stmt)
}; } PACKED;
class BST_HasNext : public BST_stmt_with_dest { class BST_HasNext : public BST_stmt_with_dest {
public: public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(HasNext, BST_stmt_with_dest) BSTFIXEDVREGS(HasNext, BST_stmt_with_dest)
}; } PACKED;
class BST_PrintExpr : public BST_stmt { class BST_PrintExpr : public BST_stmt {
public: public:
int vreg_value = VREG_UNDEFINED; int vreg_value = VREG_UNDEFINED;
BSTFIXEDVREGS(PrintExpr, BST_stmt) BSTFIXEDVREGS(PrintExpr, BST_stmt)
}; } PACKED;
template <typename T> T* bst_cast(const BST_stmt* node) {
ASSERT(!node || node->type() == T::TYPE, "%d", node ? node->type() : 0);
return static_cast<T*>(node);
}
int BST_stmt::size_in_bytes() const {
int s = is_invoke() ? 2 * sizeof(CFGBlock*) : 0;
switch (type()) {
#define DISPATCH_SIZE(x, y) \
case BST_TYPE::x: \
return bst_cast<const BST_##x>(this)->size_in_bytes() + s;
FOREACH_TYPE(DISPATCH_SIZE)
};
assert(0);
__builtin_unreachable();
#undef DISPATCH_SIZE
}
bool BST_stmt::has_dest_vreg() const {
switch (type()) {
#define DISPATCH_HAS_DEST(x, y) \
case BST_TYPE::x: \
return std::is_base_of<BST_stmt_with_dest, BST_##x>();
FOREACH_TYPE(DISPATCH_HAS_DEST)
};
assert(0);
__builtin_unreachable();
#undef DISPATCH_HAS_DEST
}
// this is not a real bytecode it's only used to initalize arguments // this is not a real bytecode it's only used to initalize arguments
class BST_Name { class BST_Name {
...@@ -715,7 +827,7 @@ public: ...@@ -715,7 +827,7 @@ public:
}; };
template <typename T> T* bst_cast(BST_stmt* node) { template <typename T> T* bst_cast(BST_stmt* node) {
ASSERT(!node || node->type == T::TYPE, "%d", node ? node->type : 0); ASSERT(!node || node->type() == T::TYPE, "%d", node ? node->type() : 0);
return static_cast<T*>(node); return static_cast<T*>(node);
} }
...@@ -754,7 +866,6 @@ public: ...@@ -754,7 +866,6 @@ public:
virtual bool visit_importfrom(BST_ImportFrom* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_importfrom(BST_ImportFrom* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_importname(BST_ImportName* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_importname(BST_ImportName* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_importstar(BST_ImportStar* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_importstar(BST_ImportStar* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_invoke(BST_Invoke* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_jump(BST_Jump* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_jump(BST_Jump* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_landingpad(BST_Landingpad* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_landingpad(BST_Landingpad* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_list(BST_List* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_list(BST_List* node) { RELEASE_ASSERT(0, ""); }
...@@ -814,7 +925,6 @@ public: ...@@ -814,7 +925,6 @@ public:
virtual bool visit_importfrom(BST_ImportFrom* node) override { return false; } virtual bool visit_importfrom(BST_ImportFrom* node) override { return false; }
virtual bool visit_importname(BST_ImportName* node) override { return false; } virtual bool visit_importname(BST_ImportName* node) override { return false; }
virtual bool visit_importstar(BST_ImportStar* node) override { return false; } virtual bool visit_importstar(BST_ImportStar* node) override { return false; }
virtual bool visit_invoke(BST_Invoke* node) override { return false; }
virtual bool visit_jump(BST_Jump* node) override { return false; } virtual bool visit_jump(BST_Jump* node) override { return false; }
virtual bool visit_landingpad(BST_Landingpad* node) override { return false; } virtual bool visit_landingpad(BST_Landingpad* node) override { return false; }
virtual bool visit_list(BST_List* node) override { return false; } virtual bool visit_list(BST_List* node) override { return false; }
...@@ -877,7 +987,6 @@ public: ...@@ -877,7 +987,6 @@ public:
virtual void visit_importfrom(BST_ImportFrom* node) { RELEASE_ASSERT(0, ""); } virtual void visit_importfrom(BST_ImportFrom* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_importname(BST_ImportName* node) { RELEASE_ASSERT(0, ""); } virtual void visit_importname(BST_ImportName* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_importstar(BST_ImportStar* node) { RELEASE_ASSERT(0, ""); } virtual void visit_importstar(BST_ImportStar* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_invoke(BST_Invoke* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_jump(BST_Jump* node) { RELEASE_ASSERT(0, ""); } virtual void visit_jump(BST_Jump* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_landingpad(BST_Landingpad* node) { RELEASE_ASSERT(0, ""); } virtual void visit_landingpad(BST_Landingpad* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_list(BST_List* node) { RELEASE_ASSERT(0, ""); } virtual void visit_list(BST_List* node) { RELEASE_ASSERT(0, ""); }
...@@ -923,6 +1032,9 @@ public: ...@@ -923,6 +1032,9 @@ public:
virtual ~PrintVisitor() {} virtual ~PrintVisitor() {}
void flush() { stream.flush(); } void flush() { stream.flush(); }
// checks if the stmt is inside an invoke an if true prints the destination blocks
bool check_if_invoke(BST_stmt* node);
virtual bool visit_vreg(int* vreg, bool is_dst = false); virtual bool visit_vreg(int* vreg, bool is_dst = false);
virtual bool visit_assert(BST_Assert* node); virtual bool visit_assert(BST_Assert* node);
...@@ -948,7 +1060,6 @@ public: ...@@ -948,7 +1060,6 @@ public:
virtual bool visit_importfrom(BST_ImportFrom* node); virtual bool visit_importfrom(BST_ImportFrom* node);
virtual bool visit_importname(BST_ImportName* node); virtual bool visit_importname(BST_ImportName* node);
virtual bool visit_importstar(BST_ImportStar* node); virtual bool visit_importstar(BST_ImportStar* node);
virtual bool visit_invoke(BST_Invoke* node);
virtual bool visit_jump(BST_Jump* node); virtual bool visit_jump(BST_Jump* node);
virtual bool visit_landingpad(BST_Landingpad* node); virtual bool visit_landingpad(BST_Landingpad* node);
virtual bool visit_list(BST_List* node); virtual bool visit_list(BST_List* node);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -75,20 +75,68 @@ public: ...@@ -75,20 +75,68 @@ public:
// contains the address of the entry function // contains the address of the entry function
std::pair<CFGBlock*, Box*>(*entry_code)(void* interpeter, CFGBlock* block, Box** vregs); std::pair<CFGBlock*, Box*>(*entry_code)(void* interpeter, CFGBlock* block, Box** vregs);
llvm::SmallVector<BST_stmt*, 4> body;
llvm::SmallVector<CFGBlock*, 2> predecessors, successors; llvm::SmallVector<CFGBlock*, 2> predecessors, successors;
int idx; // index in the CFG int idx; // index in the CFG
const char* info; const char* info;
int offset_of_first_stmt; // offset of this block into the bytecode array in bytes
typedef llvm::SmallVector<BST_stmt*, 4>::iterator iterator; #ifndef NDEBUG
// only one block at a time is allowed to add instructions to the CFG
bool allowed_to_add_stuff = false;
#endif
CFGBlock(CFG* cfg, int idx) : cfg(cfg), code(NULL), entry_code(NULL), idx(idx), info(NULL) {} CFGBlock(CFG* cfg, int idx, const char* info = NULL)
: cfg(cfg), code(NULL), entry_code(NULL), idx(idx), info(info), offset_of_first_stmt(-1) {}
BST_stmt* body() {
auto it = begin();
return it != end() ? *it : NULL;
}
int sizeInBytes() const {
int size = 0;
for (BST_stmt* stmt : *this) {
size += stmt->size_in_bytes();
}
return size;
}
BST_stmt* getLastStmt() const {
// TODO: this is inefficient
for (BST_stmt* stmt : *this) {
if (stmt->is_terminator())
return stmt;
}
return NULL;
}
bool isPlaced() const { return offset_of_first_stmt != -1; }
void connectTo(CFGBlock* successor, bool allow_backedge = false); void connectTo(CFGBlock* successor, bool allow_backedge = false);
void unconnectFrom(CFGBlock* successor); void unconnectFrom(CFGBlock* successor);
void push_back(BST_stmt* node) { body.push_back(node); }
void print(const CodeConstants& code_constants, llvm::raw_ostream& stream = llvm::outs()); void print(const CodeConstants& code_constants, llvm::raw_ostream& stream = llvm::outs());
class iterator {
private:
BST_stmt* stmt;
public:
iterator(BST_stmt* stmt) : stmt(stmt) {}
bool operator!=(const iterator& rhs) const { return stmt != rhs.stmt; }
bool operator==(const iterator& rhs) const { return stmt == rhs.stmt; }
iterator& operator++() __attribute__((always_inline)) {
if (likely(stmt)) {
if (unlikely(stmt->is_terminator()))
*this = CFGBlock::end();
else
stmt = (BST_stmt*)&((unsigned char*)stmt)[stmt->size_in_bytes()];
}
return *this;
}
BST_stmt* operator*() const { return stmt; }
};
inline iterator begin() const;
static iterator end() { return iterator(NULL); }
}; };
// the vregs are split into three parts. // the vregs are split into three parts.
...@@ -169,7 +217,7 @@ public: ...@@ -169,7 +217,7 @@ public:
bool hasVRegsAssigned() const { return num_vregs != -1; } bool hasVRegsAssigned() const { return num_vregs != -1; }
void assignVRegs(const CodeConstants& code_constants, CFG* cfg, const ParamNames& param_names, void assignVRegs(const CodeConstants& code_constants, CFG* cfg, const ParamNames& param_names,
llvm::DenseMap<int*, InternedString>& id_vreg); llvm::DenseMap<class TrackingVRegPtr, InternedString>& id_vreg);
}; };
// Control Flow Graph // Control Flow Graph
...@@ -180,22 +228,19 @@ private: ...@@ -180,22 +228,19 @@ private:
public: public:
std::vector<CFGBlock*> blocks; std::vector<CFGBlock*> blocks;
BSTAllocator bytecode;
public: public:
CFG() : next_idx(0) {} CFG() : next_idx(0) {}
~CFG() {
for (auto&& block : blocks) {
delete block;
}
}
CFGBlock* getStartingBlock() { return blocks[0]; } CFGBlock* getStartingBlock() { return blocks[0]; }
VRegInfo& getVRegInfo() { return vreg_info; } VRegInfo& getVRegInfo() { return vreg_info; }
CFGBlock* addBlock() {
int idx = next_idx;
next_idx++;
CFGBlock* block = new CFGBlock(this, idx);
blocks.push_back(block);
return block;
}
// Creates a block which must be placed later, using placeBlock(). // Creates a block which must be placed later, using placeBlock().
// Must be placed on same CFG it was created on. // Must be placed on same CFG it was created on.
// You can also safely delete it without placing it. // You can also safely delete it without placing it.
...@@ -205,15 +250,43 @@ public: ...@@ -205,15 +250,43 @@ public:
} }
void placeBlock(CFGBlock* block) { void placeBlock(CFGBlock* block) {
assert(!block->isPlaced());
#ifndef NDEBUG
// check that there is no block with the same offset of first stmt
assert(!block->allowed_to_add_stuff);
std::unordered_map<int /* offset */, int> check_no_dup_blocks;
for (auto&& b : blocks) {
b->allowed_to_add_stuff = false;
++check_no_dup_blocks[b->offset_of_first_stmt];
}
++check_no_dup_blocks[bytecode.getSize()];
assert(check_no_dup_blocks[bytecode.getSize()] == 1);
for (auto&& e : check_no_dup_blocks) {
assert(e.second == 1);
}
#endif
assert(block->idx == -1); assert(block->idx == -1);
block->idx = next_idx; block->idx = next_idx;
next_idx++; next_idx++;
blocks.push_back(block); blocks.push_back(block);
block->offset_of_first_stmt = bytecode.getSize();
#ifndef NDEBUG
block->allowed_to_add_stuff = true;
#endif
} }
void print(const CodeConstants& code_constants, llvm::raw_ostream& stream = llvm::outs()); void print(const CodeConstants& code_constants, llvm::raw_ostream& stream = llvm::outs());
}; };
CFGBlock::iterator CFGBlock::begin() const {
if (offset_of_first_stmt >= cfg->bytecode.getSize())
return end();
return iterator((BST_stmt*)&cfg->bytecode.getData()[offset_of_first_stmt]);
}
class VRegSet { class VRegSet {
private: private:
llvm::BitVector v; llvm::BitVector v;
......
...@@ -563,7 +563,7 @@ extern "C" int PyGen_NeedsFinalizing(PyGenObject* gen) noexcept { ...@@ -563,7 +563,7 @@ extern "C" int PyGen_NeedsFinalizing(PyGenObject* gen) noexcept {
return true; return true;
// TODO: is this safe? probably not... // TODO: is this safe? probably not...
// return self->paused_frame_info->stmt->type == AST_TYPE::Invoke; // return self->paused_frame_info->stmt->is_invoke();
#if 0 #if 0
int i; int i;
PyFrameObject* f = gen->gi_frame; PyFrameObject* f = gen->gi_frame;
......
...@@ -27,8 +27,8 @@ protected: ...@@ -27,8 +27,8 @@ protected:
static BoxedCode* getCodeObjectOfFirstMakeFunction(BoxedCode* module_code) { static BoxedCode* getCodeObjectOfFirstMakeFunction(BoxedCode* module_code) {
BoxedCode* code = NULL; BoxedCode* code = NULL;
for (BST_stmt* stmt : module_code->source->cfg->blocks[0]->body) { for (BST_stmt* stmt : *module_code->source->cfg->getStartingBlock()) {
if (stmt->type != BST_TYPE::MakeFunction) if (stmt->type() != BST_TYPE::MakeFunction)
continue; continue;
code = module_code->code_constants.getFuncOrClass(bst_cast<BST_MakeFunction>(stmt)->index_func_def).second; code = module_code->code_constants.getFuncOrClass(bst_cast<BST_MakeFunction>(stmt)->index_func_def).second;
break; break;
...@@ -74,7 +74,7 @@ TEST_F(AnalysisTest, augassign) { ...@@ -74,7 +74,7 @@ TEST_F(AnalysisTest, augassign) {
for (CFGBlock* block : cfg->blocks) { for (CFGBlock* block : cfg->blocks) {
//printf("%d\n", block->idx); //printf("%d\n", block->idx);
if (block->body.back()->type != BST_TYPE::Return) if (block->getLastStmt()->type() != BST_TYPE::Return)
ASSERT_TRUE(liveness->isLiveAtEnd(vregs.getVReg(module->interned_strings->get("a")), block)); ASSERT_TRUE(liveness->isLiveAtEnd(vregs.getVReg(module->interned_strings->get("a")), block));
} }
...@@ -116,10 +116,10 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -116,10 +116,10 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
CFGBlock* loop_backedge = cfg->blocks[5]; CFGBlock* loop_backedge = cfg->blocks[5];
ASSERT_EQ(6, loop_backedge->idx); ASSERT_EQ(6, loop_backedge->idx);
ASSERT_EQ(1, loop_backedge->body.size()); ASSERT_TRUE(loop_backedge->body()->is_terminator());
ASSERT_EQ(BST_TYPE::Jump, loop_backedge->body[0]->type); ASSERT_EQ(BST_TYPE::Jump, loop_backedge->body()->type());
BST_Jump* backedge = bst_cast<BST_Jump>(loop_backedge->body[0]); BST_Jump* backedge = bst_cast<BST_Jump>(loop_backedge->body());
ASSERT_LE(backedge->target->idx, loop_backedge->idx); ASSERT_LE(backedge->target->idx, loop_backedge->idx);
std::unique_ptr<PhiAnalysis> phis; std::unique_ptr<PhiAnalysis> phis;
......
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