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)
122 def compiler_ctor(self
):
125 def compiler_ctor_ref(self
):
126 return '&' + self
.compiler_ctor()
131 def type_info(self
, platform_info
):
134 def __eq__(self
, other
):
135 return isinstance(other
, Void
)
138 def __init__(self
, bitwidth
):
139 Type
.__init
__(self
, bitwidth
)
141 def modify(self
, spec
, width
, previous
):
143 return Unsigned(self
.bitwidth())
145 return Signed(self
.bitwidth())
147 return Float(self
.bitwidth())
149 return self
.__class
__(self
.bitwidth() * 2)
151 return self
.__class
__(self
.bitwidth() // 2)
153 return Vector(self
, width
// self
.bitwidth())
155 raise ValueError('unknown modification spec {}', spec
)
157 def type_info(self
, platform_info
):
158 return platform_info
.number_type_info(self
)
160 def __eq__(self
, other
):
162 return self
.__class
__ == other
.__class
__ and self
.bitwidth() == other
.bitwidth()
164 class Signed(Number
):
165 def __init__(self
, bitwidth
, llvm_bitwidth
= None):
166 Number
.__init
__(self
, bitwidth
)
167 self
._llvm
_bitwidth
= llvm_bitwidth
170 def compiler_ctor(self
):
171 if self
._llvm
_bitwidth
is None:
172 return '::I{}'.format(self
.bitwidth())
174 return '::I{}_{}'.format(self
.bitwidth(), self
._llvm
_bitwidth
)
176 def compiler_ctor_ref(self
):
177 return '&' + self
.compiler_ctor()
180 bw
= self
._llvm
_bitwidth
or self
.bitwidth()
181 return 'i{}'.format(bw
)
184 return 'i{}'.format(self
.bitwidth())
186 class Unsigned(Number
):
187 def __init__(self
, bitwidth
, llvm_bitwidth
= None):
188 Number
.__init
__(self
, bitwidth
)
189 self
._llvm
_bitwidth
= llvm_bitwidth
191 def compiler_ctor(self
):
192 if self
._llvm
_bitwidth
is None:
193 return '::U{}'.format(self
.bitwidth())
195 return '::U{}_{}'.format(self
.bitwidth(), self
._llvm
_bitwidth
)
197 def compiler_ctor_ref(self
):
198 return '&' + self
.compiler_ctor()
201 bw
= self
._llvm
_bitwidth
or self
.bitwidth()
202 return 'i{}'.format(bw
)
205 return 'u{}'.format(self
.bitwidth())
208 def __init__(self
, bitwidth
):
209 assert bitwidth
in (32, 64)
210 Number
.__init
__(self
, bitwidth
)
212 def compiler_ctor(self
):
213 return '::F{}'.format(self
.bitwidth())
215 def compiler_ctor_ref(self
):
216 return '&' + self
.compiler_ctor()
219 return 'f{}'.format(self
.bitwidth())
222 return 'f{}'.format(self
.bitwidth())
225 def __init__(self
, elem
, length
, bitcast
= None):
226 assert isinstance(elem
, Type
) and not isinstance(elem
, Vector
)
228 elem
.bitwidth() * length
)
229 self
._length
= length
231 assert bitcast
is None or (isinstance(bitcast
, Vector
) and
232 bitcast
._bitcast
is None and
233 bitcast
._elem
.bitwidth() == elem
.bitwidth())
234 if bitcast
is not None and bitcast
._elem
!= elem
:
235 self
._bitcast
= bitcast
._elem
239 def modify(self
, spec
, width
, previous
):
243 return Vector(self
._elem
, self
._length
// 2)
245 return Vector(self
._elem
, self
._length
* 2)
246 elif spec
.startswith('x'):
247 new_bitwidth
= int(spec
[1:])
248 return Vector(self
._elem
, new_bitwidth
// self
._elem
.bitwidth())
249 elif spec
.startswith('->'):
250 bitcast_to
= TypeSpec(spec
[2:])
251 choices
= list(bitcast_to
.enumerate(width
, previous
))
252 assert len(choices
) == 1
253 bitcast_to
= choices
[0]
254 return Vector(self
._elem
, self
._length
, bitcast_to
)
256 return Vector(self
._elem
.modify(spec
, width
, previous
), self
._length
)
258 def compiler_ctor(self
):
259 if self
._bitcast
is None:
260 return '{}x{}'.format(self
._elem
.compiler_ctor(),
263 return '{}x{}_{}'.format(self
._elem
.compiler_ctor(),
265 self
._bitcast
.compiler_ctor()
268 def compiler_ctor_ref(self
):
269 return '&' + self
.compiler_ctor()
272 return '{}x{}'.format(self
._elem
.rust_name(), self
._length
)
274 def type_info(self
, platform_info
):
275 elem_info
= self
._elem
.type_info(platform_info
)
276 return elem_info
.vectorize(self
._length
,
277 platform_info
.width_info(self
.bitwidth()))
279 def __eq__(self
, other
):
280 return isinstance(other
, Vector
) and self
._length
== other
._length
and \
281 self
._elem
== other
._elem
and self
._bitcast
== other
._bitcast
284 def __init__(self
, elem
, llvm_elem
, const
):
286 self
._llvm
_elem
= llvm_elem
288 Type
.__init
__(self
, BITWIDTH_POINTER
)
290 def modify(self
, spec
, width
, previous
):
294 return Pointer(self
._elem
, self
._llvm
_elem
, False)
296 return Pointer(self
._elem
, self
._llvm
_elem
, True)
298 return Pointer(self
._elem
.modify(spec
, width
, previous
), self
._llvm
_elem
, self
._const
)
300 def compiler_ctor(self
):
301 if self
._llvm
_elem
is None:
304 llvm_elem
= 'Some({})'.format(self
._llvm
_elem
.compiler_ctor_ref())
305 return 'Type::Pointer({}, {}, {})'.format(self
._elem
.compiler_ctor_ref(),
307 'true' if self
._const
else 'false')
309 def compiler_ctor_ref(self
):
310 return "{{ static PTR: Type = {}; &PTR }}".format(self
.compiler_ctor())
314 return '*{} {}'.format('const' if self
._const
else 'mut',
315 self
._elem
.rust_name())
317 def type_info(self
, platform_info
):
318 if self
._llvm
_elem
is None:
321 llvm_elem
= self
._llvm
_elem
.type_info(platform_info
)
322 return self
._elem
.type_info(platform_info
).pointer(llvm_elem
)
324 def __eq__(self
, other
):
325 return isinstance(other
, Pointer
) and self
._const
== other
._const \
326 and self
._elem
== other
._elem
and self
._llvm
_elem
== other
._llvm
_elem
328 class Aggregate(Type
):
329 def __init__(self
, flatten
, elems
):
330 self
._flatten
= flatten
332 Type
.__init
__(self
, sum(elem
.bitwidth() for elem
in elems
))
335 return '<Aggregate {}>'.format(self
._elems
)
337 def modify(self
, spec
, width
, previous
):
338 if spec
.startswith('.'):
340 return self
._elems
[num
]
343 raise NotImplementedError()
345 def compiler_ctor(self
):
346 parts
= "{{ static PARTS: [&'static Type; {}] = [{}]; &PARTS }}"
347 elems
= ', '.join(elem
.compiler_ctor_ref() for elem
in self
._elems
)
348 parts
= parts
.format(len(self
._elems
), elems
)
349 return 'Type::Aggregate({}, {})'.format('true' if self
._flatten
else 'false',
352 def compiler_ctor_ref(self
):
353 return "{{ static AGG: Type = {}; &AGG }}".format(self
.compiler_ctor())
356 return '({})'.format(', '.join(elem
.rust_name() for elem
in self
._elems
))
358 def type_info(self
, platform_info
):
359 return PlatformTypeInfo(None, None, [elem
.type_info(platform_info
) for elem
in self
._elems
])
361 def __eq__(self
, other
):
362 return isinstance(other
, Aggregate
) and self
._flatten
== other
._flatten
and \
363 self
._elems
== other
._elems
366 TYPE_ID_LOOKUP
= {'i': [Signed
, Unsigned
],
371 def ptrify(match
, elem
, width
, previous
):
372 ptr
= match
.group('pointer')
376 llvm_ptr
= match
.group('llvm_pointer')
380 assert llvm_ptr
.startswith('/')
381 options
= list(TypeSpec(llvm_ptr
[1:]).enumerate(width
, previous
))
382 assert len(options
) == 1
383 llvm_elem
= options
[0]
384 assert ptr
in ('Pc', 'Pm')
385 return Pointer(elem
, llvm_elem
, ptr
== 'Pc')
387 class TypeSpec(object):
388 def __init__(self
, spec
):
389 if not isinstance(spec
, list):
394 def enumerate(self
, width
, previous
):
395 for spec
in self
.spec
:
396 match
= SPEC
.match(spec
)
397 if match
is not None:
398 id = match
.group('id')
399 reference
= match
.group('reference')
402 index
= match
.group('index')
403 if index
is not None:
404 modifiers
.append(index
)
405 modifiers
+= list(match
.group('modifiers') or '')
406 force
= match
.group('force_width')
407 if force
is not None:
408 modifiers
.append(force
)
409 bitcast
= match
.group('bitcast')
410 if bitcast
is not None:
411 modifiers
.append(bitcast
)
413 if match
.group('void') is not None:
417 is_vector
= id.islower()
418 type_ctors
= TYPE_ID_LOOKUP
[id.lower()]
420 start
= match
.group('start')
421 if start
is not None:
422 end
= match
.group('end')
425 start
= end
= match
.group('width')
426 llvm_width
= match
.group('llvm_width')
431 while bitwidth
<= end
:
432 for ctor
in type_ctors
:
433 if llvm_width
is not None:
435 llvm_width
= int(llvm_width
)
436 assert llvm_width
< bitwidth
437 scalar
= ctor(bitwidth
, llvm_width
)
439 scalar
= ctor(bitwidth
)
442 elem
= Vector(scalar
, width
// bitwidth
)
444 assert bitcast
is None
448 elem
= elem
.modify(x
, width
, previous
)
449 yield ptrify(match
, elem
, width
, previous
)
451 elif reference
is not None:
452 reference
= int(reference
)
453 assert reference
< len(previous
), \
454 'referring to argument {}, but only {} are known'.format(reference
,
456 ret
= previous
[reference
]
458 ret
= ret
.modify(x
, width
, previous
)
459 yield ptrify(match
, ret
, width
, previous
)
461 assert False, 'matched `{}`, but didn\'t understand it?'.format(spec
)
462 elif spec
.startswith('('):
463 if spec
.endswith(')'):
464 true_spec
= spec
[1:-1]
466 elif spec
.endswith(')f'):
467 true_spec
= spec
[1:-2]
470 assert False, 'found unclosed aggregate `{}`'.format(spec
)
472 for elems
in itertools
.product(*(TypeSpec(subspec
).enumerate(width
, previous
)
473 for subspec
in true_spec
.split(','))):
474 yield Aggregate(flatten
, elems
)
475 elif spec
.startswith('['):
476 if spec
.endswith(']'):
477 true_spec
= spec
[1:-1]
479 elif spec
.endswith(']f'):
480 true_spec
= spec
[1:-2]
483 assert False, 'found unclosed aggregate `{}`'.format(spec
)
484 elem_spec
, count
= true_spec
.split(';')
487 for elem
in TypeSpec(elem_spec
).enumerate(width
, previous
):
488 yield Aggregate(flatten
, [elem
] * count
)
490 assert False, 'Failed to parse `{}`'.format(spec
)
492 class GenericIntrinsic(object):
493 def __init__(self
, platform
, intrinsic
, widths
, llvm_name
, ret
, args
):
494 self
._platform
= platform
495 self
.intrinsic
= intrinsic
496 self
.widths
= map(int, widths
)
497 self
.llvm_name
= llvm_name
498 self
.ret
= TypeSpec(ret
)
499 self
.args
= list(map(TypeSpec
, args
))
501 def monomorphise(self
):
502 for width
in self
.widths
:
503 # must be a power of two
504 assert width
& (width
- 1) == 0
505 def recur(processed
, untouched
):
509 yield MonomorphicIntrinsic(self
._platform
, self
.intrinsic
, width
,
513 raw_arg
= untouched
[0]
515 for arg
in raw_arg
.enumerate(width
, processed
):
516 for intr
in recur(processed
+ [arg
], rest
):
519 for x
in recur([], [self
.ret
] + self
.args
):
522 class MonomorphicIntrinsic(object):
523 def __init__(self
, platform
, intrinsic
, width
, llvm_name
, ret
, args
):
524 self
._platform
= platform
525 self
._intrinsic
= intrinsic
526 self
._width
= '' if width
== 64 else 'q'
527 self
._llvm
_name
= llvm_name
529 self
._ret
= ret
.type_info(platform
)
530 self
._args
_raw
= args
531 self
._args
= [arg
.type_info(platform
) for arg
in args
]
534 if self
._llvm
_name
.startswith('!'):
535 return self
._llvm
_name
[1:].format(self
._ret
, *self
._args
)
537 return self
._platform
.llvm_prefix() + self
._llvm
_name
.format(self
._ret
, *self
._args
)
539 def intrinsic_suffix(self
):
540 return self
._intrinsic
.format(self
._ret
,
544 def platform_prefix(self
):
545 return self
._platform
.platform().platform_prefix()
547 def intrinsic_set_name(self
):
548 return self
._platform
.intrinsic_prefix()
550 def intrinsic_name(self
):
551 return self
._platform
.intrinsic_prefix() + self
.intrinsic_suffix()
553 def compiler_args(self
):
554 return ', '.join(arg
.compiler_ctor_ref() for arg
in self
._args
_raw
)
556 def compiler_ret(self
):
557 return self
._ret
_raw
.compiler_ctor_ref()
559 def compiler_signature(self
):
560 return '({}) -> {}'.format(self
.compiler_args(), self
.compiler_ret())
562 def intrinsic_signature(self
):
564 return '({}) -> {}'.format(', '.join('{}: {}'.format(name
, arg
.rust_name())
565 for name
, arg
in zip(names
, self
._args
_raw
)),
566 self
._ret
_raw
.rust_name())
569 parser
= argparse
.ArgumentParser(
570 formatter_class
= argparse
.RawDescriptionHelpFormatter
,
571 description
= 'Render an intrinsic definition JSON to various formats.',
572 epilog
= textwrap
.dedent('''\
575 There are two operating modes: single file and multiple files.
577 For example, ARM is specified as a single file. To generate the
578 compiler-definitions for ARM just pass the script the "arm.json" file:
580 python generator.py --format compiler-defs arm.json
582 The X86 architecture is specified as multiple files (for the different
583 instruction sets that x86 supports). To generate the compiler
584 definitions one needs to pass the script a "platform information file"
585 (with the -i flag) next to the files of the different intruction sets.
586 For example, to generate the X86 compiler-definitions for SSE4.2, just:
588 python generator.py --format compiler-defs -i x86/info.json sse42.json
590 And to generate the compiler-definitions for SSE4.1 and SSE4.2, just:
592 python generator.py --format compiler-defs -i x86/info.json sse41.json sse42.json
594 An intrinsic definition consists of a map with fields:
595 - intrinsic: pattern for the name(s) of the vendor's C intrinsic(s)
596 - llvm: pattern for the name(s) of the internal llvm intrinsic(s)
597 - width: a vector of vector bit-widths the pattern works with
598 - ret: type specifier for the return value
599 - arguments: vector of type specifiers for arguments
601 The width and types describe a range of possible intrinsics,
602 and these are fed back into the intrinsic and llvm patterns to
603 create the appropriate definitions.
605 ## Type specifier grammar
608 type := core_type modifier* suffix?
610 core_type := void | vector | scalar | aggregate | reference
612 modifier := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' |
613 'x' number | '.' number
614 suffix := pointer | bitcast
615 pointer := 'Pm' llvm_pointer? | 'Pc' llvm_pointer?
616 llvm_pointer := '/' type
621 vector := vector_elem width |
622 vector_elem := 'i' | 'u' | 's' | 'f'
624 scalar := scalar_type number llvm_width?
625 scalar_type := 'U' | 'S' | 'F'
626 llvm_width := '/' number
628 aggregate := '(' (type),* ')' 'f'? | '[' type ';' number ']' 'f'?
632 width = number | '(' number '-' number ')'
639 The `V` type corresponds to `void` in LLVM (`()` in
640 Rust). It's likely to only work in return position.
644 The vector grammar is a pattern describing many possibilities
645 for arguments/return value. The `vector_elem` describes the
646 types of elements to use, and the `width` describes the (range
647 of) widths for those elements, which are then placed into a
648 vector with the `width` bitwidth. E.g. if an intrinsic has a
649 `width` that includes 128, and the return value is `i(8-32)`,
650 then some instantiation of that intrinsic will be `u8x16`,
651 `u32x4`, `i32x4`, etc.
655 - i: integer, both signed and unsigned
656 - u: unsigned integer
662 Similar to vectors, but these describe a single concrete type,
663 not a range. The number is the bitwidth. The optional
664 `llvm_width` is the bitwidth of the integer that should be
665 passed to LLVM (by truncating the Rust argument): this only
666 works with scalar integers and the LLVM width must be smaller
671 - U: unsigned integer
677 An aggregate is a collection of multiple types; a tuple in
678 Rust terms, or an unnamed struct in LLVM. The `f` modifiers
679 forces the tuple to be flattened in the LLVM
680 intrinsic. E.g. if `llvm.foo` takes `(F32,S32)`:
682 - no `f` corresponds to `declare ... @llvm.foo({float, i32})`.
683 - having an `f` corresponds to `declare ... @llvm.foo(float, i32)`.
685 The `[type;number]` form is a just shorter way to write
686 `(...)`, except avoids doing a cartesian product of generic
687 types, e.g. `[S32;2]` is the same as `(S32, S32)`, while
688 `[I32;2]` is describing just the two types `(S32,S32)` and
689 `(U32,U32)` (i.e. doesn't include `(S32,U32)`, `(U32,S32)` as
692 (Currently aggregates can not contain other aggregates.)
696 A reference uses the type of another argument, with possible
697 modifications. The number refers to the type to use, starting
698 with 0 == return value, 1 == first argument, 2 == second
703 The `modifier` and `suffix` adaptors change the precise
708 - 'v': put a scalar into a vector of the current width (u32 -> u32x4, when width == 128)
709 - 'S': get the scalar element of a vector (u32x4 -> u32)
710 - 'h': half the length of the vector (u32x4 -> u32x2)
711 - 'd': double the length of the vector (u32x2 -> u32x4)
712 - 'n': narrow the element of the vector (u32x4 -> u16x4)
713 - 'w': widen the element of the vector (u16x4 -> u32x4)
714 - 'u': force a number (vector or scalar) to be unsigned int (f32x4 -> u32x4)
715 - 's': force a number (vector or scalar) to be signed int (u32x4 -> i32x4)
716 - 'f': force a number (vector or scalar) to be float (u32x4 -> f32x4)
717 - 'x' number: force the type to be a vector of bitwidth `number`.
718 - '.' number: get the `number`th element of an aggregate
719 - 'D': dereference a pointer (*mut u32 -> u32)
720 - 'C': make a pointer const (*mut u32 -> *const u32)
721 - 'M': make a pointer mut (*const u32 -> *mut u32)
725 Pointers can be created of any type by appending a `P*`
726 suffix. The `m` vs. `c` chooses mut vs. const. e.g. `S32Pm`
727 corresponds to `*mut i32`, and `i32Pc` corresponds (with width
728 128) to `*const i8x16`, `*const u32x4`, etc.
730 The type after the `/` (optional) represents the type used
731 internally to LLVM, e.g. `S32pm/S8` is exposed as `*mut i32`
732 in Rust, but is `i8*` in LLVM. (This defaults to the main
737 The `'->' type` bitcast suffix will cause the value to be
738 bitcast to the right-hand type when calling the intrinsic,
739 e.g. `s32->f32` will expose the intrinsic as `i32x4` at the
740 Rust level, but will cast that vector to `f32x4` when calling
743 parser
.add_argument('--format', choices
=FORMATS
, required
=True,
744 help = 'Output format.')
745 parser
.add_argument('-o', '--out', type=argparse
.FileType('w'), default
=sys
.stdout
,
746 help = 'File to output to (default stdout).')
747 parser
.add_argument('-i', '--info', type=argparse
.FileType('r'),
748 help = 'File containing platform specific information to merge into '
749 'the input files\' header.')
750 parser
.add_argument('in_', metavar
="FILE", type=argparse
.FileType('r'), nargs
='+',
751 help = 'JSON files to load')
752 return parser
.parse_args()
755 class ExternBlock(object):
759 def open(self
, platform
):
760 return 'extern "platform-intrinsic" {'
762 def render(self
, mono
):
763 return ' fn {}{}{};'.format(mono
.platform_prefix(),
764 mono
.intrinsic_name(),
765 mono
.intrinsic_signature())
770 class CompilerDefs(object):
774 def open(self
, platform
):
776 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
777 // file at the top-level directory of this distribution and at
778 // http://rust-lang.org/COPYRIGHT.
780 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
781 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
782 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
783 // option. This file may not be copied, modified, or distributed
784 // except according to those terms.
786 // DO NOT EDIT: autogenerated by etc/platform-intrinsics/generator.py
787 // ignore-tidy-linelength
789 #![allow(unused_imports)]
791 use {{Intrinsic, Type}};
792 use IntrinsicDef::Named;
794 // The default inlining settings trigger a pathological behaviour in
795 // LLVM, which causes makes compilation very slow. See #28273.
797 pub fn find(name: &str) -> Option<Intrinsic> {{
798 if !name.starts_with("{0}") {{ return None }}
799 Some(match &name["{0}".len()..] {{'''.format(platform
.platform_prefix())
801 def render(self
, mono
):
804 inputs: {{ static INPUTS: [&'static Type; {}] = [{}]; &INPUTS }},
806 definition: Named("{}")
807 }},'''.format(mono
.intrinsic_set_name() + mono
.intrinsic_suffix(),
809 mono
.compiler_args(),
820 'extern-block': ExternBlock(),
821 'compiler-defs': CompilerDefs(),
829 out_format
= FORMATS
[args
.format
]
831 one_file_no_info
= False
832 if len(ins
) > 1 and info
is None:
833 print('error: cannot have multiple inputs without an info header.', file=sys
.stderr
)
838 one_file_no_info
= True
839 info_json
= json
.load(info
)
840 platform
= PlatformInfo(info_json
)
842 print(out_format
.open(platform
), file=out
)
849 data
= json
.load(in_
)
850 data
.update(info_json
)
852 intrinsics
= IntrinsicSet(platform
, data
)
853 for intr
in intrinsics
.intrinsics():
854 for mono
in intr
.monomorphise():
855 print(out_format
.render(mono
), file=out
)
857 print(out_format
.close(), file=out
)
859 if __name__
== '__main__':