Commit cd769bc5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Exceptions part #3: irgen

parent 7efd8225
......@@ -116,6 +116,7 @@ COMMON_CXXFLAGS := -g -Werror -Wreturn-type -Woverloaded-virtual -Wall -Wno-sign
COMMON_CXXFLAGS += -std=c++11
COMMON_CXXFLAGS += -Wextra -Wno-sign-compare
COMMON_CXXFLAGS += -Wno-unused-parameter # should use the "unused" attribute
COMMON_CXXFLAGS += -fexceptions -fno-rtti
ifeq ($(ENABLE_VALGRIND),0)
COMMON_CXXFLAGS += -DNVALGRIND
......
......@@ -170,8 +170,8 @@ public:
virtual bool isFitBy(BoxedClass* c) { return true; }
// XXX should get rid of this implementation and have it just do print o.__repr__()
virtual void print(IREmitter& emitter, ConcreteCompilerVariable* var) {
emitter.getBuilder()->CreateCall(g.funcs.print, var->getValue());
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
emitter.createCall(info.exc_info, g.funcs.print, var->getValue());
}
virtual CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
......@@ -201,9 +201,9 @@ public:
llvm_args.push_back(ptr);
llvm_args.push_back(converted->getValue());
emitter.createPatchpoint(pp, (void*)pyston::setattr, llvm_args);
emitter.createPatchpoint(pp, (void*)pyston::setattr, llvm_args, info.exc_info);
} else {
emitter.getBuilder()->CreateCall3(g.funcs.setattr, var->getValue(), ptr, converted->getValue());
emitter.createCall3(info.exc_info, g.funcs.setattr, var->getValue(), ptr, converted->getValue());
}
converted->decvref(emitter);
}
......@@ -242,9 +242,9 @@ public:
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
rtn = emitter.createPatchpoint(pp, (void*)pyston::unboxedLen, llvm_args);
rtn = emitter.createPatchpoint(pp, (void*)pyston::unboxedLen, llvm_args, info.exc_info).getInstruction();
} else {
rtn = emitter.getBuilder()->CreateCall(g.funcs.unboxedLen, var->getValue());
rtn = emitter.createCall(info.exc_info, g.funcs.unboxedLen, var->getValue()).getInstruction();
}
assert(rtn->getType() == g.i64);
return new ConcreteCompilerVariable(INT, rtn, true);
......@@ -264,10 +264,12 @@ public:
llvm_args.push_back(var->getValue());
llvm_args.push_back(converted_slice->getValue());
llvm::Value* uncasted = emitter.createPatchpoint(pp, (void*)pyston::getitem, llvm_args);
llvm::Value* uncasted
= emitter.createPatchpoint(pp, (void*)pyston::getitem, llvm_args, info.exc_info).getInstruction();
rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn = emitter.getBuilder()->CreateCall2(g.funcs.getitem, var->getValue(), converted_slice->getValue());
rtn = emitter.createCall2(info.exc_info, g.funcs.getitem, var->getValue(), converted_slice->getValue())
.getInstruction();
}
converted_slice->decvref(emitter);
......@@ -302,10 +304,10 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
llvm_args.push_back(var->getValue());
llvm_args.push_back(ptr);
llvm::Value* uncasted = emitter.createPatchpoint(pp, raw_func, llvm_args);
llvm::Value* uncasted = emitter.createPatchpoint(pp, raw_func, llvm_args, info.exc_info).getInstruction();
rtn_val = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn_val = emitter.getBuilder()->CreateCall2(llvm_func, var->getValue(), ptr);
rtn_val = emitter.createCall2(info.exc_info, llvm_func, var->getValue(), ptr).getInstruction();
}
return new ConcreteCompilerVariable(UNKNOWN, rtn_val, true);
}
......@@ -375,7 +377,7 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
PatchpointSetupInfo* pp
= patchpoints::createCallsitePatchpoint(emitter.currentFunction(), info.getTypeRecorder(), args.size());
llvm::Value* uncasted = emitter.createPatchpoint(pp, func_addr, llvm_args);
llvm::Value* uncasted = emitter.createPatchpoint(pp, func_addr, llvm_args, info.exc_info).getInstruction();
assert(llvm::cast<llvm::FunctionType>(llvm::cast<llvm::PointerType>(func->getType())->getElementType())
->getReturnType() == g.llvm_value_type_ptr);
......@@ -386,7 +388,7 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
// a->dump();
//}
// printf("%ld %ld\n", llvm_args.size(), args.size());
rtn = emitter.getBuilder()->CreateCall(func, llvm_args);
rtn = emitter.createCall(info.exc_info, func, llvm_args).getInstruction();
}
if (mallocsave) {
......@@ -460,10 +462,11 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
llvm::Value* uncasted = emitter.createPatchpoint(pp, (void*)pyston::nonzero, llvm_args);
llvm::Value* uncasted
= emitter.createPatchpoint(pp, (void*)pyston::nonzero, llvm_args, info.exc_info).getInstruction();
rtn_val = emitter.getBuilder()->CreateTrunc(uncasted, g.i1);
} else {
rtn_val = emitter.getBuilder()->CreateCall(g.funcs.nonzero, var->getValue());
rtn_val = emitter.createCall(info.exc_info, g.funcs.nonzero, var->getValue()).getInstruction();
}
return new ConcreteCompilerVariable(BOOL, rtn_val, true);
}
......@@ -572,7 +575,7 @@ public:
// pass
}
virtual void print(IREmitter& emitter, ConcreteCompilerVariable* var) {
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
assert(var->getValue()->getType() == g.i64);
llvm::Constant* int_fmt = getStringConstantPtr("%ld");
......@@ -628,9 +631,9 @@ public:
virtual void setattr(IREmitter& emitter, const OpInfo& info, VAR* var, const std::string* attr,
CompilerVariable* v) {
llvm::CallInst* call = emitter.getBuilder()->CreateCall2(
g.funcs.raiseAttributeErrorStr, getStringConstantPtr("int\0"), getStringConstantPtr(*attr + '\0'));
call->setDoesNotReturn();
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr("int\0"), getStringConstantPtr(*attr + '\0'));
call.setDoesNotReturn();
}
virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerVariable* var,
......@@ -655,9 +658,9 @@ public:
}
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) {
llvm::CallInst* call
= emitter.getBuilder()->CreateCall(g.funcs.raiseNotIterableError, getStringConstantPtr("int"));
call->setDoesNotReturn();
llvm::CallSite call
= emitter.createCall(info.exc_info, g.funcs.raiseNotIterableError, getStringConstantPtr("int"));
call.setDoesNotReturn();
return new ConcreteCompilerVariable(INT, llvm::UndefValue::get(g.i64), true);
}
......@@ -689,7 +692,7 @@ public:
// pass
}
virtual void print(IREmitter& emitter, ConcreteCompilerVariable* var) {
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
assert(var->getValue()->getType() == g.double_);
emitter.getBuilder()->CreateCall(g.funcs.printFloat, var->getValue());
......@@ -737,9 +740,9 @@ public:
virtual void setattr(IREmitter& emitter, const OpInfo& info, VAR* var, const std::string* attr,
CompilerVariable* v) {
llvm::CallInst* call = emitter.getBuilder()->CreateCall2(
g.funcs.raiseAttributeErrorStr, getStringConstantPtr("float\0"), getStringConstantPtr(*attr + '\0'));
call->setDoesNotReturn();
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr("float\0"), getStringConstantPtr(*attr + '\0'));
call.setDoesNotReturn();
}
virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerVariable* var,
......@@ -862,10 +865,10 @@ public:
if (cls->is_constant && !cls->hasattrs) {
Box* rtattr = cls->peekattr(*attr);
if (rtattr == NULL) {
llvm::CallInst* call = emitter.getBuilder()->CreateCall2(
g.funcs.raiseAttributeErrorStr, getStringConstantPtr(*getNameOfClass(cls) + "\0"),
getStringConstantPtr(*attr + '\0'));
call->setDoesNotReturn();
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(*getNameOfClass(cls) + "\0"),
getStringConstantPtr(*attr + '\0'));
call.setDoesNotReturn();
return undefVariable();
}
......@@ -899,9 +902,9 @@ public:
return rtn;
}
virtual void print(IREmitter& emitter, ConcreteCompilerVariable* var) {
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN);
converted->print(emitter);
converted->print(emitter, info);
converted->decvref(emitter);
}
......@@ -928,10 +931,10 @@ public:
if (cls->is_constant && !cls->hasattrs) {
Box* rtattr = cls->peekattr(*attr);
if (rtattr == NULL) {
llvm::CallInst* call = emitter.getBuilder()->CreateCall2(g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(debugName() + '\0'),
getStringConstantPtr(*attr + '\0'));
call->setDoesNotReturn();
llvm::CallSite call
= emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(debugName() + '\0'), getStringConstantPtr(*attr + '\0'));
call.setDoesNotReturn();
return undefVariable();
}
......@@ -1044,7 +1047,7 @@ public:
// pass
}
virtual void print(IREmitter& emitter, ValuedCompilerVariable<std::string*>* value) {
virtual void print(IREmitter& emitter, const OpInfo& info, ValuedCompilerVariable<std::string*>* value) {
llvm::Constant* ptr = getStringConstantPtr(*(value->getValue()) + '\0');
llvm::Constant* fmt = getStringConstantPtr("%s\0");
emitter.getBuilder()->CreateCall2(g.funcs.printf, fmt, ptr);
......@@ -1125,7 +1128,7 @@ public:
virtual void grab(IREmitter& emitter, VAR* var) {
// pass
}
virtual void print(IREmitter& emitter, ConcreteCompilerVariable* var) {
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
assert(var->getValue()->getType() == g.i1);
llvm::Value* true_str = getStringConstantPtr("True");
......@@ -1207,7 +1210,7 @@ public:
return rtn;
}
virtual void print(IREmitter& emitter, VAR* var) {
virtual void print(IREmitter& emitter, const OpInfo& info, VAR* var) {
llvm::Constant* open_paren = getStringConstantPtr("(");
llvm::Constant* close_paren = getStringConstantPtr(")");
llvm::Constant* comma = getStringConstantPtr(",");
......@@ -1220,7 +1223,7 @@ public:
for (int i = 0; i < v->size(); i++) {
if (i)
emitter.getBuilder()->CreateCall(g.funcs.printf, comma_space);
(*v)[i]->print(emitter);
(*v)[i]->print(emitter, info);
}
if (v->size() == 1)
emitter.getBuilder()->CreateCall(g.funcs.printf, comma);
......@@ -1273,10 +1276,10 @@ public:
rtn->incvref();
return rtn;
} else {
llvm::CallInst* call = emitter.getBuilder()->CreateCall2(g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(debugName() + '\0'),
getStringConstantPtr("__getitem__\0"));
call->setDoesNotReturn();
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(debugName() + '\0'),
getStringConstantPtr("__getitem__\0"));
call.setDoesNotReturn();
return undefVariable();
}
}
......@@ -1336,7 +1339,7 @@ public:
}
return rtn;
}
virtual void print(IREmitter& emitter, VAR* var) {}
virtual void print(IREmitter& emitter, const OpInfo& info, VAR* var) {}
virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) {
llvm::Value* v = llvm::UndefValue::get(other_type->llvmType());
return new ConcreteCompilerVariable(other_type, v, true);
......
......@@ -103,7 +103,7 @@ public:
printf("call not defined for %s\n", debugName().c_str());
abort();
}
virtual void print(IREmitter& emitter, VAR* value) {
virtual void print(IREmitter& emitter, const OpInfo& info, VAR* value) {
printf("print not defined for %s\n", debugName().c_str());
abort();
}
......@@ -219,7 +219,7 @@ public:
const std::vector<CompilerVariable*>& args) = 0;
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, const std::vector<CompilerVariable*>& args)
= 0;
virtual void print(IREmitter& emitter) = 0;
virtual void print(IREmitter& emitter, const OpInfo& info) = 0;
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable*) = 0;
};
......@@ -283,7 +283,7 @@ public:
const std::vector<CompilerVariable*>& args) override {
return type->call(emitter, info, this, args);
}
void print(IREmitter& emitter) override { type->print(emitter, this); }
void print(IREmitter& emitter, const OpInfo& info) override { type->print(emitter, info, this); }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) override {
return type->len(emitter, info, this);
}
......
......@@ -317,10 +317,10 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
SymbolTable* initial_syms = new SymbolTable();
// llvm::BranchInst::Create(llvm_entry_blocks[entry_descriptor->backedge->target->idx], entry_block);
std::unique_ptr<IREmitter> entry_emitter(createIREmitter(irstate));
entry_emitter->getBuilder()->SetInsertPoint(osr_entry_block);
std::unique_ptr<IREmitter> unbox_emitter(createIREmitter(irstate));
unbox_emitter->getBuilder()->SetInsertPoint(osr_unbox_block);
llvm::BasicBlock* osr_entry_block_end = osr_entry_block;
llvm::BasicBlock* osr_unbox_block_end = osr_unbox_block;
std::unique_ptr<IREmitter> entry_emitter(createIREmitter(irstate, osr_entry_block_end));
std::unique_ptr<IREmitter> unbox_emitter(createIREmitter(irstate, osr_unbox_block_end));
CFGBlock* target_block = entry_descriptor->backedge->target;
......@@ -493,8 +493,8 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
std::unique_ptr<IRGenerator> generator(
createIRGenerator(irstate, llvm_entry_blocks, block, types, out_guards, in_guards, is_partial));
std::unique_ptr<IREmitter> emitter(createIREmitter(irstate));
emitter->getBuilder()->SetInsertPoint(llvm_entry_blocks[block]);
llvm::BasicBlock* entry_block_end = llvm_entry_blocks[block];
std::unique_ptr<IREmitter> emitter(createIREmitter(irstate, entry_block_end));
PHITable* phis = NULL;
if (!is_partial) {
......@@ -703,8 +703,8 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
llvm::BasicBlock* off_ramp = llvm::BasicBlock::Create(g.context, "deopt_ramp", irstate->getLLVMFunction());
offramps.push_back(off_ramp);
IREmitter* emitter = createIREmitter(irstate);
emitter->getBuilder()->SetInsertPoint(off_ramp);
llvm::BasicBlock* off_ramp_end = off_ramp;
IREmitter* emitter = createIREmitter(irstate, off_ramp_end);
emitters.push_back(emitter);
block_guards[i]->branch->setSuccessor(1, off_ramp);
......
......@@ -15,6 +15,7 @@
#ifndef PYSTON_CODEGEN_IRGEN_H
#define PYSTON_CODEGEN_IRGEN_H
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IRBuilder.h"
......@@ -30,6 +31,18 @@ class AST_expr;
class GCBuilder;
class IREmitter;
struct ExcInfo {
public:
llvm::BasicBlock* exc_dest;
bool needsInvoke() { return exc_dest != NULL; }
ExcInfo(llvm::BasicBlock* exc_dest) : exc_dest(exc_dest) {}
static ExcInfo none() { return ExcInfo(NULL); }
};
// TODO get rid of this
class MyInserter : public llvm::IRBuilderDefaultInserter<true> {
private:
IREmitter* emitter;
......@@ -55,8 +68,14 @@ public:
virtual CompiledFunction* currentFunction() = 0;
virtual llvm::Function* getIntrinsic(llvm::Intrinsic::ID) = 0;
virtual llvm::Value* createPatchpoint(const PatchpointSetupInfo* pp, void* func_addr,
const std::vector<llvm::Value*>& args) = 0;
virtual llvm::CallSite createCall(ExcInfo exc_info, llvm::Value* callee, const std::vector<llvm::Value*>& args) = 0;
virtual llvm::CallSite createCall(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1) = 0;
virtual llvm::CallSite createCall2(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2) = 0;
virtual llvm::CallSite createCall3(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2,
llvm::Value* arg3) = 0;
virtual llvm::CallSite createPatchpoint(const PatchpointSetupInfo* pp, void* func_addr,
const std::vector<llvm::Value*>& args, ExcInfo exc_info) = 0;
};
CompiledFunction* compileFunction(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
......@@ -70,8 +89,10 @@ private:
TypeRecorder* const type_recorder;
public:
OpInfo(EffortLevel::EffortLevel effort, TypeRecorder* type_recorder)
: effort(effort), type_recorder(type_recorder) {}
const ExcInfo exc_info;
OpInfo(EffortLevel::EffortLevel effort, TypeRecorder* type_recorder, ExcInfo exc_info)
: effort(effort), type_recorder(type_recorder), exc_info(exc_info) {}
bool isInterpreted() const { return effort == EffortLevel::INTERPRETED; }
TypeRecorder* getTypeRecorder() const { return type_recorder; }
......
......@@ -99,10 +99,13 @@ class IREmitterImpl : public IREmitter {
private:
IRGenState* irstate;
IRBuilder* builder;
llvm::BasicBlock*& curblock;
public:
explicit IREmitterImpl(IRGenState* irstate) : irstate(irstate), builder(new IRBuilder(g.context)) {
explicit IREmitterImpl(IRGenState* irstate, llvm::BasicBlock*& curblock)
: irstate(irstate), builder(new IRBuilder(g.context)), curblock(curblock) {
builder->setEmitter(this);
builder->SetInsertPoint(curblock);
}
IRBuilder* getBuilder() override { return builder; }
......@@ -115,8 +118,46 @@ public:
CompiledFunction* currentFunction() override { return irstate->getCurFunction(); }
llvm::Value* createPatchpoint(const PatchpointSetupInfo* pp, void* func_addr,
const std::vector<llvm::Value*>& args) override {
llvm::CallSite createCall(ExcInfo exc_info, llvm::Value* callee, const std::vector<llvm::Value*>& args) override {
if (exc_info.needsInvoke()) {
llvm::BasicBlock* normal_dest
= llvm::BasicBlock::Create(g.context, curblock->getName(), irstate->getLLVMFunction());
normal_dest->moveAfter(curblock);
llvm::InvokeInst* rtn = getBuilder()->CreateInvoke(callee, normal_dest, exc_info.exc_dest, args);
getBuilder()->SetInsertPoint(normal_dest);
curblock = normal_dest;
return rtn;
} else {
return getBuilder()->CreateCall(callee, args);
}
}
llvm::CallSite createCall(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1) override {
return createCall(exc_info, callee, std::vector<llvm::Value*>({ arg1 }));
}
llvm::CallSite createCall2(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2) override {
return createCall(exc_info, callee, { arg1, arg2 });
}
llvm::CallSite createCall3(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2,
llvm::Value* arg3) override {
return createCall(exc_info, callee, { arg1, arg2, arg3 });
}
llvm::CallSite createPatchpoint(const PatchpointSetupInfo* pp, void* func_addr,
const std::vector<llvm::Value*>& args, ExcInfo exc_info) override {
if (exc_info.needsInvoke()) {
std::vector<llvm::Type*> arg_types;
for (auto v : args)
arg_types.push_back(v->getType());
return createCall(
exc_info, embedConstantPtr(func_addr, llvm::FunctionType::get(g.i64, arg_types, false)->getPointerTo()),
args);
}
assert(irstate->getEffortLevel() != EffortLevel::INTERPRETED);
std::vector<llvm::Value*> pp_args;
......@@ -136,34 +177,24 @@ public:
llvm::Intrinsic::ID intrinsic_id = pp->hasReturnValue() ? llvm::Intrinsic::experimental_patchpoint_i64
: llvm::Intrinsic::experimental_patchpoint_void;
llvm::Function* patchpoint = this->getIntrinsic(intrinsic_id);
llvm::CallInst* rtn = this->getBuilder()->CreateCall(patchpoint, pp_args);
/*
static int n = 0;
n++;
if (n >= 3)
rtn->setCallingConv(llvm::CallingConv::PreserveAll);
*/
rtn->setCallingConv(pp->getCallingConvention());
// Not sure why this doesn't work:
// rtn->setCallingConv(llvm::CallingConv::AnyReg);
llvm::CallSite rtn = this->createCall(exc_info, patchpoint, pp_args);
rtn.setCallingConv(pp->getCallingConvention());
return rtn;
}
};
IREmitter* createIREmitter(IRGenState* irstate) {
return new IREmitterImpl(irstate);
IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock) {
return new IREmitterImpl(irstate, curblock);
}
class IRGeneratorImpl : public IRGenerator {
private:
IRGenState* irstate;
llvm::BasicBlock* curblock;
IREmitterImpl emitter;
SymbolTable symbol_table;
std::unordered_map<CFGBlock*, llvm::BasicBlock*>& entry_blocks;
llvm::BasicBlock* curblock;
CFGBlock* myblock;
TypeAnalysis* types;
GuardList& out_guards;
......@@ -180,17 +211,14 @@ public:
IRGeneratorImpl(IRGenState* irstate, std::unordered_map<CFGBlock*, llvm::BasicBlock*>& entry_blocks,
CFGBlock* myblock, TypeAnalysis* types, GuardList& out_guards, const GuardList& in_guards,
bool is_partial)
: irstate(irstate), emitter(irstate), entry_blocks(entry_blocks), myblock(myblock), types(types),
out_guards(out_guards), in_guards(in_guards), state(is_partial ? PARTIAL : RUNNING) {
llvm::BasicBlock* entry_block = entry_blocks[myblock];
emitter.getBuilder()->SetInsertPoint(entry_block);
curblock = entry_block;
}
: irstate(irstate), curblock(entry_blocks[myblock]), emitter(irstate, curblock), entry_blocks(entry_blocks),
myblock(myblock), types(types), out_guards(out_guards), in_guards(in_guards),
state(is_partial ? PARTIAL : RUNNING) {}
~IRGeneratorImpl() { delete emitter.getBuilder(); }
private:
OpInfo getOpInfoForNode(AST* ast) {
OpInfo getOpInfoForNode(AST* ast, ExcInfo exc_info) {
assert(ast);
EffortLevel::EffortLevel effort = irstate->getEffortLevel();
......@@ -203,10 +231,10 @@ private:
type_recorder = NULL;
}
return OpInfo(irstate->getEffortLevel(), type_recorder);
return OpInfo(irstate->getEffortLevel(), type_recorder, exc_info);
}
OpInfo getEmptyOpInfo() { return OpInfo(irstate->getEffortLevel(), NULL); }
OpInfo getEmptyOpInfo(ExcInfo exc_info) { return OpInfo(irstate->getEffortLevel(), NULL, exc_info); }
void createExprTypeGuard(llvm::Value* check_val, AST_expr* node, CompilerVariable* node_value) {
assert(check_val->getType() == g.i1);
......@@ -235,32 +263,87 @@ private:
out_guards.addExprTypeGuard(myblock, guard, node, node_value, symbol_table);
}
CompilerVariable* evalAttribute(AST_Attribute* node) {
CompilerVariable* evalAttribute(AST_Attribute* node, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* value = evalExpr(node->value);
CompilerVariable* value = evalExpr(node->value, exc_info);
CompilerVariable* rtn = value->getattr(emitter, getOpInfoForNode(node), &node->attr, false);
CompilerVariable* rtn = value->getattr(emitter, getOpInfoForNode(node, exc_info), &node->attr, false);
value->decvref(emitter);
return rtn;
}
CompilerVariable* evalClsAttribute(AST_ClsAttribute* node) {
CompilerVariable* evalClsAttribute(AST_ClsAttribute* node, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* value = evalExpr(node->value);
CompilerVariable* rtn = value->getattr(emitter, getOpInfoForNode(node), &node->attr, true);
CompilerVariable* value = evalExpr(node->value, exc_info);
CompilerVariable* rtn = value->getattr(emitter, getOpInfoForNode(node, exc_info), &node->attr, true);
value->decvref(emitter);
return rtn;
}
CompilerVariable* evalLangPrimitive(AST_LangPrimitive* node, ExcInfo exc_info) {
switch (node->opcode) {
case AST_LangPrimitive::ISINSTANCE: {
assert(node->args.size() == 3);
CompilerVariable* obj = evalExpr(node->args[0], exc_info);
CompilerVariable* cls = evalExpr(node->args[1], exc_info);
CompilerVariable* flags = evalExpr(node->args[2], exc_info);
ConcreteCompilerVariable* converted_obj = obj->makeConverted(emitter, obj->getBoxType());
ConcreteCompilerVariable* converted_cls = cls->makeConverted(emitter, cls->getBoxType());
ConcreteCompilerVariable* converted_flags = flags->makeConverted(emitter, INT);
obj->decvref(emitter);
cls->decvref(emitter);
flags->decvref(emitter);
llvm::Value* v = emitter.createCall(exc_info, g.funcs.isinstance,
{ converted_obj->getValue(), converted_cls->getValue(),
converted_flags->getValue() }).getInstruction();
assert(v->getType() == g.i1);
return new ConcreteCompilerVariable(BOOL, v, true);
}
case AST_LangPrimitive::LANDINGPAD: {
// llvm::Function* _personality_func = g.stdlib_module->getFunction("__py_personality_v0");
llvm::Function* _personality_func = g.stdlib_module->getFunction("__gxx_personality_v0");
assert(_personality_func);
llvm::Value* personality_func = g.cur_module->getOrInsertFunction(_personality_func->getName(),
_personality_func->getFunctionType());
assert(personality_func);
llvm::LandingPadInst* landing_pad = emitter.getBuilder()->CreateLandingPad(
llvm::StructType::create(std::vector<llvm::Type*>{ g.i8_ptr, g.i64 }), personality_func, 1);
landing_pad->addClause(embedConstantPtr(NULL, g.i8_ptr));
llvm::Value* exc_pointer = emitter.getBuilder()->CreateExtractValue(landing_pad, { 0 });
llvm::Value* exc_obj;
if (irstate->getEffortLevel() != EffortLevel::INTERPRETED) {
llvm::Value* exc_obj_pointer
= emitter.getBuilder()->CreateCall(g.funcs.__cxa_begin_catch, exc_pointer);
llvm::Value* exc_obj_pointer_casted
= emitter.getBuilder()->CreateBitCast(exc_obj_pointer, g.llvm_value_type_ptr->getPointerTo());
exc_obj = emitter.getBuilder()->CreateLoad(exc_obj_pointer_casted);
emitter.getBuilder()->CreateCall(g.funcs.__cxa_end_catch);
} else {
// The interpreter can't really support the full C++ exception handling model since it's
// itself written in C++. Let's make it easier for the interpreter and use a simpler interface:
exc_obj = emitter.getBuilder()->CreateBitCast(exc_pointer, g.llvm_value_type_ptr);
}
return new ConcreteCompilerVariable(UNKNOWN, exc_obj, true);
}
default:
RELEASE_ASSERT(0, "%d", node->opcode);
}
}
enum BinExpType {
AugBinOp,
BinOp,
Compare,
};
CompilerVariable* _evalBinExp(AST* node, CompilerVariable* left, CompilerVariable* right, AST_TYPE::AST_TYPE type,
BinExpType exp_type) {
BinExpType exp_type, ExcInfo exc_info) {
assert(state != PARTIAL);
assert(left);
......@@ -271,14 +354,14 @@ private:
ConcreteCompilerVariable* converted_right = right->makeConverted(emitter, INT);
llvm::Value* v;
if (type == AST_TYPE::Mod) {
v = emitter.getBuilder()->CreateCall2(g.funcs.mod_i64_i64, converted_left->getValue(),
converted_right->getValue());
v = emitter.createCall2(exc_info, g.funcs.mod_i64_i64, converted_left->getValue(),
converted_right->getValue()).getInstruction();
} else if (type == AST_TYPE::Div || type == AST_TYPE::FloorDiv) {
v = emitter.getBuilder()->CreateCall2(g.funcs.div_i64_i64, converted_left->getValue(),
converted_right->getValue());
v = emitter.createCall2(exc_info, g.funcs.div_i64_i64, converted_left->getValue(),
converted_right->getValue()).getInstruction();
} else if (type == AST_TYPE::Pow) {
v = emitter.getBuilder()->CreateCall2(g.funcs.pow_i64_i64, converted_left->getValue(),
converted_right->getValue());
v = emitter.createCall2(exc_info, g.funcs.pow_i64_i64, converted_left->getValue(),
converted_right->getValue()).getInstruction();
} else if (exp_type == BinOp || exp_type == AugBinOp) {
llvm::Instruction::BinaryOps binopcode;
switch (type) {
......@@ -365,14 +448,14 @@ private:
llvm::Value* v;
bool succeeded = true;
if (type == AST_TYPE::Mod) {
v = emitter.getBuilder()->CreateCall2(g.funcs.mod_float_float, converted_left->getValue(),
converted_right->getValue());
v = emitter.createCall2(exc_info, g.funcs.mod_float_float, converted_left->getValue(),
converted_right->getValue()).getInstruction();
} else if (type == AST_TYPE::Div || type == AST_TYPE::FloorDiv) {
v = emitter.getBuilder()->CreateCall2(g.funcs.div_float_float, converted_left->getValue(),
converted_right->getValue());
v = emitter.createCall2(exc_info, g.funcs.div_float_float, converted_left->getValue(),
converted_right->getValue()).getInstruction();
} else if (type == AST_TYPE::Pow) {
v = emitter.getBuilder()->CreateCall2(g.funcs.pow_float_float, converted_left->getValue(),
converted_right->getValue());
v = emitter.createCall2(exc_info, g.funcs.pow_float_float, converted_left->getValue(),
converted_right->getValue()).getInstruction();
} else if (exp_type == BinOp || exp_type == AugBinOp) {
llvm::Instruction::BinaryOps binopcode;
switch (type) {
......@@ -464,20 +547,19 @@ private:
}
if (do_patchpoint) {
PatchpointSetupInfo* pp = patchpoints::createBinexpPatchpoint(emitter.currentFunction(),
getOpInfoForNode(node).getTypeRecorder());
PatchpointSetupInfo* pp = patchpoints::createBinexpPatchpoint(
emitter.currentFunction(), getOpInfoForNode(node, exc_info).getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(boxed_left->getValue());
llvm_args.push_back(boxed_right->getValue());
llvm_args.push_back(getConstantInt(type, g.i32));
llvm::Value* uncasted = emitter.createPatchpoint(pp, rt_func_addr, llvm_args);
llvm::Value* uncasted = emitter.createPatchpoint(pp, rt_func_addr, llvm_args, exc_info).getInstruction();
rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn = emitter.getBuilder()->CreateCall3(rt_func, boxed_left->getValue(), boxed_right->getValue(),
getConstantInt(type, g.i32));
rtn = emitter.createCall3(exc_info, rt_func, boxed_left->getValue(), boxed_right->getValue(),
getConstantInt(type, g.i32)).getInstruction();
}
boxed_left->decvref(emitter);
......@@ -486,52 +568,52 @@ private:
return new ConcreteCompilerVariable(UNKNOWN, rtn, true);
}
CompilerVariable* evalBinOp(AST_BinOp* node) {
CompilerVariable* evalBinOp(AST_BinOp* node, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* left = evalExpr(node->left);
CompilerVariable* right = evalExpr(node->right);
CompilerVariable* left = evalExpr(node->left, exc_info);
CompilerVariable* right = evalExpr(node->right, exc_info);
assert(node->op_type != AST_TYPE::Is && node->op_type != AST_TYPE::IsNot && "not tested yet");
CompilerVariable* rtn = this->_evalBinExp(node, left, right, node->op_type, BinOp);
CompilerVariable* rtn = this->_evalBinExp(node, left, right, node->op_type, BinOp, exc_info);
left->decvref(emitter);
right->decvref(emitter);
return rtn;
}
CompilerVariable* evalAugBinOp(AST_AugBinOp* node) {
CompilerVariable* evalAugBinOp(AST_AugBinOp* node, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* left = evalExpr(node->left);
CompilerVariable* right = evalExpr(node->right);
CompilerVariable* left = evalExpr(node->left, exc_info);
CompilerVariable* right = evalExpr(node->right, exc_info);
assert(node->op_type != AST_TYPE::Is && node->op_type != AST_TYPE::IsNot && "not tested yet");
CompilerVariable* rtn = this->_evalBinExp(node, left, right, node->op_type, AugBinOp);
CompilerVariable* rtn = this->_evalBinExp(node, left, right, node->op_type, AugBinOp, exc_info);
left->decvref(emitter);
right->decvref(emitter);
return rtn;
}
CompilerVariable* evalCompare(AST_Compare* node) {
CompilerVariable* evalCompare(AST_Compare* node, ExcInfo exc_info) {
assert(state != PARTIAL);
RELEASE_ASSERT(node->ops.size() == 1, "");
CompilerVariable* left = evalExpr(node->left);
CompilerVariable* right = evalExpr(node->comparators[0]);
CompilerVariable* left = evalExpr(node->left, exc_info);
CompilerVariable* right = evalExpr(node->comparators[0], exc_info);
assert(left);
assert(right);
CompilerVariable* rtn = _evalBinExp(node, left, right, node->ops[0], Compare);
CompilerVariable* rtn = _evalBinExp(node, left, right, node->ops[0], Compare, exc_info);
left->decvref(emitter);
right->decvref(emitter);
return rtn;
}
CompilerVariable* evalCall(AST_Call* node) {
CompilerVariable* evalCall(AST_Call* node, ExcInfo exc_info) {
assert(state != PARTIAL);
bool is_callattr;
......@@ -542,22 +624,22 @@ private:
is_callattr = true;
callattr_clsonly = false;
AST_Attribute* attr_ast = ast_cast<AST_Attribute>(node->func);
func = evalExpr(attr_ast->value);
func = evalExpr(attr_ast->value, exc_info);
attr = &attr_ast->attr;
} else if (node->func->type == AST_TYPE::ClsAttribute) {
is_callattr = true;
callattr_clsonly = true;
AST_ClsAttribute* attr_ast = ast_cast<AST_ClsAttribute>(node->func);
func = evalExpr(attr_ast->value);
func = evalExpr(attr_ast->value, exc_info);
attr = &attr_ast->attr;
} else {
is_callattr = false;
func = evalExpr(node->func);
func = evalExpr(node->func, exc_info);
}
std::vector<CompilerVariable*> args;
for (int i = 0; i < node->args.size(); i++) {
CompilerVariable* a = evalExpr(node->args[i]);
CompilerVariable* a = evalExpr(node->args[i], exc_info);
args.push_back(a);
}
......@@ -566,9 +648,9 @@ private:
CompilerVariable* rtn;
if (is_callattr) {
rtn = func->callattr(emitter, getOpInfoForNode(node), attr, callattr_clsonly, args);
rtn = func->callattr(emitter, getOpInfoForNode(node, exc_info), attr, callattr_clsonly, args);
} else {
rtn = func->call(emitter, getOpInfoForNode(node), args);
rtn = func->call(emitter, getOpInfoForNode(node, exc_info), args);
}
func->decvref(emitter);
......@@ -582,17 +664,17 @@ private:
return rtn;
}
CompilerVariable* evalDict(AST_Dict* node) {
CompilerVariable* evalDict(AST_Dict* node, ExcInfo exc_info) {
assert(state != PARTIAL);
llvm::Value* v = emitter.getBuilder()->CreateCall(g.funcs.createDict);
ConcreteCompilerVariable* rtn = new ConcreteCompilerVariable(DICT, v, true);
if (node->keys.size()) {
static const std::string setitem_str("__setitem__");
CompilerVariable* setitem = rtn->getattr(emitter, getEmptyOpInfo(), &setitem_str, true);
CompilerVariable* setitem = rtn->getattr(emitter, getEmptyOpInfo(exc_info), &setitem_str, true);
for (int i = 0; i < node->keys.size(); i++) {
CompilerVariable* key = evalExpr(node->keys[i]);
CompilerVariable* value = evalExpr(node->values[i]);
CompilerVariable* key = evalExpr(node->keys[i], exc_info);
CompilerVariable* value = evalExpr(node->values[i], exc_info);
assert(key);
assert(value);
......@@ -600,7 +682,7 @@ private:
args.push_back(key);
args.push_back(value);
// TODO could use the internal _listAppend function to avoid incref/decref'ing None
CompilerVariable* rtn = setitem->call(emitter, getEmptyOpInfo(), args);
CompilerVariable* rtn = setitem->call(emitter, getEmptyOpInfo(exc_info), args);
rtn->decvref(emitter);
key->decvref(emitter);
......@@ -619,18 +701,18 @@ private:
inst->setMetadata(message, mdnode);
}
CompilerVariable* evalIndex(AST_Index* node) {
CompilerVariable* evalIndex(AST_Index* node, ExcInfo exc_info) {
assert(state != PARTIAL);
return evalExpr(node->value);
return evalExpr(node->value, exc_info);
}
CompilerVariable* evalList(AST_List* node) {
CompilerVariable* evalList(AST_List* node, ExcInfo exc_info) {
assert(state != PARTIAL);
std::vector<CompilerVariable*> elts;
for (int i = 0; i < node->elts.size(); i++) {
CompilerVariable* value = evalExpr(node->elts[i]);
CompilerVariable* value = evalExpr(node->elts[i], exc_info);
elts.push_back(value);
}
......@@ -647,7 +729,7 @@ private:
ConcreteCompilerVariable* converted = elt->makeConverted(emitter, elt->getBoxType());
elt->decvref(emitter);
emitter.getBuilder()->CreateCall2(f, bitcast, converted->getValue());
emitter.createCall2(exc_info, f, bitcast, converted->getValue());
converted->decvref(emitter);
}
return rtn;
......@@ -659,7 +741,7 @@ private:
return v;
}
CompilerVariable* evalName(AST_Name* node) {
CompilerVariable* evalName(AST_Name* node, ExcInfo exc_info) {
assert(state != PARTIAL);
if (irstate->getScopeInfo()->refersToGlobal(node->id)) {
......@@ -670,7 +752,7 @@ private:
bool from_global = irstate->getSourceInfo()->ast->type == AST_TYPE::Module;
if (do_patchpoint) {
PatchpointSetupInfo* pp = patchpoints::createGetGlobalPatchpoint(
emitter.currentFunction(), getOpInfoForNode(node).getTypeRecorder());
emitter.currentFunction(), getOpInfoForNode(node, exc_info).getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(
......@@ -678,14 +760,16 @@ private:
llvm_args.push_back(embedConstantPtr(&node->id, g.llvm_str_type_ptr));
llvm_args.push_back(getConstantInt(from_global, g.i1));
llvm::Value* uncasted = emitter.createPatchpoint(pp, (void*)pyston::getGlobal, llvm_args);
llvm::Value* uncasted
= emitter.createPatchpoint(pp, (void*)pyston::getGlobal, llvm_args, exc_info).getInstruction();
llvm::Value* r = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
return new ConcreteCompilerVariable(UNKNOWN, r, true);
} else {
llvm::Value* r = emitter.getBuilder()->CreateCall3(
g.funcs.getGlobal,
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr),
embedConstantPtr(&node->id, g.llvm_str_type_ptr), getConstantInt(from_global, g.i1));
llvm::Value* r = emitter.createCall3(exc_info, g.funcs.getGlobal,
embedConstantPtr(irstate->getSourceInfo()->parent_module,
g.llvm_module_type_ptr),
embedConstantPtr(&node->id, g.llvm_str_type_ptr),
getConstantInt(from_global, g.i1)).getInstruction();
return new ConcreteCompilerVariable(UNKNOWN, r, true);
}
} else {
......@@ -693,7 +777,7 @@ private:
// This option exists for performance testing because method 1 does not currently use patchpoints.
ConcreteCompilerVariable* mod = new ConcreteCompilerVariable(
MODULE, embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_value_type_ptr), false);
CompilerVariable* attr = mod->getattr(emitter, getOpInfoForNode(node), &node->id, false);
CompilerVariable* attr = mod->getattr(emitter, getOpInfoForNode(node, exc_info), &node->id, false);
mod->decvref(emitter);
return attr;
}
......@@ -701,17 +785,17 @@ private:
if (symbol_table.find(node->id) == symbol_table.end()) {
// TODO should mark as DEAD here, though we won't end up setting all the names appropriately
// state = DEAD;
llvm::CallInst* call = emitter.getBuilder()->CreateCall2(
g.funcs.assertNameDefined, getConstantInt(0, g.i1), getStringConstantPtr(node->id + '\0'));
call->setDoesNotReturn();
llvm::CallSite call = emitter.createCall2(exc_info, g.funcs.assertNameDefined, getConstantInt(0, g.i1),
getStringConstantPtr(node->id + '\0'));
call.setDoesNotReturn();
return undefVariable();
}
std::string defined_name = _getFakeName("is_defined", node->id.c_str());
ConcreteCompilerVariable* is_defined = static_cast<ConcreteCompilerVariable*>(_getFake(defined_name, true));
if (is_defined) {
emitter.getBuilder()->CreateCall2(g.funcs.assertNameDefined, is_defined->getValue(),
getStringConstantPtr(node->id + '\0'));
emitter.createCall2(exc_info, g.funcs.assertNameDefined, is_defined->getValue(),
getStringConstantPtr(node->id + '\0'));
}
CompilerVariable* rtn = symbol_table[node->id];
......@@ -720,7 +804,7 @@ private:
}
}
CompilerVariable* evalNum(AST_Num* node) {
CompilerVariable* evalNum(AST_Num* node, ExcInfo exc_info) {
assert(state != PARTIAL);
if (node->num_type == AST_Num::INT)
......@@ -731,27 +815,27 @@ private:
RELEASE_ASSERT(0, "");
}
CompilerVariable* evalRepr(AST_Repr* node) {
CompilerVariable* evalRepr(AST_Repr* node, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* var = evalExpr(node->value);
CompilerVariable* var = evalExpr(node->value, exc_info);
ConcreteCompilerVariable* cvar = var->makeConverted(emitter, var->getBoxType());
var->decvref(emitter);
std::vector<llvm::Value*> args{ cvar->getValue() };
llvm::Value* rtn = emitter.getBuilder()->CreateCall(g.funcs.repr, args);
llvm::Value* rtn = emitter.createCall(exc_info, g.funcs.repr, args).getInstruction();
cvar->decvref(emitter);
return new ConcreteCompilerVariable(STR, rtn, true);
}
CompilerVariable* evalSlice(AST_Slice* node) {
CompilerVariable* evalSlice(AST_Slice* node, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* start, *stop, *step;
start = node->lower ? evalExpr(node->lower) : getNone();
stop = node->upper ? evalExpr(node->upper) : getNone();
step = node->step ? evalExpr(node->step) : getNone();
start = node->lower ? evalExpr(node->lower, exc_info) : getNone();
stop = node->upper ? evalExpr(node->upper, exc_info) : getNone();
step = node->step ? evalExpr(node->step, exc_info) : getNone();
ConcreteCompilerVariable* cstart, *cstop, *cstep;
cstart = start->makeConverted(emitter, start->getBoxType());
......@@ -773,30 +857,30 @@ private:
return new ConcreteCompilerVariable(SLICE, rtn, true);
}
CompilerVariable* evalStr(AST_Str* node) {
CompilerVariable* evalStr(AST_Str* node, ExcInfo exc_info) {
assert(state != PARTIAL);
return makeStr(&node->s);
}
CompilerVariable* evalSubscript(AST_Subscript* node) {
CompilerVariable* evalSubscript(AST_Subscript* node, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* value = evalExpr(node->value);
CompilerVariable* slice = evalExpr(node->slice);
CompilerVariable* value = evalExpr(node->value, exc_info);
CompilerVariable* slice = evalExpr(node->slice, exc_info);
CompilerVariable* rtn = value->getitem(emitter, getOpInfoForNode(node), slice);
CompilerVariable* rtn = value->getitem(emitter, getOpInfoForNode(node, exc_info), slice);
value->decvref(emitter);
slice->decvref(emitter);
return rtn;
}
CompilerVariable* evalTuple(AST_Tuple* node) {
CompilerVariable* evalTuple(AST_Tuple* node, ExcInfo exc_info) {
assert(state != PARTIAL);
std::vector<CompilerVariable*> elts;
for (int i = 0; i < node->elts.size(); i++) {
CompilerVariable* value = evalExpr(node->elts[i]);
CompilerVariable* value = evalExpr(node->elts[i], exc_info);
elts.push_back(value);
}
......@@ -808,13 +892,13 @@ private:
return rtn;
}
CompilerVariable* evalUnaryOp(AST_UnaryOp* node) {
CompilerVariable* evalUnaryOp(AST_UnaryOp* node, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* operand = evalExpr(node->operand);
CompilerVariable* operand = evalExpr(node->operand, exc_info);
if (node->op_type == AST_TYPE::Not) {
ConcreteCompilerVariable* rtn = operand->nonzero(emitter, getOpInfoForNode(node));
ConcreteCompilerVariable* rtn = operand->nonzero(emitter, getOpInfoForNode(node, exc_info));
operand->decvref(emitter);
llvm::Value* v = rtn->getValue();
......@@ -827,8 +911,8 @@ private:
ConcreteCompilerVariable* converted = operand->makeConverted(emitter, operand->getBoxType());
operand->decvref(emitter);
llvm::Value* rtn = emitter.getBuilder()->CreateCall2(g.funcs.unaryop, converted->getValue(),
getConstantInt(node->op_type, g.i32));
llvm::Value* rtn = emitter.createCall2(exc_info, g.funcs.unaryop, converted->getValue(),
getConstantInt(node->op_type, g.i32)).getInstruction();
converted->decvref(emitter);
return new ConcreteCompilerVariable(UNKNOWN, rtn, true);
......@@ -851,62 +935,65 @@ private:
return new ConcreteCompilerVariable(t, v, grabbed);
}
CompilerVariable* evalExpr(AST_expr* node) {
CompilerVariable* evalExpr(AST_expr* node, ExcInfo exc_info) {
emitter.getBuilder()->SetCurrentDebugLocation(llvm::DebugLoc::get(node->lineno, 0, irstate->getFuncDbgInfo()));
CompilerVariable* rtn = NULL;
if (state != PARTIAL) {
switch (node->type) {
case AST_TYPE::Attribute:
rtn = evalAttribute(ast_cast<AST_Attribute>(node));
rtn = evalAttribute(ast_cast<AST_Attribute>(node), exc_info);
break;
case AST_TYPE::AugBinOp:
rtn = evalAugBinOp(ast_cast<AST_AugBinOp>(node));
rtn = evalAugBinOp(ast_cast<AST_AugBinOp>(node), exc_info);
break;
case AST_TYPE::BinOp:
rtn = evalBinOp(ast_cast<AST_BinOp>(node));
rtn = evalBinOp(ast_cast<AST_BinOp>(node), exc_info);
break;
case AST_TYPE::Call:
rtn = evalCall(ast_cast<AST_Call>(node));
rtn = evalCall(ast_cast<AST_Call>(node), exc_info);
break;
case AST_TYPE::Compare:
rtn = evalCompare(ast_cast<AST_Compare>(node));
rtn = evalCompare(ast_cast<AST_Compare>(node), exc_info);
break;
case AST_TYPE::Dict:
rtn = evalDict(ast_cast<AST_Dict>(node));
rtn = evalDict(ast_cast<AST_Dict>(node), exc_info);
break;
case AST_TYPE::Index:
rtn = evalIndex(ast_cast<AST_Index>(node));
rtn = evalIndex(ast_cast<AST_Index>(node), exc_info);
break;
case AST_TYPE::List:
rtn = evalList(ast_cast<AST_List>(node));
rtn = evalList(ast_cast<AST_List>(node), exc_info);
break;
case AST_TYPE::Name:
rtn = evalName(ast_cast<AST_Name>(node));
rtn = evalName(ast_cast<AST_Name>(node), exc_info);
break;
case AST_TYPE::Num:
rtn = evalNum(ast_cast<AST_Num>(node));
rtn = evalNum(ast_cast<AST_Num>(node), exc_info);
break;
case AST_TYPE::Repr:
rtn = evalRepr(ast_cast<AST_Repr>(node));
rtn = evalRepr(ast_cast<AST_Repr>(node), exc_info);
break;
case AST_TYPE::Slice:
rtn = evalSlice(ast_cast<AST_Slice>(node));
rtn = evalSlice(ast_cast<AST_Slice>(node), exc_info);
break;
case AST_TYPE::Str:
rtn = evalStr(ast_cast<AST_Str>(node));
rtn = evalStr(ast_cast<AST_Str>(node), exc_info);
break;
case AST_TYPE::Subscript:
rtn = evalSubscript(ast_cast<AST_Subscript>(node));
rtn = evalSubscript(ast_cast<AST_Subscript>(node), exc_info);
break;
case AST_TYPE::Tuple:
rtn = evalTuple(ast_cast<AST_Tuple>(node));
rtn = evalTuple(ast_cast<AST_Tuple>(node), exc_info);
break;
case AST_TYPE::UnaryOp:
rtn = evalUnaryOp(ast_cast<AST_UnaryOp>(node));
rtn = evalUnaryOp(ast_cast<AST_UnaryOp>(node), exc_info);
break;
case AST_TYPE::ClsAttribute:
rtn = evalClsAttribute(ast_cast<AST_ClsAttribute>(node));
rtn = evalClsAttribute(ast_cast<AST_ClsAttribute>(node), exc_info);
break;
case AST_TYPE::LangPrimitive:
rtn = evalLangPrimitive(ast_cast<AST_LangPrimitive>(node), exc_info);
break;
default:
printf("Unhandled expr type: %d (irgenerator.cpp:" STRINGIFY(__LINE__) ")\n", node->type);
......@@ -1072,13 +1159,13 @@ private:
return rtn;
}
void _doSet(const std::string& name, CompilerVariable* val) {
void _doSet(const std::string& name, CompilerVariable* val, ExcInfo exc_info) {
assert(name != "None");
if (irstate->getScopeInfo()->refersToGlobal(name)) {
// TODO do something special here so that it knows to only emit a monomorphic inline cache?
ConcreteCompilerVariable* module = new ConcreteCompilerVariable(
MODULE, embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_value_type_ptr), false);
module->setattr(emitter, getEmptyOpInfo(), &name, val);
module->setattr(emitter, getEmptyOpInfo(exc_info), &name, val);
module->decvref(emitter);
} else {
CompilerVariable*& prev = symbol_table[name];
......@@ -1095,17 +1182,17 @@ private:
}
}
void _doSetattr(AST_Attribute* target, CompilerVariable* val) {
void _doSetattr(AST_Attribute* target, CompilerVariable* val, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* t = evalExpr(target->value);
t->setattr(emitter, getEmptyOpInfo(), &target->attr, val);
CompilerVariable* t = evalExpr(target->value, exc_info);
t->setattr(emitter, getEmptyOpInfo(exc_info), &target->attr, val);
t->decvref(emitter);
}
void _doSetitem(AST_Subscript* target, CompilerVariable* val) {
void _doSetitem(AST_Subscript* target, CompilerVariable* val, ExcInfo exc_info) {
assert(state != PARTIAL);
CompilerVariable* tget = evalExpr(target->value);
CompilerVariable* slice = evalExpr(target->slice);
CompilerVariable* tget = evalExpr(target->value, exc_info);
CompilerVariable* slice = evalExpr(target->slice, exc_info);
ConcreteCompilerVariable* converted_target = tget->makeConverted(emitter, tget->getBoxType());
ConcreteCompilerVariable* converted_slice = slice->makeConverted(emitter, slice->getBoxType());
......@@ -1116,18 +1203,18 @@ private:
bool do_patchpoint = ENABLE_ICSETITEMS && (irstate->getEffortLevel() != EffortLevel::INTERPRETED);
if (do_patchpoint) {
PatchpointSetupInfo* pp
= patchpoints::createSetitemPatchpoint(emitter.currentFunction(), getEmptyOpInfo().getTypeRecorder());
PatchpointSetupInfo* pp = patchpoints::createSetitemPatchpoint(emitter.currentFunction(),
getEmptyOpInfo(exc_info).getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(converted_target->getValue());
llvm_args.push_back(converted_slice->getValue());
llvm_args.push_back(converted_val->getValue());
emitter.createPatchpoint(pp, (void*)pyston::setitem, llvm_args);
emitter.createPatchpoint(pp, (void*)pyston::setitem, llvm_args, exc_info);
} else {
emitter.getBuilder()->CreateCall3(g.funcs.setitem, converted_target->getValue(),
converted_slice->getValue(), converted_val->getValue());
emitter.createCall3(exc_info, g.funcs.setitem, converted_target->getValue(), converted_slice->getValue(),
converted_val->getValue());
}
converted_target->decvref(emitter);
......@@ -1135,35 +1222,34 @@ private:
converted_val->decvref(emitter);
}
void _doUnpackTuple(AST_Tuple* target, CompilerVariable* val) {
void _doUnpackTuple(AST_Tuple* target, CompilerVariable* val, ExcInfo exc_info) {
assert(state != PARTIAL);
int ntargets = target->elts.size();
// TODO do type recording here?
ConcreteCompilerVariable* len = val->len(emitter, getEmptyOpInfo());
emitter.getBuilder()->CreateCall2(g.funcs.checkUnpackingLength, getConstantInt(ntargets, g.i64),
len->getValue());
ConcreteCompilerVariable* len = val->len(emitter, getEmptyOpInfo(exc_info));
emitter.createCall2(exc_info, g.funcs.checkUnpackingLength, getConstantInt(ntargets, g.i64), len->getValue());
for (int i = 0; i < ntargets; i++) {
CompilerVariable* unpacked = val->getitem(emitter, getEmptyOpInfo(), makeInt(i));
_doSet(target->elts[i], unpacked);
CompilerVariable* unpacked = val->getitem(emitter, getEmptyOpInfo(exc_info), makeInt(i));
_doSet(target->elts[i], unpacked, exc_info);
unpacked->decvref(emitter);
}
}
void _doSet(AST* target, CompilerVariable* val) {
void _doSet(AST* target, CompilerVariable* val, ExcInfo exc_info) {
assert(state != PARTIAL);
switch (target->type) {
case AST_TYPE::Attribute:
_doSetattr(ast_cast<AST_Attribute>(target), val);
_doSetattr(ast_cast<AST_Attribute>(target), val, exc_info);
break;
case AST_TYPE::Name:
_doSet(ast_cast<AST_Name>(target)->id, val);
_doSet(ast_cast<AST_Name>(target)->id, val, exc_info);
break;
case AST_TYPE::Subscript:
_doSetitem(ast_cast<AST_Subscript>(target), val);
_doSetitem(ast_cast<AST_Subscript>(target), val, exc_info);
break;
case AST_TYPE::Tuple:
_doUnpackTuple(ast_cast<AST_Tuple>(target), val);
_doUnpackTuple(ast_cast<AST_Tuple>(target), val, exc_info);
break;
default:
ASSERT(0, "Unknown type for IRGenerator: %d", target->type);
......@@ -1171,7 +1257,7 @@ private:
}
}
void doAssert(AST_Assert* node) {
void doAssert(AST_Assert* node, ExcInfo exc_info) {
AST_expr* test = node->test;
assert(test->type == AST_TYPE::Num);
AST_Num* num = ast_cast<AST_Num>(test);
......@@ -1183,37 +1269,38 @@ private:
ConcreteCompilerVariable* converted_msg = NULL;
if (node->msg) {
CompilerVariable* msg = evalExpr(node->msg);
CompilerVariable* msg = evalExpr(node->msg, exc_info);
converted_msg = msg->makeConverted(emitter, msg->getBoxType());
msg->decvref(emitter);
llvm_args.push_back(converted_msg->getValue());
} else {
llvm_args.push_back(embedConstantPtr(NULL, g.llvm_value_type_ptr));
}
llvm::CallInst* call = emitter.getBuilder()->CreateCall(g.funcs.assertFail, llvm_args);
call->setDoesNotReturn();
llvm::CallSite call = emitter.createCall(exc_info, g.funcs.assertFail, llvm_args);
call.setDoesNotReturn();
}
void doAssign(AST_Assign* node) {
CompilerVariable* val = evalExpr(node->value);
void doAssign(AST_Assign* node, ExcInfo exc_info) {
CompilerVariable* val = evalExpr(node->value, exc_info);
if (state == PARTIAL)
return;
for (int i = 0; i < node->targets.size(); i++) {
_doSet(node->targets[i], val);
_doSet(node->targets[i], val, exc_info);
}
val->decvref(emitter);
}
void doClassDef(AST_ClassDef* node) {
void doClassDef(AST_ClassDef* node, ExcInfo exc_info) {
if (state == PARTIAL)
return;
ScopeInfo* scope_info = irstate->getSourceInfo()->scoping->getScopeInfoForNode(node);
llvm::Value* classobj = emitter.getBuilder()->CreateCall2(
g.funcs.createClass, embedConstantPtr(&node->name, g.llvm_str_type_ptr),
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr));
llvm::Value* classobj
= emitter.createCall2(exc_info, g.funcs.createClass, embedConstantPtr(&node->name, g.llvm_str_type_ptr),
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr))
.getInstruction();
ConcreteCompilerVariable* cls = new ConcreteCompilerVariable(typeFromClass(type_cls), classobj, true);
RELEASE_ASSERT(node->bases.size() == 1, "");
......@@ -1232,14 +1319,14 @@ private:
AST_FunctionDef* fdef = ast_cast<AST_FunctionDef>(node->body[i]);
CLFunction* cl = this->_wrapFunction(fdef);
CompilerVariable* func = makeFunction(emitter, cl);
cls->setattr(emitter, getEmptyOpInfo(), &fdef->name, func);
cls->setattr(emitter, getEmptyOpInfo(exc_info), &fdef->name, func);
func->decvref(emitter);
} else {
RELEASE_ASSERT(node->body[i]->type == AST_TYPE::Pass, "%d", type);
}
}
_doSet(node->name, cls);
_doSet(node->name, cls, exc_info);
cls->decvref(emitter);
}
......@@ -1257,7 +1344,7 @@ private:
return cl;
}
void doFunction(AST_FunctionDef* node) {
void doFunction(AST_FunctionDef* node, ExcInfo exc_info) {
if (state == PARTIAL)
return;
......@@ -1269,11 +1356,11 @@ private:
// boxCLFuncArgType));
// CompilerVariable *func = new ConcreteCompilerVariable(typeFromClass(function_cls), boxed, true);
_doSet(node->name, func);
_doSet(node->name, func, exc_info);
func->decvref(emitter);
}
void doImport(AST_Import* node) {
void doImport(AST_Import* node, ExcInfo exc_info) {
if (state == PARTIAL)
return;
......@@ -1284,21 +1371,23 @@ private:
const std::string& asname = alias->asname.size() ? alias->asname : alias->name;
llvm::Value* imported
= emitter.getBuilder()->CreateCall(g.funcs.import, embedConstantPtr(&modname, g.llvm_str_type_ptr));
= emitter.createCall(exc_info, g.funcs.import, embedConstantPtr(&modname, g.llvm_str_type_ptr))
.getInstruction();
ConcreteCompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, imported, true);
_doSet(asname, v);
_doSet(asname, v, exc_info);
v->decvref(emitter);
}
}
void doImportFrom(AST_ImportFrom* node) {
void doImportFrom(AST_ImportFrom* node, ExcInfo exc_info) {
if (state == PARTIAL)
return;
assert(node->level == 0);
llvm::Value* imported_v
= emitter.getBuilder()->CreateCall(g.funcs.import, embedConstantPtr(&node->module, g.llvm_str_type_ptr));
= emitter.createCall(exc_info, g.funcs.import, embedConstantPtr(&node->module, g.llvm_str_type_ptr))
.getInstruction();
ConcreteCompilerVariable* module = new ConcreteCompilerVariable(typeFromClass(module_cls), imported_v, true);
for (int i = 0; i < node->names.size(); i++) {
......@@ -1307,15 +1396,15 @@ private:
const std::string& name = alias->name;
const std::string& asname = alias->asname.size() ? alias->asname : alias->name;
CompilerVariable* v = module->getattr(emitter, getEmptyOpInfo(), &name, false);
_doSet(asname, v);
CompilerVariable* v = module->getattr(emitter, getEmptyOpInfo(exc_info), &name, false);
_doSet(asname, v, exc_info);
v->decvref(emitter);
}
module->decvref(emitter);
}
void doPrint(AST_Print* node) {
void doPrint(AST_Print* node, ExcInfo exc_info) {
if (state == PARTIAL)
return;
......@@ -1324,18 +1413,19 @@ private:
if (i > 0) {
emitter.getBuilder()->CreateCall(g.funcs.printf, getStringConstantPtr(" "));
}
CompilerVariable* var = evalExpr(node->values[i]);
var->print(emitter);
CompilerVariable* var = evalExpr(node->values[i], exc_info);
var->print(emitter, getEmptyOpInfo(exc_info));
var->decvref(emitter);
}
if (node->nl)
emitter.getBuilder()->CreateCall(g.funcs.printf, getStringConstantPtr("\n"));
emitter.createCall(exc_info, g.funcs.printf, getStringConstantPtr("\n"));
else
emitter.getBuilder()->CreateCall(g.funcs.printf, getStringConstantPtr(" "));
emitter.createCall(exc_info, g.funcs.printf, getStringConstantPtr(" "));
}
void doReturn(AST_Return* node) {
void doReturn(AST_Return* node, ExcInfo exc_info) {
assert(!exc_info.needsInvoke());
CompilerVariable* val;
if (node->value == NULL) {
......@@ -1347,7 +1437,7 @@ private:
val = new ConcreteCompilerVariable(NONE, embedConstantPtr(None, g.llvm_value_type_ptr), false);
} else {
val = evalExpr(node->value);
val = evalExpr(node->value, exc_info);
}
assert(state != PARTIAL);
assert(val);
......@@ -1370,18 +1460,23 @@ private:
endBlock(DEAD);
ASSERT(rtn->getVrefs() == 1, "%d", rtn->getVrefs());
assert(rtn->getValue());
emitter.getBuilder()->CreateRet(rtn->getValue());
}
void doBranch(AST_Branch* node) {
void doBranch(AST_Branch* node, ExcInfo exc_info) {
assert(!exc_info.needsInvoke());
assert(node->iftrue->idx > myblock->idx);
assert(node->iffalse->idx > myblock->idx);
CompilerVariable* val = evalExpr(node->test);
CompilerVariable* val = evalExpr(node->test, exc_info);
assert(state != PARTIAL);
assert(val);
ConcreteCompilerVariable* nonzero = val->nonzero(emitter, getOpInfoForNode(node));
// ASSERT(val->getType() == BOOL, "%s", val->getType()->debugName().c_str());
ConcreteCompilerVariable* nonzero = val->nonzero(emitter, getOpInfoForNode(node, exc_info));
assert(nonzero->getType() == BOOL);
val->decvref(emitter);
......@@ -1396,8 +1491,8 @@ private:
emitter.getBuilder()->CreateCondBr(llvm_nonzero, iftrue, iffalse);
}
void doExpr(AST_Expr* node) {
CompilerVariable* var = evalExpr(node->value);
void doExpr(AST_Expr* node, ExcInfo exc_info) {
CompilerVariable* var = evalExpr(node->value, exc_info);
if (state == PARTIAL)
return;
......@@ -1568,7 +1663,7 @@ private:
emitter.getBuilder()->SetInsertPoint(starting_block);
}
void doJump(AST_Jump* node) {
void doJump(AST_Jump* node, ExcInfo exc_info) {
assert(state != PARTIAL);
endBlock(FINISHED);
......@@ -1583,31 +1678,54 @@ private:
}
}
void doStmt(AST* node) {
void doRaise(AST_Raise* node, ExcInfo exc_info) {
RELEASE_ASSERT(node->arg0 != NULL, "");
RELEASE_ASSERT(node->arg1 == NULL, "");
RELEASE_ASSERT(node->arg2 == NULL, "");
CompilerVariable* arg0 = evalExpr(node->arg0, exc_info);
ConcreteCompilerVariable* converted_arg0 = arg0->makeConverted(emitter, arg0->getBoxType());
arg0->decvref(emitter);
llvm::Value* exc_mem
= emitter.getBuilder()->CreateCall(g.funcs.__cxa_allocate_exception, getConstantInt(sizeof(void*), g.i64));
llvm::Value* bitcasted = emitter.getBuilder()->CreateBitCast(exc_mem, g.llvm_value_type_ptr->getPointerTo());
emitter.getBuilder()->CreateStore(converted_arg0->getValue(), bitcasted);
converted_arg0->decvref(emitter);
void* type_id = NULL;
emitter.createCall(exc_info, g.funcs.__cxa_throw,
{ exc_mem, embedConstantPtr(type_id, g.i8_ptr), embedConstantPtr(nullptr, g.i8_ptr) });
emitter.getBuilder()->CreateUnreachable();
endBlock(DEAD);
}
void doStmt(AST* node, ExcInfo exc_info) {
switch (node->type) {
case AST_TYPE::Assert:
doAssert(ast_cast<AST_Assert>(node));
doAssert(ast_cast<AST_Assert>(node), exc_info);
break;
case AST_TYPE::Assign:
doAssign(ast_cast<AST_Assign>(node));
doAssign(ast_cast<AST_Assign>(node), exc_info);
break;
case AST_TYPE::ClassDef:
doClassDef(ast_cast<AST_ClassDef>(node));
doClassDef(ast_cast<AST_ClassDef>(node), exc_info);
break;
case AST_TYPE::Expr:
doExpr(ast_cast<AST_Expr>(node));
doExpr(ast_cast<AST_Expr>(node), exc_info);
break;
case AST_TYPE::FunctionDef:
doFunction(ast_cast<AST_FunctionDef>(node));
doFunction(ast_cast<AST_FunctionDef>(node), exc_info);
break;
// case AST_TYPE::If:
// doIf(ast_cast<AST_If>(node));
// break;
case AST_TYPE::Import:
doImport(ast_cast<AST_Import>(node));
doImport(ast_cast<AST_Import>(node), exc_info);
break;
case AST_TYPE::ImportFrom:
doImportFrom(ast_cast<AST_ImportFrom>(node));
doImportFrom(ast_cast<AST_ImportFrom>(node), exc_info);
break;
case AST_TYPE::Global:
// Should have been handled already
......@@ -1615,16 +1733,35 @@ private:
case AST_TYPE::Pass:
break;
case AST_TYPE::Print:
doPrint(ast_cast<AST_Print>(node));
doPrint(ast_cast<AST_Print>(node), exc_info);
break;
case AST_TYPE::Return:
doReturn(ast_cast<AST_Return>(node));
assert(!exc_info.needsInvoke());
doReturn(ast_cast<AST_Return>(node), exc_info);
break;
case AST_TYPE::Branch:
doBranch(ast_cast<AST_Branch>(node));
assert(!exc_info.needsInvoke());
doBranch(ast_cast<AST_Branch>(node), exc_info);
break;
case AST_TYPE::Jump:
doJump(ast_cast<AST_Jump>(node));
assert(!exc_info.needsInvoke());
doJump(ast_cast<AST_Jump>(node), exc_info);
break;
case AST_TYPE::Invoke: {
assert(!exc_info.needsInvoke());
AST_Invoke* invoke = ast_cast<AST_Invoke>(node);
doStmt(invoke->stmt, ExcInfo(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 AST_TYPE::Raise:
doRaise(ast_cast<AST_Raise>(node), exc_info);
break;
default:
printf("Unhandled stmt type at " __FILE__ ":" STRINGIFY(__LINE__) ": %d\n", node->type);
......@@ -1632,9 +1769,9 @@ private:
}
}
template <typename T> void loadArgument(const T& name, ConcreteCompilerType* t, llvm::Value* v) {
template <typename T> void loadArgument(const T& name, ConcreteCompilerType* t, llvm::Value* v, ExcInfo exc_info) {
ConcreteCompilerVariable* var = unboxVar(t, v, false);
_doSet(name, var);
_doSet(name, var, exc_info);
var->decvref(emitter);
}
......@@ -1813,7 +1950,7 @@ public:
argarray = AI;
break;
}
loadArgument(arg_names[i], arg_types[i], AI);
loadArgument(arg_names[i], arg_types[i], AI, ExcInfo::none());
}
for (int i = 3; i < arg_types.size(); i++) {
......@@ -1825,16 +1962,17 @@ public:
else
assert(arg_types[i]->llvmType() == g.llvm_value_type_ptr);
loadArgument(arg_names[i], arg_types[i], loaded);
loadArgument(arg_names[i], arg_types[i], loaded, ExcInfo::none());
}
}
void run(const CFGBlock* block) override {
ExcInfo exc_info = ExcInfo::none();
for (int i = 0; i < block->body.size(); i++) {
if (state == DEAD)
break;
assert(state != FINISHED);
doStmt(block->body[i]);
doStmt(block->body[i], exc_info);
}
}
};
......
......@@ -190,7 +190,7 @@ public:
virtual EndingState getEndingSymbolTable() = 0;
};
IREmitter* createIREmitter(IRGenState* irstate);
IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock);
IRGenerator* createIRGenerator(IRGenState* irstate, std::unordered_map<CFGBlock*, llvm::BasicBlock*>& entry_blocks,
CFGBlock* myblock, TypeAnalysis* types, GuardList& out_guards,
const GuardList& in_guards, bool is_partial);
......
......@@ -40,6 +40,11 @@
#include "runtime/inline/boxing.h"
extern "C" void* __cxa_begin_catch(void*);
extern "C" void __cxa_end_catch();
extern "C" void* __cxa_allocate_exception(size_t);
extern "C" void __cxa_throw(void*, void*, void (*)(void*));
namespace pyston {
static llvm::Function* lookupFunction(const std::string& name) {
......@@ -168,6 +173,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(unaryop);
GET(import);
GET(repr);
GET(isinstance);
GET(checkUnpackingLength);
GET(raiseAttributeError);
......@@ -203,6 +209,11 @@ void initGlobalFuncs(GlobalState& g) {
g.funcs.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, g.i8_ptr, g.i8_ptr);
g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr);
GET(__cxa_begin_catch);
g.funcs.__cxa_end_catch = addFunc((void*)__cxa_end_catch, g.void_);
g.funcs.__cxa_allocate_exception = addFunc((void*)__cxa_allocate_exception, g.i8_ptr, g.i64);
g.funcs.__cxa_throw = addFunc((void*)__cxa_throw, g.void_, g.i8_ptr, g.i8_ptr, g.i8_ptr);
g.funcs.div_i64_i64 = getFunc((void*)div_i64_i64, "div_i64_i64");
g.funcs.mod_i64_i64 = getFunc((void*)mod_i64_i64, "mod_i64_i64");
g.funcs.pow_i64_i64 = getFunc((void*)pow_i64_i64, "pow_i64_i64");
......
......@@ -23,7 +23,7 @@ struct GlobalFuncs {
llvm::Value* boxInt, *unboxInt, *boxFloat, *unboxFloat, *boxStringPtr, *boxCLFunction, *unboxCLFunction,
*boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *createClass;
llvm::Value* getattr, *setattr, *print, *nonzero, *binop, *compare, *augbinop, *unboxedLen, *getitem, *getclsattr,
*getGlobal, *setitem, *unaryop, *import, *repr;
*getGlobal, *setitem, *unaryop, *import, *repr, *isinstance;
llvm::Value* checkUnpackingLength, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError,
*assertNameDefined, *assertFail;
llvm::Value* printFloat, *listAppendInternal;
......@@ -32,6 +32,8 @@ struct GlobalFuncs {
llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr;
llvm::Value* reoptCompiledFunc, *compilePartialFunc;
llvm::Value* __cxa_begin_catch, *__cxa_end_catch, *__cxa_allocate_exception, *__cxa_throw;
llvm::Value* div_i64_i64, *mod_i64_i64, *pow_i64_i64;
llvm::Value* div_float_float, *mod_float_float, *pow_float_float;
};
......
......@@ -1200,10 +1200,6 @@ bool PrintVisitor::visit_index(AST_Index* node) {
}
bool PrintVisitor::visit_invoke(AST_Invoke* node) {
// printf("invoke: ");
// node->value->accept(this);
// printf("; on success goto %d; on error goto %d", node->normal_dest->idx, node->exc_dest->idx);
printf("invoke %d %d: ", node->normal_dest->idx, node->exc_dest->idx);
node->stmt->accept(this);
return true;
......
......@@ -182,12 +182,8 @@ Box* sorted(Box* obj) {
return rtn;
}
Box* isinstance(Box* obj, Box* cls) {
assert(cls->cls == type_cls);
BoxedClass* ccls = static_cast<BoxedClass*>(cls);
// TODO need to check if it's a subclass, or if subclasshook exists
return boxBool(obj->cls == cls);
Box* isinstance_func(Box* obj, Box* cls) {
return boxBool(isinstance(obj, cls, 0));
}
Box* getattr2(Box* obj, Box* _str) {
......@@ -288,7 +284,7 @@ void setupBuiltins() {
addRTFunction(getattr_func, (void*)getattr3, NULL, 3, false);
builtins_module->giveAttr("getattr", new BoxedFunction(getattr_func));
Box* isinstance_obj = new BoxedFunction(boxRTFunction((void*)isinstance, NULL, 2, false));
Box* isinstance_obj = new BoxedFunction(boxRTFunction((void*)isinstance_func, NULL, 2, false));
builtins_module->giveAttr("isinstance", isinstance_obj);
builtins_module->giveAttr("sorted", new BoxedFunction(boxRTFunction((void*)sorted, NULL, 1, false)));
......
......@@ -34,6 +34,11 @@ static void forceLink(void* x) {
printf("%p\n", x);
}
extern "C" void __py_personality_v0() {
RELEASE_ASSERT(0, "not used");
}
namespace _force {
#define FORCE(name) forceLink((void*)name)
......@@ -71,6 +76,7 @@ void force() {
FORCE(unaryop);
FORCE(import);
FORCE(repr);
FORCE(isinstance);
FORCE(checkUnpackingLength);
FORCE(raiseAttributeError);
......
......@@ -1018,6 +1018,22 @@ extern "C" Box* repr(Box* obj) {
return static_cast<BoxedString*>(obj);
}
extern "C" bool isinstance(Box* obj, Box* cls, int64_t flags) {
bool false_on_noncls = (flags & 0x1);
if (!false_on_noncls) {
assert(cls->cls == type_cls);
} else {
if (cls->cls != type_cls)
return false;
}
BoxedClass* ccls = static_cast<BoxedClass*>(cls);
// TODO more complicated than this, but there's no inheritance yet...
return ccls == obj->cls;
}
extern "C" BoxedInt* hash(Box* obj) {
static StatCounter slowpath_hash("slowpath_hash");
slowpath_hash.log();
......
......@@ -40,6 +40,7 @@ extern "C" Box* runtimeCall(Box*, int64_t, Box*, Box*, Box*, Box**);
extern "C" Box* callattr(Box*, std::string*, bool, int64_t, Box*, Box*, Box*, Box**);
extern "C" BoxedString* str(Box* obj);
extern "C" Box* repr(Box* obj);
extern "C" bool isinstance(Box* obj, Box* cls, int64_t flags);
extern "C" BoxedInt* hash(Box* obj);
// extern "C" Box* abs_(Box* obj);
// extern "C" Box* min_(Box* o0, Box* o1);
......
......@@ -136,7 +136,7 @@ public:
class BoxedList : public Box {
public:
class ElementArray : GCObject {
class ElementArray : public GCObject {
public:
Box* elts[0];
......
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