Skip to content

Commit add0430

Browse files
committed
Support non-return value references in platform intrinsic generator.
1 parent d12135a commit add0430

File tree

1 file changed

+79
-74
lines changed

1 file changed

+79
-74
lines changed

src/etc/platform-intrinsics/generator.py

Lines changed: 79 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import sys
1515
import re
1616
import textwrap
17+
import itertools
1718

1819
SPEC = re.compile(
1920
r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
@@ -258,7 +259,7 @@ def type_info(self, platform_info):
258259
'u': [Unsigned],
259260
'f': [Float]}
260261

261-
def ptrify(match, elem, width):
262+
def ptrify(match, elem, width, previous):
262263
ptr = match.group('pointer')
263264
if ptr is None:
264265
return elem
@@ -268,7 +269,7 @@ def ptrify(match, elem, width):
268269
llvm_elem = None
269270
else:
270271
assert llvm_ptr.startswith('/')
271-
options = list(TypeSpec(llvm_ptr[1:]).enumerate(width))
272+
options = list(TypeSpec(llvm_ptr[1:]).enumerate(width, previous))
272273
assert len(options) == 1
273274
llvm_elem = options[0]
274275
assert ptr in ('Pc', 'Pm')
@@ -281,77 +282,70 @@ def __init__(self, spec):
281282

282283
self.spec = spec
283284

284-
def enumerate(self, width):
285+
def enumerate(self, width, previous):
285286
for spec in self.spec:
286287
match = SPEC.match(spec)
287-
assert match is not None
288-
if True:
288+
if match is not None:
289289
id = match.group('id')
290-
assert id is not None
291-
is_vector = id.islower()
292-
type_ctors = TYPE_ID_LOOKUP[id.lower()]
293-
294-
start = match.group('start')
295-
if start is not None:
296-
end = match.group('end')
297-
llvm_width = None
290+
reference = match.group('reference')
291+
292+
if id is not None:
293+
is_vector = id.islower()
294+
type_ctors = TYPE_ID_LOOKUP[id.lower()]
295+
296+
start = match.group('start')
297+
if start is not None:
298+
end = match.group('end')
299+
llvm_width = None
300+
else:
301+
start = end = match.group('width')
302+
llvm_width = match.group('llvm_width')
303+
start = int(start)
304+
end = int(end)
305+
306+
bitwidth = start
307+
while bitwidth <= end:
308+
for ctor in type_ctors:
309+
if llvm_width is not None:
310+
assert not is_vector
311+
llvm_width = int(llvm_width)
312+
assert llvm_width < bitwidth
313+
scalar = ctor(bitwidth, llvm_width)
314+
else:
315+
scalar = ctor(bitwidth)
316+
317+
if is_vector:
318+
elem = Vector(scalar, width // bitwidth)
319+
else:
320+
elem = scalar
321+
yield ptrify(match, elem, width, previous)
322+
bitwidth *= 2
323+
elif reference is not None:
324+
reference = int(reference)
325+
assert reference < len(previous), \
326+
'referring to argument {}, but only {} are known'.format(reference,
327+
len(previous))
328+
ret = previous[reference]
329+
for x in match.group('modifiers') or []:
330+
ret = ret.modify(x, width)
331+
force = match.group('force_width')
332+
if force is not None:
333+
ret = ret.modify(force, width)
334+
yield ptrify(match, ret, width, previous)
298335
else:
299-
start = end = match.group('width')
300-
llvm_width = match.group('llvm_width')
301-
start = int(start)
302-
end = int(end)
303-
304-
bitwidth = start
305-
while bitwidth <= end:
306-
for ctor in type_ctors:
307-
if llvm_width is not None:
308-
assert not is_vector
309-
llvm_width = int(llvm_width)
310-
assert llvm_width < bitwidth
311-
scalar = ctor(bitwidth, llvm_width)
312-
else:
313-
scalar = ctor(bitwidth)
314-
315-
if is_vector:
316-
elem = Vector(scalar, width // bitwidth)
317-
else:
318-
elem = scalar
319-
yield ptrify(match, elem, width)
320-
bitwidth *= 2
336+
assert False, 'matched `{}`, but didn\'t understand it?'.format(spec)
337+
elif spec.startswith('('):
338+
if spec.endswith(')'):
339+
raise NotImplementedError()
340+
elif spec.endswith(')f'):
341+
true_spec = spec[1:-2]
342+
flatten = True
343+
344+
for elems in itertools.product(*(TypeSpec(subspec).enumerate(width, previous)
345+
for subspec in true_spec.split(','))):
346+
yield Aggregate(flatten, elems)
321347
else:
322-
pass
323-
#print('Failed to parse: `{}`'.format(spec), file=sys.stderr)
324-
325-
def resolve(self, width, zero):
326-
assert len(self.spec) == 1
327-
spec = self.spec[0]
328-
match = SPEC.match(spec)
329-
if match:
330-
id = match.group('id')
331-
if id is not None:
332-
options = list(self.enumerate(width))
333-
assert len(options) == 1
334-
return options[0]
335-
reference = match.group('reference')
336-
if reference != '0':
337-
raise NotImplementedError('only argument 0 (return value) references are supported')
338-
ret = zero
339-
for x in match.group('modifiers') or []:
340-
ret = ret.modify(x, width)
341-
force = match.group('force_width')
342-
if force is not None:
343-
ret = ret.modify(force, width)
344-
return ptrify(match, ret, width)
345-
elif spec.startswith('('):
346-
if spec.endswith(')'):
347-
raise NotImplementedError()
348-
elif spec.endswith(')f'):
349-
true_spec = spec[1:-2]
350-
flatten = True
351-
elems = [TypeSpec(subspec).resolve(width, zero) for subspec in true_spec.split(',')]
352-
return Aggregate(flatten, elems)
353-
else:
354-
assert False, 'Failed to resolve: {}'.format(spec)
348+
assert False, 'Failed to parse `{}`'.format(spec)
355349

356350
class GenericIntrinsic(object):
357351
def __init__(self, platform, intrinsic, widths, llvm_name, ret, args):
@@ -366,10 +360,22 @@ def monomorphise(self):
366360
for width in self.widths:
367361
# must be a power of two
368362
assert width & (width - 1) == 0
369-
for ret in self.ret.enumerate(width):
370-
args = [arg.resolve(width, ret) for arg in self.args]
371-
yield MonomorphicIntrinsic(self._platform, self.intrinsic, width, self.llvm_name,
372-
ret, args)
363+
def recur(processed, untouched):
364+
if untouched == []:
365+
ret = processed[0]
366+
args = processed[1:]
367+
yield MonomorphicIntrinsic(self._platform, self.intrinsic, width,
368+
self.llvm_name,
369+
ret, args)
370+
else:
371+
raw_arg = untouched[0]
372+
rest = untouched[1:]
373+
for arg in raw_arg.enumerate(width, processed):
374+
for intr in recur(processed + [arg], rest):
375+
yield intr
376+
377+
for x in recur([], [self.ret] + self.args):
378+
yield x
373379

374380
class MonomorphicIntrinsic(object):
375381
def __init__(self, platform, intrinsic, width, llvm_name, ret, args):
@@ -517,8 +523,7 @@ def parse_args():
517523
A reference uses the type of another argument, with possible
518524
modifications. The number refers to the type to use, starting
519525
with 0 == return value, 1 == first argument, 2 == second
520-
argument, etc. (Currently only referencing 0, the return
521-
value, is supported.)
526+
argument, etc.
522527
523528
### Modifiers
524529

0 commit comments

Comments
 (0)