Commit 2e409bdd authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add unaryop to our codegen type system

This is a temporary fix for the fact that "-1" is currently getting
parsed as "-(1)", which will cause us to call '(1).__neg__()' with
the associated overhead and allocation.

It should be useful even after that gets fixed though.
parent 2153e8e3
......@@ -239,6 +239,8 @@ public:
CallattrFlags flags, const std::vector<CompilerVariable*>& args,
const std::vector<BoxedString*>* keyword_names) override;
ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override;
ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
AST_TYPE::AST_TYPE op_type) override;
ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override;
void setattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, BoxedString* attr,
......@@ -731,6 +733,31 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
return boolFromI1(emitter, rtn_val);
}
ConcreteCompilerVariable* UnknownType::unaryop(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
AST_TYPE::AST_TYPE op_type) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, var->getBoxType());
llvm::Value* rtn = NULL;
bool do_patchpoint = ENABLE_ICGENERICS;
if (do_patchpoint) {
ICSetupInfo* pp = createGenericIC(info.getTypeRecorder(), true, 256);
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(converted->getValue());
llvm_args.push_back(getConstantInt(op_type, g.i32));
llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::unaryop, llvm_args, info.unw_info);
rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn = emitter.createCall2(info.unw_info, g.funcs.unaryop, converted->getValue(),
getConstantInt(op_type, g.i32));
}
converted->decvref(emitter);
return new ConcreteCompilerVariable(UNKNOWN, rtn, true);
}
ConcreteCompilerVariable* UnknownType::hasnext(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
bool do_patchpoint = ENABLE_ICS;
do_patchpoint = false; // we are currently using runtime ics for this
......@@ -1014,6 +1041,26 @@ public:
return boolFromI1(emitter, cmp);
}
ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
AST_TYPE::AST_TYPE op_type) override {
llvm::Value* unboxed = var->getValue();
if (op_type == AST_TYPE::USub) {
if (llvm::ConstantInt* llvm_val = llvm::dyn_cast<llvm::ConstantInt>(unboxed)) {
int64_t val = llvm_val->getSExtValue();
if (val != PYSTON_INT_MIN) {
return makeInt(-val);
}
}
// Not safe to emit a simple negation in the general case since val could be INT_MIN.
// Could emit a check though.
}
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT);
auto rtn = converted->unaryop(emitter, info, op_type);
converted->decvref(emitter);
return rtn;
}
CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs,
AST_TYPE::AST_TYPE op_type, BinExpType exp_type) override {
bool can_lower = (rhs->getType() == INT && exp_type == Compare);
......@@ -1836,6 +1883,11 @@ public:
return UNKNOWN->nonzero(emitter, info, var);
}
ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
AST_TYPE::AST_TYPE op_type) override {
return UNKNOWN->unaryop(emitter, info, var, op_type);
}
ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override {
static BoxedString* attr = internStringImmortal("__hasnext__");
......
......@@ -105,6 +105,8 @@ public:
printf("nonzero not defined for %s\n", debugName().c_str());
abort();
}
virtual ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, VAR* var,
AST_TYPE::AST_TYPE op_type);
virtual ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("hasnext not defined for %s\n", debugName().c_str());
abort();
......@@ -264,6 +266,7 @@ public:
virtual BoxedClass* guaranteedClass() = 0;
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info) = 0;
virtual ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, AST_TYPE::AST_TYPE op_type) = 0;
virtual ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, BoxedString* attr, bool cls_only) = 0;
virtual void setattr(IREmitter& emitter, const OpInfo& info, BoxedString* attr, CompilerVariable* v) = 0;
......@@ -335,6 +338,9 @@ public:
ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info) override {
return type->nonzero(emitter, info, this);
}
ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, AST_TYPE::AST_TYPE op_type) override {
return type->unaryop(emitter, info, this, op_type);
}
ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info) override {
return type->hasnext(emitter, info, this);
}
......@@ -439,6 +445,15 @@ CompilerVariable* _ValuedCompilerType<V>::contains(IREmitter& emitter, const OpI
return r;
}
template <typename V>
ConcreteCompilerVariable* _ValuedCompilerType<V>::unaryop(IREmitter& emitter, const OpInfo& info, VAR* var,
AST_TYPE::AST_TYPE op_type) {
ConcreteCompilerVariable* converted = makeConverted(emitter, var, getBoxType());
auto r = UNKNOWN->unaryop(emitter, info, converted, op_type);
converted->decvref(emitter);
return r;
}
template <typename V>
std::vector<CompilerVariable*> _ValuedCompilerType<V>::unpack(IREmitter& emitter, const OpInfo& info, VAR* var,
int num_into) {
......
......@@ -1333,29 +1333,9 @@ private:
rtn->decvref(emitter);
return boolFromI1(emitter, negated);
} else {
// TODO These are pretty inefficient, but luckily I don't think they're used that often:
ConcreteCompilerVariable* converted = operand->makeConverted(emitter, operand->getBoxType());
ConcreteCompilerVariable* rtn = operand->unaryop(emitter, getOpInfoForNode(node, unw_info), node->op_type);
operand->decvref(emitter);
llvm::Value* rtn = NULL;
bool do_patchpoint = ENABLE_ICGENERICS;
if (do_patchpoint) {
ICSetupInfo* pp = createGenericIC(getEmptyOpInfo(unw_info).getTypeRecorder(), true, 256);
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(converted->getValue());
llvm_args.push_back(getConstantInt(node->op_type, g.i32));
llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::unaryop, llvm_args, unw_info);
rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn = emitter.createCall2(unw_info, g.funcs.unaryop, converted->getValue(),
getConstantInt(node->op_type, g.i32));
}
converted->decvref(emitter);
return new ConcreteCompilerVariable(UNKNOWN, rtn, true);
return rtn;
}
}
......
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