Commit dbc15587 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Change how we create and represent patchpoints

parent f074ed04
......@@ -198,8 +198,8 @@ ICInfo::ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int
}
static std::unordered_map<void*, ICInfo*> ics_by_return_addr;
void registerCompiledPatchpoint(CompiledFunction* cf, uint8_t* start_addr, PatchpointSetupInfo* pp,
StackInfo stack_info, std::unordered_set<int> live_outs) {
void registerCompiledPatchpoint(CompiledFunction* cf, uint8_t* start_addr, const ICSetupInfo* pp, StackInfo stack_info,
std::unordered_set<int> live_outs) {
int size = pp->totalSize();
uint8_t* end_addr = start_addr + size;
uint8_t* slowpath_addr = end_addr;
......
......@@ -127,9 +127,9 @@ public:
friend class ICSlotRewrite;
};
class PatchpointSetupInfo;
class ICSetupInfo;
class CompiledFunction;
void registerCompiledPatchpoint(CompiledFunction* cf, uint8_t* start_addr, PatchpointSetupInfo*, StackInfo stack_info,
void registerCompiledPatchpoint(CompiledFunction* cf, uint8_t* start_addr, const ICSetupInfo*, StackInfo stack_info,
std::unordered_set<int> live_outs);
ICInfo* getICInfo(void* rtn_addr);
......
......@@ -204,15 +204,14 @@ public:
// converted->getValue()->dump(); llvm::errs() << '\n';
bool do_patchpoint = ENABLE_ICSETATTRS && !info.isInterpreted();
if (do_patchpoint) {
PatchpointSetupInfo* pp
= patchpoints::createSetattrPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
ICSetupInfo* pp = createSetattrIC(info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
llvm_args.push_back(ptr);
llvm_args.push_back(converted->getValue());
emitter.createPatchpoint(pp, (void*)pyston::setattr, llvm_args, info.exc_info);
emitter.createIC(pp, (void*)pyston::setattr, llvm_args, info.exc_info);
} else {
emitter.createCall3(info.exc_info, g.funcs.setattr, var->getValue(), ptr, converted->getValue());
}
......@@ -227,14 +226,13 @@ public:
bool do_patchpoint = false;
if (do_patchpoint) {
PatchpointSetupInfo* pp
= patchpoints::createDelattrPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
ICSetupInfo* pp = createDelattrIC(info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
llvm_args.push_back(ptr);
emitter.createPatchpoint(pp, (void*)pyston::delattr, llvm_args, info.exc_info);
emitter.createIC(pp, (void*)pyston::delattr, llvm_args, info.exc_info);
} else {
emitter.createCall2(info.exc_info, g.funcs.delattr, var->getValue(), ptr);
}
......@@ -274,15 +272,14 @@ public:
bool do_patchpoint = ENABLE_ICGENERICS && !info.isInterpreted();
llvm::Value* rtn;
if (do_patchpoint) {
PatchpointSetupInfo* pp
= patchpoints::createGenericPatchpoint(emitter.currentFunction(), info.getTypeRecorder(), true, 256);
ICSetupInfo* pp = createGenericIC(info.getTypeRecorder(), true, 256);
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
rtn = emitter.createPatchpoint(pp, (void*)pyston::unboxedLen, llvm_args, info.exc_info).getInstruction();
rtn = emitter.createIC(pp, (void*)pyston::unboxedLen, llvm_args, info.exc_info);
} else {
rtn = emitter.createCall(info.exc_info, g.funcs.unboxedLen, var->getValue()).getInstruction();
rtn = emitter.createCall(info.exc_info, g.funcs.unboxedLen, var->getValue());
}
assert(rtn->getType() == g.i64);
return new ConcreteCompilerVariable(INT, rtn, true);
......@@ -295,19 +292,16 @@ public:
bool do_patchpoint = ENABLE_ICGETITEMS && !info.isInterpreted();
llvm::Value* rtn;
if (do_patchpoint) {
PatchpointSetupInfo* pp
= patchpoints::createGetitemPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
ICSetupInfo* pp = createGetitemIC(info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
llvm_args.push_back(converted_slice->getValue());
llvm::Value* uncasted
= emitter.createPatchpoint(pp, (void*)pyston::getitem, llvm_args, info.exc_info).getInstruction();
llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::getitem, llvm_args, info.exc_info);
rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn = emitter.createCall2(info.exc_info, g.funcs.getitem, var->getValue(), converted_slice->getValue())
.getInstruction();
rtn = emitter.createCall2(info.exc_info, g.funcs.getitem, var->getValue(), converted_slice->getValue());
}
converted_slice->decvref(emitter);
......@@ -335,20 +329,18 @@ public:
}
if (do_patchpoint) {
PatchpointSetupInfo* pp
= patchpoints::createBinexpPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
ICSetupInfo* pp = createBinexpIC(info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
llvm_args.push_back(converted_rhs->getValue());
llvm_args.push_back(getConstantInt(op_type, g.i32));
llvm::Value* uncasted
= emitter.createPatchpoint(pp, rt_func_addr, llvm_args, info.exc_info).getInstruction();
llvm::Value* uncasted = emitter.createIC(pp, rt_func_addr, llvm_args, info.exc_info);
rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn = emitter.createCall3(info.exc_info, rt_func, var->getValue(), converted_rhs->getValue(),
getConstantInt(op_type, g.i32)).getInstruction();
getConstantInt(op_type, g.i32));
}
converted_rhs->decvref(emitter);
......@@ -383,17 +375,16 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
bool do_patchpoint = ENABLE_ICGETATTRS && !info.isInterpreted();
if (do_patchpoint) {
PatchpointSetupInfo* pp
= patchpoints::createGetattrPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
ICSetupInfo* pp = createGetattrIC(info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
llvm_args.push_back(ptr);
llvm::Value* uncasted = emitter.createPatchpoint(pp, raw_func, llvm_args, info.exc_info).getInstruction();
llvm::Value* uncasted = emitter.createIC(pp, raw_func, llvm_args, info.exc_info);
rtn_val = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn_val = emitter.createCall2(info.exc_info, llvm_func, var->getValue(), ptr).getInstruction();
rtn_val = emitter.createCall2(info.exc_info, llvm_func, var->getValue(), ptr);
}
return new ConcreteCompilerVariable(UNKNOWN, rtn_val, true);
}
......@@ -483,10 +474,9 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
if (do_patchpoint) {
assert(func_addr);
PatchpointSetupInfo* pp
= patchpoints::createCallsitePatchpoint(emitter.currentFunction(), info.getTypeRecorder(), args.size());
ICSetupInfo* pp = createCallsiteIC(info.getTypeRecorder(), args.size());
llvm::Value* uncasted = emitter.createPatchpoint(pp, func_addr, llvm_args, info.exc_info).getInstruction();
llvm::Value* uncasted = emitter.createIC(pp, func_addr, llvm_args, info.exc_info);
assert(llvm::cast<llvm::FunctionType>(llvm::cast<llvm::PointerType>(func->getType())->getElementType())
->getReturnType() == g.llvm_value_type_ptr);
......@@ -500,7 +490,7 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
//}
// printf("%ld %ld\n", llvm_args.size(), args.size());
// printf("\n");
rtn = emitter.createCall(info.exc_info, func, llvm_args).getInstruction();
rtn = emitter.createCall(info.exc_info, func, llvm_args);
}
if (mallocsave) {
......@@ -580,17 +570,15 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
bool do_patchpoint = ENABLE_ICNONZEROS && !info.isInterpreted();
llvm::Value* rtn_val;
if (do_patchpoint) {
PatchpointSetupInfo* pp
= patchpoints::createNonzeroPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
ICSetupInfo* pp = createNonzeroIC(info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
llvm::Value* uncasted
= emitter.createPatchpoint(pp, (void*)pyston::nonzero, llvm_args, info.exc_info).getInstruction();
llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::nonzero, llvm_args, info.exc_info);
rtn_val = emitter.getBuilder()->CreateTrunc(uncasted, g.i1);
} else {
rtn_val = emitter.createCall(info.exc_info, g.funcs.nonzero, var->getValue()).getInstruction();
rtn_val = emitter.createCall(info.exc_info, g.funcs.nonzero, var->getValue());
}
return boolFromI1(emitter, rtn_val);
}
......@@ -840,13 +828,13 @@ public:
llvm::Value* v;
/*if (op_type == AST_TYPE::Mod) {
v = emitter.createCall2(info.exc_info, g.funcs.mod_i64_i64, var->getValue(), converted_right->getValue())
.getInstruction();
;
} else if (op_type == AST_TYPE::Div || op_type == AST_TYPE::FloorDiv) {
v = emitter.createCall2(info.exc_info, g.funcs.div_i64_i64, var->getValue(), converted_right->getValue())
.getInstruction();
;
} else if (op_type == AST_TYPE::Pow) {
v = emitter.createCall2(info.exc_info, g.funcs.pow_i64_i64, var->getValue(), converted_right->getValue())
.getInstruction();
;
} else if (exp_type == BinOp || exp_type == AugBinOp) {
llvm::Instruction::BinaryOps binopcode;
switch (op_type) {
......@@ -1047,16 +1035,16 @@ public:
bool succeeded = true;
if (op_type == AST_TYPE::Mod) {
v = emitter.createCall2(info.exc_info, g.funcs.mod_float_float, var->getValue(),
converted_right->getValue()).getInstruction();
converted_right->getValue());
} else if (op_type == AST_TYPE::Div || op_type == AST_TYPE::TrueDiv) {
v = emitter.createCall2(info.exc_info, g.funcs.div_float_float, var->getValue(),
converted_right->getValue()).getInstruction();
converted_right->getValue());
} else if (op_type == AST_TYPE::FloorDiv) {
v = emitter.createCall2(info.exc_info, g.funcs.floordiv_float_float, var->getValue(),
converted_right->getValue()).getInstruction();
converted_right->getValue());
} else if (op_type == AST_TYPE::Pow) {
v = emitter.createCall2(info.exc_info, g.funcs.pow_float_float, var->getValue(),
converted_right->getValue()).getInstruction();
converted_right->getValue());
} else if (exp_type == BinOp || exp_type == AugBinOp) {
llvm::Instruction::BinaryOps binopcode;
switch (op_type) {
......
......@@ -52,7 +52,7 @@ public:
void setEmitter(IREmitter* emitter) { this->emitter = emitter; }
};
class PatchpointSetupInfo;
class ICSetupInfo;
class IREmitter {
public:
......@@ -69,13 +69,13 @@ public:
virtual llvm::Function* getIntrinsic(llvm::Intrinsic::ID) = 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;
virtual llvm::Value* createCall(ExcInfo exc_info, llvm::Value* callee, const std::vector<llvm::Value*>& args) = 0;
virtual llvm::Value* createCall(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1) = 0;
virtual llvm::Value* createCall2(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2) = 0;
virtual llvm::Value* createCall3(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2,
llvm::Value* arg3) = 0;
virtual llvm::Value* createIC(const ICSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*>& args,
ExcInfo exc_info) = 0;
};
CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
......
......@@ -129,7 +129,8 @@ static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) {
}
StackMap* stackmap = parseStackMap();
patchpoints::processStackmap(cf, stackmap);
processStackmap(cf, stackmap);
delete stackmap;
}
static std::unordered_map<std::string, CompiledFunction*> machine_name_to_cf;
......
......@@ -15,6 +15,7 @@
#include "codegen/irgen/irgenerator.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
#include "analysis/function_analysis.h"
#include "analysis/scoping_analysis.h"
......@@ -100,10 +101,67 @@ private:
IRGenState* irstate;
IRBuilder* builder;
llvm::BasicBlock*& curblock;
IRGenerator* irgenerator;
llvm::CallSite emitCall(ExcInfo exc_info, llvm::Value* callee, const std::vector<llvm::Value*>& args) {
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 emitPatchpoint(llvm::Type* return_type, const ICSetupInfo* pp, llvm::Value* func,
const std::vector<llvm::Value*>& args,
const std::vector<llvm::Value*>& ic_stackmap_args, ExcInfo exc_info) {
if (pp == NULL)
assert(ic_stackmap_args.size() == 0);
PatchpointInfo* info = PatchpointInfo::create(currentFunction(), pp, ic_stackmap_args.size());
int64_t pp_id = reinterpret_cast<int64_t>(info);
int pp_size = pp ? pp->totalSize() : CALL_ONLY_SIZE;
std::vector<llvm::Value*> pp_args;
pp_args.push_back(getConstantInt(pp_id, g.i64)); // pp_id: will fill this in later
pp_args.push_back(getConstantInt(pp_size, g.i32));
pp_args.push_back(func);
pp_args.push_back(getConstantInt(args.size(), g.i32));
pp_args.insert(pp_args.end(), args.begin(), args.end());
int num_scratch_bytes = info->scratchSize();
llvm::Value* scratch_space = irstate->getScratchSpace(num_scratch_bytes);
pp_args.push_back(scratch_space);
pp_args.insert(pp_args.end(), ic_stackmap_args.begin(), ic_stackmap_args.end());
llvm::Intrinsic::ID intrinsic_id;
if (return_type->isIntegerTy() || return_type->isPointerTy()) {
intrinsic_id = llvm::Intrinsic::experimental_patchpoint_i64;
} else if (return_type->isVoidTy()) {
intrinsic_id = llvm::Intrinsic::experimental_patchpoint_void;
} else if (return_type->isDoubleTy()) {
intrinsic_id = llvm::Intrinsic::experimental_patchpoint_double;
} else {
return_type->dump();
abort();
}
llvm::Function* patchpoint = this->getIntrinsic(intrinsic_id);
llvm::CallSite rtn = this->emitCall(exc_info, patchpoint, pp_args);
return rtn;
}
public:
explicit IREmitterImpl(IRGenState* irstate, llvm::BasicBlock*& curblock)
: irstate(irstate), builder(new IRBuilder(g.context)), curblock(curblock) {
explicit IREmitterImpl(IRGenState* irstate, llvm::BasicBlock*& curblock, IRGenerator* irgenerator)
: irstate(irstate), builder(new IRBuilder(g.context)), curblock(curblock), irgenerator(irgenerator) {
builder->setEmitter(this);
builder->SetInsertPoint(curblock);
}
......@@ -122,66 +180,40 @@ public:
CompiledFunction* currentFunction() override { return irstate->getCurFunction(); }
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::Value* createCall(ExcInfo exc_info, llvm::Value* callee, const std::vector<llvm::Value*>& args) override {
llvm::CallSite cs = this->emitCall(exc_info, callee, args);
return cs.getInstruction();
}
llvm::CallSite createCall(ExcInfo exc_info, llvm::Value* callee, llvm::Value* arg1) override {
llvm::Value* 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 {
llvm::Value* 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 {
llvm::Value* 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 {
int64_t pp_id = pp->getPatchpointId();
int pp_size = pp->totalSize();
llvm::Value* createIC(const ICSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*>& args,
ExcInfo exc_info) override {
assert(irstate->getEffortLevel() != EffortLevel::INTERPRETED);
std::vector<llvm::Value*> pp_args;
pp_args.push_back(getConstantInt(pp_id, g.i64));
pp_args.push_back(getConstantInt(pp_size, g.i32));
pp_args.push_back(embedConstantPtr(func_addr, g.i8->getPointerTo()));
pp_args.push_back(getConstantInt(args.size(), g.i32));
std::vector<llvm::Value*> stackmap_args;
pp_args.insert(pp_args.end(), args.begin(), args.end());
int num_scratch_bytes = pp->numScratchBytes();
if (num_scratch_bytes) {
llvm::Value* scratch_space = irstate->getScratchSpace(num_scratch_bytes);
pp_args.push_back(scratch_space);
}
llvm::CallSite rtn
= emitPatchpoint(pp->hasReturnValue() ? g.i64 : g.void_, pp,
embedConstantPtr(func_addr, g.i8->getPointerTo()), args, stackmap_args, exc_info);
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::CallSite rtn = this->createCall(exc_info, patchpoint, pp_args);
rtn.setCallingConv(pp->getCallingConvention());
return rtn;
return rtn.getInstruction();
}
};
IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock) {
return new IREmitterImpl(irstate, curblock);
IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock, IRGenerator* irgenerator) {
return new IREmitterImpl(irstate, curblock, irgenerator);
}
static std::unordered_map<AST_expr*, std::vector<const std::string*>*> made_keyword_storage;
......@@ -223,8 +255,8 @@ 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), curblock(entry_blocks[myblock]), emitter(irstate, curblock), entry_blocks(entry_blocks),
myblock(myblock), types(types), out_guards(out_guards), in_guards(in_guards),
: irstate(irstate), curblock(entry_blocks[myblock]), emitter(irstate, curblock, this),
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(); }
......@@ -309,9 +341,9 @@ private:
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();
llvm::Value* v = emitter.createCall(
exc_info, g.funcs.isinstance,
{ converted_obj->getValue(), converted_cls->getValue(), converted_flags->getValue() });
assert(v->getType() == g.i1);
return boolFromI1(emitter, v);
......@@ -403,8 +435,7 @@ private:
ConcreteCompilerVariable* converted_obj = obj->makeConverted(emitter, obj->getBoxType());
obj->decvref(emitter);
llvm::Value* v
= emitter.createCall(exc_info, g.funcs.getiter, { converted_obj->getValue() }).getInstruction();
llvm::Value* v = emitter.createCall(exc_info, g.funcs.getiter, { converted_obj->getValue() });
assert(v->getType() == g.llvm_value_type_ptr);
return new ConcreteCompilerVariable(UNKNOWN, v, true);
......@@ -422,7 +453,7 @@ private:
assert(name.size());
llvm::Value* r = emitter.createCall2(exc_info, g.funcs.importFrom, converted_module->getValue(),
embedConstantPtr(&name, g.llvm_str_type_ptr)).getInstruction();
embedConstantPtr(&name, g.llvm_str_type_ptr));
CompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, r, true);
......@@ -440,9 +471,9 @@ private:
ConcreteCompilerVariable* converted_module = module->makeConverted(emitter, module->getBoxType());
module->decvref(emitter);
llvm::Value* r = emitter.createCall2(exc_info, g.funcs.importStar, converted_module->getValue(),
embedConstantPtr(irstate->getSourceInfo()->parent_module,
g.llvm_module_type_ptr)).getInstruction();
llvm::Value* r = emitter.createCall2(
exc_info, g.funcs.importStar, converted_module->getValue(),
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr));
CompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, r, true);
converted_module->decvref(emitter);
......@@ -463,10 +494,9 @@ private:
const std::string& module_name = static_cast<AST_Str*>(node->args[2])->s;
llvm::Value* imported
= emitter.createCall3(exc_info, g.funcs.import, getConstantInt(level, g.i32),
converted_froms->getValue(),
embedConstantPtr(&module_name, g.llvm_str_type_ptr)).getInstruction();
llvm::Value* imported = emitter.createCall3(exc_info, g.funcs.import, getConstantInt(level, g.i32),
converted_froms->getValue(),
embedConstantPtr(&module_name, g.llvm_str_type_ptr));
ConcreteCompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, imported, true);
converted_froms->decvref(emitter);
......@@ -713,22 +743,20 @@ private:
ConcreteCompilerVariable* _getGlobal(AST_Name* node, ExcInfo exc_info) {
bool do_patchpoint = ENABLE_ICGETGLOBALS && (irstate->getEffortLevel() != EffortLevel::INTERPRETED);
if (do_patchpoint) {
PatchpointSetupInfo* pp = patchpoints::createGetGlobalPatchpoint(
emitter.currentFunction(), getOpInfoForNode(node, exc_info).getTypeRecorder());
ICSetupInfo* pp = createGetGlobalIC(getOpInfoForNode(node, exc_info).getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr));
llvm_args.push_back(embedConstantPtr(&node->id, g.llvm_str_type_ptr));
llvm::Value* uncasted
= emitter.createPatchpoint(pp, (void*)pyston::getGlobal, llvm_args, exc_info).getInstruction();
llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::getGlobal, llvm_args, exc_info);
llvm::Value* r = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
return new ConcreteCompilerVariable(UNKNOWN, r, true);
} else {
llvm::Value* r
= emitter.createCall2(exc_info, g.funcs.getGlobal,
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr),
embedConstantPtr(&node->id, g.llvm_str_type_ptr)).getInstruction();
embedConstantPtr(&node->id, g.llvm_str_type_ptr));
return new ConcreteCompilerVariable(UNKNOWN, r, true);
}
}
......@@ -836,7 +864,7 @@ private:
var->decvref(emitter);
std::vector<llvm::Value*> args{ cvar->getValue() };
llvm::Value* rtn = emitter.createCall(exc_info, g.funcs.repr, args).getInstruction();
llvm::Value* rtn = emitter.createCall(exc_info, g.funcs.repr, args);
cvar->decvref(emitter);
rtn = emitter.getBuilder()->CreateBitCast(rtn, g.llvm_value_type_ptr);
......@@ -954,7 +982,7 @@ private:
operand->decvref(emitter);
llvm::Value* rtn = emitter.createCall2(exc_info, g.funcs.unaryop, converted->getValue(),
getConstantInt(node->op_type, g.i32)).getInstruction();
getConstantInt(node->op_type, g.i32));
converted->decvref(emitter);
return new ConcreteCompilerVariable(UNKNOWN, rtn, true);
......@@ -972,8 +1000,8 @@ private:
ConcreteCompilerVariable* convertedValue = value->makeConverted(emitter, value->getBoxType());
value->decvref(emitter);
llvm::Value* rtn = emitter.createCall2(exc_info, g.funcs.yield, convertedGenerator->getValue(),
convertedValue->getValue()).getInstruction();
llvm::Value* rtn
= emitter.createCall2(exc_info, g.funcs.yield, convertedGenerator->getValue(), convertedValue->getValue());
convertedGenerator->decvref(emitter);
convertedValue->decvref(emitter);
......@@ -1302,15 +1330,14 @@ private:
// patchpoints if it couldn't.
bool do_patchpoint = ENABLE_ICSETITEMS && (irstate->getEffortLevel() != EffortLevel::INTERPRETED);
if (do_patchpoint) {
PatchpointSetupInfo* pp = patchpoints::createSetitemPatchpoint(emitter.currentFunction(),
getEmptyOpInfo(exc_info).getTypeRecorder());
ICSetupInfo* pp = createSetitemIC(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, exc_info);
emitter.createIC(pp, (void*)pyston::setitem, llvm_args, exc_info);
} else {
emitter.createCall3(exc_info, g.funcs.setitem, converted_target->getValue(), converted_slice->getValue(),
converted_val->getValue());
......@@ -1339,7 +1366,7 @@ private:
ConcreteCompilerVariable* converted_val = val->makeConverted(emitter, val->getBoxType());
llvm::Value* unpacked = emitter.createCall2(exc_info, g.funcs.unpackIntoArray, converted_val->getValue(),
getConstantInt(ntargets, g.i64)).getInstruction();
getConstantInt(ntargets, g.i64));
assert(unpacked->getType() == g.llvm_value_type_ptr->getPointerTo());
converted_val->decvref(emitter);
......@@ -1461,7 +1488,7 @@ private:
llvm::Value* classobj
= emitter.createCall3(exc_info, g.funcs.createUserClass, embedConstantPtr(&node->name, g.llvm_str_type_ptr),
bases_tuple->getValue(), converted_attr_dict->getValue()).getInstruction();
bases_tuple->getValue(), converted_attr_dict->getValue());
// Note: createuserClass is free to manufacture non-class objects
CompilerVariable* cls = new ConcreteCompilerVariable(UNKNOWN, classobj, true);
......@@ -1508,14 +1535,13 @@ private:
bool do_patchpoint = ENABLE_ICDELITEMS && (irstate->getEffortLevel() != EffortLevel::INTERPRETED);
if (do_patchpoint) {
PatchpointSetupInfo* pp = patchpoints::createDelitemPatchpoint(emitter.currentFunction(),
getEmptyOpInfo(exc_info).getTypeRecorder());
ICSetupInfo* pp = createDelitemIC(getEmptyOpInfo(exc_info).getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(converted_target->getValue());
llvm_args.push_back(converted_slice->getValue());
emitter.createPatchpoint(pp, (void*)pyston::delitem, llvm_args, exc_info);
emitter.createIC(pp, (void*)pyston::delitem, llvm_args, exc_info);
} else {
emitter.createCall2(exc_info, g.funcs.delitem, converted_target->getValue(), converted_slice->getValue());
}
......@@ -1682,9 +1708,8 @@ private:
// begin code for handling of softspace
bool new_softspace = (i < nvals - 1) || (!node->nl);
llvm::Value* dospace
= emitter.createCall(exc_info, g.funcs.softspace,
{ dest->getValue(), getConstantInt(new_softspace, g.i1) }).getInstruction();
llvm::Value* dospace = emitter.createCall(exc_info, g.funcs.softspace,
{ dest->getValue(), getConstantInt(new_softspace, g.i1) });
assert(dospace->getType() == g.i1);
llvm::BasicBlock* ss_block = llvm::BasicBlock::Create(g.context, "softspace", irstate->getLLVMFunction());
......@@ -1705,7 +1730,7 @@ private:
// end code for handling of softspace
llvm::Value* v = emitter.createCall(exc_info, g.funcs.str, { converted->getValue() }).getInstruction();
llvm::Value* v = emitter.createCall(exc_info, g.funcs.str, { converted->getValue() });
v = emitter.getBuilder()->CreateBitCast(v, g.llvm_value_type_ptr);
auto s = new ConcreteCompilerVariable(STR, v, true);
r = dest->callattr(emitter, getOpInfoForNode(node, exc_info), &write_str, false, ArgPassSpec(1), { s },
......
......@@ -199,7 +199,7 @@ public:
};
class IREmitter;
IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock);
IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock, IRGenerator* irgenerator = NULL);
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);
......
......@@ -27,6 +27,7 @@
#include "codegen/codegen.h"
#include "codegen/irgen/hooks.h"
#include "codegen/irgen/util.h"
#include "codegen/patchpoints.h"
#include "core/common.h"
#include "core/stats.h"
#include "core/thread_utils.h"
......@@ -566,32 +567,36 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
llvm::InvokeInst* invoke = llvm::dyn_cast<llvm::InvokeInst>(inst);
void* f;
int arg_start;
int arg_start, num_args;
if (cs.getCalledFunction()
&& (cs.getCalledFunction()->getName() == "llvm.experimental.patchpoint.void"
|| cs.getCalledFunction()->getName() == "llvm.experimental.patchpoint.i64")) {
// cs.dump();
assert(0 && "shouldn't be generating patchpoints for interpretation!");
|| cs.getCalledFunction()->getName() == "llvm.experimental.patchpoint.i64"
|| cs.getCalledFunction()->getName() == "llvm.experimental.patchpoint.double")) {
// cs.dump();
#ifndef NDEBUG
// We use size == CALL_ONLY_SIZE to imply that the call isn't patchable
int pp_size = (int64_t)fetch(cs.getArgument(1), dl, symbols).n;
ASSERT(pp_size == CALL_ONLY_SIZE, "shouldn't be generating patchpoints for interpretation");
#endif
f = (void*)fetch(cs.getArgument(2), dl, symbols).n;
arg_start = 4;
num_args = (int64_t)fetch(cs.getArgument(3), dl, symbols).n;
} else {
f = (void*)fetch(cs.getCalledValue(), dl, symbols).n;
arg_start = 0;
num_args = cs.arg_size();
}
if (VERBOSITY("interpreter") >= 2)
printf("calling %s\n", g.func_addr_registry.getFuncNameAtAddress(f, true).c_str());
std::vector<Val> args;
int nargs = cs.arg_size();
for (int i = arg_start; i < nargs; i++) {
for (int i = arg_start; i < arg_start + num_args; i++) {
// cs.getArgument(i)->dump();
args.push_back(fetch(cs.getArgument(i), dl, symbols));
}
int npassed_args = nargs - arg_start;
// printf("%d %d %d\n", nargs, arg_start, npassed_args);
#ifdef TIME_INTERPRETS
this_us += _t.end();
#endif
......@@ -603,7 +608,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
else
mask = 2;
for (int i = 0; i < npassed_args; i++) {
for (int i = arg_start; i < arg_start + num_args; i++) {
mask <<= 1;
if (cs.getArgument(i)->getType() == g.double_)
mask |= 1;
......@@ -636,6 +641,9 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
case 0b1011:
r = reinterpret_cast<int64_t (*)(double, double)>(f)(args[0].d, args[1].d);
break;
case 0b1100:
r = reinterpret_cast<double (*)(int64_t, int64_t)>(f)(args[0].n, args[1].n);
break;
case 0b1111:
r = reinterpret_cast<double (*)(double, double)>(f)(args[0].d, args[1].d);
break;
......
......@@ -18,6 +18,8 @@
#include <unordered_map>
#include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h"
#include "codegen/compvars.h"
#include "codegen/stackmaps.h"
#include "core/common.h"
#include "core/options.h"
......@@ -26,33 +28,71 @@
namespace pyston {
int PatchpointSetupInfo::totalSize() const {
int call_size = 13;
int ICSetupInfo::totalSize() const {
int call_size = CALL_ONLY_SIZE;
if (getCallingConvention() != llvm::CallingConv::C) {
// have no idea what the precise number is:
call_size = 128;
// 14 bytes per reg that needs to be spilled
call_size += 14 * 4;
}
return num_slots * slot_size + call_size;
}
int64_t PatchpointSetupInfo::getPatchpointId() const {
return pp_id;
}
static std::unordered_map<int64_t, PatchpointSetupInfo*> new_patchpoints_by_id;
static std::vector<PatchpointInfo*> new_patchpoints;
ICSetupInfo* ICSetupInfo::initialize(bool has_return_value, int num_slots, int slot_size, ICType type,
TypeRecorder* type_recorder) {
ICSetupInfo* rtn = new ICSetupInfo(type, num_slots, slot_size, has_return_value, type_recorder);
PatchpointSetupInfo* PatchpointSetupInfo::initialize(bool has_return_value, int num_slots, int slot_size,
CompiledFunction* parent_cf, patchpoints::PatchpointType type,
TypeRecorder* type_recorder) {
static int64_t next_id = 100;
int64_t id = next_id++;
// We use size == CALL_ONLY_SIZE to imply that the call isn't patchable
assert(rtn->totalSize() > CALL_ONLY_SIZE);
PatchpointSetupInfo* rtn
= new PatchpointSetupInfo(id, type, num_slots, slot_size, parent_cf, has_return_value, type_recorder);
new_patchpoints_by_id[id] = rtn;
return rtn;
}
namespace patchpoints {
int PatchpointInfo::patchpointSize() {
if (icinfo) {
int r = icinfo->totalSize();
assert(r > CALL_ONLY_SIZE);
return r;
}
return CALL_ONLY_SIZE;
}
static int extractScratchOffset(PatchpointInfo* pp, StackMap::Record* r) {
StackMap::Record::Location l = r->locations[pp->scratchStackmapArg()];
static const int DWARF_RBP_REGNUM = 6;
assert(l.type == StackMap::Record::Location::LocationType::Direct);
assert(l.regnum == DWARF_RBP_REGNUM);
return l.offset;
}
static std::unordered_set<int> extractLiveOuts(StackMap::Record* r, llvm::CallingConv::ID cc) {
std::unordered_set<int> live_outs;
// Using the C calling convention, there shouldn't be any non-callee-save registers in here,
// but LLVM is conservative and will add some. So with the C cc, ignored the specified live outs
if (cc != llvm::CallingConv::C) {
for (const auto& live_out : r->live_outs) {
live_outs.insert(live_out.regnum);
}
}
// llvm doesn't consider callee-save registers to be live
// if they're never allocated, but I think it makes much more
// sense to track them as live_outs.
// Unfortunately this means we need to be conservative about it unless
// we can change llvm's behavior.
live_outs.insert(3);
live_outs.insert(12);
live_outs.insert(13);
live_outs.insert(14);
live_outs.insert(15);
return live_outs;
}
void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
int nrecords = stackmap ? stackmap->records.size() : 0;
......@@ -64,104 +104,97 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
const StackMap::StackSizeRecord& stack_size_record = stackmap->stack_size_records[0];
int stack_size = stack_size_record.stack_size;
PatchpointSetupInfo* pp = new_patchpoints_by_id[r->id];
PatchpointInfo* pp = reinterpret_cast<PatchpointInfo*>(r->id);
assert(pp);
bool has_scratch = (pp->numScratchBytes() != 0);
int scratch_rbp_offset = 0;
if (has_scratch) {
assert(r->locations.size() == 1);
if (VERBOSITY())
printf("Processing pp %ld\n", reinterpret_cast<int64_t>(pp));
StackMap::Record::Location l = r->locations[0];
assert(r->locations.size() == pp->totalStackmapArgs());
static const int DWARF_RBP_REGNUM = 6;
int scratch_rbp_offset = extractScratchOffset(pp, r);
int scratch_size = pp->scratchSize();
assert(scratch_size % sizeof(void*) == 0);
assert(scratch_rbp_offset % sizeof(void*) == 0);
assert(l.type == 2); // "Direct"
assert(l.regnum == DWARF_RBP_REGNUM);
scratch_rbp_offset = l.offset;
} else {
assert(r->locations.size() == 0);
}
uint8_t* start_addr = (uint8_t*)pp->parentFunction()->code + r->offset;
uint8_t* end_addr = start_addr + pp->patchpointSize();
uint8_t* func_addr = (uint8_t*)pp->parent_cf->code;
assert(func_addr);
uint8_t* start_addr = func_addr + r->offset;
const ICSetupInfo* ic = pp->getICInfo();
if (ic == NULL)
continue;
std::unordered_set<int> live_outs;
for (const auto& live_out : r->live_outs) {
live_outs.insert(live_out.regnum);
}
std::unordered_set<int> live_outs(extractLiveOuts(r, ic->getCallingConvention()));
// llvm doesn't consider callee-save registers to be live
// if they're never allocated, but I think it makes much more
// sense to track them as live_outs.
// Unfortunately this means we need to be conservative about it unless
// we can change llvm's behavior.
live_outs.insert(3);
live_outs.insert(12);
live_outs.insert(13);
live_outs.insert(14);
live_outs.insert(15);
registerCompiledPatchpoint(cf, start_addr, pp,
StackInfo({ stack_size, has_scratch, pp->numScratchBytes(), scratch_rbp_offset }),
registerCompiledPatchpoint(cf, start_addr, ic,
StackInfo({ stack_size, true, scratch_size, scratch_rbp_offset }),
std::move(live_outs));
}
for (const std::pair<int64_t, PatchpointSetupInfo*>& p : new_patchpoints_by_id) {
delete p.second;
for (PatchpointInfo* pp : new_patchpoints) {
const ICSetupInfo* ic = pp->getICInfo();
if (ic)
delete ic;
delete pp;
}
new_patchpoints_by_id.clear();
new_patchpoints.clear();
}
PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo,
int num_ic_stackmap_args) {
if (icinfo == NULL)
assert(num_ic_stackmap_args == 0);
auto* r = new PatchpointInfo(parent_cf, icinfo, num_ic_stackmap_args);
new_patchpoints.push_back(r);
return r;
}
PatchpointSetupInfo* createGenericPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder,
bool has_return_value, int size) {
return PatchpointSetupInfo::initialize(has_return_value, 1, size, parent_cf, Generic, type_recorder);
ICSetupInfo* createGenericIC(TypeRecorder* type_recorder, bool has_return_value, int size) {
return ICSetupInfo::initialize(has_return_value, 1, size, ICSetupInfo::Generic, type_recorder);
}
PatchpointSetupInfo* createGetattrPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 512, parent_cf, Getattr, type_recorder);
ICSetupInfo* createGetattrIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 1, 512, ICSetupInfo::Getattr, type_recorder);
}
PatchpointSetupInfo* createGetitemPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 512, parent_cf, Getitem, type_recorder);
ICSetupInfo* createGetitemIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 1, 512, ICSetupInfo::Getitem, type_recorder);
}
PatchpointSetupInfo* createSetitemPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 256, parent_cf, Setitem, type_recorder);
ICSetupInfo* createSetitemIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 1, 256, ICSetupInfo::Setitem, type_recorder);
}
PatchpointSetupInfo* createDelitemPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(false, 1, 256, parent_cf, Delitem, type_recorder);
ICSetupInfo* createDelitemIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(false, 1, 256, ICSetupInfo::Delitem, type_recorder);
}
PatchpointSetupInfo* createSetattrPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(false, 2, 512, parent_cf, Setattr, type_recorder);
ICSetupInfo* createSetattrIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(false, 2, 512, ICSetupInfo::Setattr, type_recorder);
}
PatchpointSetupInfo* createDelattrPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(false, 1, 144, parent_cf, Delattr, type_recorder);
ICSetupInfo* createDelattrIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(false, 1, 144, ICSetupInfo::Delattr, type_recorder);
}
PatchpointSetupInfo* createCallsitePatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder, int num_args) {
ICSetupInfo* createCallsiteIC(TypeRecorder* type_recorder, int num_args) {
// TODO These are very large, but could probably be made much smaller with IC optimizations
// - using rewriter2 for better code
// - not emitting duplicate guards
return PatchpointSetupInfo::initialize(true, 3, 640 + 48 * num_args, parent_cf, Callsite, type_recorder);
return ICSetupInfo::initialize(true, 3, 640 + 48 * num_args, ICSetupInfo::Callsite, type_recorder);
}
PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 128, parent_cf, GetGlobal, type_recorder);
ICSetupInfo* createGetGlobalIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 1, 128, ICSetupInfo::GetGlobal, type_recorder);
}
PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 4, 512, parent_cf, Binexp, type_recorder);
ICSetupInfo* createBinexpIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 4, 512, ICSetupInfo::Binexp, type_recorder);
}
PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 2, 64, parent_cf, Nonzero, type_recorder);
ICSetupInfo* createNonzeroIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 2, 64, ICSetupInfo::Nonzero, type_recorder);
}
} // namespace patchpoints
} // namespace pyston
......@@ -20,85 +20,102 @@
#include "llvm/IR/CallingConv.h"
#include "codegen/stackmaps.h"
#include "core/common.h"
namespace pyston {
class CompiledFunction;
class CompilerType;
struct StackMap;
class TypeRecorder;
class ICSetupInfo;
namespace patchpoints {
enum PatchpointType {
Generic,
Callsite,
GetGlobal,
Getattr,
Setattr,
Delattr,
Getitem,
Setitem,
Delitem,
Binexp,
Nonzero,
};
}
static const int CALL_ONLY_SIZE = 13;
class CompiledFunction;
void processStackmap(CompiledFunction* cf, StackMap* stackmap);
class PatchpointSetupInfo {
struct PatchpointInfo {
private:
PatchpointSetupInfo(int64_t pp_id, patchpoints::PatchpointType type, int num_slots, int slot_size,
CompiledFunction* parent_cf, bool has_return_value, TypeRecorder* type_recorder)
: pp_id(pp_id), type(type), num_slots(num_slots), slot_size(slot_size), has_return_value(has_return_value),
parent_cf(parent_cf), type_recorder(type_recorder) {}
CompiledFunction* const parent_cf;
const ICSetupInfo* icinfo;
int num_ic_stackmap_args;
PatchpointInfo(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args)
: parent_cf(parent_cf), icinfo(icinfo), num_ic_stackmap_args(num_ic_stackmap_args) {}
public:
const ICSetupInfo* getICInfo() { return icinfo; }
int patchpointSize();
CompiledFunction* parentFunction() { return parent_cf; }
int scratchStackmapArg() { return 0; }
int scratchSize() { return 80; }
int icStackmapArgsStart() { return 1; }
int numICStackmapArgs() { return num_ic_stackmap_args; }
const int64_t pp_id;
int totalStackmapArgs() { return icStackmapArgsStart() + numICStackmapArgs(); }
static PatchpointInfo* create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args);
};
class ICSetupInfo {
public:
const patchpoints::PatchpointType type;
enum ICType {
Generic,
Callsite,
GetGlobal,
Getattr,
Setattr,
Delattr,
Getitem,
Setitem,
Delitem,
Binexp,
Nonzero,
};
private:
ICSetupInfo(ICType type, int num_slots, int slot_size, bool has_return_value, TypeRecorder* type_recorder)
: type(type), num_slots(num_slots), slot_size(slot_size), has_return_value(has_return_value),
type_recorder(type_recorder) {}
public:
const ICType type;
const int num_slots, slot_size;
const bool has_return_value;
CompiledFunction* const parent_cf;
TypeRecorder* const type_recorder;
int totalSize() const;
int64_t getPatchpointId() const;
bool hasReturnValue() const { return has_return_value; }
int numScratchBytes() const { return 64; }
llvm::CallingConv::ID getCallingConvention() const {
// The plan is to switch probably everything over to PreseveAll (and potentially AnyReg),
// but for only switch Getattr so the testing can be localized:
if (type == patchpoints::Getattr || type == patchpoints::Setattr)
if (type == Getattr || type == Setattr)
return llvm::CallingConv::PreserveAll;
return llvm::CallingConv::C;
}
static PatchpointSetupInfo* initialize(bool has_return_value, int num_slots, int slot_size,
CompiledFunction* parent_cf, patchpoints::PatchpointType type,
TypeRecorder* type_recorder);
static ICSetupInfo* initialize(bool has_return_value, int num_slots, int slot_size, ICType type,
TypeRecorder* type_recorder);
};
struct StackMap;
namespace patchpoints {
void processStackmap(CompiledFunction* cf, StackMap* stackmap);
PatchpointSetupInfo* createGenericPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder,
bool has_return_value, int size);
PatchpointSetupInfo* createCallsitePatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder, int num_args);
PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
PatchpointSetupInfo* createGetattrPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
PatchpointSetupInfo* createSetattrPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
PatchpointSetupInfo* createDelattrPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
PatchpointSetupInfo* createGetitemPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
PatchpointSetupInfo* createSetitemPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
PatchpointSetupInfo* createDelitemPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder);
}
ICSetupInfo* createGenericIC(TypeRecorder* type_recorder, bool has_return_value, int size);
ICSetupInfo* createCallsiteIC(TypeRecorder* type_recorder, int num_args);
ICSetupInfo* createGetGlobalIC(TypeRecorder* type_recorder);
ICSetupInfo* createGetattrIC(TypeRecorder* type_recorder);
ICSetupInfo* createSetattrIC(TypeRecorder* type_recorder);
ICSetupInfo* createDelattrIC(TypeRecorder* type_recorder);
ICSetupInfo* createGetitemIC(TypeRecorder* type_recorder);
ICSetupInfo* createSetitemIC(TypeRecorder* type_recorder);
ICSetupInfo* createDelitemIC(TypeRecorder* type_recorder);
ICSetupInfo* createBinexpIC(TypeRecorder* type_recorder);
ICSetupInfo* createNonzeroIC(TypeRecorder* type_recorder);
} // namespace pyston
......
......@@ -32,7 +32,14 @@ struct StackMap {
struct Record {
struct __attribute__((__packed__)) Location {
uint8_t type;
enum LocationType : uint8_t {
Register = 0x1,
Direct = 0x2,
Indirect = 0x3,
Constant = 0x4,
ConstIndex = 0x5,
} type;
uint8_t flags;
uint16_t regnum;
int32_t offset;
......
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