Commit 0514bf3c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add a testing mode to force-use capi exceptions

And fix a bunch of resulting issues (mostly just some pretty benign
assertion errors).
parent ae770511
...@@ -338,7 +338,7 @@ public: ...@@ -338,7 +338,7 @@ public:
ConcreteCompilerVariable* converted_slice = slice->makeConverted(emitter, slice->getBoxType()); ConcreteCompilerVariable* converted_slice = slice->makeConverted(emitter, slice->getBoxType());
ExceptionStyle target_exception_style = CXX; ExceptionStyle target_exception_style = CXX;
if (info.unw_info.capi_exc_dest) if (FORCE_LLVM_CAPI || info.unw_info.capi_exc_dest)
target_exception_style = CAPI; target_exception_style = CAPI;
bool do_patchpoint = ENABLE_ICGETITEMS; bool do_patchpoint = ENABLE_ICGETITEMS;
...@@ -501,7 +501,7 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C ...@@ -501,7 +501,7 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
llvm::Value* rtn_val = NULL; llvm::Value* rtn_val = NULL;
ExceptionStyle target_exception_style = CXX; ExceptionStyle target_exception_style = CXX;
if (info.unw_info.capi_exc_dest) if (info.unw_info.capi_exc_dest || (!cls_only && FORCE_LLVM_CAPI))
target_exception_style = CAPI; target_exception_style = CAPI;
llvm::Value* llvm_func; llvm::Value* llvm_func;
...@@ -1505,7 +1505,7 @@ public: ...@@ -1505,7 +1505,7 @@ public:
if (canStaticallyResolveGetattrs()) { if (canStaticallyResolveGetattrs()) {
Box* rtattr = typeLookup(cls, attr, nullptr); Box* rtattr = typeLookup(cls, attr, nullptr);
if (rtattr == NULL) { if (rtattr == NULL) {
ExceptionStyle exception_style = info.unw_info.capi_exc_dest ? CAPI : CXX; ExceptionStyle exception_style = (FORCE_LLVM_CAPI || info.unw_info.capi_exc_dest) ? CAPI : CXX;
llvm::Value* raise_func = exception_style == CXX ? g.funcs.raiseAttributeErrorStr llvm::Value* raise_func = exception_style == CXX ? g.funcs.raiseAttributeErrorStr
: g.funcs.raiseAttributeErrorStrCapi; : g.funcs.raiseAttributeErrorStrCapi;
llvm::CallSite call = emitter.createCall3( llvm::CallSite call = emitter.createCall3(
...@@ -1557,14 +1557,10 @@ public: ...@@ -1557,14 +1557,10 @@ public:
BoxedString* attr, bool clsonly, ArgPassSpec argspec, BoxedString* attr, bool clsonly, ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args, const std::vector<CompilerVariable*>& args,
const std::vector<BoxedString*>* keyword_names, const std::vector<BoxedString*>* keyword_names,
bool* no_attribute = NULL) { bool* no_attribute = NULL, ExceptionStyle exception_style = CXX) {
if (!canStaticallyResolveGetattrs()) if (!canStaticallyResolveGetattrs())
return NULL; return NULL;
ExceptionStyle exception_style = CXX;
if (info.unw_info.capi_exc_dest)
exception_style = CAPI;
Box* rtattr = cls->getattr(attr); Box* rtattr = cls->getattr(attr);
if (rtattr == NULL) { if (rtattr == NULL) {
if (no_attribute) { if (no_attribute) {
...@@ -1763,8 +1759,13 @@ public: ...@@ -1763,8 +1759,13 @@ public:
CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* slice) override { CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* slice) override {
static BoxedString* attr = internStringImmortal("__getitem__"); static BoxedString* attr = internStringImmortal("__getitem__");
bool no_attribute = false; bool no_attribute = false;
ExceptionStyle exception_style = CXX;
if (FORCE_LLVM_CAPI || info.unw_info.capi_exc_dest)
exception_style = CAPI;
ConcreteCompilerVariable* called_constant = tryCallattrConstant( ConcreteCompilerVariable* called_constant = tryCallattrConstant(
emitter, info, var, attr, true, ArgPassSpec(1, 0, 0, 0), { slice }, NULL, &no_attribute); emitter, info, var, attr, true, ArgPassSpec(1, 0, 0, 0), { slice }, NULL, &no_attribute, exception_style);
if (no_attribute) { if (no_attribute) {
assert(called_constant->getType() == UNDEF); assert(called_constant->getType() == UNDEF);
...@@ -2269,9 +2270,20 @@ public: ...@@ -2269,9 +2270,20 @@ public:
rtn->incvref(); rtn->incvref();
return rtn; return rtn;
} else { } else {
llvm::CallSite call = emitter.createCall(info.unw_info, g.funcs.raiseIndexErrorStr, ExceptionStyle target_exception_style = CXX;
embedConstantPtr("tuple", g.i8_ptr)); if (FORCE_LLVM_CAPI || info.unw_info.capi_exc_dest)
call.setDoesNotReturn(); target_exception_style = CAPI;
if (target_exception_style == CAPI) {
llvm::CallSite call = emitter.createCall(info.unw_info, g.funcs.raiseIndexErrorStrCapi,
embedConstantPtr("tuple", g.i8_ptr), CAPI);
emitter.checkAndPropagateCapiException(info.unw_info, getNullPtr(g.llvm_value_type_ptr),
getNullPtr(g.llvm_value_type_ptr));
} else {
llvm::CallSite call = emitter.createCall(info.unw_info, g.funcs.raiseIndexErrorStr,
embedConstantPtr("tuple", g.i8_ptr), CXX);
call.setDoesNotReturn();
}
return undefVariable(); return undefVariable();
} }
} }
......
...@@ -40,6 +40,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm); ...@@ -40,6 +40,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm);
CompiledFunction* cfForMachineFunctionName(const std::string&); CompiledFunction* cfForMachineFunctionName(const std::string&);
extern "C" void capiExcCaughtInJit(AST_stmt* current_stmt, void* source_info); extern "C" void capiExcCaughtInJit(AST_stmt* current_stmt, void* source_info);
// This is just meant for the use of the JIT (normal runtime code should call throwCAPIException)
extern "C" void reraiseJitCapiExc() __attribute__((noreturn));
extern "C" Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags); extern "C" Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags);
extern "C" Box* eval(Box* boxedCode, Box* globals, Box* locals); extern "C" Box* eval(Box* boxedCode, Box* globals, Box* locals);
......
...@@ -508,7 +508,8 @@ public: ...@@ -508,7 +508,8 @@ public:
embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr)); embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr));
if (!exc_caught) { if (!exc_caught) {
RELEASE_ASSERT(0, "need to implement this"); getBuilder()->CreateCall(g.funcs.reraiseJitCapiExc);
getBuilder()->CreateUnreachable();
} }
setCurrentBasicBlock(normal_dest); setCurrentBasicBlock(normal_dest);
...@@ -2318,7 +2319,7 @@ private: ...@@ -2318,7 +2319,7 @@ private:
// but ommitting the first argument is *not* the same as passing None. // but ommitting the first argument is *not* the same as passing None.
ExceptionStyle target_exception_style = CXX; ExceptionStyle target_exception_style = CXX;
if (unw_info.capi_exc_dest) if (unw_info.capi_exc_dest || (FORCE_LLVM_CAPI && node->arg0 && !node->arg2))
target_exception_style = CAPI; target_exception_style = CAPI;
if (node->arg0 == NULL) { if (node->arg0 == NULL) {
......
...@@ -228,6 +228,7 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -228,6 +228,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(raiseAttributeErrorCapi); GET(raiseAttributeErrorCapi);
GET(raiseAttributeErrorStrCapi); GET(raiseAttributeErrorStrCapi);
GET(raiseIndexErrorStr); GET(raiseIndexErrorStr);
GET(raiseIndexErrorStrCapi);
GET(raiseNotIterableError); GET(raiseNotIterableError);
GET(assertNameDefined); GET(assertNameDefined);
GET(assertFailDerefNameDefined); GET(assertFailDerefNameDefined);
...@@ -278,6 +279,7 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -278,6 +279,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(PyErr_Fetch); GET(PyErr_Fetch);
GET(PyErr_NormalizeException); GET(PyErr_NormalizeException);
GET(capiExcCaughtInJit); GET(capiExcCaughtInJit);
GET(reraiseJitCapiExc);
GET(deopt); GET(deopt);
GET(div_float_float); GET(div_float_float);
......
...@@ -40,8 +40,8 @@ struct GlobalFuncs { ...@@ -40,8 +40,8 @@ struct GlobalFuncs {
*importFrom, *importStar, *repr, *str, *strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext; *importFrom, *importStar, *repr, *str, *strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext;
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi, llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi,
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *assertNameDefined, *assertFail, *raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi,
*assertFailDerefNameDefined; *assertNameDefined, *assertFail, *assertFailDerefNameDefined;
llvm::Value* printFloat, *listAppendInternal, *getSysStdout; llvm::Value* printFloat, *listAppendInternal, *getSysStdout;
llvm::Value* runtimeCall0, *runtimeCall1, *runtimeCall2, *runtimeCall3, *runtimeCall, *runtimeCallN; llvm::Value* runtimeCall0, *runtimeCall1, *runtimeCall2, *runtimeCall3, *runtimeCall, *runtimeCallN;
llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr, *callattrN; llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr, *callattrN;
...@@ -51,7 +51,7 @@ struct GlobalFuncs { ...@@ -51,7 +51,7 @@ struct GlobalFuncs {
llvm::Value* __cxa_end_catch; llvm::Value* __cxa_end_catch;
llvm::Value* raise0, *raise3, *raise3_capi; llvm::Value* raise0, *raise3, *raise3_capi;
llvm::Value* PyErr_Fetch, *PyErr_NormalizeException, *capiExcCaughtInJit; llvm::Value* PyErr_Fetch, *PyErr_NormalizeException, *capiExcCaughtInJit, *reraiseJitCapiExc;
llvm::Value* deopt; llvm::Value* deopt;
llvm::Value* div_float_float, *floordiv_float_float, *mod_float_float, *pow_float_float; llvm::Value* div_float_float, *floordiv_float_float, *mod_float_float, *pow_float_float;
......
...@@ -481,6 +481,16 @@ bool frameIsPythonFrame(unw_word_t ip, unw_word_t bp, unw_cursor_t* cursor, Pyth ...@@ -481,6 +481,16 @@ bool frameIsPythonFrame(unw_word_t ip, unw_word_t bp, unw_cursor_t* cursor, Pyth
return true; return true;
} }
static const LineInfo lineInfoForFrame(PythonFrameIteratorImpl* frame_it) {
AST_stmt* current_stmt = frame_it->getCurrentStatement();
auto* cl = frame_it->getCL();
assert(cl);
auto source = cl->source.get();
return LineInfo(current_stmt->lineno, current_stmt->col_offset, source->fn, source->getName());
}
class PythonUnwindSession : public Box { class PythonUnwindSession : public Box {
ExcInfo exc_info; ExcInfo exc_info;
bool skip; bool skip;
...@@ -518,12 +528,13 @@ public: ...@@ -518,12 +528,13 @@ public:
stat.log(t.end()); stat.log(t.end());
} }
void addTraceback(const LineInfo& line_info) { void addTraceback(PythonFrameIteratorImpl& frame_iter) {
RELEASE_ASSERT(is_active, ""); RELEASE_ASSERT(is_active, "");
if (exc_info.reraise) { if (exc_info.reraise) {
exc_info.reraise = false; exc_info.reraise = false;
return; return;
} }
auto line_info = lineInfoForFrame(&frame_iter);
BoxedTraceback::here(line_info, &exc_info.traceback); BoxedTraceback::here(line_info, &exc_info.traceback);
} }
...@@ -593,16 +604,6 @@ void throwingException(PythonUnwindSession* unwind) { ...@@ -593,16 +604,6 @@ void throwingException(PythonUnwindSession* unwind) {
unwind->logException(); unwind->logException();
} }
static const LineInfo lineInfoForFrame(PythonFrameIteratorImpl* frame_it) {
AST_stmt* current_stmt = frame_it->getCurrentStatement();
auto* cl = frame_it->getCL();
assert(cl);
auto source = cl->source.get();
return LineInfo(current_stmt->lineno, current_stmt->col_offset, source->fn, source->getName());
}
extern "C" void capiExcCaughtInJit(AST_stmt* stmt, void* _source_info) { extern "C" void capiExcCaughtInJit(AST_stmt* stmt, void* _source_info) {
SourceInfo* source = static_cast<SourceInfo*>(_source_info); SourceInfo* source = static_cast<SourceInfo*>(_source_info);
// TODO: handle reraise (currently on the ExcInfo object) // TODO: handle reraise (currently on the ExcInfo object)
...@@ -611,6 +612,16 @@ extern "C" void capiExcCaughtInJit(AST_stmt* stmt, void* _source_info) { ...@@ -611,6 +612,16 @@ extern "C" void capiExcCaughtInJit(AST_stmt* stmt, void* _source_info) {
&tstate->curexc_traceback); &tstate->curexc_traceback);
} }
extern "C" void reraiseJitCapiExc() {
ensureCAPIExceptionSet();
// TODO: we are normalizing to many times?
ExcInfo e = excInfoForRaise(cur_thread_state.curexc_type, cur_thread_state.curexc_value,
cur_thread_state.curexc_traceback);
PyErr_Clear();
e.reraise = true;
throw e;
}
void exceptionCaughtInInterpreter(LineInfo line_info, ExcInfo* exc_info) { void exceptionCaughtInInterpreter(LineInfo line_info, ExcInfo* exc_info) {
static StatCounter frames_unwound("num_frames_unwound_python"); static StatCounter frames_unwound("num_frames_unwound_python");
frames_unwound.log(); frames_unwound.log();
...@@ -647,7 +658,7 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu ...@@ -647,7 +658,7 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu
frames_unwound.log(); frames_unwound.log();
if (!unwind_session->shouldSkipFrame()) if (!unwind_session->shouldSkipFrame())
unwind_session->addTraceback(lineInfoForFrame(&frame_iter)); unwind_session->addTraceback(frame_iter);
// frame_iter->cf->entry_descriptor will be non-null for OSR frames. // frame_iter->cf->entry_descriptor will be non-null for OSR frames.
bool was_osr = (frame_iter.getId().type == PythonFrameId::COMPILED) && (frame_iter.cf->entry_descriptor); bool was_osr = (frame_iter.getId().type == PythonFrameId::COMPILED) && (frame_iter.cf->entry_descriptor);
......
...@@ -44,6 +44,9 @@ bool ENABLE_PYPA_PARSER = true; ...@@ -44,6 +44,9 @@ bool ENABLE_PYPA_PARSER = true;
bool USE_REGALLOC_BASIC = true; bool USE_REGALLOC_BASIC = true;
bool PAUSE_AT_ABORT = false; bool PAUSE_AT_ABORT = false;
bool ENABLE_TRACEBACKS = true; bool ENABLE_TRACEBACKS = true;
// Forces the llvm jit to use capi exceptions whenever it can, as opposed to whenever it thinks
// it is faster:
bool FORCE_LLVM_CAPI = false;
int OSR_THRESHOLD_INTERPRETER = 25; int OSR_THRESHOLD_INTERPRETER = 25;
int REOPT_THRESHOLD_INTERPRETER = 25; int REOPT_THRESHOLD_INTERPRETER = 25;
......
...@@ -39,7 +39,7 @@ extern int MAX_OBJECT_CACHE_ENTRIES; ...@@ -39,7 +39,7 @@ extern int MAX_OBJECT_CACHE_ENTRIES;
extern bool SHOW_DISASM, FORCE_INTERPRETER, FORCE_OPTIMIZE, PROFILE, DUMPJIT, TRAP, USE_STRIPPED_STDLIB, extern bool SHOW_DISASM, FORCE_INTERPRETER, FORCE_OPTIMIZE, PROFILE, DUMPJIT, TRAP, USE_STRIPPED_STDLIB,
CONTINUE_AFTER_FATAL, ENABLE_INTERPRETER, ENABLE_BASELINEJIT, ENABLE_PYPA_PARSER, USE_REGALLOC_BASIC, CONTINUE_AFTER_FATAL, ENABLE_INTERPRETER, ENABLE_BASELINEJIT, ENABLE_PYPA_PARSER, USE_REGALLOC_BASIC,
PAUSE_AT_ABORT, ENABLE_TRACEBACKS, ASSEMBLY_LOGGING; PAUSE_AT_ABORT, ENABLE_TRACEBACKS, ASSEMBLY_LOGGING, FORCE_LLVM_CAPI;
extern bool ENABLE_ICS, ENABLE_ICGENERICS, ENABLE_ICGETITEMS, ENABLE_ICSETITEMS, ENABLE_ICDELITEMS, ENABLE_ICBINEXPS, extern bool ENABLE_ICS, ENABLE_ICGENERICS, ENABLE_ICGETITEMS, ENABLE_ICSETITEMS, ENABLE_ICDELITEMS, ENABLE_ICBINEXPS,
ENABLE_ICNONZEROS, ENABLE_ICCALLSITES, ENABLE_ICSETATTRS, ENABLE_ICGETATTRS, ENALBE_ICDELATTRS, ENABLE_ICGETGLOBALS, ENABLE_ICNONZEROS, ENABLE_ICCALLSITES, ENABLE_ICSETATTRS, ENABLE_ICGETATTRS, ENALBE_ICDELATTRS, ENABLE_ICGETGLOBALS,
......
...@@ -106,6 +106,7 @@ void force() { ...@@ -106,6 +106,7 @@ void force() {
FORCE(raiseAttributeErrorCapi); FORCE(raiseAttributeErrorCapi);
FORCE(raiseAttributeErrorStrCapi); FORCE(raiseAttributeErrorStrCapi);
FORCE(raiseIndexErrorStr); FORCE(raiseIndexErrorStr);
FORCE(raiseIndexErrorStrCapi);
FORCE(raiseNotIterableError); FORCE(raiseNotIterableError);
FORCE(assertNameDefined); FORCE(assertNameDefined);
FORCE(assertFailDerefNameDefined); FORCE(assertFailDerefNameDefined);
...@@ -125,6 +126,7 @@ void force() { ...@@ -125,6 +126,7 @@ void force() {
FORCE(PyErr_Fetch); FORCE(PyErr_Fetch);
FORCE(PyErr_NormalizeException); FORCE(PyErr_NormalizeException);
FORCE(capiExcCaughtInJit); FORCE(capiExcCaughtInJit);
FORCE(reraiseJitCapiExc);
FORCE(deopt); FORCE(deopt);
FORCE(div_i64_i64); FORCE(div_i64_i64);
......
...@@ -224,7 +224,16 @@ extern "C" PyObject* PyList_GetItem(PyObject* op, Py_ssize_t i) noexcept { ...@@ -224,7 +224,16 @@ extern "C" PyObject* PyList_GetItem(PyObject* op, Py_ssize_t i) noexcept {
} }
} }
extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) { template <ExceptionStyle S> Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) {
if (S == CAPI) {
try {
return listGetitemSlice<CXX>(self, slice);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
assert(isSubclass(self->cls, list_cls)); assert(isSubclass(self->cls, list_cls));
assert(slice->cls == slice_cls); assert(slice->cls == slice_cls);
i64 start, stop, step, length; i64 start, stop, step, length;
...@@ -242,7 +251,16 @@ extern "C" Box* listGetslice(BoxedList* self, Box* boxedStart, Box* boxedStop) { ...@@ -242,7 +251,16 @@ extern "C" Box* listGetslice(BoxedList* self, Box* boxedStart, Box* boxedStop) {
return _listSlice(self, start, stop, 1, stop - start); return _listSlice(self, start, stop, 1, stop - start);
} }
extern "C" Box* listGetitem(BoxedList* self, Box* slice) { template <ExceptionStyle S> Box* listGetitem(BoxedList* self, Box* slice) {
if (S == CAPI) {
try {
return listGetitem<CXX>(self, slice);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
assert(isSubclass(self->cls, list_cls)); assert(isSubclass(self->cls, list_cls));
if (PyIndex_Check(slice)) { if (PyIndex_Check(slice)) {
Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError);
...@@ -250,7 +268,7 @@ extern "C" Box* listGetitem(BoxedList* self, Box* slice) { ...@@ -250,7 +268,7 @@ extern "C" Box* listGetitem(BoxedList* self, Box* slice) {
throwCAPIException(); throwCAPIException();
return listGetitemUnboxed(self, i); return listGetitemUnboxed(self, i);
} else if (slice->cls == slice_cls) { } else if (slice->cls == slice_cls) {
return listGetitemSlice(self, static_cast<BoxedSlice*>(slice)); return listGetitemSlice<CXX>(self, static_cast<BoxedSlice*>(slice));
} else { } else {
raiseExcHelper(TypeError, "list indices must be integers, not %s", getTypeName(slice)); raiseExcHelper(TypeError, "list indices must be integers, not %s", getTypeName(slice));
} }
...@@ -799,13 +817,8 @@ extern "C" int PyList_Sort(PyObject* v) noexcept { ...@@ -799,13 +817,8 @@ extern "C" int PyList_Sort(PyObject* v) noexcept {
extern "C" Box* PyList_GetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh) noexcept { extern "C" Box* PyList_GetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh) noexcept {
assert(isSubclass(a->cls, list_cls)); assert(isSubclass(a->cls, list_cls));
BoxedList* self = static_cast<BoxedList*>(a); BoxedList* self = static_cast<BoxedList*>(a);
try { // Lots of extra copies here; we can do better if we need to:
// Lots of extra copies here; we can do better if we need to: return listGetitemSlice<CAPI>(self, new BoxedSlice(boxInt(ilow), boxInt(ihigh), boxInt(1)));
return listGetitemSlice(self, new BoxedSlice(boxInt(ilow), boxInt(ihigh), boxInt(1)));
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} }
Box* listContains(BoxedList* self, Box* elt) { Box* listContains(BoxedList* self, Box* elt) {
...@@ -1092,8 +1105,13 @@ void setupList() { ...@@ -1092,8 +1105,13 @@ void setupList() {
CLFunction* getitem = createRTFunction(2, 0, false, false); CLFunction* getitem = createRTFunction(2, 0, false, false);
addRTFunction(getitem, (void*)listGetitemInt, UNKNOWN, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT }); addRTFunction(getitem, (void*)listGetitemInt, UNKNOWN, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT });
addRTFunction(getitem, (void*)listGetitemSlice, LIST, std::vector<ConcreteCompilerType*>{ LIST, SLICE }); addRTFunction(getitem, (void*)listGetitemSlice<CXX>, LIST, std::vector<ConcreteCompilerType*>{ LIST, SLICE }, CXX);
addRTFunction(getitem, (void*)listGetitem, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, UNKNOWN }); addRTFunction(getitem, (void*)listGetitem<CXX>, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, UNKNOWN },
CXX);
addRTFunction(getitem, (void*)listGetitemSlice<CAPI>, LIST, std::vector<ConcreteCompilerType*>{ LIST, SLICE },
CAPI);
addRTFunction(getitem, (void*)listGetitem<CAPI>, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, UNKNOWN },
CAPI);
list_cls->giveAttr("__getitem__", new BoxedFunction(getitem)); list_cls->giveAttr("__getitem__", new BoxedFunction(getitem));
list_cls->giveAttr("__getslice__", new BoxedFunction(boxRTFunction((void*)listGetslice, LIST, 3))); list_cls->giveAttr("__getslice__", new BoxedFunction(boxRTFunction((void*)listGetslice, LIST, 3)));
......
...@@ -305,6 +305,10 @@ extern "C" void raiseIndexErrorStr(const char* typeName) { ...@@ -305,6 +305,10 @@ extern "C" void raiseIndexErrorStr(const char* typeName) {
raiseExcHelper(IndexError, "%s index out of range", typeName); raiseExcHelper(IndexError, "%s index out of range", typeName);
} }
extern "C" void raiseIndexErrorStrCapi(const char* typeName) noexcept {
PyErr_Format(IndexError, "%s index out of range", typeName);
}
extern "C" void raiseNotIterableError(const char* typeName) { extern "C" void raiseNotIterableError(const char* typeName) {
raiseExcHelper(TypeError, "'%s' object is not iterable", typeName); raiseExcHelper(TypeError, "'%s' object is not iterable", typeName);
} }
...@@ -4517,7 +4521,7 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) ...@@ -4517,7 +4521,7 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args)
} }
if (S == CAPI) { if (S == CAPI) {
assert(!rewrite_args && "implement me"); // assert(!rewrite_args && "implement me");
rewrite_args = NULL; rewrite_args = NULL;
} }
......
...@@ -160,6 +160,7 @@ extern "C" void raiseAttributeErrorStrCapi(const char* typeName, llvm::StringRef ...@@ -160,6 +160,7 @@ extern "C" void raiseAttributeErrorStrCapi(const char* typeName, llvm::StringRef
extern "C" void raiseAttributeErrorCapi(Box* obj, llvm::StringRef attr) noexcept; extern "C" void raiseAttributeErrorCapi(Box* obj, llvm::StringRef attr) noexcept;
extern "C" void raiseNotIterableError(const char* typeName) __attribute__((__noreturn__)); extern "C" void raiseNotIterableError(const char* typeName) __attribute__((__noreturn__));
extern "C" void raiseIndexErrorStr(const char* typeName) __attribute__((__noreturn__)); extern "C" void raiseIndexErrorStr(const char* typeName) __attribute__((__noreturn__));
extern "C" void raiseIndexErrorStrCapi(const char* typeName) noexcept;
Box* typeCall(Box*, BoxedTuple*, BoxedDict*); Box* typeCall(Box*, BoxedTuple*, BoxedDict*);
Box* type_new(BoxedClass* metatype, Box* args, Box* kwds) noexcept; Box* type_new(BoxedClass* metatype, Box* args, Box* kwds) noexcept;
......
...@@ -2216,7 +2216,15 @@ Box* strEncode(BoxedString* self, Box* encoding, Box* error) { ...@@ -2216,7 +2216,15 @@ Box* strEncode(BoxedString* self, Box* encoding, Box* error) {
return result; return result;
} }
extern "C" Box* strGetitem(BoxedString* self, Box* slice) { template <ExceptionStyle S> Box* strGetitem(BoxedString* self, Box* slice) {
if (S == CAPI) {
try {
return strGetitem<CXX>(self, slice);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
assert(PyString_Check(self)); assert(PyString_Check(self));
if (PyIndex_Check(slice)) { if (PyIndex_Check(slice)) {
...@@ -2760,7 +2768,9 @@ void setupStr() { ...@@ -2760,7 +2768,9 @@ void setupStr() {
str_cls->giveAttr("center", str_cls->giveAttr("center",
new BoxedFunction(boxRTFunction((void*)strCenter, UNKNOWN, 3, 1, false, false), { spaceChar })); new BoxedFunction(boxRTFunction((void*)strCenter, UNKNOWN, 3, 1, false, false), { spaceChar }));
str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, STR, 2))); auto str_getitem = boxRTFunction((void*)strGetitem<CXX>, STR, 2, ParamNames::empty(), CXX);
addRTFunction(str_getitem, (void*)strGetitem<CAPI>, STR, CAPI);
str_cls->giveAttr("__getitem__", new BoxedFunction(str_getitem));
str_cls->giveAttr("__getslice__", new BoxedFunction(boxRTFunction((void*)strGetslice, STR, 3))); str_cls->giveAttr("__getslice__", new BoxedFunction(boxRTFunction((void*)strGetslice, STR, 3)));
......
...@@ -135,7 +135,16 @@ int BoxedTuple::Resize(BoxedTuple** pv, size_t newsize) noexcept { ...@@ -135,7 +135,16 @@ int BoxedTuple::Resize(BoxedTuple** pv, size_t newsize) noexcept {
return 0; return 0;
} }
Box* tupleGetitem(BoxedTuple* self, Box* slice) { template <ExceptionStyle S> Box* tupleGetitem(BoxedTuple* self, Box* slice) {
if (S == CAPI) {
try {
return tupleGetitem<CXX>(self, slice);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
assert(self->cls == tuple_cls); assert(self->cls == tuple_cls);
if (PyIndex_Check(slice)) { if (PyIndex_Check(slice)) {
...@@ -555,7 +564,10 @@ void setupTuple() { ...@@ -555,7 +564,10 @@ void setupTuple() {
CLFunction* getitem = createRTFunction(2, 0, 0, 0); CLFunction* getitem = createRTFunction(2, 0, 0, 0);
addRTFunction(getitem, (void*)tupleGetitemInt, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, BOXED_INT }); addRTFunction(getitem, (void*)tupleGetitemInt, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, BOXED_INT });
addRTFunction(getitem, (void*)tupleGetitemSlice, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, SLICE }); addRTFunction(getitem, (void*)tupleGetitemSlice, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, SLICE });
addRTFunction(getitem, (void*)tupleGetitem, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, UNKNOWN }); addRTFunction(getitem, (void*)tupleGetitem<CXX>, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, UNKNOWN },
CXX);
addRTFunction(getitem, (void*)tupleGetitem<CAPI>, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, UNKNOWN },
CAPI);
tuple_cls->giveAttr("__getitem__", new BoxedFunction(getitem)); tuple_cls->giveAttr("__getitem__", new BoxedFunction(getitem));
tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, BOXED_BOOL, 2))); tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, BOXED_BOOL, 2)));
......
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