Commit 464c98e7 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #969 from kmod/unboxed3

Reenable unboxed values
parents 40c4e710 96555a1e
...@@ -57,15 +57,13 @@ ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockEnd(InternedString name, C ...@@ -57,15 +57,13 @@ ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockEnd(InternedString name, C
// Note: the behavior of this function must match irgenerator.cpp::unboxVar() // Note: the behavior of this function must match irgenerator.cpp::unboxVar()
static ConcreteCompilerType* unboxedType(ConcreteCompilerType* t) { static CompilerType* unboxedType(ConcreteCompilerType* t) {
if (t == BOXED_BOOL) if (t == BOXED_BOOL)
return BOOL; return BOOL;
#if ENABLE_UNBOXED_VALUES
if (t == BOXED_INT) if (t == BOXED_INT)
return INT; return INT;
if (t == BOXED_FLOAT) if (t == BOXED_FLOAT)
return FLOAT; return FLOAT;
#endif
return t; return t;
} }
...@@ -117,17 +115,17 @@ private: ...@@ -117,17 +115,17 @@ private:
assert(speculation != TypeAnalysis::NONE); assert(speculation != TypeAnalysis::NONE);
if (speculated_cls != NULL && speculated_cls->is_constant) { if (speculated_cls != NULL && speculated_cls->is_constant) {
ConcreteCompilerType* speculated_type = unboxedType(typeFromClass(speculated_cls)); CompilerType* speculated_type = unboxedType(typeFromClass(speculated_cls));
if (VERBOSITY() >= 2) {
printf("in propagator, speculating that %s would actually be %s, at ", old_type->debugName().c_str(),
speculated_type->debugName().c_str());
fflush(stdout);
print_ast(node);
llvm::outs().flush();
printf("\n");
}
if (!old_type->canConvertTo(speculated_type)) { if (!old_type->canConvertTo(speculated_type)) {
if (VERBOSITY() >= 2) {
printf("in propagator, speculating that %s would actually be %s, at ",
old_type->debugName().c_str(), speculated_type->debugName().c_str());
fflush(stdout);
print_ast(node);
llvm::outs().flush();
printf("\n");
}
type_speculations[node] = speculated_cls; type_speculations[node] = speculated_cls;
return speculated_type; return speculated_type;
} }
...@@ -147,6 +145,7 @@ private: ...@@ -147,6 +145,7 @@ private:
} }
expr_types[node] = rtn; expr_types[node] = rtn;
assert(rtn->isUsable());
return rtn; return rtn;
} }
...@@ -163,10 +162,12 @@ private: ...@@ -163,10 +162,12 @@ private:
} }
expr_types[node] = rtn; expr_types[node] = rtn;
assert(rtn->isUsable());
return rtn; return rtn;
} }
void _doSet(InternedString target, CompilerType* t) { void _doSet(InternedString target, CompilerType* t) {
assert(t->isUsable());
if (t) if (t)
sym_table[target] = t; sym_table[target] = t;
} }
...@@ -196,7 +197,7 @@ private: ...@@ -196,7 +197,7 @@ private:
} }
} }
void* visit_ellipsis(AST_Ellipsis* node) override { return ELLIPSIS; } void* visit_ellipsis(AST_Ellipsis* node) override { return typeFromClass(ellipsis_cls); }
void* visit_attribute(AST_Attribute* node) override { void* visit_attribute(AST_Attribute* node) override {
CompilerType* t = getType(node->value); CompilerType* t = getType(node->value);
......
...@@ -155,7 +155,7 @@ public: ...@@ -155,7 +155,7 @@ public:
return var->getValue()->func->call(emitter, info, new_argspec, new_args, keyword_names); return var->getValue()->func->call(emitter, info, new_argspec, new_args, keyword_names);
} }
bool canConvertTo(ConcreteCompilerType* other_type) override { return other_type == UNKNOWN; } bool canConvertTo(CompilerType* other_type) override { return other_type == UNKNOWN; }
ConcreteCompilerType* getConcreteType() override { return typeFromClass(instancemethod_cls); } ConcreteCompilerType* getConcreteType() override { return typeFromClass(instancemethod_cls); }
ConcreteCompilerType* getBoxType() override { return getConcreteType(); } ConcreteCompilerType* getBoxType() override { return getConcreteType(); }
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) override { ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) override {
...@@ -324,7 +324,7 @@ public: ...@@ -324,7 +324,7 @@ public:
abort(); abort();
} }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override { CompilerVariable* len(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override {
bool do_patchpoint = ENABLE_ICGENERICS; bool do_patchpoint = ENABLE_ICGENERICS;
llvm::Value* rtn; llvm::Value* rtn;
if (do_patchpoint) { if (do_patchpoint) {
...@@ -338,7 +338,7 @@ public: ...@@ -338,7 +338,7 @@ public:
rtn = emitter.createCall(info.unw_info, g.funcs.unboxedLen, var->getValue()); rtn = emitter.createCall(info.unw_info, g.funcs.unboxedLen, var->getValue());
} }
assert(rtn->getType() == g.i64); assert(rtn->getType() == g.i64);
return new ConcreteCompilerVariable(INT, rtn, true); return makeInt(rtn);
} }
CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
...@@ -849,7 +849,7 @@ public: ...@@ -849,7 +849,7 @@ public:
ConcreteCompilerType* getBoxType() override { return UNKNOWN; } ConcreteCompilerType* getBoxType() override { return UNKNOWN; }
bool canConvertTo(ConcreteCompilerType* other_type) override { return other_type == UNKNOWN; } bool canConvertTo(CompilerType* other_type) override { return other_type == UNKNOWN; }
CompilerType* getattrType(BoxedString* attr, bool cls_only) override { return UNDEF; } CompilerType* getattrType(BoxedString* attr, bool cls_only) override { return UNDEF; }
...@@ -901,7 +901,7 @@ public: ...@@ -901,7 +901,7 @@ public:
Sig* type_sig = new Sig(); Sig* type_sig = new Sig();
auto paramspec = rtfunc->getParamspec(); auto paramspec = rtfunc->getParamspec();
type_sig->rtn_type = fspec->rtn_type; type_sig->rtn_type = fspec->rtn_type->getUsableType();
type_sig->ndefaults = paramspec.num_defaults; type_sig->ndefaults = paramspec.num_defaults;
type_sig->takes_varargs = paramspec.takes_varargs; type_sig->takes_varargs = paramspec.takes_varargs;
type_sig->takes_kwargs = paramspec.takes_kwargs; type_sig->takes_kwargs = paramspec.takes_kwargs;
...@@ -928,21 +928,144 @@ public: ...@@ -928,21 +928,144 @@ public:
int numFrameArgs() override { abort(); } int numFrameArgs() override { abort(); }
}; };
class IntType : public ConcreteCompilerType { template <typename T> struct UnboxedVal {
T val;
ConcreteCompilerVariable* boxed;
UnboxedVal(T val, ConcreteCompilerVariable* boxed) : val(std::move(val)), boxed(boxed) {}
};
// XXX: make this a over a unique_ptr<UnboxedVal>
template <typename T, typename D> class UnboxedType : public ValuedCompilerType<std::shared_ptr<UnboxedVal<T>>> {
public: public:
IntType() {} // Subclasses need to implement:
// _makeConverted
// _dup
// _drop
// _numFrameArgs
// _serializeToFrame
// _deserializeFromFrame
typedef UnboxedVal<T> Unboxed;
typedef typename ValuedCompilerType<std::shared_ptr<UnboxedVal<T>>>::VAR VAR;
llvm::Type* llvmType() override { return g.i64; } void drop(IREmitter& emitter, VAR* var) override final {
auto v = var->getValue();
if (v->boxed)
v->boxed->decvref(emitter);
static_cast<D*>(this)->_drop(emitter, v->val);
}
bool isFitBy(BoxedClass* c) override { return false; } void grab(IREmitter& emitter, VAR* var) override final { RELEASE_ASSERT(0, ""); }
void drop(IREmitter& emitter, ConcreteCompilerVariable* var) override { void assertMatches(std::shared_ptr<Unboxed> val) override final {
// pass static_cast<D*>(this)->_assertMatches(val->val);
assert(!val->boxed || val->boxed->getType() == static_cast<D*>(this)->getBoxType());
} }
void grab(IREmitter& emitter, ConcreteCompilerVariable* var) override {
// pass CompilerVariable* dup(VAR* var, DupCache& cache) override final {
CompilerVariable*& rtn = cache[var];
if (rtn == NULL) {
auto orig_v = var->getValue();
T val_duped = static_cast<D*>(this)->_dup(orig_v->val, cache);
CompilerVariable* box_duped = orig_v->boxed ? orig_v->boxed->dup(cache) : NULL;
assert(!box_duped || box_duped->getType() == box_duped->getType()->getBoxType());
auto val
= std::make_shared<Unboxed>(std::move(val_duped), static_cast<ConcreteCompilerVariable*>(box_duped));
rtn = new VAR(this, val, var->isGrabbed());
while (rtn->getVrefs() < var->getVrefs())
rtn->incvref();
}
return rtn;
}
ConcreteCompilerType* getConcreteType() override final { return this->getBoxType(); }
bool canConvertTo(CompilerType* other_type) override final {
return (other_type == this || other_type == UNKNOWN || other_type == this->getBoxType());
}
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var,
ConcreteCompilerType* other_type) override final {
assert(canConvertTo(other_type));
auto val = var->getValue();
ConcreteCompilerVariable* boxed = val->boxed;
if (!boxed) {
boxed = static_cast<D*>(this)->_makeConverted(emitter, val->val, this->getBoxType());
ASSERT(boxed->getType() == this->getBoxType(), "%s %s", boxed->getType()->debugName().c_str(),
this->getBoxType()->debugName().c_str());
val->boxed = boxed;
}
if (boxed->getType() != other_type) {
assert(other_type == UNKNOWN);
return boxed->makeConverted(emitter, other_type);
}
boxed->incvref();
return boxed;
}
// Serialization strategy is a bit silly for now: we will emit a bool saying whether we emitted the
// boxed or unboxed value. There's no reason that has to be in the serialization though (it could
// be in the metadata), and we shouldn't have to pad the smaller version to the size of the larger one.
int numFrameArgs() override final {
return 1 + std::max(static_cast<D*>(this)->_numFrameArgs(), this->getBoxType()->numFrameArgs());
}
void serializeToFrame(VAR* var, std::vector<llvm::Value*>& stackmap_args) override final {
auto v = var->getValue();
int total_args = numFrameArgs();
int needed_args = stackmap_args.size() + total_args;
if (v->boxed) {
stackmap_args.push_back(getConstantInt(1, g.i64));
v->boxed->serializeToFrame(stackmap_args);
} else {
stackmap_args.push_back(getConstantInt(0, g.i64));
static_cast<D*>(this)->_serializeToFrame(v->val, stackmap_args);
}
while (stackmap_args.size() < needed_args)
stackmap_args.push_back(getConstantInt(0, g.i64));
} }
Box* deserializeFromFrame(const FrameVals& vals) override final {
assert(vals.size() == numFrameArgs());
bool is_boxed = vals[0];
if (is_boxed) {
// TODO: inefficient
FrameVals sub_vals(vals.begin() + 1, vals.begin() + 1 + this->getBoxType()->numFrameArgs());
return this->getBoxType()->deserializeFromFrame(sub_vals);
} else {
FrameVals sub_vals(vals.begin() + 1, vals.begin() + 1 + static_cast<D*>(this)->_numFrameArgs());
return static_cast<D*>(this)->_deserializeFromFrame(sub_vals);
}
}
};
class IntType : public UnboxedType<llvm::Value*, IntType> {
public:
IntType() {}
void _drop(IREmitter& emitter, llvm::Value* v) {}
llvm::Value* _dup(llvm::Value* v, DupCache& cache) { return v; }
void _assertMatches(llvm::Value* v) { assert(v->getType() == g.i64); }
std::string debugName() override { return "int"; }
CompilerType* getattrType(BoxedString* attr, bool cls_only) override { CompilerType* getattrType(BoxedString* attr, bool cls_only) override {
/* /*
static std::vector<AbstractFunctionType::Sig*> sigs; static std::vector<AbstractFunctionType::Sig*> sigs;
...@@ -974,8 +1097,8 @@ public: ...@@ -974,8 +1097,8 @@ public:
static std::vector<AbstractFunctionType::Sig*> sigs; static std::vector<AbstractFunctionType::Sig*> sigs;
if (sigs.size() == 0) { if (sigs.size() == 0) {
AbstractFunctionType::Sig* int__float_sig = new AbstractFunctionType::Sig(); AbstractFunctionType::Sig* int__float_sig = new AbstractFunctionType::Sig();
int__float_sig->rtn_type = FLOAT; int__float_sig->rtn_type = UNBOXED_FLOAT;
int__float_sig->arg_types.push_back(FLOAT); int__float_sig->arg_types.push_back(UNBOXED_FLOAT);
sigs.push_back(int__float_sig); sigs.push_back(int__float_sig);
AbstractFunctionType::Sig* unknown_sig = new AbstractFunctionType::Sig(); AbstractFunctionType::Sig* unknown_sig = new AbstractFunctionType::Sig();
...@@ -993,8 +1116,8 @@ public: ...@@ -993,8 +1116,8 @@ public:
return BOXED_INT->getattrType(attr, cls_only); return BOXED_INT->getattrType(attr, cls_only);
} }
CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, BoxedString* attr, CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, VAR* var, BoxedString* attr, CallattrFlags flags,
CallattrFlags flags, const std::vector<CompilerVariable*>& args, const std::vector<CompilerVariable*>& args,
const std::vector<BoxedString*>* keyword_names) override { const std::vector<BoxedString*>* keyword_names) override {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT); ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT);
CompilerVariable* rtn = converted->callattr(emitter, info, attr, flags, args, keyword_names); CompilerVariable* rtn = converted->callattr(emitter, info, attr, flags, args, keyword_names);
...@@ -1002,7 +1125,7 @@ public: ...@@ -1002,7 +1125,7 @@ public:
return rtn; return rtn;
} }
CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, BoxedString* attr, CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, VAR* var, BoxedString* attr,
bool cls_only) override { bool cls_only) override {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT); ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT);
CompilerVariable* rtn = converted->getattr(emitter, info, attr, cls_only); CompilerVariable* rtn = converted->getattr(emitter, info, attr, cls_only);
...@@ -1024,24 +1147,16 @@ public: ...@@ -1024,24 +1147,16 @@ public:
call.setDoesNotReturn(); call.setDoesNotReturn();
} }
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerVariable* var, ConcreteCompilerVariable* _makeConverted(IREmitter& emitter, llvm::Value* unboxed,
ConcreteCompilerType* other_type) override { ConcreteCompilerType* other_type) {
if (other_type == this) { assert(other_type == BOXED_INT);
var->incvref(); llvm::Value* boxed;
return var; if (llvm::ConstantInt* llvm_val = llvm::dyn_cast<llvm::ConstantInt>(unboxed)) {
} else if (other_type == UNKNOWN || other_type == BOXED_INT) { boxed = embedRelocatablePtr(emitter.getIntConstant(llvm_val->getSExtValue()), g.llvm_value_type_ptr);
llvm::Value* unboxed = var->getValue();
llvm::Value* boxed;
if (llvm::ConstantInt* llvm_val = llvm::dyn_cast<llvm::ConstantInt>(unboxed)) {
boxed = embedRelocatablePtr(emitter.getIntConstant(llvm_val->getSExtValue()), g.llvm_value_type_ptr);
} else {
boxed = emitter.getBuilder()->CreateCall(g.funcs.boxInt, var->getValue());
}
return new ConcreteCompilerVariable(other_type, boxed, true);
} else { } else {
printf("Don't know how to convert i64 to %s\n", other_type->debugName().c_str()); boxed = emitter.getBuilder()->CreateCall(g.funcs.boxInt, unboxed);
abort();
} }
return new ConcreteCompilerVariable(other_type, boxed, true);
} }
CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* slice) override { CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* slice) override {
...@@ -1051,21 +1166,21 @@ public: ...@@ -1051,21 +1166,21 @@ public:
return rtn; return rtn;
} }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) override { CompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) override {
llvm::CallSite call llvm::CallSite call
= emitter.createCall(info.unw_info, g.funcs.raiseNotIterableError, embedConstantPtr("int", g.i8_ptr)); = emitter.createCall(info.unw_info, g.funcs.raiseNotIterableError, embedConstantPtr("int", g.i8_ptr));
call.setDoesNotReturn(); call.setDoesNotReturn();
return new ConcreteCompilerVariable(INT, llvm::UndefValue::get(g.i64), true); return makeInt(llvm::UndefValue::get(g.i64));
} }
ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override { ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, VAR* var) override {
llvm::Value* cmp = emitter.getBuilder()->CreateICmpNE(var->getValue(), llvm::ConstantInt::get(g.i64, 0, false)); llvm::Value* cmp
= emitter.getBuilder()->CreateICmpNE(var->getValue()->val, llvm::ConstantInt::get(g.i64, 0, false));
return boolFromI1(emitter, cmp); return boolFromI1(emitter, cmp);
} }
ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, CompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, VAR* var, AST_TYPE::AST_TYPE op_type) override {
AST_TYPE::AST_TYPE op_type) override { llvm::Value* unboxed = var->getValue()->val;
llvm::Value* unboxed = var->getValue();
if (op_type == AST_TYPE::USub) { if (op_type == AST_TYPE::USub) {
if (llvm::ConstantInt* llvm_val = llvm::dyn_cast<llvm::ConstantInt>(unboxed)) { if (llvm::ConstantInt* llvm_val = llvm::dyn_cast<llvm::ConstantInt>(unboxed)) {
int64_t val = llvm_val->getSExtValue(); int64_t val = llvm_val->getSExtValue();
...@@ -1092,10 +1207,8 @@ public: ...@@ -1092,10 +1207,8 @@ public:
if (op_type == AST_TYPE::IsNot || op_type == AST_TYPE::Is) if (op_type == AST_TYPE::IsNot || op_type == AST_TYPE::Is)
return makeBool(op_type == AST_TYPE::IsNot); return makeBool(op_type == AST_TYPE::IsNot);
ConcreteCompilerVariable* converted_left = var->makeConverted(emitter, INT); llvm::Value* conv = emitter.getBuilder()->CreateSIToFP(var->getValue()->val, g.double_);
llvm::Value* conv = emitter.getBuilder()->CreateSIToFP(converted_left->getValue(), g.double_); auto converted_left = makeFloat(conv);
converted_left->decvref(emitter);
converted_left = new ConcreteCompilerVariable(FLOAT, conv, true);
return converted_left->binexp(emitter, info, rhs, op_type, exp_type); return converted_left->binexp(emitter, info, rhs, op_type, exp_type);
} }
...@@ -1105,7 +1218,8 @@ public: ...@@ -1105,7 +1218,8 @@ public:
return rtn; return rtn;
} }
ConcreteCompilerVariable* converted_right = rhs->makeConverted(emitter, INT); assert(rhs->getType() == INT);
llvm::Value* right_val = static_cast<VAR*>(rhs)->getValue()->val;
llvm::Value* v; llvm::Value* v;
/*if (op_type == AST_TYPE::Mod) { /*if (op_type == AST_TYPE::Mod) {
v = emitter.createCall2(info.unw_info, g.funcs.mod_i64_i64, var->getValue(), converted_right->getValue()) v = emitter.createCall2(info.unw_info, g.funcs.mod_i64_i64, var->getValue(), converted_right->getValue())
...@@ -1178,14 +1292,10 @@ public: ...@@ -1178,14 +1292,10 @@ public:
abort(); abort();
break; break;
} }
v = emitter.getBuilder()->CreateICmp(cmp_pred, var->getValue(), converted_right->getValue()); v = emitter.getBuilder()->CreateICmp(cmp_pred, var->getValue()->val, right_val);
}
converted_right->decvref(emitter);
if (v->getType() == g.i64) {
return new ConcreteCompilerVariable(INT, v, true);
} else {
return boolFromI1(emitter, v);
} }
assert(v->getType() == g.i1);
return boolFromI1(emitter, v);
} }
CompilerVariable* contains(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* lhs) override { CompilerVariable* contains(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* lhs) override {
...@@ -1197,44 +1307,68 @@ public: ...@@ -1197,44 +1307,68 @@ public:
ConcreteCompilerType* getBoxType() override { return BOXED_INT; } ConcreteCompilerType* getBoxType() override { return BOXED_INT; }
Box* deserializeFromFrame(const FrameVals& vals) override { int _numFrameArgs() { return 1; }
Box* _deserializeFromFrame(const FrameVals& vals) {
assert(vals.size() == 1); assert(vals.size() == 1);
return boxInt(vals[0]); return boxInt(vals[0]);
} }
void _serializeToFrame(llvm::Value* val, std::vector<llvm::Value*>& stackmap_args) { stackmap_args.push_back(val); }
static llvm::Value* extractInt(CompilerVariable* v) {
assert(v->getType() == INT);
return static_cast<VAR*>(v)->getValue()->val;
}
} _INT; } _INT;
ConcreteCompilerType* INT = &_INT; CompilerType* INT = &_INT;
CompilerVariable* makeInt(llvm::Value* n) {
assert(n->getType() == g.i64);
return new IntType::VAR(&_INT, std::make_shared<IntType::Unboxed>(n, nullptr), true);
}
CompilerVariable* makeInt(int64_t n) {
return makeInt(llvm::ConstantInt::get(g.i64, n, true));
}
CompilerVariable* makeUnboxedInt(IREmitter& emitter, ConcreteCompilerVariable* v) {
assert(v->getType() == BOXED_INT);
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxInt, v->getValue());
return new IntType::VAR(&_INT, std::make_shared<IntType::Unboxed>(unboxed, v), true);
}
ConcreteCompilerVariable* makeInt(int64_t n) { CompilerVariable* makeUnboxedInt(IREmitter& emitter, llvm::Value* v) {
return new ConcreteCompilerVariable(INT, llvm::ConstantInt::get(g.i64, n, true), true); assert(v->getType() == g.llvm_value_type_ptr);
return makeUnboxedInt(emitter, new ConcreteCompilerVariable(BOXED_INT, v, false));
} }
class FloatType : public ConcreteCompilerType { class FloatType : public UnboxedType<llvm::Value*, FloatType> {
public: public:
FloatType() {} FloatType() {}
llvm::Type* llvmType() override { return g.double_; } std::string debugName() override { return "float"; }
bool isFitBy(BoxedClass* c) override { return false; }
void drop(IREmitter& emitter, ConcreteCompilerVariable* var) override { void _drop(IREmitter& emitter, llvm::Value* v) {
// pass
}
void grab(IREmitter& emitter, ConcreteCompilerVariable* var) override {
// pass // pass
} }
void _assertMatches(llvm::Value* v) { assert(v->getType() == g.double_); }
llvm::Value* _dup(llvm::Value* v, DupCache& cache) { return v; }
CompilerType* getattrType(BoxedString* attr, bool cls_only) override { CompilerType* getattrType(BoxedString* attr, bool cls_only) override {
static std::vector<AbstractFunctionType::Sig*> sigs; static std::vector<AbstractFunctionType::Sig*> sigs;
if (sigs.size() == 0) { if (sigs.size() == 0) {
AbstractFunctionType::Sig* float_sig = new AbstractFunctionType::Sig(); AbstractFunctionType::Sig* float_sig = new AbstractFunctionType::Sig();
float_sig->rtn_type = FLOAT; float_sig->rtn_type = UNBOXED_FLOAT;
float_sig->arg_types.push_back(FLOAT); float_sig->arg_types.push_back(UNBOXED_FLOAT);
sigs.push_back(float_sig); sigs.push_back(float_sig);
AbstractFunctionType::Sig* int_sig = new AbstractFunctionType::Sig(); AbstractFunctionType::Sig* int_sig = new AbstractFunctionType::Sig();
int_sig->rtn_type = FLOAT; int_sig->rtn_type = UNBOXED_FLOAT;
int_sig->arg_types.push_back(INT); int_sig->arg_types.push_back(UNBOXED_INT);
sigs.push_back(int_sig); sigs.push_back(int_sig);
AbstractFunctionType::Sig* unknown_sig = new AbstractFunctionType::Sig(); AbstractFunctionType::Sig* unknown_sig = new AbstractFunctionType::Sig();
...@@ -1258,7 +1392,7 @@ public: ...@@ -1258,7 +1392,7 @@ public:
return BOXED_FLOAT->getattrType(attr, cls_only); return BOXED_FLOAT->getattrType(attr, cls_only);
} }
CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, BoxedString* attr, CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, VAR* var, BoxedString* attr,
bool cls_only) override { bool cls_only) override {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT); ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT);
CompilerVariable* rtn = converted->getattr(emitter, info, attr, cls_only); CompilerVariable* rtn = converted->getattr(emitter, info, attr, cls_only);
...@@ -1266,8 +1400,8 @@ public: ...@@ -1266,8 +1400,8 @@ public:
return rtn; return rtn;
} }
CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, BoxedString* attr, CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, VAR* var, BoxedString* attr, CallattrFlags flags,
CallattrFlags flags, const std::vector<CompilerVariable*>& args, const std::vector<CompilerVariable*>& args,
const std::vector<BoxedString*>* keyword_names) override { const std::vector<BoxedString*>* keyword_names) override {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT); ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT);
CompilerVariable* rtn = converted->callattr(emitter, info, attr, flags, args, keyword_names); CompilerVariable* rtn = converted->callattr(emitter, info, attr, flags, args, keyword_names);
...@@ -1289,35 +1423,27 @@ public: ...@@ -1289,35 +1423,27 @@ public:
call.setDoesNotReturn(); call.setDoesNotReturn();
} }
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerVariable* var, ConcreteCompilerVariable* _makeConverted(IREmitter& emitter, llvm::Value* unboxed,
ConcreteCompilerType* other_type) override { ConcreteCompilerType* other_type) {
if (other_type == this) { assert(other_type == BOXED_FLOAT);
var->incvref(); llvm::Value* boxed;
return var; if (llvm::ConstantFP* llvm_val = llvm::dyn_cast<llvm::ConstantFP>(unboxed)) {
} else if (other_type == UNKNOWN || other_type == BOXED_FLOAT) { // Will this ever hit the cache?
llvm::Value* unboxed = var->getValue(); boxed = embedRelocatablePtr(emitter.getFloatConstant(llvm_val->getValueAPF().convertToDouble()),
llvm::Value* boxed; g.llvm_value_type_ptr);
if (llvm::ConstantFP* llvm_val = llvm::dyn_cast<llvm::ConstantFP>(unboxed)) {
// Will this ever hit the cache?
boxed = embedRelocatablePtr(emitter.getFloatConstant(llvm_val->getValueAPF().convertToDouble()),
g.llvm_value_type_ptr);
} else {
boxed = emitter.getBuilder()->CreateCall(g.funcs.boxFloat, var->getValue());
}
return new ConcreteCompilerVariable(other_type, boxed, true);
} else { } else {
printf("Don't know how to convert float to %s\n", other_type->debugName().c_str()); boxed = emitter.getBuilder()->CreateCall(g.funcs.boxFloat, unboxed);
abort();
} }
return new ConcreteCompilerVariable(other_type, boxed, true);
} }
ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override { ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, VAR* var) override {
llvm::Value* cmp = emitter.getBuilder()->CreateFCmpUNE(var->getValue(), llvm::ConstantFP::get(g.double_, 0)); llvm::Value* cmp
= emitter.getBuilder()->CreateFCmpUNE(var->getValue()->val, llvm::ConstantFP::get(g.double_, 0));
return boolFromI1(emitter, cmp); return boolFromI1(emitter, cmp);
} }
ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, CompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, VAR* var, AST_TYPE::AST_TYPE op_type) override {
AST_TYPE::AST_TYPE op_type) override {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT); ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT);
auto rtn = converted->unaryop(emitter, info, op_type); auto rtn = converted->unaryop(emitter, info, op_type);
converted->decvref(emitter); converted->decvref(emitter);
...@@ -1333,6 +1459,8 @@ public: ...@@ -1333,6 +1459,8 @@ public:
CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs, CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs,
AST_TYPE::AST_TYPE op_type, BinExpType exp_type) override { AST_TYPE::AST_TYPE op_type, BinExpType exp_type) override {
assert(rhs->getType() != UNBOXED_FLOAT); // we could handle this here but it shouldn't happen
if (rhs->getType() != INT && rhs->getType() != FLOAT) { if (rhs->getType() != INT && rhs->getType() != FLOAT) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT); ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT);
CompilerVariable* rtn = converted->binexp(emitter, info, rhs, op_type, exp_type); CompilerVariable* rtn = converted->binexp(emitter, info, rhs, op_type, exp_type);
...@@ -1340,33 +1468,28 @@ public: ...@@ -1340,33 +1468,28 @@ public:
return rtn; return rtn;
} }
ConcreteCompilerVariable* converted_right; llvm::Value* rhs_val;
if (rhs->getType() == FLOAT) { if (rhs->getType() == FLOAT) {
converted_right = rhs->makeConverted(emitter, FLOAT); rhs_val = static_cast<FloatType::VAR*>(rhs)->getValue()->val;
} else { } else {
if (op_type == AST_TYPE::IsNot || op_type == AST_TYPE::Is) if (op_type == AST_TYPE::IsNot || op_type == AST_TYPE::Is)
return makeBool(op_type == AST_TYPE::IsNot); return makeBool(op_type == AST_TYPE::IsNot);
converted_right = rhs->makeConverted(emitter, INT); assert(rhs->getType() == INT);
llvm::Value* conv = emitter.getBuilder()->CreateSIToFP(converted_right->getValue(), g.double_); llvm::Value* right_val = IntType::extractInt(rhs);
converted_right->decvref(emitter); rhs_val = emitter.getBuilder()->CreateSIToFP(right_val, g.double_);
converted_right = new ConcreteCompilerVariable(FLOAT, conv, true);
} }
llvm::Value* v; llvm::Value* v;
bool succeeded = true; bool succeeded = true;
if (op_type == AST_TYPE::Mod) { if (op_type == AST_TYPE::Mod) {
v = emitter.createCall2(info.unw_info, g.funcs.mod_float_float, var->getValue(), v = emitter.createCall2(info.unw_info, g.funcs.mod_float_float, var->getValue()->val, rhs_val);
converted_right->getValue());
} else if (op_type == AST_TYPE::Div || op_type == AST_TYPE::TrueDiv) { } else if (op_type == AST_TYPE::Div || op_type == AST_TYPE::TrueDiv) {
v = emitter.createCall2(info.unw_info, g.funcs.div_float_float, var->getValue(), v = emitter.createCall2(info.unw_info, g.funcs.div_float_float, var->getValue()->val, rhs_val);
converted_right->getValue());
} else if (op_type == AST_TYPE::FloorDiv) { } else if (op_type == AST_TYPE::FloorDiv) {
v = emitter.createCall2(info.unw_info, g.funcs.floordiv_float_float, var->getValue(), v = emitter.createCall2(info.unw_info, g.funcs.floordiv_float_float, var->getValue()->val, rhs_val);
converted_right->getValue());
} else if (op_type == AST_TYPE::Pow) { } else if (op_type == AST_TYPE::Pow) {
v = emitter.createCall2(info.unw_info, g.funcs.pow_float_float, var->getValue(), v = emitter.createCall2(info.unw_info, g.funcs.pow_float_float, var->getValue()->val, rhs_val);
converted_right->getValue());
} else if (exp_type == BinOp || exp_type == AugBinOp) { } else if (exp_type == BinOp || exp_type == AugBinOp) {
llvm::Instruction::BinaryOps binopcode; llvm::Instruction::BinaryOps binopcode;
switch (op_type) { switch (op_type) {
...@@ -1393,7 +1516,7 @@ public: ...@@ -1393,7 +1516,7 @@ public:
} }
if (succeeded) { if (succeeded) {
v = emitter.getBuilder()->CreateBinOp(binopcode, var->getValue(), converted_right->getValue()); v = emitter.getBuilder()->CreateBinOp(binopcode, var->getValue()->val, rhs_val);
} }
} else { } else {
assert(exp_type == Compare); assert(exp_type == Compare);
...@@ -1424,13 +1547,12 @@ public: ...@@ -1424,13 +1547,12 @@ public:
abort(); abort();
break; break;
} }
v = emitter.getBuilder()->CreateFCmp(cmp_pred, var->getValue(), converted_right->getValue()); v = emitter.getBuilder()->CreateFCmp(cmp_pred, var->getValue()->val, rhs_val);
} }
converted_right->decvref(emitter);
if (succeeded) { if (succeeded) {
if (v->getType() == g.double_) { if (v->getType() == g.double_) {
return new ConcreteCompilerVariable(FLOAT, v, true); return makeFloat(v);
} else { } else {
return boolFromI1(emitter, v); return boolFromI1(emitter, v);
} }
...@@ -1452,19 +1574,60 @@ public: ...@@ -1452,19 +1574,60 @@ public:
ConcreteCompilerType* getBoxType() override { return BOXED_FLOAT; } ConcreteCompilerType* getBoxType() override { return BOXED_FLOAT; }
Box* deserializeFromFrame(const FrameVals& vals) override { int _numFrameArgs() { return 1; }
void _serializeToFrame(llvm::Value* v, std::vector<llvm::Value*>& stackmap_args) { stackmap_args.push_back(v); }
Box* _deserializeFromFrame(const FrameVals& vals) {
assert(vals.size() == 1); assert(vals.size() == 1);
double d = *reinterpret_cast<const double*>(&vals[0]); double d = *reinterpret_cast<const double*>(&vals[0]);
return boxFloat(d); return boxFloat(d);
} }
} _FLOAT; } _FLOAT;
ConcreteCompilerType* FLOAT = &_FLOAT; CompilerType* FLOAT = &_FLOAT;
class PhonyUnboxedType : public ConcreteCompilerType {
private:
llvm::Type* t;
CompilerType* usable_type;
public:
PhonyUnboxedType(llvm::Type* t, CompilerType* usable_type) : t(t), usable_type(usable_type) {}
ConcreteCompilerVariable* makeFloat(double d) { std::string debugName() { return "phony(" + ConcreteCompilerType::debugName() + ")"; }
return new ConcreteCompilerVariable(FLOAT, llvm::ConstantFP::get(g.double_, d), true);
CompilerType* getUsableType() override { return usable_type; }
llvm::Type* llvmType() override { return t; }
Box* deserializeFromFrame(const FrameVals& vals) override { RELEASE_ASSERT(0, "unavailable for phony types"); }
};
ConcreteCompilerType* UNBOXED_INT = new PhonyUnboxedType(llvm::Type::getInt64Ty(llvm::getGlobalContext()), INT);
ConcreteCompilerType* UNBOXED_FLOAT = new PhonyUnboxedType(llvm::Type::getDoubleTy(llvm::getGlobalContext()), FLOAT);
CompilerVariable* makeFloat(llvm::Value* n) {
assert(n->getType() == g.double_);
return new FloatType::VAR(&_FLOAT, std::make_shared<FloatType::Unboxed>(n, nullptr), true);
}
CompilerVariable* makeFloat(double n) {
return makeFloat(llvm::ConstantFP::get(g.double_, n));
} }
CompilerVariable* makeUnboxedFloat(IREmitter& emitter, ConcreteCompilerVariable* v) {
assert(v->getType() == BOXED_FLOAT);
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxFloat, v->getValue());
return new FloatType::VAR(&_FLOAT, std::make_shared<FloatType::Unboxed>(unboxed, v), true);
}
CompilerVariable* makeUnboxedFloat(IREmitter& emitter, llvm::Value* v) {
assert(v->getType() == g.llvm_value_type_ptr);
return makeUnboxedFloat(emitter, new ConcreteCompilerVariable(BOXED_FLOAT, v, false));
}
ConcreteCompilerVariable* makeLong(Box* v) { ConcreteCompilerVariable* makeLong(Box* v) {
return new ConcreteCompilerVariable(LONG, embedRelocatablePtr(v, g.llvm_value_type_ptr), true); return new ConcreteCompilerVariable(LONG, embedRelocatablePtr(v, g.llvm_value_type_ptr), true);
} }
...@@ -1638,11 +1801,11 @@ public: ...@@ -1638,11 +1801,11 @@ public:
return rtn; return rtn;
} }
ConcreteCompilerVariable* tryCallattrConstant(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, CompilerVariable* tryCallattrConstant(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
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) { ExceptionStyle exception_style = CXX) {
if (!canStaticallyResolveGetattrs()) if (!canStaticallyResolveGetattrs())
return NULL; return NULL;
...@@ -1770,27 +1933,25 @@ public: ...@@ -1770,27 +1933,25 @@ public:
ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->exception_style, cf->code, other_args, ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->exception_style, cf->code, other_args,
argspec, new_args, keyword_names, cf->spec->rtn_type); argspec, new_args, keyword_names, cf->spec->rtn_type);
assert(rtn->getType() == cf->spec->rtn_type); assert(rtn->getType() == cf->spec->rtn_type);
assert(rtn->getType() != UNDEF); ConcreteCompilerType* rtn_type = rtn->getType();
assert(rtn_type != UNDEF);
// We should provide unboxed versions of these rather than boxing then unboxing: // We should provide unboxed versions of these rather than boxing then unboxing:
// TODO is it more efficient to unbox here, or should we leave it boxed? // TODO is it more efficient to unbox here, or should we leave it boxed?
if (cf->spec->rtn_type == BOXED_BOOL) { if (rtn_type == BOXED_BOOL) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, rtn->getValue()); llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, rtn->getValue());
return boolFromI1(emitter, unboxed); return boolFromI1(emitter, unboxed);
} }
#if ENABLE_UNBOXED_VALUES if (rtn_type == BOXED_INT) {
if (cf->spec->rtn_type == BOXED_INT) { return makeUnboxedInt(emitter, rtn);
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxInt, rtn->getValue());
return new ConcreteCompilerVariable(INT, unboxed, true);
} }
if (cf->spec->rtn_type == BOXED_FLOAT) { if (rtn_type == UNBOXED_INT) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxFloat, rtn->getValue()); return makeInt(rtn->getValue());
return new ConcreteCompilerVariable(FLOAT, unboxed, true); }
if (rtn_type == BOXED_FLOAT) {
return makeUnboxedFloat(emitter, rtn);
} }
assert(cf->spec->rtn_type != BOXED_INT);
assert(cf->spec->rtn_type != BOXED_FLOAT);
#endif
ASSERT(cf->spec->rtn_type != BOXED_BOOL, "%p", cf->code);
return rtn; return rtn;
} }
...@@ -1800,8 +1961,8 @@ public: ...@@ -1800,8 +1961,8 @@ public:
const std::vector<BoxedString*>* keyword_names) override { const std::vector<BoxedString*>* keyword_names) override {
ExceptionStyle exception_style = info.preferredExceptionStyle(); ExceptionStyle exception_style = info.preferredExceptionStyle();
ConcreteCompilerVariable* called_constant = tryCallattrConstant( CompilerVariable* called_constant = tryCallattrConstant(emitter, info, var, attr, flags.cls_only, flags.argspec,
emitter, info, var, attr, flags.cls_only, flags.argspec, args, keyword_names, NULL, exception_style); args, keyword_names, NULL, exception_style);
if (called_constant) if (called_constant)
return called_constant; return called_constant;
...@@ -1827,7 +1988,7 @@ public: ...@@ -1827,7 +1988,7 @@ public:
bool no_attribute = false; bool no_attribute = false;
ConcreteCompilerVariable* called_constant CompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, left_side_name, true, ArgPassSpec(1, 0, 0, 0), = tryCallattrConstant(emitter, info, var, left_side_name, true, ArgPassSpec(1, 0, 0, 0),
{ converted_rhs }, NULL, &no_attribute); { converted_rhs }, NULL, &no_attribute);
...@@ -1863,8 +2024,8 @@ public: ...@@ -1863,8 +2024,8 @@ public:
ExceptionStyle exception_style = info.preferredExceptionStyle(); ExceptionStyle exception_style = info.preferredExceptionStyle();
ConcreteCompilerVariable* called_constant = tryCallattrConstant( CompilerVariable* called_constant = tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(1, 0, 0, 0),
emitter, info, var, attr, true, ArgPassSpec(1, 0, 0, 0), { slice }, NULL, &no_attribute, exception_style); { slice }, NULL, &no_attribute, exception_style);
if (no_attribute) { if (no_attribute) {
assert(called_constant->getType() == UNDEF); assert(called_constant->getType() == UNDEF);
...@@ -1886,9 +2047,9 @@ public: ...@@ -1886,9 +2047,9 @@ public:
return UNKNOWN->getPystonIter(emitter, info, var); return UNKNOWN->getPystonIter(emitter, info, var);
} }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) override { CompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) override {
static BoxedString* attr = internStringImmortal("__len__"); static BoxedString* attr = internStringImmortal("__len__");
ConcreteCompilerVariable* called_constant CompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL); = tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL);
if (called_constant) if (called_constant)
return called_constant; return called_constant;
...@@ -1896,13 +2057,13 @@ public: ...@@ -1896,13 +2057,13 @@ public:
return UNKNOWN->len(emitter, info, var); return UNKNOWN->len(emitter, info, var);
} }
ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override { CompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override {
if (cls == None->cls) if (cls == None->cls)
return makeBool(false); return makeBool(false);
static BoxedString* attr = internStringImmortal("__nonzero__"); static BoxedString* attr = internStringImmortal("__nonzero__");
bool no_attribute = false; bool no_attribute = false;
ConcreteCompilerVariable* called_constant CompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL, &no_attribute); = tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL, &no_attribute);
// TODO: if no_attribute, we could optimize by continuing the dispatch process and trying // TODO: if no_attribute, we could optimize by continuing the dispatch process and trying
...@@ -1922,12 +2083,12 @@ public: ...@@ -1922,12 +2083,12 @@ public:
return UNKNOWN->nonzero(emitter, info, var); return UNKNOWN->nonzero(emitter, info, var);
} }
ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, CompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
AST_TYPE::AST_TYPE op_type) override { AST_TYPE::AST_TYPE op_type) override {
BoxedString* attr = getOpName(op_type); BoxedString* attr = getOpName(op_type);
bool no_attribute = false; bool no_attribute = false;
ConcreteCompilerVariable* called_constant CompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL, &no_attribute); = tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL, &no_attribute);
if (called_constant && !no_attribute) if (called_constant && !no_attribute)
...@@ -1936,10 +2097,10 @@ public: ...@@ -1936,10 +2097,10 @@ public:
return UNKNOWN->unaryop(emitter, info, var, op_type); return UNKNOWN->unaryop(emitter, info, var, op_type);
} }
ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override { CompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override {
static BoxedString* attr = internStringImmortal("__hasnext__"); static BoxedString* attr = internStringImmortal("__hasnext__");
ConcreteCompilerVariable* called_constant CompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL, NULL); = tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL, NULL);
if (called_constant) if (called_constant)
...@@ -1966,7 +2127,7 @@ public: ...@@ -1966,7 +2127,7 @@ public:
} }
}; };
std::unordered_map<BoxedClass*, NormalObjectType*> NormalObjectType::made; std::unordered_map<BoxedClass*, NormalObjectType*> NormalObjectType::made;
ConcreteCompilerType* STR, *BOXED_INT, *BOXED_FLOAT, *BOXED_BOOL, *NONE, *ELLIPSIS; ConcreteCompilerType* STR, *BOXED_INT, *BOXED_FLOAT, *BOXED_BOOL, *NONE;
class ClosureType : public ConcreteCompilerType { class ClosureType : public ConcreteCompilerType {
public: public:
...@@ -2068,7 +2229,7 @@ public: ...@@ -2068,7 +2229,7 @@ public:
return new ConcreteCompilerVariable(other_type, boxed, true); return new ConcreteCompilerVariable(other_type, boxed, true);
} }
bool canConvertTo(ConcreteCompilerType* other) override { return (other == STR || other == UNKNOWN); } bool canConvertTo(CompilerType* other) override { return (other == STR || other == UNKNOWN); }
CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, VAR* var, BoxedString* attr, CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, VAR* var, BoxedString* attr,
bool cls_only) override { bool cls_only) override {
...@@ -2181,7 +2342,7 @@ public: ...@@ -2181,7 +2342,7 @@ public:
return var; return var;
} }
bool canConvertTo(ConcreteCompilerType* other_type) override { bool canConvertTo(CompilerType* other_type) override {
return (other_type == UNKNOWN || other_type == BOXED_BOOL || other_type == BOOL); return (other_type == UNKNOWN || other_type == BOXED_BOOL || other_type == BOOL);
} }
...@@ -2266,114 +2427,6 @@ ConcreteCompilerVariable* doIs(IREmitter& emitter, CompilerVariable* lhs, Compil ...@@ -2266,114 +2427,6 @@ ConcreteCompilerVariable* doIs(IREmitter& emitter, CompilerVariable* lhs, Compil
return boolFromI1(emitter, cmp); return boolFromI1(emitter, cmp);
} }
template <typename T> struct UnboxedVal {
T val;
ConcreteCompilerVariable* boxed;
};
template <typename T, typename D> class UnboxedType : public ValuedCompilerType<UnboxedVal<T>*> {
public:
typedef UnboxedVal<T> Unboxed;
typedef typename ValuedCompilerType<UnboxedVal<T>*>::VAR VAR;
void drop(IREmitter& emitter, VAR* var) override final {
Unboxed* v = var->getValue();
if (v->boxed)
v->boxed->decvref(emitter);
static_cast<D*>(this)->_drop(emitter, v->val);
}
void grab(IREmitter& emitter, VAR* var) override final { RELEASE_ASSERT(0, ""); }
CompilerVariable* dup(VAR* var, DupCache& cache) override final {
CompilerVariable*& rtn = cache[var];
if (rtn == NULL) {
Unboxed* orig_v = var->getValue();
T val_duped = static_cast<D*>(this)->_dup(orig_v->val, cache);
CompilerVariable* box_duped = orig_v->boxed ? orig_v->boxed->dup(cache) : NULL;
assert(!box_duped || box_duped->getType() == box_duped->getType()->getBoxType());
rtn = new VAR(this, new Unboxed{ std::move(val_duped), static_cast<ConcreteCompilerVariable*>(box_duped) },
var->isGrabbed());
while (rtn->getVrefs() < var->getVrefs())
rtn->incvref();
}
return rtn;
}
bool canConvertTo(ConcreteCompilerType* other_type) override final {
return (other_type == UNKNOWN || other_type == this->getBoxType());
}
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var,
ConcreteCompilerType* other_type) override final {
assert(canConvertTo(other_type));
Unboxed* val = var->getValue();
ConcreteCompilerVariable* boxed = val->boxed;
if (!boxed) {
boxed = static_cast<D*>(this)->_makeConverted(emitter, val->val, this->getBoxType());
ASSERT(boxed->getType() == this->getBoxType(), "%s %s", boxed->getType()->debugName().c_str(),
this->getBoxType()->debugName().c_str());
val->boxed = boxed;
}
if (boxed->getType() != other_type) {
assert(other_type == UNKNOWN);
return boxed->makeConverted(emitter, other_type);
}
boxed->incvref();
return boxed;
}
// Serialization strategy is a bit silly for now: we will emit a bool saying whether we emitted the
// boxed or unboxed value. There's no reason that has to be in the serialization though (it could
// be in the metadata), and we shouldn't have to pad the smaller version to the size of the larger one.
int numFrameArgs() override final {
return 1 + std::max(static_cast<D*>(this)->_numFrameArgs(), this->getBoxType()->numFrameArgs());
}
void serializeToFrame(VAR* var, std::vector<llvm::Value*>& stackmap_args) override final {
Unboxed* v = var->getValue();
int total_args = numFrameArgs();
int needed_args = stackmap_args.size() + total_args;
if (v->boxed) {
stackmap_args.push_back(getConstantInt(1, g.i64));
v->boxed->serializeToFrame(stackmap_args);
} else {
stackmap_args.push_back(getConstantInt(0, g.i64));
static_cast<D*>(this)->_serializeToFrame(v->val, stackmap_args);
}
while (stackmap_args.size() < needed_args)
stackmap_args.push_back(getConstantInt(0, g.i64));
}
Box* deserializeFromFrame(const FrameVals& vals) override final {
assert(vals.size() == numFrameArgs());
bool is_boxed = vals[0];
if (is_boxed) {
// TODO: inefficient
FrameVals sub_vals(vals.begin() + 1, vals.begin() + 1 + this->getBoxType()->numFrameArgs());
return this->getBoxType()->deserializeFromFrame(sub_vals);
} else {
FrameVals sub_vals(vals.begin() + 1, vals.begin() + 1 + static_cast<D*>(this)->_numFrameArgs());
return static_cast<D*>(this)->_deserializeFromFrame(sub_vals);
}
}
};
ConcreteCompilerType* BOXED_TUPLE; ConcreteCompilerType* BOXED_TUPLE;
class TupleType : public UnboxedType<const std::vector<CompilerVariable*>, TupleType> { class TupleType : public UnboxedType<const std::vector<CompilerVariable*>, TupleType> {
private: private:
...@@ -2395,11 +2448,11 @@ private: ...@@ -2395,11 +2448,11 @@ private:
public: public:
typedef const std::vector<CompilerVariable*> VEC; typedef const std::vector<CompilerVariable*> VEC;
void assertMatches(Unboxed* v) override { void _assertMatches(const VEC& v) {
assert(v->val.size() == elt_types.size()); assert(v.size() == elt_types.size());
for (int i = 0; i < v->val.size(); i++) { for (int i = 0; i < v.size(); i++) {
assert((v->val)[i]->getType() == elt_types[i]); assert(v[i]->getType() == elt_types[i]);
} }
} }
...@@ -2456,17 +2509,16 @@ public: ...@@ -2456,17 +2509,16 @@ public:
ConcreteCompilerType* getBoxType() override { return BOXED_TUPLE; } ConcreteCompilerType* getBoxType() override { return BOXED_TUPLE; }
ConcreteCompilerType* getConcreteType() override { return BOXED_TUPLE; }
static TupleType* make(const std::vector<CompilerType*>& elt_types) { return new TupleType(elt_types); } static TupleType* make(const std::vector<CompilerType*>& elt_types) { return new TupleType(elt_types); }
CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* slice) override { CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* slice) override {
assert(slice->getType() != UNBOXED_INT);
if (slice->getType() == INT) { if (slice->getType() == INT) {
llvm::Value* v = static_cast<ConcreteCompilerVariable*>(slice)->getValue(); llvm::Value* v = IntType::extractInt(slice);
assert(v->getType() == g.i64); assert(v->getType() == g.i64);
if (llvm::ConstantInt* ci = llvm::dyn_cast<llvm::ConstantInt>(v)) { if (llvm::ConstantInt* ci = llvm::dyn_cast<llvm::ConstantInt>(v)) {
int64_t i = ci->getSExtValue(); int64_t i = ci->getSExtValue();
Unboxed* v = var->getValue(); auto v = var->getValue();
const VEC* elts = &v->val; const VEC* elts = &v->val;
if (i >= 0 && i < elts->size()) { if (i >= 0 && i < elts->size()) {
CompilerVariable* rtn = (*elts)[i]; CompilerVariable* rtn = (*elts)[i];
...@@ -2500,8 +2552,8 @@ public: ...@@ -2500,8 +2552,8 @@ public:
return rtn; return rtn;
} }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) override { CompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) override {
return new ConcreteCompilerVariable(INT, getConstantInt(var->getValue()->val.size(), g.i64), true); return makeInt(var->getValue()->val.size());
} }
CompilerType* getattrType(BoxedString* attr, bool cls_only) override { CompilerType* getattrType(BoxedString* attr, bool cls_only) override {
...@@ -2539,9 +2591,9 @@ public: ...@@ -2539,9 +2591,9 @@ public:
{ {
CompilerVariable* eq = converted_lhs->binexp(emitter, info, e, AST_TYPE::Eq, Compare); CompilerVariable* eq = converted_lhs->binexp(emitter, info, e, AST_TYPE::Eq, Compare);
ConcreteCompilerVariable* eq_nonzero = eq->nonzero(emitter, info); CompilerVariable* eq_nonzero = eq->nonzero(emitter, info);
assert(eq_nonzero->getType() == BOOL); assert(eq_nonzero->getType() == BOOL);
llvm::Value* raw = i1FromBool(emitter, eq_nonzero); llvm::Value* raw = i1FromBool(emitter, static_cast<ConcreteCompilerVariable*>(eq_nonzero));
phi_incoming.push_back(std::make_pair(emitter.currentBasicBlock(), getConstantInt(1, g.i1))); phi_incoming.push_back(std::make_pair(emitter.currentBasicBlock(), getConstantInt(1, g.i1)));
llvm::BasicBlock* new_bb = emitter.createBasicBlock(); llvm::BasicBlock* new_bb = emitter.createBasicBlock();
...@@ -2640,7 +2692,7 @@ CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts) { ...@@ -2640,7 +2692,7 @@ CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts) {
} }
TupleType* type = TupleType::make(elt_types); TupleType* type = TupleType::make(elt_types);
auto alloc_var = new TupleType::Unboxed({ elts, NULL }); auto alloc_var = std::make_shared<TupleType::Unboxed>(elts, nullptr);
return new TupleType::VAR(type, alloc_var, true); return new TupleType::VAR(type, alloc_var, true);
} }
...@@ -2715,7 +2767,7 @@ public: ...@@ -2715,7 +2767,7 @@ public:
CompilerType* getattrType(BoxedString* attr, bool cls_only) override { return UNDEF; } CompilerType* getattrType(BoxedString* attr, bool cls_only) override { return UNDEF; }
bool canConvertTo(ConcreteCompilerType* other_type) override { return true; } bool canConvertTo(CompilerType* other_type) override { return true; }
BoxedClass* guaranteedClass() override { return NULL; } BoxedClass* guaranteedClass() override { return NULL; }
......
...@@ -47,7 +47,7 @@ public: ...@@ -47,7 +47,7 @@ public:
virtual std::string debugName() = 0; virtual std::string debugName() = 0;
virtual ConcreteCompilerType* getConcreteType() = 0; virtual ConcreteCompilerType* getConcreteType() = 0;
virtual ConcreteCompilerType* getBoxType() = 0; virtual ConcreteCompilerType* getBoxType() = 0;
virtual bool canConvertTo(ConcreteCompilerType* other_type) = 0; virtual bool canConvertTo(CompilerType* other_type) = 0;
virtual CompilerType* getattrType(BoxedString* attr, bool cls_only) = 0; virtual CompilerType* getattrType(BoxedString* attr, bool cls_only) = 0;
virtual CompilerType* getPystonIterType(); virtual CompilerType* getPystonIterType();
virtual Result hasattr(BoxedString* attr); virtual Result hasattr(BoxedString* attr);
...@@ -58,6 +58,13 @@ public: ...@@ -58,6 +58,13 @@ public:
virtual Box* deserializeFromFrame(const FrameVals& vals) = 0; virtual Box* deserializeFromFrame(const FrameVals& vals) = 0;
virtual int numFrameArgs() = 0; virtual int numFrameArgs() = 0;
virtual std::vector<CompilerType*> unpackTypes(int num_into); virtual std::vector<CompilerType*> unpackTypes(int num_into);
// Some types are not "usable" even if they are "concrete". Concrete means that it's possible to
// represent the value as an llvm::Value*; usable means that we are allowed to use it as a variable's
// type. Some concrete types are not usable; for example unboxed ints are concrete (can be represented
// as an i64) but are not usable, since we need to use the form that remembers what it gets boxed to.
virtual CompilerType* getUsableType() { return this; }
bool isUsable() { return this == getUsableType(); }
}; };
typedef std::unordered_map<CompilerVariable*, CompilerVariable*> DupCache; typedef std::unordered_map<CompilerVariable*, CompilerVariable*> DupCache;
...@@ -94,7 +101,7 @@ public: ...@@ -94,7 +101,7 @@ public:
printf("grab not defined for %s\n", debugName().c_str()); printf("grab not defined for %s\n", debugName().c_str());
abort(); abort();
} }
bool canConvertTo(ConcreteCompilerType* other_type) override { bool canConvertTo(CompilerType* other_type) override {
printf("canConvertTo not defined for %s\n", debugName().c_str()); printf("canConvertTo not defined for %s\n", debugName().c_str());
abort(); abort();
} }
...@@ -102,13 +109,12 @@ public: ...@@ -102,13 +109,12 @@ public:
printf("makeConverted not defined for %s\n", debugName().c_str()); printf("makeConverted not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, VAR* var) { virtual CompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("nonzero not defined for %s\n", debugName().c_str()); printf("nonzero not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, VAR* var, virtual CompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, VAR* var, AST_TYPE::AST_TYPE op_type);
AST_TYPE::AST_TYPE op_type); virtual CompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info, VAR* var) {
virtual ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("hasnext not defined for %s\n", debugName().c_str()); printf("hasnext not defined for %s\n", debugName().c_str());
abort(); abort();
} }
...@@ -139,7 +145,7 @@ public: ...@@ -139,7 +145,7 @@ public:
printf("call not defined for %s\n", debugName().c_str()); printf("call not defined for %s\n", debugName().c_str());
abort(); abort();
} }
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) { virtual CompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("len not defined for %s\n", debugName().c_str()); printf("len not defined for %s\n", debugName().c_str());
abort(); abort();
} }
...@@ -202,7 +208,7 @@ public: ...@@ -202,7 +208,7 @@ public:
CompilerVariable* dup(ConcreteCompilerVariable* v, DupCache& cache) override; CompilerVariable* dup(ConcreteCompilerVariable* v, DupCache& cache) override;
ConcreteCompilerType* getConcreteType() override { return this; } ConcreteCompilerType* getConcreteType() override { return this; }
bool canConvertTo(ConcreteCompilerType* other_type) override { return other_type == this || other_type == UNKNOWN; } bool canConvertTo(CompilerType* other_type) override { return other_type == this || other_type == UNKNOWN; }
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerVariable* var, ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerVariable* var,
ConcreteCompilerType* other_type) override; ConcreteCompilerType* other_type) override;
void serializeToFrame(VAR* var, std::vector<llvm::Value*>& stackmap_args) override; void serializeToFrame(VAR* var, std::vector<llvm::Value*>& stackmap_args) override;
...@@ -261,14 +267,14 @@ public: ...@@ -261,14 +267,14 @@ public:
virtual CompilerType* getType() = 0; virtual CompilerType* getType() = 0;
virtual ConcreteCompilerType* getConcreteType() = 0; virtual ConcreteCompilerType* getConcreteType() = 0;
virtual ConcreteCompilerType* getBoxType() = 0; virtual ConcreteCompilerType* getBoxType() = 0;
virtual bool canConvertTo(ConcreteCompilerType* other_type) = 0; virtual bool canConvertTo(CompilerType* other_type) = 0;
virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerType* other_type) = 0; virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerType* other_type) = 0;
virtual llvm::Value* makeClassCheck(IREmitter& emitter, BoxedClass* cls) = 0; virtual llvm::Value* makeClassCheck(IREmitter& emitter, BoxedClass* cls) = 0;
virtual BoxedClass* guaranteedClass() = 0; virtual BoxedClass* guaranteedClass() = 0;
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info) = 0; virtual CompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info) = 0;
virtual ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, AST_TYPE::AST_TYPE op_type) = 0; virtual CompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, AST_TYPE::AST_TYPE op_type) = 0;
virtual ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info) = 0; virtual CompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, BoxedString* attr, bool cls_only) = 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; virtual void setattr(IREmitter& emitter, const OpInfo& info, BoxedString* attr, CompilerVariable* v) = 0;
virtual void delattr(IREmitter& emitter, const OpInfo& info, BoxedString* attr) = 0; virtual void delattr(IREmitter& emitter, const OpInfo& info, BoxedString* attr) = 0;
...@@ -278,7 +284,7 @@ public: ...@@ -278,7 +284,7 @@ public:
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, struct ArgPassSpec argspec, virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args, const std::vector<CompilerVariable*>& args,
const std::vector<BoxedString*>* keyword_names) = 0; const std::vector<BoxedString*>* keyword_names) = 0;
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) = 0; virtual CompilerVariable* 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;
virtual CompilerVariable* getPystonIter(IREmitter& emitter, const OpInfo& info) = 0; virtual CompilerVariable* getPystonIter(IREmitter& emitter, const OpInfo& info) = 0;
virtual CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, CompilerVariable* rhs, virtual CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, CompilerVariable* rhs,
...@@ -330,19 +336,19 @@ public: ...@@ -330,19 +336,19 @@ public:
return rtn; return rtn;
} }
bool canConvertTo(ConcreteCompilerType* other_type) override { return type->canConvertTo(other_type); } bool canConvertTo(CompilerType* other_type) override { return type->canConvertTo(other_type); }
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerType* other_type) override { ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ConcreteCompilerType* other_type) override {
ConcreteCompilerVariable* rtn = type->makeConverted(emitter, this, other_type); ConcreteCompilerVariable* rtn = type->makeConverted(emitter, this, other_type);
ASSERT(rtn->getType() == other_type, "%s", type->debugName().c_str()); ASSERT(rtn->getType() == other_type, "%s", type->debugName().c_str());
return rtn; return rtn;
} }
ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info) override { CompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info) override {
return type->nonzero(emitter, info, this); return type->nonzero(emitter, info, this);
} }
ConcreteCompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, AST_TYPE::AST_TYPE op_type) override { CompilerVariable* unaryop(IREmitter& emitter, const OpInfo& info, AST_TYPE::AST_TYPE op_type) override {
return type->unaryop(emitter, info, this, op_type); return type->unaryop(emitter, info, this, op_type);
} }
ConcreteCompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info) override { CompilerVariable* hasnext(IREmitter& emitter, const OpInfo& info) override {
return type->hasnext(emitter, info, this); return type->hasnext(emitter, info, this);
} }
CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, BoxedString* attr, bool cls_only) override { CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, BoxedString* attr, bool cls_only) override {
...@@ -366,9 +372,7 @@ public: ...@@ -366,9 +372,7 @@ public:
const std::vector<BoxedString*>* keyword_names) override { const std::vector<BoxedString*>* keyword_names) override {
return type->call(emitter, info, this, argspec, args, keyword_names); return type->call(emitter, info, this, argspec, args, keyword_names);
} }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) override { CompilerVariable* len(IREmitter& emitter, const OpInfo& info) override { return type->len(emitter, info, this); }
return type->len(emitter, info, this);
}
CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable* slice) override { CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable* slice) override {
return type->getitem(emitter, info, this, slice); return type->getitem(emitter, info, this, slice);
} }
...@@ -407,9 +411,20 @@ public: ...@@ -407,9 +411,20 @@ public:
// Emit the test for whether one variable 'is' another one. // Emit the test for whether one variable 'is' another one.
ConcreteCompilerVariable* doIs(IREmitter& emitter, CompilerVariable* lhs, CompilerVariable* rhs, bool negate); ConcreteCompilerVariable* doIs(IREmitter& emitter, CompilerVariable* lhs, CompilerVariable* rhs, bool negate);
// These functions all return an INT variable, from either an unboxed representation (makeInt) or
// a boxed representation (makeUnboxedInt)
CompilerVariable* makeInt(int64_t);
CompilerVariable* makeInt(llvm::Value*);
CompilerVariable* makeUnboxedInt(IREmitter&, ConcreteCompilerVariable*);
CompilerVariable* makeUnboxedInt(IREmitter&, llvm::Value*);
// Same for floats:
CompilerVariable* makeFloat(llvm::Value*);
CompilerVariable* makeFloat(double);
CompilerVariable* makeUnboxedFloat(IREmitter&, ConcreteCompilerVariable*);
CompilerVariable* makeUnboxedFloat(IREmitter&, llvm::Value*);
ConcreteCompilerVariable* makeBool(bool); ConcreteCompilerVariable* makeBool(bool);
ConcreteCompilerVariable* makeInt(int64_t);
ConcreteCompilerVariable* makeFloat(double);
ConcreteCompilerVariable* makeLong(Box*); ConcreteCompilerVariable* makeLong(Box*);
ConcreteCompilerVariable* makePureImaginary(Box*); ConcreteCompilerVariable* makePureImaginary(Box*);
CompilerVariable* makeStr(BoxedString*); CompilerVariable* makeStr(BoxedString*);
...@@ -447,8 +462,8 @@ CompilerVariable* _ValuedCompilerType<V>::contains(IREmitter& emitter, const OpI ...@@ -447,8 +462,8 @@ CompilerVariable* _ValuedCompilerType<V>::contains(IREmitter& emitter, const OpI
} }
template <typename V> template <typename V>
ConcreteCompilerVariable* _ValuedCompilerType<V>::unaryop(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* _ValuedCompilerType<V>::unaryop(IREmitter& emitter, const OpInfo& info, VAR* var,
AST_TYPE::AST_TYPE op_type) { AST_TYPE::AST_TYPE op_type) {
ConcreteCompilerVariable* converted = makeConverted(emitter, var, getBoxType()); ConcreteCompilerVariable* converted = makeConverted(emitter, var, getBoxType());
auto r = UNKNOWN->unaryop(emitter, info, converted, op_type); auto r = UNKNOWN->unaryop(emitter, info, converted, op_type);
converted->decvref(emitter); converted->decvref(emitter);
......
...@@ -799,7 +799,7 @@ private: ...@@ -799,7 +799,7 @@ private:
assert(node->args.size() == 1); assert(node->args.size() == 1);
CompilerVariable* obj = evalExpr(node->args[0], unw_info); CompilerVariable* obj = evalExpr(node->args[0], unw_info);
ConcreteCompilerVariable* rtn = obj->nonzero(emitter, getOpInfoForNode(node, unw_info)); CompilerVariable* rtn = obj->nonzero(emitter, getOpInfoForNode(node, unw_info));
obj->decvref(emitter); obj->decvref(emitter);
return rtn; return rtn;
} }
...@@ -807,7 +807,7 @@ private: ...@@ -807,7 +807,7 @@ private:
assert(node->args.size() == 1); assert(node->args.size() == 1);
CompilerVariable* obj = evalExpr(node->args[0], unw_info); CompilerVariable* obj = evalExpr(node->args[0], unw_info);
ConcreteCompilerVariable* rtn = obj->hasnext(emitter, getOpInfoForNode(node, unw_info)); CompilerVariable* rtn = obj->hasnext(emitter, getOpInfoForNode(node, unw_info));
obj->decvref(emitter); obj->decvref(emitter);
return rtn; return rtn;
} }
...@@ -1348,18 +1348,18 @@ private: ...@@ -1348,18 +1348,18 @@ private:
CompilerVariable* operand = evalExpr(node->operand, unw_info); CompilerVariable* operand = evalExpr(node->operand, unw_info);
if (node->op_type == AST_TYPE::Not) { if (node->op_type == AST_TYPE::Not) {
ConcreteCompilerVariable* rtn = operand->nonzero(emitter, getOpInfoForNode(node, unw_info)); CompilerVariable* rtn = operand->nonzero(emitter, getOpInfoForNode(node, unw_info));
operand->decvref(emitter); operand->decvref(emitter);
assert(rtn->getType() == BOOL); assert(rtn->getType() == BOOL);
llvm::Value* v = i1FromBool(emitter, rtn); llvm::Value* v = i1FromBool(emitter, static_cast<ConcreteCompilerVariable*>(rtn));
assert(v->getType() == g.i1); assert(v->getType() == g.i1);
llvm::Value* negated = emitter.getBuilder()->CreateNot(v); llvm::Value* negated = emitter.getBuilder()->CreateNot(v);
rtn->decvref(emitter); rtn->decvref(emitter);
return boolFromI1(emitter, negated); return boolFromI1(emitter, negated);
} else { } else {
ConcreteCompilerVariable* rtn = operand->unaryop(emitter, getOpInfoForNode(node, unw_info), node->op_type); CompilerVariable* rtn = operand->unaryop(emitter, getOpInfoForNode(node, unw_info), node->op_type);
operand->decvref(emitter); operand->decvref(emitter);
return rtn; return rtn;
} }
...@@ -1517,19 +1517,13 @@ private: ...@@ -1517,19 +1517,13 @@ private:
} }
// Note: the behavior of this function must match type_analysis.cpp:unboxedType() // Note: the behavior of this function must match type_analysis.cpp:unboxedType()
ConcreteCompilerVariable* unboxVar(ConcreteCompilerType* t, llvm::Value* v, bool grabbed) { CompilerVariable* unboxVar(ConcreteCompilerType* t, llvm::Value* v, bool grabbed) {
#if ENABLE_UNBOXED_VALUES
if (t == BOXED_INT) { if (t == BOXED_INT) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxInt, v); return makeUnboxedInt(emitter, v);
ConcreteCompilerVariable* rtn = new ConcreteCompilerVariable(INT, unboxed, true);
return rtn;
} }
if (t == BOXED_FLOAT) { if (t == BOXED_FLOAT) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxFloat, v); return makeUnboxedFloat(emitter, v);
ConcreteCompilerVariable* rtn = new ConcreteCompilerVariable(FLOAT, unboxed, true);
return rtn;
} }
#endif
if (t == BOXED_BOOL) { if (t == BOXED_BOOL) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, v); llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, v);
return boolFromI1(emitter, unboxed); return boolFromI1(emitter, unboxed);
...@@ -1548,7 +1542,7 @@ private: ...@@ -1548,7 +1542,7 @@ private:
ConcreteCompilerType* speculated_type = typeFromClass(speculated_class); ConcreteCompilerType* speculated_type = typeFromClass(speculated_class);
if (VERBOSITY("irgen") >= 2) { if (VERBOSITY("irgen") >= 2) {
printf("Speculating that %s is actually %s, at ", rtn->getConcreteType()->debugName().c_str(), printf("Speculating that %s is actually %s, at ", rtn->getType()->debugName().c_str(),
speculated_type->debugName().c_str()); speculated_type->debugName().c_str());
fflush(stdout); fflush(stdout);
print_ast(node); print_ast(node);
...@@ -1580,6 +1574,7 @@ private: ...@@ -1580,6 +1574,7 @@ private:
} }
assert(rtn); assert(rtn);
assert(rtn->getType()->isUsable());
return rtn; return rtn;
} }
...@@ -1728,6 +1723,7 @@ private: ...@@ -1728,6 +1723,7 @@ private:
void _doSet(InternedString name, CompilerVariable* val, const UnwindInfo& unw_info) { void _doSet(InternedString name, CompilerVariable* val, const UnwindInfo& unw_info) {
assert(name.s() != "None"); assert(name.s() != "None");
assert(name.s() != FRAME_INFO_PTR_NAME); assert(name.s() != FRAME_INFO_PTR_NAME);
assert(val->getType()->isUsable());
auto scope_info = irstate->getScopeInfo(); auto scope_info = irstate->getScopeInfo();
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name); ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name);
...@@ -2210,11 +2206,9 @@ private: ...@@ -2210,11 +2206,9 @@ private:
ConcreteCompilerVariable* var = p.second->makeConverted(emitter, p.second->getConcreteType()); ConcreteCompilerVariable* var = p.second->makeConverted(emitter, p.second->getConcreteType());
converted_args.push_back(var); converted_args.push_back(var);
#if ENABLE_UNBOXED_VALUES assert(var->getType() != BOXED_INT);
assert(var->getType() != BOXED_INT && "should probably unbox it, but why is it boxed in the first place?");
assert(var->getType() != BOXED_FLOAT assert(var->getType() != BOXED_FLOAT
&& "should probably unbox it, but why is it boxed in the first place?"); && "should probably unbox it, but why is it boxed in the first place?");
#endif
// This line can never get hit right now for the same reason that the variables must already be // This line can never get hit right now for the same reason that the variables must already be
// concrete, // concrete,
...@@ -2438,13 +2432,13 @@ private: ...@@ -2438,13 +2432,13 @@ private:
void loadArgument(InternedString name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) { void loadArgument(InternedString name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) {
assert(name.s() != FRAME_INFO_PTR_NAME); assert(name.s() != FRAME_INFO_PTR_NAME);
ConcreteCompilerVariable* var = unboxVar(t, v, false); CompilerVariable* var = unboxVar(t, v, false);
_doSet(name, var, unw_info); _doSet(name, var, unw_info);
var->decvref(emitter); var->decvref(emitter);
} }
void loadArgument(AST_expr* name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) { void loadArgument(AST_expr* name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) {
ConcreteCompilerVariable* var = unboxVar(t, v, false); CompilerVariable* var = unboxVar(t, v, false);
_doSet(name, var, unw_info); _doSet(name, var, unw_info);
var->decvref(emitter); var->decvref(emitter);
} }
...@@ -2467,6 +2461,7 @@ private: ...@@ -2467,6 +2461,7 @@ private:
std::map<InternedString, CompilerVariable*> sorted_symbol_table(symbol_table.begin(), symbol_table.end()); std::map<InternedString, CompilerVariable*> sorted_symbol_table(symbol_table.begin(), symbol_table.end());
for (const auto& p : sorted_symbol_table) { for (const auto& p : sorted_symbol_table) {
assert(p.first.s() != FRAME_INFO_PTR_NAME); assert(p.first.s() != FRAME_INFO_PTR_NAME);
assert(p.second->getType()->isUsable());
if (allowableFakeEndingSymbol(p.first)) if (allowableFakeEndingSymbol(p.first))
continue; continue;
...@@ -2483,6 +2478,7 @@ private: ...@@ -2483,6 +2478,7 @@ private:
} else if (irstate->getPhis()->isRequiredAfter(p.first, myblock)) { } else if (irstate->getPhis()->isRequiredAfter(p.first, myblock)) {
assert(scope_info->getScopeTypeOfName(p.first) != ScopeInfo::VarScopeType::GLOBAL); assert(scope_info->getScopeTypeOfName(p.first) != ScopeInfo::VarScopeType::GLOBAL);
ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(p.first, myblock); ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(p.first, myblock);
assert(phi_type->isUsable());
// printf("Converting %s from %s to %s\n", p.first.c_str(), // printf("Converting %s from %s to %s\n", p.first.c_str(),
// p.second->getType()->debugName().c_str(), phi_type->debugName().c_str()); // p.second->getType()->debugName().c_str(), phi_type->debugName().c_str());
// printf("have to convert %s from %s to %s\n", p.first.c_str(), // printf("have to convert %s from %s to %s\n", p.first.c_str(),
...@@ -2533,6 +2529,7 @@ private: ...@@ -2533,6 +2529,7 @@ private:
} else { } else {
// printf("no st entry, setting undefined\n"); // printf("no st entry, setting undefined\n");
ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(*it, myblock); ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(*it, myblock);
assert(phi_type->isUsable());
cur = new ConcreteCompilerVariable(phi_type, llvm::UndefValue::get(phi_type->llvmType()), true); cur = new ConcreteCompilerVariable(phi_type, llvm::UndefValue::get(phi_type->llvmType()), true);
_setFake(defined_name, makeBool(0)); _setFake(defined_name, makeBool(0));
} }
...@@ -2553,7 +2550,7 @@ public: ...@@ -2553,7 +2550,7 @@ public:
pp->addFrameVar(PASSED_GLOBALS_NAME, UNKNOWN); pp->addFrameVar(PASSED_GLOBALS_NAME, UNKNOWN);
} }
assert(INT->llvmType() == g.i64); assert(UNBOXED_INT->llvmType() == g.i64);
if (ENABLE_JIT_OBJECT_CACHE) { if (ENABLE_JIT_OBJECT_CACHE) {
llvm::Value* v; llvm::Value* v;
if (current_stmt) if (current_stmt)
...@@ -2565,7 +2562,7 @@ public: ...@@ -2565,7 +2562,7 @@ public:
stackmap_args.push_back(getConstantInt((uint64_t)current_stmt, g.i64)); stackmap_args.push_back(getConstantInt((uint64_t)current_stmt, g.i64));
} }
pp->addFrameVar("!current_stmt", INT); pp->addFrameVar("!current_stmt", UNBOXED_INT);
if (ENABLE_FRAME_INTROSPECTION) { if (ENABLE_FRAME_INTROSPECTION) {
// TODO: don't need to use a sorted symbol table if we're explicitly recording the names! // TODO: don't need to use a sorted symbol table if we're explicitly recording the names!
...@@ -2600,6 +2597,10 @@ public: ...@@ -2600,6 +2597,10 @@ public:
// This should have been consumed: // This should have been consumed:
assert(incoming_exc_state.empty()); assert(incoming_exc_state.empty());
for (auto&& p : symbol_table) {
ASSERT(p.second->getType()->isUsable(), "%s", p.first.c_str());
}
if (myblock->successors.size() == 0) { if (myblock->successors.size() == 0) {
for (auto& p : *st) { for (auto& p : *st) {
p.second->decvref(emitter); p.second->decvref(emitter);
...@@ -2645,6 +2646,7 @@ public: ...@@ -2645,6 +2646,7 @@ public:
} else { } else {
ending_type = types->getTypeAtBlockEnd(it->first, myblock); ending_type = types->getTypeAtBlockEnd(it->first, myblock);
} }
assert(ending_type->isUsable());
//(*phi_st)[it->first] = it->second->makeConverted(emitter, it->second->getConcreteType()); //(*phi_st)[it->first] = it->second->makeConverted(emitter, it->second->getConcreteType());
// printf("%s %p %d\n", it->first.c_str(), it->second, it->second->getVrefs()); // printf("%s %p %d\n", it->first.c_str(), it->second, it->second->getVrefs());
(*phi_st)[it->first] = it->second->split(emitter)->makeConverted(emitter, ending_type); (*phi_st)[it->first] = it->second->split(emitter)->makeConverted(emitter, ending_type);
...@@ -2661,10 +2663,9 @@ public: ...@@ -2661,10 +2663,9 @@ public:
assert(name.s() != FRAME_INFO_PTR_NAME); assert(name.s() != FRAME_INFO_PTR_NAME);
ASSERT(irstate->getScopeInfo()->getScopeTypeOfName(name) != ScopeInfo::VarScopeType::GLOBAL, "%s", ASSERT(irstate->getScopeInfo()->getScopeTypeOfName(name) != ScopeInfo::VarScopeType::GLOBAL, "%s",
name.c_str()); name.c_str());
#if ENABLE_UNBOXED_VALUES
assert(var->getType() != BOXED_INT); ASSERT(var->getType()->isUsable(), "%s", name.c_str());
assert(var->getType() != BOXED_FLOAT);
#endif
CompilerVariable*& cur = symbol_table[name]; CompilerVariable*& cur = symbol_table[name];
assert(cur == NULL); assert(cur == NULL);
cur = var; cur = var;
...@@ -2675,7 +2676,9 @@ public: ...@@ -2675,7 +2676,9 @@ public:
DupCache cache; DupCache cache;
for (SymbolTable::iterator it = st->begin(); it != st->end(); ++it) { for (SymbolTable::iterator it = st->begin(); it != st->end(); ++it) {
// printf("Copying in %s: %p, %d\n", it->first.c_str(), it->second, it->second->getVrefs()); // printf("Copying in %s: %p, %d\n", it->first.c_str(), it->second, it->second->getVrefs());
// printf("Copying in %s, a %s\n", it->first.c_str(), it->second->getType()->debugName().c_str());
symbol_table[it->first] = it->second->dup(cache); symbol_table[it->first] = it->second->dup(cache);
assert(symbol_table[it->first]->getType()->isUsable());
// printf("got: %p, %d\n", symbol_table[it->first], symbol_table[it->first]->getVrefs()); // printf("got: %p, %d\n", symbol_table[it->first], symbol_table[it->first]->getVrefs());
} }
} }
......
...@@ -51,12 +51,6 @@ extern bool ENABLE_ICS, ENABLE_ICGENERICS, ENABLE_ICGETITEMS, ENABLE_ICSETITEMS, ...@@ -51,12 +51,6 @@ extern bool ENABLE_ICS, ENABLE_ICGENERICS, ENABLE_ICGETITEMS, ENABLE_ICSETITEMS,
extern bool BOOLS_AS_I64; extern bool BOOLS_AS_I64;
#define ENABLE_SAMPLING_PROFILER 0 #define ENABLE_SAMPLING_PROFILER 0
// Our current implementation of unbox values has some minor compatibility issues, where it can
// change the apparent id() / is-equality of a boxed value (by inserting extra unbox+box pairs).
// I think it can be rescued (we need the unboxed compilertype to remember the boxed value),
// but for now it's just turned off with this flag.
#define ENABLE_UNBOXED_VALUES 0
} }
} }
......
...@@ -93,10 +93,10 @@ template <class V> class ValuedCompilerType; ...@@ -93,10 +93,10 @@ template <class V> class ValuedCompilerType;
typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType; typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType;
ConcreteCompilerType* typeFromClass(BoxedClass*); ConcreteCompilerType* typeFromClass(BoxedClass*);
extern ConcreteCompilerType* INT, *BOXED_INT, *LONG, *FLOAT, *BOXED_FLOAT, *UNKNOWN, *BOOL, *STR, *NONE, *LIST, *SLICE,*ELLIPSIS, extern ConcreteCompilerType* UNBOXED_INT, *BOXED_INT, *LONG, *UNBOXED_FLOAT, *BOXED_FLOAT, *UNKNOWN, *BOOL, *STR, *NONE,
*MODULE, *DICT, *BOOL, *BOXED_BOOL, *BOXED_TUPLE, *SET, *FROZENSET, *CLOSURE, *GENERATOR, *BOXED_COMPLEX, *LIST, *SLICE, *MODULE, *DICT, *BOOL, *BOXED_BOOL, *BOXED_TUPLE, *SET, *FROZENSET, *CLOSURE, *GENERATOR,
*FRAME_INFO; *BOXED_COMPLEX, *FRAME_INFO;
extern CompilerType* UNDEF; extern CompilerType* UNDEF, *INT, *FLOAT;
class CompilerVariable; class CompilerVariable;
template <class V> class ValuedCompilerVariable; template <class V> class ValuedCompilerVariable;
......
...@@ -1524,12 +1524,16 @@ Box* builtinFormat(Box* value, Box* format_spec) { ...@@ -1524,12 +1524,16 @@ Box* builtinFormat(Box* value, Box* format_spec) {
return res; return res;
} }
extern "C" {
BoxedClass* ellipsis_cls;
}
void setupBuiltins() { void setupBuiltins() {
builtins_module = createModule(boxString("__builtin__"), NULL, builtins_module = createModule(boxString("__builtin__"), NULL,
"Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is " "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is "
"the `nil' object; Ellipsis represents `...' in slices."); "the `nil' object; Ellipsis represents `...' in slices.");
BoxedClass* ellipsis_cls = BoxedClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(Box), false, "ellipsis"); ellipsis_cls = BoxedClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(Box), false, "ellipsis");
ellipsis_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)ellipsisRepr, STR, 1))); ellipsis_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)ellipsisRepr, STR, 1)));
Ellipsis = new (ellipsis_cls) Box(); Ellipsis = new (ellipsis_cls) Box();
assert(Ellipsis->cls); assert(Ellipsis->cls);
......
...@@ -270,7 +270,7 @@ void setupXrange() { ...@@ -270,7 +270,7 @@ void setupXrange() {
"__iter__", new BoxedFunction(boxRTFunction((void*)xrangeIterIter, typeFromClass(xrange_iterator_cls), 1))); "__iter__", new BoxedFunction(boxRTFunction((void*)xrangeIterIter, typeFromClass(xrange_iterator_cls), 1)));
xrange_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); xrange_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
CLFunction* next = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorNextUnboxed, INT, 1); CLFunction* next = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorNextUnboxed, UNBOXED_INT, 1);
addRTFunction(next, (void*)BoxedXrangeIterator::xrangeIteratorNext, BOXED_INT); addRTFunction(next, (void*)BoxedXrangeIterator::xrangeIteratorNext, BOXED_INT);
xrange_iterator_cls->giveAttr("next", new BoxedFunction(next)); xrange_iterator_cls->giveAttr("next", new BoxedFunction(next));
......
...@@ -42,6 +42,14 @@ def f4(a, b): ...@@ -42,6 +42,14 @@ def f4(a, b):
for i in xrange(11000): for i in xrange(11000):
f4(1000, 1000) f4(1000, 1000)
def f6():
for i in xrange(11000):
a = b = 1000
if True:
pass
f4(a, b)
f6()
# This applies to other data types as well. (maybe should call this test file something else) # This applies to other data types as well. (maybe should call this test file something else)
def ident(x): def ident(x):
...@@ -49,7 +57,7 @@ def ident(x): ...@@ -49,7 +57,7 @@ def ident(x):
def f5(): def f5():
t = (1, 2, 3) t = (1, 2, 3)
print ident(t) is t assert ident(t) is t
for i in xrange(10): for i in xrange(10):
f5() f5()
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