py2llvm/base_types: fix corner cases with bool/int/float conversion

This commit is contained in:
Sebastien Bourdeauducq 2014-09-17 16:23:02 +08:00
parent 2e45d7267d
commit 80f4bc7741
1 changed files with 27 additions and 15 deletions

View File

@ -65,7 +65,11 @@ class VInt(VGeneric):
def o_float(self, builder): def o_float(self, builder):
r = VFloat() r = VFloat()
if builder is not None: if builder is not None:
r.auto_store(builder, builder.sitofp(self.auto_load(builder), if isinstance(self, VBool):
cf = builder.uitofp
else:
cf = builder.sitofp
r.auto_store(builder, cf(self.auto_load(builder),
r.get_llvm_type())) r.get_llvm_type()))
return r return r
@ -92,8 +96,12 @@ class VInt(VGeneric):
builder, builder.trunc(self.auto_load(builder), builder, builder.trunc(self.auto_load(builder),
r.get_llvm_type())) r.get_llvm_type()))
if self.nbits < target_bits: if self.nbits < target_bits:
if isinstance(self, VBool):
ef = builder.zext
else:
ef = builder.sext
r.auto_store( r.auto_store(
builder, builder.sext(self.auto_load(builder), builder, ef(self.auto_load(builder),
r.get_llvm_type())) r.get_llvm_type()))
return r return r
o_roundx = o_intx o_roundx = o_intx
@ -106,11 +114,15 @@ class VInt(VGeneric):
else: else:
return NotImplemented return NotImplemented
def _make_vint_binop_method(builder_name, bool_op):
def _make_vint_binop_method(builder_name):
def binop_method(self, other, builder): def binop_method(self, other, builder):
if isinstance(other, VInt): if isinstance(other, VInt):
target_bits = max(self.nbits, other.nbits) target_bits = max(self.nbits, other.nbits)
if not bool_op and target_bits == 1:
target_bits = 32
if bool_op and target_bits == 1:
r = VBool()
else:
r = VInt(target_bits) r = VInt(target_bits)
if builder is not None: if builder is not None:
left = self.o_intx(target_bits, builder) left = self.o_intx(target_bits, builder)
@ -124,15 +136,15 @@ def _make_vint_binop_method(builder_name):
return NotImplemented return NotImplemented
return binop_method return binop_method
for _method_name, _builder_name in (("o_add", "add"), for _method_name, _builder_name, _bool_op in (("o_add", "add", False),
("o_sub", "sub"), ("o_sub", "sub", False),
("o_mul", "mul"), ("o_mul", "mul", False),
("o_floordiv", "sdiv"), ("o_floordiv", "sdiv", False),
("o_mod", "srem"), ("o_mod", "srem", False),
("o_and", "and_"), ("o_and", "and_", True),
("o_xor", "xor"), ("o_xor", "xor", True),
("o_or", "or_")): ("o_or", "or_", True)):
setattr(VInt, _method_name, _make_vint_binop_method(_builder_name)) setattr(VInt, _method_name, _make_vint_binop_method(_builder_name, _bool_op))
def _make_vint_cmp_method(icmp_val): def _make_vint_cmp_method(icmp_val):