1 # Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 # file at the top-level directory of this distribution and at
3 # http://rust-lang.org/COPYRIGHT.
5 # Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 # http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 # <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 # option. This file may not be copied, modified, or distributed
9 # except according to those terms.
11 from __future__
import division
, print_function
20 r
'^(?:(?P<void>V)|(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
21 r
'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
22 r
'|(?P<reference>\d+))(?P<index>\.\d+)?(?P<modifiers>[vShdnwusfDMC]*)(?P<force_width>x\d+)?'
23 r
'(?:(?P<pointer>Pm|Pc)(?P<llvm_pointer>/.*)?|(?P<bitcast>->.*))?$'
26 class PlatformInfo(object):
27 def __init__(self
, json
):
28 self
._platform
= json
['platform']
30 def platform_prefix(self
):
33 class IntrinsicSet(object):
34 def __init__(self
, platform
, json
):
35 self
._llvm
_prefix
= json
['llvm_prefix']
36 self
._type
_info
= json
['number_info']
37 self
._intrinsics
= json
['intrinsics']
38 self
._widths
= json
['width_info']
39 self
._platform
= platform
40 self
._intrinsic
_prefix
= json
['intrinsic_prefix']
43 for raw
in self
._intrinsics
:
44 yield GenericIntrinsic(self
,
45 raw
['intrinsic'], raw
['width'], raw
['llvm'],
46 raw
['ret'], raw
['args'])
51 def intrinsic_prefix(self
):
52 return self
._intrinsic
_prefix
54 def llvm_prefix(self
):
55 return self
._llvm
_prefix
57 def width_info(self
, bitwidth
):
58 return self
._widths
[str(bitwidth
)]
60 def number_type_info(self
, value
):
61 data
= self
._type
_info
[value
.__class
__.__name
__.lower()]
62 bitwidth
= value
.bitwidth()
64 if not isinstance(raw
, dict):
68 return raw
[str(bitwidth
)]
70 return raw
['pattern'].format(bitwidth
= bitwidth
)
72 return PlatformTypeInfo(value
.llvm_name(),
73 {k
: lookup(v
) for k
, v
in data
.items()})
75 class PlatformTypeInfo(object):
76 def __init__(self
, llvm_name
, properties
, elems
= None):
78 self
.properties
= properties
79 self
.llvm_name
= llvm_name
81 assert properties
is None and llvm_name
is None
86 return '<PlatformTypeInfo {}, {}>'.format(self
.llvm_name
, self
.properties
)
88 def __getattr__(self
, name
):
89 return self
.properties
[name
]
91 def __getitem__(self
, idx
):
92 return self
.elems
[idx
]
94 def vectorize(self
, length
, width_info
):
95 props
= self
.properties
.copy()
96 props
.update(width_info
)
97 return PlatformTypeInfo('v{}{}'.format(length
, self
.llvm_name
), props
)
99 def pointer(self
, llvm_elem
):
100 name
= self
.llvm_name
if llvm_elem
is None else llvm_elem
.llvm_name
101 return PlatformTypeInfo('p0{}'.format(name
), self
.properties
)
103 BITWIDTH_POINTER
= '<pointer>'
106 def __init__(self
, bitwidth
):
107 self
._bitwidth
= bitwidth
110 return self
._bitwidth
112 def modify(self
, spec
, width
, previous
):
113 raise NotImplementedError()
115 def __ne__(self
, other
):
116 return not (self
== other
)
120 Type
.__init
__(self
, 0)
126 def compiler_ctor_ref(self
):
127 return '&' + self
.compiler_ctor()
134 def type_info(platform_info
):
137 def __eq__(self
, other
):
138 return isinstance(other
, Void
)
141 def __init__(self
, bitwidth
):
142 Type
.__init
__(self
, bitwidth
)
144 def modify(self
, spec
, width
, previous
):
146 return Unsigned(self
.bitwidth())
148 return Signed(self
.bitwidth())
150 return Float(self
.bitwidth())
152 return self
.__class
__(self
.bitwidth() * 2)
154 return self
.__class
__(self
.bitwidth() // 2)
156 return Vector(self
, width
// self
.bitwidth())
158 raise ValueError('unknown modification spec {}', spec
)
160 def type_info(self
, platform_info
):
161 return platform_info
.number_type_info(self
)
163 def __eq__(self
, other
):
165 return self
.__class
__ == other
.__class
__ and self
.bitwidth() == other
.bitwidth()
167 class Signed(Number
):
168 def __init__(self
, bitwidth
, llvm_bitwidth
= None):
169 Number
.__init
__(self
, bitwidth
)
170 self
._llvm
_bitwidth
= llvm_bitwidth
173 def compiler_ctor(self
):
174 if self
._llvm
_bitwidth
is None:
175 return '::I{}'.format(self
.bitwidth())
177 return '::I{}_{}'.format(self
.bitwidth(), self
._llvm
_bitwidth
)
179 def compiler_ctor_ref(self
):
180 return '&' + self
.compiler_ctor()
183 bw
= self
._llvm
_bitwidth
or self
.bitwidth()
184 return 'i{}'.format(bw
)
187 return 'i{}'.format(self
.bitwidth())
189 class Unsigned(Number
):
190 def __init__(self
, bitwidth
, llvm_bitwidth
= None):
191 Number
.__init
__(self
, bitwidth
)
192 self
._llvm
_bitwidth
= llvm_bitwidth
194 def compiler_ctor(self
):
195 if self
._llvm
_bitwidth
is None:
196 return '::U{}'.format(self
.bitwidth())
198 return '::U{}_{}'.format(self
.bitwidth(), self
._llvm
_bitwidth
)
200 def compiler_ctor_ref(self
):
201 return '&' + self
.compiler_ctor()
204 bw
= self
._llvm
_bitwidth
or self
.bitwidth()
205 return 'i{}'.format(bw
)
208 return 'u{}'.format(self
.bitwidth())
211 def __init__(self
, bitwidth
):
212 assert bitwidth
in (32, 64)
213 Number
.__init
__(self
, bitwidth
)
215 def compiler_ctor(self
):
216 return '::F{}'.format(self
.bitwidth())
218 def compiler_ctor_ref(self
):
219 return '&' + self
.compiler_ctor()
222 return 'f{}'.format(self
.bitwidth())
225 return 'f{}'.format(self
.bitwidth())
228 def __init__(self
, elem
, length
, bitcast
= None):
229 assert isinstance(elem
, Type
) and not isinstance(elem
, Vector
)
231 elem
.bitwidth() * length
)
232 self
._length
= length
234 assert bitcast
is None or (isinstance(bitcast
, Vector
) and
235 bitcast
._bitcast
is None and
236 bitcast
._elem
.bitwidth() == elem
.bitwidth())
237 if bitcast
is not None and bitcast
._elem
!= elem
:
238 self
._bitcast
= bitcast
._elem
242 def modify(self
, spec
, width
, previous
):
246 return Vector(self
._elem
, self
._length
// 2)
248 return Vector(self
._elem
, self
._length
* 2)
249 elif spec
.startswith('x'):
250 new_bitwidth
= int(spec
[1:])
251 return Vector(self
._elem
, new_bitwidth
// self
._elem
.bitwidth())
252 elif spec
.startswith('->'):
253 bitcast_to
= TypeSpec(spec
[2:])
254 choices
= list(bitcast_to
.enumerate(width
, previous
))
255 assert len(choices
) == 1
256 bitcast_to
= choices
[0]
257 return Vector(self
._elem
, self
._length
, bitcast_to
)
259 return Vector(self
._elem
.modify(spec
, width
, previous
), self
._length
)
261 def compiler_ctor(self
):
262 if self
._bitcast
is None:
263 return '{}x{}'.format(self
._elem
.compiler_ctor(),
266 return '{}x{}_{}'.format(self
._elem
.compiler_ctor(),
268 self
._bitcast
.compiler_ctor()
271 def compiler_ctor_ref(self
):
272 return '&' + self
.compiler_ctor()
275 return '{}x{}'.format(self
._elem
.rust_name(), self
._length
)
277 def type_info(self
, platform_info
):
278 elem_info
= self
._elem
.type_info(platform_info
)
279 return elem_info
.vectorize(self
._length
,
280 platform_info
.width_info(self
.bitwidth()))
282 def __eq__(self
, other
):
283 return isinstance(other
, Vector
) and self
._length
== other
._length
and \
284 self
._elem
== other
._elem
and self
._bitcast
== other
._bitcast
287 def __init__(self
, elem
, llvm_elem
, const
):
289 self
._llvm
_elem
= llvm_elem
291 Type
.__init
__(self
, BITWIDTH_POINTER
)
293 def modify(self
, spec
, width
, previous
):
297 return Pointer(self
._elem
, self
._llvm
_elem
, False)
299 return Pointer(self
._elem
, self
._llvm
_elem
, True)
301 return Pointer(self
._elem
.modify(spec
, width
, previous
), self
._llvm
_elem
, self
._const
)
303 def compiler_ctor(self
):
304 if self
._llvm
_elem
is None:
307 llvm_elem
= 'Some({})'.format(self
._llvm
_elem
.compiler_ctor_ref())
308 return 'Type::Pointer({}, {}, {})'.format(self
._elem
.compiler_ctor_ref(),
310 'true' if self
._const
else 'false')
312 def compiler_ctor_ref(self
):
313 return "{{ static PTR: Type = {}; &PTR }}".format(self
.compiler_ctor())
317 return '*{} {}'.format('const' if self
._const
else 'mut',
318 self
._elem
.rust_name())
320 def type_info(self
, platform_info
):
321 if self
._llvm
_elem
is None:
324 llvm_elem
= self
._llvm
_elem
.type_info(platform_info
)
325 return self
._elem
.type_info(platform_info
).pointer(llvm_elem
)
327 def __eq__(self
, other
):
328 return isinstance(other
, Pointer
) and self
._const
== other
._const \
329 and self
._elem
== other
._elem
and self
._llvm
_elem
== other
._llvm
_elem
331 class Aggregate(Type
):
332 def __init__(self
, flatten
, elems
):
333 self
._flatten
= flatten
335 Type
.__init
__(self
, sum(elem
.bitwidth() for elem
in elems
))
338 return '<Aggregate {}>'.format(self
._elems
)
340 def modify(self
, spec
, width
, previous
):
341 if spec
.startswith('.'):
343 return self
._elems
[num
]
346 raise NotImplementedError()
348 def compiler_ctor(self
):
349 parts
= "{{ static PARTS: [&'static Type; {}] = [{}]; &PARTS }}"
350 elems
= ', '.join(elem
.compiler_ctor_ref() for elem
in self
._elems
)
351 parts
= parts
.format(len(self
._elems
), elems
)
352 return 'Type::Aggregate({}, {})'.format('true' if self
._flatten
else 'false',
355 def compiler_ctor_ref(self
):
356 return "{{ static AGG: Type = {}; &AGG }}".format(self
.compiler_ctor())
359 return '({})'.format(', '.join(elem
.rust_name() for elem
in self
._elems
))
361 def type_info(self
, platform_info
):
362 return PlatformTypeInfo(None, None, [elem
.type_info(platform_info
) for elem
in self
._elems
])
364 def __eq__(self
, other
):
365 return isinstance(other
, Aggregate
) and self
._flatten
== other
._flatten
and \
366 self
._elems
== other
._elems
369 TYPE_ID_LOOKUP
= {'i': [Signed
, Unsigned
],
374 def ptrify(match
, elem
, width
, previous
):
375 ptr
= match
.group('pointer')
379 llvm_ptr
= match
.group('llvm_pointer')
383 assert llvm_ptr
.startswith('/')
384 options
= list(TypeSpec(llvm_ptr
[1:]).enumerate(width
, previous
))
385 assert len(options
) == 1
386 llvm_elem
= options
[0]
387 assert ptr
in ('Pc', 'Pm')
388 return Pointer(elem
, llvm_elem
, ptr
== 'Pc')
390 class TypeSpec(object):
391 def __init__(self
, spec
):
392 if not isinstance(spec
, list):
397 def enumerate(self
, width
, previous
):
398 for spec
in self
.spec
:
399 match
= SPEC
.match(spec
)
400 if match
is not None:
401 id = match
.group('id')
402 reference
= match
.group('reference')
405 index
= match
.group('index')
406 if index
is not None:
407 modifiers
.append(index
)
408 modifiers
+= list(match
.group('modifiers') or '')
409 force
= match
.group('force_width')
410 if force
is not None:
411 modifiers
.append(force
)
412 bitcast
= match
.group('bitcast')
413 if bitcast
is not None:
414 modifiers
.append(bitcast
)
416 if match
.group('void') is not None:
420 is_vector
= id.islower()
421 type_ctors
= TYPE_ID_LOOKUP
[id.lower()]
423 start
= match
.group('start')
424 if start
is not None:
425 end
= match
.group('end')
428 start
= end
= match
.group('width')
429 llvm_width
= match
.group('llvm_width')
434 while bitwidth
<= end
:
435 for ctor
in type_ctors
:
436 if llvm_width
is not None:
438 llvm_width
= int(llvm_width
)
439 assert llvm_width
< bitwidth
440 scalar
= ctor(bitwidth
, llvm_width
)
442 scalar
= ctor(bitwidth
)
445 elem
= Vector(scalar
, width
// bitwidth
)
447 assert bitcast
is None
451 elem
= elem
.modify(x
, width
, previous
)
452 yield ptrify(match
, elem
, width
, previous
)
454 elif reference
is not None:
455 reference
= int(reference
)
456 assert reference
< len(previous
), \
457 'referring to argument {}, but only {} are known'.format(reference
,
459 ret
= previous
[reference
]
461 ret
= ret
.modify(x
, width
, previous
)
462 yield ptrify(match
, ret
, width
, previous
)
464 assert False, 'matched `{}`, but didn\'t understand it?'.format(spec
)
465 elif spec
.startswith('('):
466 if spec
.endswith(')'):
467 true_spec
= spec
[1:-1]
469 elif spec
.endswith(')f'):
470 true_spec
= spec
[1:-2]
473 assert False, 'found unclosed aggregate `{}`'.format(spec
)
475 for elems
in itertools
.product(*(TypeSpec(subspec
).enumerate(width
, previous
)
476 for subspec
in true_spec
.split(','))):
477 yield Aggregate(flatten
, elems
)
478 elif spec
.startswith('['):
479 if spec
.endswith(']'):
480 true_spec
= spec
[1:-1]
482 elif spec
.endswith(']f'):
483 true_spec
= spec
[1:-2]
486 assert False, 'found unclosed aggregate `{}`'.format(spec
)
487 elem_spec
, count
= true_spec
.split(';')
490 for elem
in TypeSpec(elem_spec
).enumerate(width
, previous
):
491 yield Aggregate(flatten
, [elem
] * count
)
493 assert False, 'Failed to parse `{}`'.format(spec
)
495 class GenericIntrinsic(object):
496 def __init__(self
, platform
, intrinsic
, widths
, llvm_name
, ret
, args
):
497 self
._platform
= platform
498 self
.intrinsic
= intrinsic
499 self
.widths
= map(int, widths
)
500 self
.llvm_name
= llvm_name
501 self
.ret
= TypeSpec(ret
)
502 self
.args
= list(map(TypeSpec
, args
))
504 def monomorphise(self
):
505 for width
in self
.widths
:
506 # must be a power of two
507 assert width
& (width
- 1) == 0
508 def recur(processed
, untouched
):
512 yield MonomorphicIntrinsic(self
._platform
, self
.intrinsic
, width
,
516 raw_arg
= untouched
[0]
518 for arg
in raw_arg
.enumerate(width
, processed
):
519 for intr
in recur(processed
+ [arg
], rest
):
522 for x
in recur([], [self
.ret
] + self
.args
):
525 class MonomorphicIntrinsic(object):
526 def __init__(self
, platform
, intrinsic
, width
, llvm_name
, ret
, args
):
527 self
._platform
= platform
528 self
._intrinsic
= intrinsic
529 self
._width
= '' if width
== 64 else 'q'
530 self
._llvm
_name
= llvm_name
532 self
._ret
= ret
.type_info(platform
)
533 self
._args
_raw
= args
534 self
._args
= [arg
.type_info(platform
) for arg
in args
]
537 if self
._llvm
_name
.startswith('!'):
538 return self
._llvm
_name
[1:].format(self
._ret
, *self
._args
)
540 return self
._platform
.llvm_prefix() + self
._llvm
_name
.format(self
._ret
, *self
._args
)
542 def intrinsic_suffix(self
):
543 return self
._intrinsic
.format(self
._ret
,
547 def platform_prefix(self
):
548 return self
._platform
.platform().platform_prefix()
550 def intrinsic_set_name(self
):
551 return self
._platform
.intrinsic_prefix()
553 def intrinsic_name(self
):
554 return self
._platform
.intrinsic_prefix() + self
.intrinsic_suffix()
556 def compiler_args(self
):
557 return ', '.join(arg
.compiler_ctor_ref() for arg
in self
._args
_raw
)
559 def compiler_ret(self
):
560 return self
._ret
_raw
.compiler_ctor_ref()
562 def compiler_signature(self
):
563 return '({}) -> {}'.format(self
.compiler_args(), self
.compiler_ret())
565 def intrinsic_signature(self
):
567 return '({}) -> {}'.format(', '.join('{}: {}'.format(name
, arg
.rust_name())
568 for name
, arg
in zip(names
, self
._args
_raw
)),
569 self
._ret
_raw
.rust_name())
572 parser
= argparse
.ArgumentParser(
573 formatter_class
= argparse
.RawDescriptionHelpFormatter
,
574 description
= 'Render an intrinsic definition JSON to various formats.',
575 epilog
= textwrap
.dedent('''\
578 There are two operating modes: single file and multiple files.
580 For example, ARM is specified as a single file. To generate the
581 compiler-definitions for ARM just pass the script the "arm.json" file:
583 python generator.py --format compiler-defs arm.json
585 The X86 architecture is specified as multiple files (for the different
586 instruction sets that x86 supports). To generate the compiler
587 definitions one needs to pass the script a "platform information file"
588 (with the -i flag) next to the files of the different intruction sets.
589 For example, to generate the X86 compiler-definitions for SSE4.2, just:
591 python generator.py --format compiler-defs -i x86/info.json sse42.json
593 And to generate the compiler-definitions for SSE4.1 and SSE4.2, just:
595 python generator.py --format compiler-defs -i x86/info.json sse41.json sse42.json
597 An intrinsic definition consists of a map with fields:
598 - intrinsic: pattern for the name(s) of the vendor's C intrinsic(s)
599 - llvm: pattern for the name(s) of the internal llvm intrinsic(s)
600 - width: a vector of vector bit-widths the pattern works with
601 - ret: type specifier for the return value
602 - arguments: vector of type specifiers for arguments
604 The width and types describe a range of possible intrinsics,
605 and these are fed back into the intrinsic and llvm patterns to
606 create the appropriate definitions.
608 ## Type specifier grammar
611 type := core_type modifier* suffix?
613 core_type := void | vector | scalar | aggregate | reference
615 modifier := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' |
616 'x' number | '.' number
617 suffix := pointer | bitcast
618 pointer := 'Pm' llvm_pointer? | 'Pc' llvm_pointer?
619 llvm_pointer := '/' type
624 vector := vector_elem width |
625 vector_elem := 'i' | 'u' | 's' | 'f'
627 scalar := scalar_type number llvm_width?
628 scalar_type := 'U' | 'S' | 'F'
629 llvm_width := '/' number
631 aggregate := '(' (type),* ')' 'f'? | '[' type ';' number ']' 'f'?
635 width = number | '(' number '-' number ')'
642 The `V` type corresponds to `void` in LLVM (`()` in
643 Rust). It's likely to only work in return position.
647 The vector grammar is a pattern describing many possibilities
648 for arguments/return value. The `vector_elem` describes the
649 types of elements to use, and the `width` describes the (range
650 of) widths for those elements, which are then placed into a
651 vector with the `width` bitwidth. E.g. if an intrinsic has a
652 `width` that includes 128, and the return value is `i(8-32)`,
653 then some instantiation of that intrinsic will be `u8x16`,
654 `u32x4`, `i32x4`, etc.
658 - i: integer, both signed and unsigned
659 - u: unsigned integer
665 Similar to vectors, but these describe a single concrete type,
666 not a range. The number is the bitwidth. The optional
667 `llvm_width` is the bitwidth of the integer that should be
668 passed to LLVM (by truncating the Rust argument): this only
669 works with scalar integers and the LLVM width must be smaller
674 - U: unsigned integer
680 An aggregate is a collection of multiple types; a tuple in
681 Rust terms, or an unnamed struct in LLVM. The `f` modifiers
682 forces the tuple to be flattened in the LLVM
683 intrinsic. E.g. if `llvm.foo` takes `(F32,S32)`:
685 - no `f` corresponds to `declare ... @llvm.foo({float, i32})`.
686 - having an `f` corresponds to `declare ... @llvm.foo(float, i32)`.
688 The `[type;number]` form is a just shorter way to write
689 `(...)`, except avoids doing a cartesian product of generic
690 types, e.g. `[S32;2]` is the same as `(S32, S32)`, while
691 `[I32;2]` is describing just the two types `(S32,S32)` and
692 `(U32,U32)` (i.e. doesn't include `(S32,U32)`, `(U32,S32)` as
695 (Currently aggregates can not contain other aggregates.)
699 A reference uses the type of another argument, with possible
700 modifications. The number refers to the type to use, starting
701 with 0 == return value, 1 == first argument, 2 == second
706 The `modifier` and `suffix` adaptors change the precise
711 - 'v': put a scalar into a vector of the current width (u32 -> u32x4, when width == 128)
712 - 'S': get the scalar element of a vector (u32x4 -> u32)
713 - 'h': half the length of the vector (u32x4 -> u32x2)
714 - 'd': double the length of the vector (u32x2 -> u32x4)
715 - 'n': narrow the element of the vector (u32x4 -> u16x4)
716 - 'w': widen the element of the vector (u16x4 -> u32x4)
717 - 'u': force a number (vector or scalar) to be unsigned int (f32x4 -> u32x4)
718 - 's': force a number (vector or scalar) to be signed int (u32x4 -> i32x4)
719 - 'f': force a number (vector or scalar) to be float (u32x4 -> f32x4)
720 - 'x' number: force the type to be a vector of bitwidth `number`.
721 - '.' number: get the `number`th element of an aggregate
722 - 'D': dereference a pointer (*mut u32 -> u32)
723 - 'C': make a pointer const (*mut u32 -> *const u32)
724 - 'M': make a pointer mut (*const u32 -> *mut u32)
728 Pointers can be created of any type by appending a `P*`
729 suffix. The `m` vs. `c` chooses mut vs. const. e.g. `S32Pm`
730 corresponds to `*mut i32`, and `i32Pc` corresponds (with width
731 128) to `*const i8x16`, `*const u32x4`, etc.
733 The type after the `/` (optional) represents the type used
734 internally to LLVM, e.g. `S32pm/S8` is exposed as `*mut i32`
735 in Rust, but is `i8*` in LLVM. (This defaults to the main
740 The `'->' type` bitcast suffix will cause the value to be
741 bitcast to the right-hand type when calling the intrinsic,
742 e.g. `s32->f32` will expose the intrinsic as `i32x4` at the
743 Rust level, but will cast that vector to `f32x4` when calling
746 parser
.add_argument('--format', choices
=FORMATS
, required
=True,
747 help = 'Output format.')
748 parser
.add_argument('-o', '--out', type=argparse
.FileType('w'), default
=sys
.stdout
,
749 help = 'File to output to (default stdout).')
750 parser
.add_argument('-i', '--info', type=argparse
.FileType('r'),
751 help = 'File containing platform specific information to merge into '
752 'the input files\' header.')
753 parser
.add_argument('in_', metavar
="FILE", type=argparse
.FileType('r'), nargs
='+',
754 help = 'JSON files to load')
755 return parser
.parse_args()
758 class ExternBlock(object):
764 return 'extern "platform-intrinsic" {'
768 return ' fn {}{}{};'.format(mono
.platform_prefix(),
769 mono
.intrinsic_name(),
770 mono
.intrinsic_signature())
776 class CompilerDefs(object):
783 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
784 // file at the top-level directory of this distribution and at
785 // http://rust-lang.org/COPYRIGHT.
787 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
788 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
789 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
790 // option. This file may not be copied, modified, or distributed
791 // except according to those terms.
793 // DO NOT EDIT: autogenerated by etc/platform-intrinsics/generator.py
794 // ignore-tidy-linelength
796 #![allow(unused_imports)]
798 use {{Intrinsic, Type}};
799 use IntrinsicDef::Named;
801 // The default inlining settings trigger a pathological behaviour in
802 // LLVM, which causes makes compilation very slow. See #28273.
804 pub fn find(name: &str) -> Option<Intrinsic> {{
805 if !name.starts_with("{0}") {{ return None }}
806 Some(match &name["{0}".len()..] {{'''.format(platform
.platform_prefix())
812 inputs: {{ static INPUTS: [&'static Type; {}] = [{}]; &INPUTS }},
814 definition: Named("{}")
815 }},'''.format(mono
.intrinsic_set_name() + mono
.intrinsic_suffix(),
817 mono
.compiler_args(),
829 'extern-block': ExternBlock(),
830 'compiler-defs': CompilerDefs(),
838 out_format
= FORMATS
[args
.format
]
840 one_file_no_info
= False
841 if len(ins
) > 1 and info
is None:
842 print('error: cannot have multiple inputs without an info header.', file=sys
.stderr
)
847 one_file_no_info
= True
848 info_json
= json
.load(info
)
849 platform
= PlatformInfo(info_json
)
851 print(out_format
.open(platform
), file=out
)
858 data
= json
.load(in_
)
859 data
.update(info_json
)
861 intrinsics
= IntrinsicSet(platform
, data
)
862 for intr
in intrinsics
.intrinsics():
863 for mono
in intr
.monomorphise():
864 print(out_format
.render(mono
), file=out
)
866 print(out_format
.close(), file=out
)
868 if __name__
== '__main__':