Skip to content
This repository was archived by the owner on Jan 12, 2025. It is now read-only.

Commit ae50446

Browse files
committed
value_to_ir_value new optional argument type_
1 parent 58d3126 commit ae50446

File tree

3 files changed

+60
-65
lines changed

3 files changed

+60
-65
lines changed

py2llvm/py2llvm.py

+13-44
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
class Range:
1919

20-
def __init__(self, *args):
20+
def __init__(self, builder, *args):
2121
start = step = None
2222

2323
# Unpack
@@ -37,9 +37,9 @@ def __init__(self, *args):
3737
step = ir.Constant(type_, 1)
3838

3939
# Keep IR values
40-
self.start = types.value_to_ir_value(start)
41-
self.stop = types.value_to_ir_value(stop)
42-
self.step = types.value_to_ir_value(step)
40+
self.start = types.value_to_ir_value(builder, start)
41+
self.stop = types.value_to_ir_value(builder, stop)
42+
self.step = types.value_to_ir_value(builder, step)
4343

4444

4545
def values_to_type(left, right):
@@ -504,39 +504,7 @@ def convert(self, value, type_):
504504
"""
505505
Return the value converted to the given type.
506506
"""
507-
# If Python value, return a constant
508-
if not isinstance(value, ir.Value):
509-
return ir.Constant(type_, value)
510-
511-
if value.type is type_:
512-
return value
513-
514-
conversions = {
515-
# Integer to float
516-
(ir.IntType, ir.FloatType): self.builder.sitofp,
517-
(ir.IntType, ir.DoubleType): self.builder.sitofp,
518-
# Float to integer
519-
(ir.FloatType, ir.IntType): self.builder.fptosi,
520-
(ir.DoubleType, ir.IntType): self.builder.fptosi,
521-
# Float to float
522-
(ir.FloatType, ir.DoubleType): self.builder.fpext,
523-
(ir.DoubleType, ir.FloatType): self.builder.fptrunc,
524-
}
525-
526-
if isinstance(value.type, ir.IntType) and isinstance(type_, ir.IntType):
527-
# Integer to integer
528-
if value.type.width < type_.width:
529-
conversion = self.builder.zext
530-
else:
531-
conversion = self.builder.trunc
532-
else:
533-
# To or from float
534-
conversion = conversions.get((type(value.type), type(type_)))
535-
if conversion is None:
536-
err = f'Conversion from {value.type} to {type_} not supported'
537-
raise NotImplementedError(err)
538-
539-
return conversion(value, type_)
507+
return types.value_to_ir_value(self.builder, value, type_)
540508

541509
#
542510
# Leaf nodes
@@ -925,7 +893,8 @@ def Assign_exit(self, node, parent, targets, value, *args):
925893
if len(targets) > 1:
926894
raise NotImplementedError(f'unpacking not supported')
927895

928-
value = types.value_to_ir_value(value, visitor=self)
896+
builder = self.builder
897+
value = types.value_to_ir_value(builder, value)
929898

930899
target = targets[0]
931900
if type(target) is str:
@@ -934,16 +903,16 @@ def Assign_exit(self, node, parent, targets, value, *args):
934903
try:
935904
ptr = self.lookup(name)
936905
except AttributeError:
937-
block_cur = self.builder.block
938-
self.builder.position_at_end(self.block_vars)
939-
ptr = self.builder.alloca(value.type, name=name)
940-
self.builder.position_at_end(block_cur)
906+
block_cur = builder.block
907+
builder.position_at_end(self.block_vars)
908+
ptr = builder.alloca(value.type, name=name)
909+
builder.position_at_end(block_cur)
941910
self.locals[name] = ptr
942911
else:
943912
# x[i] =
944913
ptr = target
945914

946-
return self.builder.store(value, ptr)
915+
return builder.store(value, ptr)
947916

948917
def AugAssign_exit(self, node, parent, target, op, value):
949918
"""
@@ -975,7 +944,7 @@ def Call_exit(self, node, parent, func, args, keywords):
975944
"""
976945
assert not keywords
977946
if func is range:
978-
return Range(*args)
947+
return Range(self.builder, *args)
979948

980949
func = self.root.compiled.get(func, func)
981950
return self.builder.call(func, args)

py2llvm/types.py

+44-19
Original file line numberDiff line numberDiff line change
@@ -80,25 +80,48 @@ def value_to_ir_type(value):
8080
return type_to_ir_type(type_)
8181

8282

83-
def value_to_ir_value(value, visitor=None):
83+
def value_to_ir_value(builder, value, type_=None):
8484
"""
85-
Return a IR value for the given value, where value may be:
86-
- an IR value, then we're done, return it
87-
- a special object that knows to return a IR value (duck typing)
88-
- a regular Python value, then return a IR constant
85+
Return a IR value for the given value, where value may be either a Python
86+
or an IR value. If type_ is given the value will be converted to the given
87+
type (if necessary).
8988
"""
90-
if isinstance(value, ir.Value):
89+
if type_ is None:
90+
type_ = value_to_ir_type(value)
91+
92+
# If Python value, return a constant
93+
if not isinstance(value, ir.Value):
94+
return ir.Constant(type_, value)
95+
96+
if value.type is type_:
9197
return value
9298

93-
# Special object
94-
to_ir_value = getattr(value, 'to_ir_value', None)
95-
if to_ir_value is not None:
96-
assert visitor is not None
97-
return to_ir_value(visitor)
99+
conversions = {
100+
# Integer to float
101+
(ir.IntType, ir.FloatType): builder.sitofp,
102+
(ir.IntType, ir.DoubleType): builder.sitofp,
103+
# Float to integer
104+
(ir.FloatType, ir.IntType): builder.fptosi,
105+
(ir.DoubleType, ir.IntType): builder.fptosi,
106+
# Float to float
107+
(ir.FloatType, ir.DoubleType): builder.fpext,
108+
(ir.DoubleType, ir.FloatType): builder.fptrunc,
109+
}
110+
111+
if isinstance(value.type, ir.IntType) and isinstance(type_, ir.IntType):
112+
# Integer to integer
113+
if value.type.width < type_.width:
114+
conversion = builder.zext
115+
else:
116+
conversion = builder.trunc
117+
else:
118+
# To or from float
119+
conversion = conversions.get((type(value.type), type(type_)))
120+
if conversion is None:
121+
err = f'Conversion from {value.type} to {type_} not supported'
122+
raise NotImplementedError(err)
98123

99-
# Regular Python object
100-
ir_type = value_to_ir_type(value)
101-
return ir.Constant(ir_type, value)
124+
return conversion(value, type_)
102125

103126

104127
#
@@ -143,6 +166,8 @@ def get_ptr(self, visitor):
143166
return visitor.builder.load(self.ptr)
144167

145168
def subscript(self, visitor, slice, ctx):
169+
builder = visitor.builder
170+
146171
# To make it simpler, make the slice to be a list always
147172
if type(slice) is not list:
148173
slice = [slice]
@@ -152,7 +177,7 @@ def subscript(self, visitor, slice, ctx):
152177

153178
assert ptr.type.is_pointer
154179
if isinstance(ptr.type.pointee, ir.ArrayType):
155-
ptr = visitor.builder.gep(ptr, [zero])
180+
ptr = builder.gep(ptr, [zero])
156181

157182
# Support for multidimensional arrays.
158183
# Let's we have 3 dimensions (d0, d1, d2), each with a length (dl0,
@@ -163,17 +188,17 @@ def subscript(self, visitor, slice, ctx):
163188
dim = 1
164189
while slice:
165190
idx = slice.pop(0)
166-
idx = value_to_ir_value(idx)
191+
idx = value_to_ir_value(builder, idx)
167192
for i in range(dim, self.ndim):
168193
dim_len = self.shape.get(visitor, dim)
169-
idx = visitor.builder.mul(idx, dim_len)
194+
idx = builder.mul(idx, dim_len)
170195

171-
ptr = visitor.builder.gep(ptr, [idx])
196+
ptr = builder.gep(ptr, [idx])
172197
dim += 1
173198

174199
# Return the value
175200
if ctx is ast.Load:
176-
return visitor.builder.load(ptr)
201+
return builder.load(ptr)
177202
elif ctx is ast.Store:
178203
return ptr
179204

try_ia.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ def __init__(self, ptr, typs):
7272
self.typs = typs
7373

7474
def subscript(self, visitor, slice, ctx):
75+
builder = visitor.builder
7576
typ = self.typs[slice]
76-
idx = types.value_to_ir_value(slice)
77-
ptr = visitor.builder.gep(self.ptr, [types.zero, idx])
77+
idx = types.value_to_ir_value(builder, slice)
78+
ptr = builder.gep(self.ptr, [types.zero, idx])
7879
return params_type_input(ptr, typ)
7980

8081
class params_type_out:

0 commit comments

Comments
 (0)