Commit 9a33763c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Some initial refactoring work for arg passing

Replace a simple "num_args" argument with a packed struct that takes
num_args and adds num_keywords, has_varargs, and has_kwargs.  Tried
to add asserts in all the places that don't allow
keywords/varargs/starargs

Started refactoring things; got to the point of attempting
argument->parameter shuffling, but it's tricky if we allow every
compilation to have a different signature (used by builtins).
Really they all have the same signatures but different
specializations; to get to that point, need to add defaults.
parent a8c83341
...@@ -273,7 +273,7 @@ pyston_all: pyston_dbg pyston pyston_oprof pyston_prof $(OPTIONAL_SRCS:.cpp=.o) ...@@ -273,7 +273,7 @@ pyston_all: pyston_dbg pyston pyston_oprof pyston_prof $(OPTIONAL_SRCS:.cpp=.o)
ALL_HEADERS := $(wildcard */*.h) $(wildcard */*/*.h) ALL_HEADERS := $(wildcard */*.h) $(wildcard */*/*.h)
tags: $(SRCS) $(OPTIONAL_SRCS) $(ALL_HEADERS) tags: $(SRCS) $(OPTIONAL_SRCS) $(ALL_HEADERS)
$(ECHO) Computing tags... $(ECHO) Calculating tags...
$(VERB) ctags $^ $(VERB) ctags $^
$(UNITTEST_SRCS:.cpp=.o): CXXFLAGS := $(CXXFLAGS) -isystem $(GTEST_DIR)/include $(UNITTEST_SRCS:.cpp=.o): CXXFLAGS := $(CXXFLAGS) -isystem $(GTEST_DIR)/include
......
...@@ -210,7 +210,7 @@ private: ...@@ -210,7 +210,7 @@ private:
std::vector<CompilerType*> arg_types; std::vector<CompilerType*> arg_types;
arg_types.push_back(right); arg_types.push_back(right);
CompilerType* rtn = attr_type->callType(arg_types); CompilerType* rtn = attr_type->callType(ArgPassSpec(2), arg_types, NULL);
if (left == right && (left == INT || left == FLOAT)) { if (left == right && (left == INT || left == FLOAT)) {
ASSERT((rtn == left || rtn == UNKNOWN) && "not strictly required but probably something worth looking into", ASSERT((rtn == left || rtn == UNKNOWN) && "not strictly required but probably something worth looking into",
...@@ -237,7 +237,7 @@ private: ...@@ -237,7 +237,7 @@ private:
std::vector<CompilerType*> arg_types; std::vector<CompilerType*> arg_types;
arg_types.push_back(right); arg_types.push_back(right);
CompilerType* rtn = attr_type->callType(arg_types); CompilerType* rtn = attr_type->callType(ArgPassSpec(2), arg_types, NULL);
if (left == right && (left == INT || left == FLOAT)) { if (left == right && (left == INT || left == FLOAT)) {
ASSERT((rtn == left || rtn == UNKNOWN) && "not strictly required but probably something worth looking into", ASSERT((rtn == left || rtn == UNKNOWN) && "not strictly required but probably something worth looking into",
...@@ -287,7 +287,7 @@ private: ...@@ -287,7 +287,7 @@ private:
return UNKNOWN; return UNKNOWN;
} }
CompilerType* rtn_type = func->callType(arg_types); CompilerType* rtn_type = func->callType(ArgPassSpec(arg_types.size()), arg_types, NULL);
// Should be unboxing things before getting here: // Should be unboxing things before getting here:
ASSERT(rtn_type == unboxedType(rtn_type->getConcreteType()), "%s", rtn_type->debugName().c_str()); ASSERT(rtn_type == unboxedType(rtn_type->getConcreteType()), "%s", rtn_type->debugName().c_str());
...@@ -322,7 +322,7 @@ private: ...@@ -322,7 +322,7 @@ private:
std::vector<CompilerType*> arg_types; std::vector<CompilerType*> arg_types;
arg_types.push_back(right); arg_types.push_back(right);
return attr_type->callType(arg_types); return attr_type->callType(ArgPassSpec(2), arg_types, NULL);
} }
virtual void* visit_dict(AST_Dict* node) { virtual void* visit_dict(AST_Dict* node) {
...@@ -404,7 +404,7 @@ private: ...@@ -404,7 +404,7 @@ private:
CompilerType* getitem_type = val->getattrType(&name, true); CompilerType* getitem_type = val->getattrType(&name, true);
std::vector<CompilerType*> args; std::vector<CompilerType*> args;
args.push_back(slice); args.push_back(slice);
return getitem_type->callType(args); return getitem_type->callType(ArgPassSpec(1), args, NULL);
} }
virtual void* visit_tuple(AST_Tuple* node) { virtual void* visit_tuple(AST_Tuple* node) {
...@@ -422,7 +422,7 @@ private: ...@@ -422,7 +422,7 @@ private:
const std::string& name = getOpName(node->op_type); const std::string& name = getOpName(node->op_type);
CompilerType* attr_type = operand->getattrType(&name, true); CompilerType* attr_type = operand->getattrType(&name, true);
std::vector<CompilerType*> arg_types; std::vector<CompilerType*> arg_types;
return attr_type->callType(arg_types); return attr_type->callType(ArgPassSpec(0), arg_types, NULL);
} }
......
...@@ -72,6 +72,7 @@ struct GlobalState { ...@@ -72,6 +72,7 @@ struct GlobalState {
llvm::Type* llvm_clfunction_type_ptr; llvm::Type* llvm_clfunction_type_ptr;
llvm::Type* llvm_module_type_ptr, *llvm_bool_type_ptr; llvm::Type* llvm_module_type_ptr, *llvm_bool_type_ptr;
llvm::Type* i1, *i8, *i8_ptr, *i32, *i64, *void_, *double_; llvm::Type* i1, *i8, *i8_ptr, *i32, *i64, *void_, *double_;
llvm::Type* vector_ptr;
GlobalFuncs funcs; GlobalFuncs funcs;
......
This diff is collapsed.
...@@ -40,7 +40,8 @@ public: ...@@ -40,7 +40,8 @@ public:
virtual ConcreteCompilerType* getBoxType() = 0; virtual ConcreteCompilerType* getBoxType() = 0;
virtual bool canConvertTo(ConcreteCompilerType* other_type) = 0; virtual bool canConvertTo(ConcreteCompilerType* other_type) = 0;
virtual CompilerType* getattrType(const std::string* attr, bool cls_only) = 0; virtual CompilerType* getattrType(const std::string* attr, bool cls_only) = 0;
virtual CompilerType* callType(std::vector<CompilerType*>& arg_types) = 0; virtual CompilerType* callType(ArgPassSpec argspec, const std::vector<CompilerType*>& arg_types,
const std::vector<const std::string*>* keyword_names) = 0;
virtual BoxedClass* guaranteedClass() = 0; virtual BoxedClass* guaranteedClass() = 0;
}; };
...@@ -93,12 +94,15 @@ public: ...@@ -93,12 +94,15 @@ public:
abort(); abort();
} }
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, VAR* value, const std::string* attr, virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, VAR* value, const std::string* attr,
bool clsonly, const std::vector<CompilerVariable*>& args) { bool clsonly, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
printf("callattr not defined for %s\n", debugName().c_str()); printf("callattr not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, VAR* value, virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, VAR* value, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args) { const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
printf("call not defined for %s\n", debugName().c_str()); printf("call not defined for %s\n", debugName().c_str());
abort(); abort();
} }
...@@ -122,7 +126,8 @@ public: ...@@ -122,7 +126,8 @@ public:
printf("getattrType not defined for %s\n", debugName().c_str()); printf("getattrType not defined for %s\n", debugName().c_str());
abort(); abort();
} }
CompilerType* callType(std::vector<CompilerType*>& arg_types) override { CompilerType* callType(struct ArgPassSpec argspec, const std::vector<CompilerType*>& arg_types,
const std::vector<const std::string*>* keyword_names) override {
printf("callType not defined for %s\n", debugName().c_str()); printf("callType not defined for %s\n", debugName().c_str());
abort(); abort();
} }
...@@ -213,9 +218,11 @@ public: ...@@ -213,9 +218,11 @@ public:
= 0; = 0;
virtual void setattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, CompilerVariable* v) = 0; virtual void setattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, CompilerVariable* v) = 0;
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, bool clsonly, virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, bool clsonly,
const std::vector<CompilerVariable*>& args) = 0; struct ArgPassSpec argspec, const std::vector<CompilerVariable*>& args,
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, const std::vector<CompilerVariable*>& args) const std::vector<const std::string*>* keyword_names) = 0;
= 0; virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) = 0;
virtual void print(IREmitter& emitter, const OpInfo& info) = 0; virtual void print(IREmitter& emitter, const OpInfo& info) = 0;
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) = 0; virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable*) = 0; virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable*) = 0;
...@@ -273,12 +280,14 @@ public: ...@@ -273,12 +280,14 @@ public:
type->setattr(emitter, info, this, attr, v); type->setattr(emitter, info, this, attr, v);
} }
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, bool clsonly, virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, bool clsonly,
const std::vector<CompilerVariable*>& args) { struct ArgPassSpec argspec, const std::vector<CompilerVariable*>& args,
return type->callattr(emitter, info, this, attr, clsonly, args); const std::vector<const std::string*>* keyword_names) {
} return type->callattr(emitter, info, this, attr, clsonly, argspec, args, keyword_names);
CompilerVariable* call(IREmitter& emitter, const OpInfo& info, }
const std::vector<CompilerVariable*>& args) override { CompilerVariable* call(IREmitter& emitter, const OpInfo& info, struct ArgPassSpec argspec,
return type->call(emitter, info, this, args); const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) override {
return type->call(emitter, info, this, argspec, args, keyword_names);
} }
void print(IREmitter& emitter, const OpInfo& info) override { type->print(emitter, info, this); } void print(IREmitter& emitter, const OpInfo& info) override { type->print(emitter, info, this); }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) override { ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) override {
......
...@@ -881,10 +881,10 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::Ef ...@@ -881,10 +881,10 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::Ef
return os.str(); return os.str();
} }
CompiledFunction* compileFunction(SourceInfo* source, const OSREntryDescriptor* entry_descriptor, CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSignature* sig, EffortLevel::EffortLevel effort, FunctionSignature* sig,
const std::vector<AST_expr*>& arg_names, std::string nameprefix) { const std::vector<AST_expr*>& arg_names, std::string nameprefix) {
Timer _t("in compileFunction"); Timer _t("in doCompile");
if (VERBOSITY("irgen") >= 1) if (VERBOSITY("irgen") >= 1)
source->cfg->print(); source->cfg->print();
......
...@@ -76,7 +76,7 @@ public: ...@@ -76,7 +76,7 @@ public:
const std::vector<llvm::Value*>& args, ExcInfo exc_info) = 0; const std::vector<llvm::Value*>& args, ExcInfo exc_info) = 0;
}; };
CompiledFunction* compileFunction(SourceInfo* source, const OSREntryDescriptor* entry_descriptor, CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSignature* sig, EffortLevel::EffortLevel effort, FunctionSignature* sig,
const std::vector<AST_expr*>& arg_names, std::string nameprefix); const std::vector<AST_expr*>& arg_names, std::string nameprefix);
......
This diff is collapsed.
...@@ -190,6 +190,17 @@ IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock) { ...@@ -190,6 +190,17 @@ IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock) {
return new IREmitterImpl(irstate, curblock); return new IREmitterImpl(irstate, curblock);
} }
static std::unordered_map<AST_expr*, std::vector<const std::string*>*> made_keyword_storage;
static std::vector<const std::string*>* getKeywordNameStorage(AST_Call* node) {
auto it = made_keyword_storage.find(node);
if (it != made_keyword_storage.end())
return it->second;
auto rtn = new std::vector<const std::string*>();
made_keyword_storage.insert(it, std::make_pair(node, rtn));
return rtn;
}
class IRGeneratorImpl : public IRGenerator { class IRGeneratorImpl : public IRGenerator {
private: private:
IRGenState* irstate; IRGenState* irstate;
...@@ -623,10 +634,6 @@ private: ...@@ -623,10 +634,6 @@ private:
CompilerVariable* evalCall(AST_Call* node, ExcInfo exc_info) { CompilerVariable* evalCall(AST_Call* node, ExcInfo exc_info) {
assert(state != PARTIAL); assert(state != PARTIAL);
assert(!node->starargs);
assert(!node->kwargs);
assert(!node->keywords.size());
bool is_callattr; bool is_callattr;
bool callattr_clsonly = false; bool callattr_clsonly = false;
std::string* attr = NULL; std::string* attr = NULL;
...@@ -649,19 +656,42 @@ private: ...@@ -649,19 +656,42 @@ private:
} }
std::vector<CompilerVariable*> args; std::vector<CompilerVariable*> args;
std::vector<const std::string*>* keyword_names;
if (node->keywords.size()) {
keyword_names = getKeywordNameStorage(node);
} else {
keyword_names = NULL;
}
for (int i = 0; i < node->args.size(); i++) { for (int i = 0; i < node->args.size(); i++) {
CompilerVariable* a = evalExpr(node->args[i], exc_info); CompilerVariable* a = evalExpr(node->args[i], exc_info);
args.push_back(a); args.push_back(a);
} }
for (int i = 0; i < node->keywords.size(); i++) {
CompilerVariable* a = evalExpr(node->keywords[i]->value, exc_info);
args.push_back(a);
keyword_names->push_back(&node->keywords[i]->arg);
}
if (node->starargs)
args.push_back(evalExpr(node->starargs, exc_info));
if (node->kwargs)
args.push_back(evalExpr(node->kwargs, exc_info));
struct ArgPassSpec argspec(node->args.size(), node->keywords.size(), node->starargs != NULL,
node->kwargs != NULL);
// if (VERBOSITY("irgen") >= 1) // if (VERBOSITY("irgen") >= 1)
//_addAnnotation("before_call"); //_addAnnotation("before_call");
CompilerVariable* rtn; CompilerVariable* rtn;
if (is_callattr) { if (is_callattr) {
rtn = func->callattr(emitter, getOpInfoForNode(node, exc_info), attr, callattr_clsonly, args); rtn = func->callattr(emitter, getOpInfoForNode(node, exc_info), attr, callattr_clsonly, argspec, args,
keyword_names);
} else { } else {
rtn = func->call(emitter, getOpInfoForNode(node, exc_info), args); rtn = func->call(emitter, getOpInfoForNode(node, exc_info), argspec, args, keyword_names);
} }
func->decvref(emitter); func->decvref(emitter);
...@@ -669,9 +699,6 @@ private: ...@@ -669,9 +699,6 @@ private:
args[i]->decvref(emitter); args[i]->decvref(emitter);
} }
// if (VERBOSITY("irgen") >= 1)
//_addAnnotation("end_of_call");
return rtn; return rtn;
} }
...@@ -693,7 +720,7 @@ private: ...@@ -693,7 +720,7 @@ private:
args.push_back(key); args.push_back(key);
args.push_back(value); args.push_back(value);
// TODO could use the internal _listAppend function to avoid incref/decref'ing None // TODO could use the internal _listAppend function to avoid incref/decref'ing None
CompilerVariable* rtn = setitem->call(emitter, getEmptyOpInfo(exc_info), args); CompilerVariable* rtn = setitem->call(emitter, getEmptyOpInfo(exc_info), ArgPassSpec(2), args, NULL);
rtn->decvref(emitter); rtn->decvref(emitter);
key->decvref(emitter); key->decvref(emitter);
......
...@@ -642,12 +642,18 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* arg1, Box* arg2, Box* ...@@ -642,12 +642,18 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* arg1, Box* arg2, Box*
int64_t)>(f)(args[0].n, args[1].n, args[2].n, args[3].n, int64_t)>(f)(args[0].n, args[1].n, args[2].n, args[3].n,
args[4].n, args[5].n, args[6].n); args[4].n, args[5].n, args[6].n);
break; break;
case 0b1000000000: case 0b1000000000: // 512
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t,
int64_t, int64_t)>(f)(args[0].n, args[1].n, args[2].n, int64_t, int64_t)>(f)(args[0].n, args[1].n, args[2].n,
args[3].n, args[4].n, args[5].n, args[3].n, args[4].n, args[5].n,
args[6].n, args[7].n); args[6].n, args[7].n);
break; break;
case 0b10000000000: // 1024
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t,
int64_t, int64_t, int64_t)>(
f)(args[0].n, args[1].n, args[2].n, args[3].n, args[4].n, args[5].n, args[6].n,
args[7].n, args[8].n);
break;
default: default:
inst->dump(); inst->dump();
RELEASE_ASSERT(0, "%d", mask); RELEASE_ASSERT(0, "%d", mask);
......
...@@ -132,6 +132,9 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -132,6 +132,9 @@ void initGlobalFuncs(GlobalState& g) {
g.llvm_str_type_ptr = lookupFunction("boxStringPtr")->arg_begin()->getType(); g.llvm_str_type_ptr = lookupFunction("boxStringPtr")->arg_begin()->getType();
auto vector_type = g.stdlib_module->getTypeByName("class.std::vector");
assert(vector_type);
g.vector_ptr = vector_type->getPointerTo();
#define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N)) #define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N))
...@@ -185,23 +188,23 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -185,23 +188,23 @@ void initGlobalFuncs(GlobalState& g) {
GET(listAppendInternal); GET(listAppendInternal);
g.funcs.runtimeCall = getFunc((void*)runtimeCall, "runtimeCall"); g.funcs.runtimeCall = getFunc((void*)runtimeCall, "runtimeCall");
g.funcs.runtimeCall0 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i64); g.funcs.runtimeCall0 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32);
g.funcs.runtimeCall1 g.funcs.runtimeCall1
= addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i64, g.llvm_value_type_ptr); = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.llvm_value_type_ptr);
g.funcs.runtimeCall2 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i64, g.funcs.runtimeCall2 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32,
g.llvm_value_type_ptr, g.llvm_value_type_ptr); g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.runtimeCall3 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i64, g.funcs.runtimeCall3 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr); g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattr = getFunc((void*)callattr, "callattr"); g.funcs.callattr = getFunc((void*)callattr, "callattr");
g.funcs.callattr0 g.funcs.callattr0
= addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr, g.i1, g.i64); = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr, g.i1, g.i32);
g.funcs.callattr1 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr, g.funcs.callattr1 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr,
g.i1, g.i64, g.llvm_value_type_ptr); g.i1, g.i32, g.llvm_value_type_ptr);
g.funcs.callattr2 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr, g.funcs.callattr2 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr,
g.i1, g.i64, g.llvm_value_type_ptr, g.llvm_value_type_ptr); g.i1, g.i32, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattr3 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr, g.funcs.callattr3 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr,
g.i1, g.i64, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr); g.i1, g.i32, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, g.i8_ptr, g.i8_ptr); g.funcs.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, g.i8_ptr, g.i8_ptr);
g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr); g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr);
......
...@@ -32,6 +32,31 @@ class Value; ...@@ -32,6 +32,31 @@ class Value;
namespace pyston { namespace pyston {
struct ArgPassSpec {
bool has_starargs : 1;
bool has_kwargs : 1;
unsigned int num_keywords : 14;
unsigned int num_args : 16;
static const int MAX_ARGS = (1 << 16) - 1;
static const int MAX_KEYWORDS = (1 << 14) - 1;
explicit ArgPassSpec(int num_args) : has_starargs(false), has_kwargs(false), num_keywords(0), num_args(num_args) {
assert(num_args <= MAX_ARGS);
assert(num_keywords <= MAX_KEYWORDS);
}
explicit ArgPassSpec(int num_args, int num_keywords, bool has_starargs, bool has_kwargs)
: has_starargs(has_starargs), has_kwargs(has_kwargs), num_keywords(num_keywords), num_args(num_args) {
assert(num_args <= MAX_ARGS);
assert(num_keywords <= MAX_KEYWORDS);
}
int totalPassed() { return num_args + num_keywords + (has_starargs ? 1 : 0) + (has_kwargs ? 1 : 0); }
uintptr_t asInt() const { return *reinterpret_cast<const uintptr_t*>(this); }
};
static_assert(sizeof(ArgPassSpec) <= sizeof(void*), "ArgPassSpec doesn't fit in register!");
class GCVisitor { class GCVisitor {
public: public:
virtual ~GCVisitor() {} virtual ~GCVisitor() {}
...@@ -129,20 +154,30 @@ public: ...@@ -129,20 +154,30 @@ public:
struct FunctionSignature { struct FunctionSignature {
ConcreteCompilerType* rtn_type; ConcreteCompilerType* rtn_type;
const std::vector<AST_expr*>* arg_names;
std::vector<ConcreteCompilerType*> arg_types; std::vector<ConcreteCompilerType*> arg_types;
bool is_vararg; int ndefaults;
bool takes_varargs, takes_kwargs;
FunctionSignature(ConcreteCompilerType* rtn_type, bool is_vararg) : rtn_type(rtn_type), is_vararg(is_vararg) {}
FunctionSignature(ConcreteCompilerType* rtn_type, const std::vector<AST_expr*>* arg_names, int ndefaults,
FunctionSignature(ConcreteCompilerType* rtn_type, ConcreteCompilerType* arg1, ConcreteCompilerType* arg2, bool takes_varargs, bool takes_kwargs)
bool is_vararg) : rtn_type(rtn_type), arg_names(arg_names), ndefaults(ndefaults), takes_varargs(takes_varargs),
: rtn_type(rtn_type), is_vararg(is_vararg) { takes_kwargs(takes_kwargs) {}
FunctionSignature(ConcreteCompilerType* rtn_type, const std::vector<AST_expr*>* arg_names,
ConcreteCompilerType* arg1, ConcreteCompilerType* arg2, int ndefaults, bool takes_varargs,
bool takes_kwargs)
: rtn_type(rtn_type), arg_names(arg_names), ndefaults(ndefaults), takes_varargs(takes_varargs),
takes_kwargs(takes_kwargs) {
arg_types.push_back(arg1); arg_types.push_back(arg1);
arg_types.push_back(arg2); arg_types.push_back(arg2);
} }
FunctionSignature(ConcreteCompilerType* rtn_type, std::vector<ConcreteCompilerType*>& arg_types, bool is_vararg) FunctionSignature(ConcreteCompilerType* rtn_type, const std::vector<AST_expr*>* arg_names,
: rtn_type(rtn_type), arg_types(arg_types), is_vararg(is_vararg) {} std::vector<ConcreteCompilerType*>& arg_types, int ndefaults, bool takes_varargs,
bool takes_kwargs)
: rtn_type(rtn_type), arg_names(arg_names), arg_types(arg_types), ndefaults(ndefaults),
takes_varargs(takes_varargs), takes_kwargs(takes_kwargs) {}
}; };
struct CompiledFunction { struct CompiledFunction {
...@@ -190,13 +225,23 @@ public: ...@@ -190,13 +225,23 @@ public:
SourceInfo(BoxedModule* m, ScopingAnalysis* scoping) SourceInfo(BoxedModule* m, ScopingAnalysis* scoping)
: parent_module(m), scoping(scoping), ast(NULL), cfg(NULL), liveness(NULL), phis(NULL) {} : parent_module(m), scoping(scoping), ast(NULL), cfg(NULL), liveness(NULL), phis(NULL) {}
}; };
typedef std::vector<CompiledFunction*> FunctionList; typedef std::vector<CompiledFunction*> FunctionList;
class CallRewriteArgs;
struct CLFunction { struct CLFunction {
SourceInfo* source; SourceInfo* source;
FunctionList FunctionList
versions; // any compiled versions along with their type parameters; in order from most preferred to least versions; // any compiled versions along with their type parameters; in order from most preferred to least
std::unordered_map<const OSREntryDescriptor*, CompiledFunction*> osr_versions; std::unordered_map<const OSREntryDescriptor*, CompiledFunction*> osr_versions;
// Functions can provide an "internal" version, which will get called instead
// of the normal dispatch through the functionlist.
// This can be used to implement functions which know how to rewrite themselves,
// such as typeCall.
typedef Box* (*InternalCallable)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<const std::string*>*);
InternalCallable internal_callable = NULL;
CLFunction(SourceInfo* source) : source(source) {} CLFunction(SourceInfo* source) : source(source) {}
void addVersion(CompiledFunction* compiled) { void addVersion(CompiledFunction* compiled) {
...@@ -215,14 +260,20 @@ struct CLFunction { ...@@ -215,14 +260,20 @@ struct CLFunction {
}; };
extern "C" CLFunction* createRTFunction(); extern "C" CLFunction* createRTFunction();
extern "C" CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, bool is_vararg); extern "C" CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs = false,
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, int nargs, bool is_vararg); bool takes_kwargs = false);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs = false,
bool takes_kwargs = false);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types, bool is_vararg); const std::vector<ConcreteCompilerType*>& arg_types, bool takes_varargs = false,
bool takes_kwargs = false);
CLFunction* unboxRTFunction(Box*); CLFunction* unboxRTFunction(Box*);
// extern "C" CLFunction* boxRTFunctionVariadic(const char* name, int nargs_min, int nargs_max, void* f);
extern "C" CompiledFunction* resolveCLFunc(CLFunction* f, int64_t nargs, Box* arg1, Box* arg2, Box* arg3, Box** args); // Compiles a new version of the function with the given signature and adds it to the list;
extern "C" Box* callCompiledFunc(CompiledFunction* cf, int64_t nargs, Box* arg1, Box* arg2, Box* arg3, Box** args); // should only be called after checking to see if the other versions would work.
CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortLevel::EffortLevel effort,
const OSREntryDescriptor* entry);
EffortLevel::EffortLevel initialEffort();
typedef bool i1; typedef bool i1;
typedef int64_t i64; typedef int64_t i64;
......
...@@ -40,7 +40,8 @@ extern "C" Box* dir1(Box* obj) { ...@@ -40,7 +40,8 @@ extern "C" Box* dir1(Box* obj) {
BoxedList* result = nullptr; BoxedList* result = nullptr;
// If __dir__ is present just call it and return what it returns // If __dir__ is present just call it and return what it returns
static std::string attr_dir = "__dir__"; static std::string attr_dir = "__dir__";
Box* dir_result = callattrInternal(obj, &attr_dir, CLASS_ONLY, nullptr, 0, nullptr, nullptr, nullptr, nullptr); Box* dir_result = callattrInternal(obj, &attr_dir, CLASS_ONLY, nullptr, ArgPassSpec(0), nullptr, nullptr, nullptr,
nullptr, nullptr);
if (dir_result && dir_result->cls == list_cls) { if (dir_result && dir_result->cls == list_cls) {
return dir_result; return dir_result;
} }
...@@ -366,7 +367,7 @@ Box* hasattr(Box* obj, Box* _str) { ...@@ -366,7 +367,7 @@ Box* hasattr(Box* obj, Box* _str) {
Box* map2(Box* f, Box* container) { Box* map2(Box* f, Box* container) {
Box* rtn = new BoxedList(); Box* rtn = new BoxedList();
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
listAppendInternal(rtn, runtimeCall(f, 1, e, NULL, NULL, NULL)); listAppendInternal(rtn, runtimeCall(f, ArgPassSpec(1), e, NULL, NULL, NULL, NULL));
} }
return rtn; return rtn;
} }
......
This diff is collapsed.
...@@ -39,8 +39,9 @@ extern "C" void my_assert(bool b); ...@@ -39,8 +39,9 @@ extern "C" void my_assert(bool b);
extern "C" Box* getattr(Box* obj, const char* attr); extern "C" Box* getattr(Box* obj, const char* attr);
extern "C" void setattr(Box* obj, const char* attr, Box* attr_val); extern "C" void setattr(Box* obj, const char* attr, Box* attr_val);
extern "C" bool nonzero(Box* obj); extern "C" bool nonzero(Box* obj);
extern "C" Box* runtimeCall(Box*, int64_t, Box*, Box*, Box*, Box**); extern "C" Box* runtimeCall(Box*, ArgPassSpec, Box*, Box*, Box*, Box**, const std::vector<const std::string*>*);
extern "C" Box* callattr(Box*, std::string*, bool, int64_t, Box*, Box*, Box*, Box**); extern "C" Box* callattr(Box*, std::string*, bool, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<const std::string*>*);
extern "C" BoxedString* str(Box* obj); extern "C" BoxedString* str(Box* obj);
extern "C" Box* repr(Box* obj); extern "C" Box* repr(Box* obj);
extern "C" BoxedString* reprOrNull(Box* obj); // similar to repr, but returns NULL on exception extern "C" BoxedString* reprOrNull(Box* obj); // similar to repr, but returns NULL on exception
...@@ -73,6 +74,9 @@ extern "C" bool isSubclass(BoxedClass* child, BoxedClass* parent); ...@@ -73,6 +74,9 @@ extern "C" bool isSubclass(BoxedClass* child, BoxedClass* parent);
class BinopRewriteArgs; class BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args); extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
Box* typeCallInternal(BoxedFunction* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names);
class CallRewriteArgs; class CallRewriteArgs;
enum LookupScope { enum LookupScope {
CLASS_ONLY = 1, CLASS_ONLY = 1,
...@@ -80,7 +84,8 @@ enum LookupScope { ...@@ -80,7 +84,8 @@ enum LookupScope {
CLASS_OR_INST = 3, CLASS_OR_INST = 3,
}; };
extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope, CallRewriteArgs* rewrite_args, extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope, CallRewriteArgs* rewrite_args,
int64_t nargs, Box* arg1, Box* arg2, Box* arg3, Box** args); ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<const std::string*>* keyword_names);
struct CompareRewriteArgs; struct CompareRewriteArgs;
Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args); Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args);
......
...@@ -43,9 +43,9 @@ BoxIterator& BoxIterator::operator++() { ...@@ -43,9 +43,9 @@ BoxIterator& BoxIterator::operator++() {
static std::string hasnext_str("__hasnext__"); static std::string hasnext_str("__hasnext__");
static std::string next_str("next"); static std::string next_str("next");
Box* hasnext = callattrInternal(iter, &hasnext_str, CLASS_ONLY, NULL, 0, NULL, NULL, NULL, NULL); Box* hasnext = callattrInternal(iter, &hasnext_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (nonzero(hasnext)) { if (nonzero(hasnext)) {
value = callattrInternal(iter, &next_str, CLASS_ONLY, NULL, 0, NULL, NULL, NULL, NULL); value = callattrInternal(iter, &next_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} else { } else {
iter = nullptr; iter = nullptr;
value = nullptr; value = nullptr;
...@@ -56,7 +56,7 @@ BoxIterator& BoxIterator::operator++() { ...@@ -56,7 +56,7 @@ BoxIterator& BoxIterator::operator++() {
llvm::iterator_range<BoxIterator> Box::pyElements() { llvm::iterator_range<BoxIterator> Box::pyElements() {
static std::string iter_str("__iter__"); static std::string iter_str("__iter__");
Box* iter = callattr(const_cast<Box*>(this), &iter_str, true, 0, NULL, NULL, NULL, NULL); Box* iter = callattr(const_cast<Box*>(this), &iter_str, true, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (iter) { if (iter) {
return llvm::iterator_range<BoxIterator>(++BoxIterator(iter), BoxIterator(nullptr)); return llvm::iterator_range<BoxIterator>(++BoxIterator(iter), BoxIterator(nullptr));
} }
...@@ -466,8 +466,11 @@ void setupRuntime() { ...@@ -466,8 +466,11 @@ void setupRuntime() {
object_cls->giveAttr("__new__", new BoxedFunction(object_new)); object_cls->giveAttr("__new__", new BoxedFunction(object_new));
object_cls->freeze(); object_cls->freeze();
auto typeCallObj = boxRTFunction((void*)typeCall, NULL, 1, true);
typeCallObj->internal_callable = &typeCallInternal;
type_cls->giveAttr("__call__", new BoxedFunction(typeCallObj));
type_cls->giveAttr("__name__", boxStrConstant("type")); type_cls->giveAttr("__name__", boxStrConstant("type"));
type_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)typeCall, NULL, 1, true)));
type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, NULL, 2, true))); type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, NULL, 2, true)));
type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, NULL, 1, true))); type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, NULL, 1, true)));
type_cls->giveAttr("__str__", type_cls->getattr("__repr__")); type_cls->giveAttr("__str__", type_cls->getattr("__repr__"));
......
# expected: fail
# - keywords
def f(a, b, c):
print a, b, c
f(1, 2, 3)
f(1, b=2, c=3)
f(1, b=2, c=3)
f(1, c=2, b=3)
f(1, b="2", c=3)
f(1, b=2, c="3")
f(1, c="2", b=3)
f(1, c=2, b="3")
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