Skip to content

Commit bea3f09

Browse files
committed
Add support for arbitrary metadata for numbers and widths.
This means that each platform has total control over the formatting info it needs.
1 parent 083f613 commit bea3f09

File tree

3 files changed

+79
-58
lines changed

3 files changed

+79
-58
lines changed

src/etc/platform-intrinsics/aarch64.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
"data_type": { "pattern": "f{bitwidth}" }
1717
}
1818
},
19-
"widths": {
20-
"64": "",
21-
"128": "q"
19+
"width_info": {
20+
"64": { "width": "" },
21+
"128": { "width": "q" }
2222
},
2323
"intrinsics": [
2424
{

src/etc/platform-intrinsics/arm.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
"data_type": { "pattern": "f{bitwidth}" }
1717
}
1818
},
19-
"widths": {
20-
"64": "",
21-
"128": "q"
19+
"width_info": {
20+
"64": { "width": "" },
21+
"128": { "width": "q" }
2222
},
2323
"intrinsics": [
2424
{

src/etc/platform-intrinsics/generator.py

Lines changed: 73 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,59 @@
2020
r'|(?P<reference>\d+)(?P<modifiers>[vShdnwus]*)(?P<force_width>x\d+)?)$'
2121
)
2222

23-
class IntrinsicSet(object):
23+
class PlatformInfo(object):
2424
def __init__(self, json):
2525
self._platform = json['platform']
2626
self._intrinsic_prefix = json['intrinsic_prefix']
27+
def intrinsic_prefix(self):
28+
return self._intrinsic_prefix
29+
30+
31+
class IntrinsicSet(object):
32+
def __init__(self, platform, json):
2733
self._llvm_prefix = json['llvm_prefix']
28-
self._intrinsics = json['intrinsics']
2934
self._type_info = json['number_info']
30-
self._widths = json['widths']
35+
self._intrinsics = json['intrinsics']
36+
self._widths = json['width_info']
37+
self._platform = platform
3138

3239
def intrinsics(self):
3340
for raw in self._intrinsics:
3441
yield GenericIntrinsic(self,
3542
raw['intrinsic'], raw['width'], raw['llvm'],
3643
raw['ret'], raw['args'])
44+
def platform(self):
45+
return self._platform
3746
def llvm_prefix(self):
3847
return self._llvm_prefix
39-
def intrinsic_prefix(self):
40-
return self._intrinsic_prefix
41-
42-
def width_name(self, bitwidth):
48+
def width_info(self, bitwidth):
4349
return self._widths[str(bitwidth)]
4450

4551
def number_type_info(self, value):
4652
data = self._type_info[value.__class__.__name__.lower()]
4753
bitwidth = value.bitwidth()
48-
raw_dtype = data['data_type']
49-
try:
50-
dtype = raw_dtype[str(bitwidth)]
51-
except KeyError:
52-
dtype = raw_dtype['pattern'].format(bitwidth = bitwidth)
53-
return PlatformTypeInfo(data['kind'],
54-
dtype,
55-
value.llvm_name())
54+
def lookup(raw):
55+
if not isinstance(raw, dict):
56+
return raw
57+
58+
try:
59+
return raw[str(bitwidth)]
60+
except KeyError:
61+
return raw['pattern'].format(bitwidth = bitwidth)
62+
63+
return PlatformTypeInfo(value.llvm_name(),
64+
{k: lookup(v) for k, v in data.items()})
5665

5766
class PlatformTypeInfo(object):
58-
def __init__(self, kind, data_type, llvm_name, width = None):
59-
self.kind = kind
60-
self.data_type = data_type
67+
def __init__(self, llvm_name, properties):
68+
self.properties = properties
6169
self.llvm_name = llvm_name
62-
if width is not None:
63-
self.width = width
64-
def vectorize(self, length, width):
65-
return PlatformTypeInfo(self.kind, self.data_type,
66-
'v{}{}'.format(length, self.llvm_name),
67-
width)
70+
def __getattr__(self, name):
71+
return self.properties[name]
72+
def vectorize(self, length, width_info):
73+
props = self.properties.copy()
74+
props.update(width_info)
75+
return PlatformTypeInfo('v{}{}'.format(length, self.llvm_name), props)
6876

6977
class Type(object):
7078
def __init__(self, bitwidth):
@@ -79,7 +87,11 @@ class Number(Type):
7987
def __init__(self, bitwidth):
8088
Type.__init__(self, bitwidth)
8189
def modify(self, spec, width):
82-
if spec == 'w':
90+
if spec == 'u':
91+
return Unsigned(self.bitwidth())
92+
elif spec == 's':
93+
return Signed(self.bitwidth())
94+
elif spec == 'w':
8395
return self.__class__(self.bitwidth() * 2)
8496
elif spec == 'n':
8597
return self.__class__(self.bitwidth() // 2)
@@ -94,13 +106,6 @@ def type_info(self, platform_info):
94106
class Signed(Number):
95107
def __init__(self, bitwidth):
96108
Number.__init__(self, bitwidth)
97-
def modify(self, spec, width):
98-
if spec == 'u':
99-
return Unsigned(self.bitwidth())
100-
elif spec == 's':
101-
return Signed(self.bitwidth())
102-
else:
103-
return Number.modify(self, spec, width)
104109
def compiler_ctor(self):
105110
return 'i({})'.format(self.bitwidth())
106111
def llvm_name(self):
@@ -111,13 +116,6 @@ def rust_name(self):
111116
class Unsigned(Number):
112117
def __init__(self, bitwidth):
113118
Number.__init__(self, bitwidth)
114-
def modify(self, spec, width):
115-
if spec == 'u':
116-
return Unsigned(self.bitwidth())
117-
elif spec == 's':
118-
return Signed(self.bitwidth())
119-
else:
120-
return Number.modify(self, spec, width)
121119
def compiler_ctor(self):
122120
return 'u({})'.format(self.bitwidth())
123121
def llvm_name(self):
@@ -159,7 +157,7 @@ def rust_name(self):
159157
def type_info(self, platform_info):
160158
elem_info = self._elem.type_info(platform_info)
161159
return elem_info.vectorize(self._length,
162-
platform_info.width_name(self.bitwidth()))
160+
platform_info.width_info(self.bitwidth()))
163161

164162
class Aggregate(Type):
165163
def __init__(self, flatten, elems):
@@ -216,7 +214,7 @@ def enumerate(self, width):
216214
yield scalar
217215
bitwidth *= 2
218216
else:
219-
print('Failed to parse: {}'.format(spec), file=sys.stderr)
217+
print('Failed to parse: `{}`'.format(spec), file=sys.stderr)
220218
def resolve(self, width, zero):
221219
assert len(self.spec) == 1
222220
spec = self.spec[0]
@@ -257,7 +255,8 @@ def __init__(self, platform, intrinsic, widths, llvm_name, ret, args):
257255

258256
def monomorphise(self):
259257
for width in self.widths:
260-
assert width in (64, 128)
258+
# must be a power of two
259+
assert width & (width - 1) == 0
261260
for ret in self.ret.enumerate(width):
262261
args = [arg.resolve(width, ret) for arg in self.args]
263262
yield MonomorphicIntrinsic(self._platform, self.intrinsic, width, self.llvm_name,
@@ -283,7 +282,7 @@ def intrinsic_suffix(self):
283282
*self._args,
284283
width = self._width)
285284
def intrinsic_name(self):
286-
return self._platform.intrinsic_prefix() + self.intrinsic_suffix()
285+
return self._platform.platform().intrinsic_prefix() + self.intrinsic_suffix()
287286
def compiler_args(self):
288287
return ', '.join(arg.compiler_ctor() for arg in self._args_raw)
289288
def compiler_ret(self):
@@ -294,7 +293,7 @@ def intrinsic_signature(self):
294293
names = 'xyzwabcdef'
295294
return '({}) -> {}'.format(', '.join('{}: {}'.format(name, arg.rust_name())
296295
for name, arg in zip(names, self._args_raw)),
297-
self._ret.rust_name())
296+
self._ret_raw.rust_name())
298297

299298
def parse_args():
300299
parser = argparse.ArgumentParser(
@@ -400,8 +399,11 @@ def parse_args():
400399
help = 'Output format.')
401400
parser.add_argument('-o', '--out', type=argparse.FileType('w'), default=sys.stdout,
402401
help = 'File to output to (default stdout).')
403-
parser.add_argument('in_', metavar="FILE", type=argparse.FileType('r'),
404-
help = 'JSON file to load')
402+
parser.add_argument('-i', '--info', type=argparse.FileType('r'),
403+
help = 'File containing platform specific information to merge into'
404+
'the input files\' header.')
405+
parser.add_argument('in_', metavar="FILE", type=argparse.FileType('r'), nargs='+',
406+
help = 'JSON files to load')
405407
return parser.parse_args()
406408

407409

@@ -466,16 +468,35 @@ def close(self):
466468

467469
def main():
468470
args = parse_args()
469-
in_ = args.in_
471+
ins = args.in_
470472
out = args.out
471473
out_format = FORMATS[args.format]
474+
info = args.info
475+
one_file_no_info = False
476+
if len(ins) > 1 and info is None:
477+
print('error: cannot have multiple inputs without an info header.', file=sys.stderr)
478+
sys.exit(1)
472479

473-
intrinsics = IntrinsicSet(json.load(in_))
480+
elif info is None:
481+
info = ins[0]
482+
one_file_no_info = True
483+
info_json = json.load(info)
484+
platform = PlatformInfo(info_json)
485+
486+
print(out_format.open(platform), file=out)
487+
488+
for in_ in ins:
489+
490+
if one_file_no_info:
491+
data = info_json
492+
else:
493+
data = json.load(in_)
494+
data.update(info_json)
474495

475-
print(out_format.open(intrinsics), file=out)
476-
for intr in intrinsics.intrinsics():
477-
for mono in intr.monomorphise():
478-
print(out_format.render(mono), file=out)
496+
intrinsics = IntrinsicSet(platform, data)
497+
for intr in intrinsics.intrinsics():
498+
for mono in intr.monomorphise():
499+
print(out_format.render(mono), file=out)
479500
print(out_format.close(), file=out)
480501

481502
if __name__ == '__main__':

0 commit comments

Comments
 (0)