Commit f074ed04 authored by Kevin Modzelewski's avatar Kevin Modzelewski Committed by Kevin Modzelewski

Add the ability to represent bools as non-i1

Turned off for now; will need this for a later patch.
parent c6d65967
......@@ -356,8 +356,7 @@ public:
if (op_type == AST_TYPE::In || op_type == AST_TYPE::NotIn || op_type == AST_TYPE::Is
|| op_type == AST_TYPE::IsNot) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, rtn);
ConcreteCompilerVariable* rtn = new ConcreteCompilerVariable(BOOL, unboxed, true);
return rtn;
return boolFromI1(emitter, unboxed);
}
return new ConcreteCompilerVariable(UNKNOWN, rtn, true);
......@@ -593,7 +592,7 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
} else {
rtn_val = emitter.createCall(info.exc_info, g.funcs.nonzero, var->getValue()).getInstruction();
}
return new ConcreteCompilerVariable(BOOL, rtn_val, true);
return boolFromI1(emitter, rtn_val);
}
CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariable* closure, bool isGenerator,
......@@ -824,7 +823,7 @@ public:
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
llvm::Value* cmp = emitter.getBuilder()->CreateICmpNE(var->getValue(), llvm::ConstantInt::get(g.i64, 0, false));
return new ConcreteCompilerVariable(BOOL, cmp, true);
return boolFromI1(emitter, cmp);
}
CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs,
......@@ -913,8 +912,11 @@ public:
v = emitter.getBuilder()->CreateICmp(cmp_pred, var->getValue(), converted_right->getValue());
}
converted_right->decvref(emitter);
assert(v->getType() == g.i64 || v->getType() == g.i1);
return new ConcreteCompilerVariable(v->getType() == g.i64 ? INT : BOOL, v, true);
if (v->getType() == g.i64) {
return new ConcreteCompilerVariable(INT, v, true);
} else {
return boolFromI1(emitter, v);
}
}
virtual ConcreteCompilerType* getBoxType() { return BOXED_INT; }
......@@ -1019,7 +1021,7 @@ public:
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
llvm::Value* cmp = emitter.getBuilder()->CreateFCmpUNE(var->getValue(), llvm::ConstantFP::get(g.double_, 0));
return new ConcreteCompilerVariable(BOOL, cmp, true);
return boolFromI1(emitter, cmp);
}
CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs,
......@@ -1117,8 +1119,11 @@ public:
converted_right->decvref(emitter);
if (succeeded) {
assert(v->getType() == g.double_ || v->getType() == g.i1);
return new ConcreteCompilerVariable(v->getType() == g.double_ ? FLOAT : BOOL, v, true);
if (v->getType() == g.double_) {
return new ConcreteCompilerVariable(FLOAT, v, true);
} else {
return boolFromI1(emitter, v);
}
}
// TODO duplication with top of function, other functions, etc
......@@ -1390,7 +1395,7 @@ public:
// TODO is it more efficient to unbox here, or should we leave it boxed?
if (cf->spec->rtn_type == BOXED_BOOL) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, rtn->getValue());
return new ConcreteCompilerVariable(BOOL, unboxed, true);
return boolFromI1(emitter, unboxed);
}
if (cf->spec->rtn_type == BOXED_INT) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxInt, rtn->getValue());
......@@ -1480,7 +1485,7 @@ public:
assert(0 && "should have been caught by above case");
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, var->getValue());
assert(unboxed->getType() == g.i1);
return new ConcreteCompilerVariable(BOOL, unboxed, true);
return boolFromI1(emitter, unboxed);
}
return UNKNOWN->nonzero(emitter, info, var);
......@@ -1637,9 +1642,18 @@ ConcreteCompilerType* typeFromClass(BoxedClass* c) {
return NormalObjectType::fromClass(c);
}
// Due to a temporary LLVM limitation, can represent bools as i64's instead of i1's.
// #define BOOLS_AS_I64
class BoolType : public ConcreteCompilerType {
public:
llvm::Type* llvmType() { return g.i1; }
std::string debugName() { return "bool"; }
llvm::Type* llvmType() {
#ifdef BOOLS_AS_I64
return g.i64;
#else
return g.i1;
#endif
}
virtual bool isFitBy(BoxedClass* c) { return false; }
......@@ -1667,7 +1681,7 @@ public:
}
ASSERT(other_type == UNKNOWN || other_type == BOXED_BOOL, "%s", other_type->debugName().c_str());
llvm::Value* boxed = emitter.getBuilder()->CreateCall(g.funcs.boxBool, var->getValue());
llvm::Value* boxed = emitter.getBuilder()->CreateCall(g.funcs.boxBool, i1FromBool(emitter, var));
return new ConcreteCompilerVariable(other_type, boxed, true);
}
......@@ -1705,7 +1719,7 @@ public:
};
ConcreteCompilerType* BOOL = new BoolType();
ConcreteCompilerVariable* makeBool(bool b) {
return new ConcreteCompilerVariable(BOOL, llvm::ConstantInt::get(g.i1, b, false), true);
return new ConcreteCompilerVariable(BOOL, llvm::ConstantInt::get(BOOL->llvmType(), b, false), true);
}
ConcreteCompilerType* BOXED_TUPLE;
......@@ -1922,7 +1936,7 @@ public:
}
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, VAR* var) {
return new ConcreteCompilerVariable(BOOL, llvm::UndefValue::get(g.i1), true);
return new ConcreteCompilerVariable(BOOL, llvm::UndefValue::get(BOOL->llvmType()), true);
}
CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs,
......@@ -1946,6 +1960,28 @@ ConcreteCompilerVariable* undefVariable() {
return new ConcreteCompilerVariable(&_UNDEF, llvm::UndefValue::get(_UNDEF.llvmType()), true);
}
ConcreteCompilerVariable* boolFromI1(IREmitter& emitter, llvm::Value* v) {
#ifdef BOOLS_AS_I64
assert(v->getType() == g.i1);
assert(BOOL->llvmType() == g.i64);
llvm::Value* v2 = emitter.getBuilder()->CreateZExt(v, BOOL->llvmType());
return new ConcreteCompilerVariable(BOOL, v2, true);
#else
return new ConcreteCompilerVariable(BOOL, v, true);
#endif
}
llvm::Value* i1FromBool(IREmitter& emitter, ConcreteCompilerVariable* v) {
#ifdef BOOLS_AS_I64
assert(v->getType() == BOOL);
assert(BOOL->llvmType() == g.i64);
llvm::Value* v2 = emitter.getBuilder()->CreateTrunc(v->getValue(), g.i1);
return v2;
#else
return v->getValue();
#endif
}
ConcreteCompilerType* LIST, *SLICE, *MODULE, *DICT, *SET, *FROZENSET, *LONG, *BOXED_COMPLEX;
......
......@@ -366,6 +366,9 @@ CompilerType* typeOfClassobj(BoxedClass*);
CompilerType* makeTupleType(const std::vector<CompilerType*>& elt_types);
CompilerType* makeFuncType(ConcreteCompilerType* rtn_type, const std::vector<ConcreteCompilerType*>& arg_types);
ConcreteCompilerVariable* boolFromI1(IREmitter&, llvm::Value*);
llvm::Value* i1FromBool(IREmitter&, ConcreteCompilerVariable*);
} // namespace pyston
#endif
......@@ -367,7 +367,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
if (p.second == INT) {
ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, g.i64->getPointerTo());
} else if (p.second == BOOL) {
ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, g.i1->getPointerTo());
ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, BOOL->llvmType()->getPointerTo());
} else if (p.second == FLOAT) {
ptr = entry_emitter->getBuilder()->CreateBitCast(ptr, g.double_->getPointerTo());
} else {
......@@ -633,8 +633,8 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
if (source->phis->isPotentiallyUndefinedAfter(s, block->predecessors[0])) {
std::string is_defined_name = "!is_defined_" + s;
llvm::PHINode* phi
= emitter->getBuilder()->CreatePHI(g.i1, block->predecessors.size(), is_defined_name);
llvm::PHINode* phi = emitter->getBuilder()->CreatePHI(BOOL->llvmType(), block->predecessors.size(),
is_defined_name);
ConcreteCompilerVariable* var = new ConcreteCompilerVariable(BOOL, phi, true);
generator->giveLocalSymbol(is_defined_name, var);
......
......@@ -314,7 +314,7 @@ private:
converted_flags->getValue() }).getInstruction();
assert(v->getType() == g.i1);
return new ConcreteCompilerVariable(BOOL, v, true);
return boolFromI1(emitter, v);
}
case AST_LangPrimitive::LANDINGPAD: {
// llvm::Function* _personality_func = g.stdlib_module->getFunction("__py_personality_v0");
......@@ -374,7 +374,7 @@ private:
= llvm::BasicBlock::Create(g.context, "was_defined", irstate->getLLVMFunction());
llvm::BasicBlock* join
= llvm::BasicBlock::Create(g.context, "join", irstate->getLLVMFunction());
emitter.getBuilder()->CreateCondBr(is_defined_var->getValue(), was_defined, join);
emitter.getBuilder()->CreateCondBr(i1FromBool(emitter, is_defined_var), was_defined, join);
emitter.getBuilder()->SetInsertPoint(was_defined);
ConcreteCompilerVariable* converted = p.second->makeConverted(emitter, p.second->getBoxType());
......@@ -777,7 +777,7 @@ private:
= llvm::BasicBlock::Create(g.context, "from_global", irstate->getLLVMFunction());
llvm::BasicBlock* join = llvm::BasicBlock::Create(g.context, "join", irstate->getLLVMFunction());
emitter.getBuilder()->CreateCondBr(is_defined_var->getValue(), from_local, from_global);
emitter.getBuilder()->CreateCondBr(i1FromBool(emitter, is_defined_var), from_local, from_global);
emitter.getBuilder()->SetInsertPoint(from_local);
curblock = from_local;
......@@ -801,7 +801,7 @@ private:
}
emitter.createCall(exc_info, g.funcs.assertNameDefined,
{ is_defined_var->getValue(), getStringConstantPtr(node->id + '\0'),
{ i1FromBool(emitter, is_defined_var), getStringConstantPtr(node->id + '\0'),
embedConstantPtr(UnboundLocalError, g.llvm_class_type_ptr),
getConstantInt(true, g.i1) });
......@@ -941,12 +941,13 @@ private:
ConcreteCompilerVariable* rtn = operand->nonzero(emitter, getOpInfoForNode(node, exc_info));
operand->decvref(emitter);
llvm::Value* v = rtn->getValue();
ASSERT(v->getType() == g.i1, "%s %s", operand->getType()->debugName().c_str(),
rtn->getType()->debugName().c_str());
assert(rtn->getType() == BOOL);
llvm::Value* v = i1FromBool(emitter, rtn);
assert(v->getType() == g.i1);
llvm::Value* negated = emitter.getBuilder()->CreateNot(v);
rtn->decvref(emitter);
return new ConcreteCompilerVariable(BOOL, negated, true);
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());
......@@ -994,8 +995,7 @@ private:
}
if (t == BOXED_BOOL) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, v);
ConcreteCompilerVariable* rtn = new ConcreteCompilerVariable(BOOL, unboxed, true);
return rtn;
return boolFromI1(emitter, unboxed);
}
return new ConcreteCompilerVariable(t, v, grabbed);
}
......@@ -1560,7 +1560,7 @@ private:
if (is_defined_var) {
emitter.createCall(exc_info, g.funcs.assertNameDefined,
{ is_defined_var->getValue(), getStringConstantPtr(target->id + '\0'),
{ i1FromBool(emitter, is_defined_var), getStringConstantPtr(target->id + '\0'),
embedConstantPtr(NameError, g.llvm_class_type_ptr),
getConstantInt(local_error_msg, g.i1) });
_popFake(defined_name);
......@@ -1790,7 +1790,7 @@ private:
nonzero->getType()->debugName().c_str());
val->decvref(emitter);
llvm::Value* llvm_nonzero = nonzero->getValue();
llvm::Value* llvm_nonzero = i1FromBool(emitter, nonzero);
llvm::BasicBlock* iftrue = entry_blocks[node->iftrue];
llvm::BasicBlock* iffalse = entry_blocks[node->iffalse];
......@@ -2172,7 +2172,7 @@ private:
if (is_defined) {
_setFake(defined_name, is_defined);
} else {
_setFake(defined_name, new ConcreteCompilerVariable(BOOL, getConstantInt(1, g.i1), true));
_setFake(defined_name, makeBool(1));
}
} else {
// printf("is defined in all later paths, so not marking\n");
......@@ -2182,7 +2182,7 @@ private:
// printf("no st entry, setting undefined\n");
ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(*it, myblock);
cur = new ConcreteCompilerVariable(phi_type, llvm::UndefValue::get(phi_type->llvmType()), true);
_setFake(defined_name, new ConcreteCompilerVariable(BOOL, getConstantInt(0, g.i1), true));
_setFake(defined_name, makeBool(0));
}
}
......
......@@ -550,6 +550,17 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generato
}
continue;
//} else if (llvm::CallInst* ci = llvm::dyn_cast<llvm::CallInst>(inst)) {
} else if (llvm::TruncInst* tr = llvm::dyn_cast<llvm::TruncInst>(inst)) {
Val r = fetch(tr->getOperand(0), dl, symbols);
assert(tr->getType() == g.i1);
SET(r.n & 0x1);
continue;
} else if (llvm::ZExtInst* se = llvm::dyn_cast<llvm::ZExtInst>(inst)) {
Val r = fetch(se->getOperand(0), dl, symbols);
assert(se->getOperand(0)->getType() == g.i1);
assert(se->getType() == g.i64);
SET((int64_t)(uint64_t)(uint8_t)r.n);
continue;
} else if (llvm::isa<llvm::CallInst>(inst) || llvm::isa<llvm::InvokeInst>(inst)) {
llvm::CallSite cs(inst);
llvm::InvokeInst* invoke = llvm::dyn_cast<llvm::InvokeInst>(inst);
......
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