diff --git a/configure b/configure index 7c54bcd5a4f14..45e137d4a9f41 100755 --- a/configure +++ b/configure @@ -1180,16 +1180,27 @@ do # MSVC requires cmake because that's how we're going to build LLVM probe_need CFG_CMAKE cmake + # There are three builds of cmake on windows: MSVC, MinGW and Cygwin + # The Cygwin build does not have generators for Visual Studio, so + # detect that here and error. + if ! "$CFG_CMAKE" --help | sed -n '/^Generators/,$p' | grep 'Visual Studio' > /dev/null + then + err "cmake does not support Visual Studio generators.\n\n \ + This is likely due to it being an msys/cygwin build of cmake, \ + rather than the required windows version, built using MinGW \ + or Visual Studio." + fi + # Use the REG program to figure out where VS is installed # We need to figure out where cl.exe and link.exe are, so we do some # munging and some probing here. We also look for the default # INCLUDE and LIB variables for MSVC so we can set those in the # build system as well. - install=$(reg QUERY \ + install=$(cmd //c reg QUERY \ 'HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0' \ -v InstallDir) if [ -z "$install" ]; then - install=$(reg QUERY \ + install=$(cmd //c reg QUERY \ 'HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0' \ -v InstallDir) fi @@ -1222,9 +1233,9 @@ do eval CFG_MSVC_LINK_$bits="\"$bindir/link.exe\"" vcvarsall="${CFG_MSVC_ROOT}/VC/vcvarsall.bat" - include_path=$(cmd /c "\"$vcvarsall\" $msvc_part && cmd /c echo %INCLUDE%") + include_path=$(cmd //V:ON //c "$vcvarsall" $msvc_part \& echo !INCLUDE!) need_ok "failed to learn about MSVC's INCLUDE" - lib_path=$(cmd /c "\"$vcvarsall\" $msvc_part && cmd /c echo %LIB%") + lib_path=$(cmd //V:ON //c "$vcvarsall" $msvc_part \& echo !LIB!) need_ok "failed to learn about MSVC's LIB" eval CFG_MSVC_INCLUDE_PATH_${bits}="\"$include_path\"" diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index 1afa622db7dd3..a2bdd66b0c253 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -7,7 +7,7 @@ can be awkward. Consider this code: baz(bar(foo)); ``` -We would read this left-to right, and so we see ‘baz bar foo’. But this isn’t the +We would read this left-to-right, and so we see ‘baz bar foo’. But this isn’t the order that the functions would get called in, that’s inside-out: ‘foo bar baz’. Wouldn’t it be nice if we could do this instead? @@ -45,17 +45,17 @@ This will print `12.566371`. -We’ve made a struct that represents a circle. We then write an `impl` block, +We’ve made a `struct` that represents a circle. We then write an `impl` block, and inside it, define a method, `area`. -Methods take a special first parameter, of which there are three variants: +Methods take a special first parameter, of which there are three variants: `self`, `&self`, and `&mut self`. You can think of this first parameter as being the `foo` in `foo.bar()`. The three variants correspond to the three kinds of things `foo` could be: `self` if it’s just a value on the stack, `&self` if it’s a reference, and `&mut self` if it’s a mutable reference. Because we took the `&self` parameter to `area`, we can use it just like any other parameter. Because we know it’s a `Circle`, we can access the `radius` -just like we would with any other struct. +just like we would with any other `struct`. We should default to using `&self`, as you should prefer borrowing over taking ownership, as well as taking immutable references over mutable ones. Here’s an @@ -120,12 +120,12 @@ Check the return type: ```rust # struct Circle; # impl Circle { -fn grow(&self) -> Circle { +fn grow(&self, increment: f64) -> Circle { # Circle } } ``` We just say we’re returning a `Circle`. With this method, we can grow a new -circle to any arbitrary size. +`Circle` to any arbitrary size. # Associated functions @@ -161,7 +161,7 @@ methods’. # Builder Pattern -Let’s say that we want our users to be able to create Circles, but we will +Let’s say that we want our users to be able to create `Circle`s, but we will allow them to only set the properties they care about. Otherwise, the `x` and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn’t have method overloading, named arguments, or variable arguments. We employ @@ -224,7 +224,7 @@ fn main() { } ``` -What we’ve done here is make another struct, `CircleBuilder`. We’ve defined our +What we’ve done here is make another `struct`, `CircleBuilder`. We’ve defined our builder methods on it. We’ve also defined our `area()` method on `Circle`. We also made one more method on `CircleBuilder`: `finalize()`. This method creates our final `Circle` from the builder. Now, we’ve used the type system to enforce diff --git a/src/etc/platform-intrinsics/aarch64.json b/src/etc/platform-intrinsics/aarch64.json index dbccdc37d3f40..79fd769942889 100644 --- a/src/etc/platform-intrinsics/aarch64.json +++ b/src/etc/platform-intrinsics/aarch64.json @@ -336,6 +336,48 @@ "ret": "i8", "args": ["0"] }, + { + "intrinsic": "ld2{0[0].width}_{0[0].data_type}", + "width": [64, 128], + "llvm": "ld2.{0[0].llvm_name}.{1.llvm_name}", + "ret": ["[i(8-64);2]","[f(32-64);2]"], + "args": ["0.0SPc/0.0"] + }, + { + "intrinsic": "ld3{0[0].width}_{0[0].data_type}", + "width": [64, 128], + "llvm": "ld3.{0[0].llvm_name}.{1.llvm_name}", + "ret": ["[i(8-64);3]","[f(32-64);3]"], + "args": ["0.0SPc/0.0"] + }, + { + "intrinsic": "ld4{0[0].width}_{0[0].data_type}", + "width": [64, 128], + "llvm": "ld4.{0[0].llvm_name}.{1.llvm_name}", + "ret": ["[i(8-64);4]","[f(32-64);4]"], + "args": ["0.0SPc/0.0"] + }, + { + "intrinsic": "ld2{0[0].width}_dup_{0[0].data_type}", + "width": [64, 128], + "llvm": "ld2.{0[0].llvm_name}.{1.llvm_name}", + "ret": ["[i(8-64);2]","[f(32-64);2]"], + "args": ["0.0SPc"] + }, + { + "intrinsic": "ld3{0[0].width}_dup_{0[0].data_type}", + "width": [64, 128], + "llvm": "ld3.{0[0].llvm_name}.{1.llvm_name}", + "ret": ["[i(8-64);3]","[f(32-64);3]"], + "args": ["0.0SPc"] + }, + { + "intrinsic": "ld4{0[0].width}_dup_{0[0].data_type}", + "width": [64, 128], + "llvm": "ld4.{0[0].llvm_name}.{1.llvm_name}", + "ret": ["[i(8-64);4]","[f(32-64);4]"], + "args": ["0.0SPc"] + }, { "intrinsic": "padd{0.width}_{0.data_type}", "width": [64, 128], diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py index 97b2f57010b97..d1217c1fb2b4a 100644 --- a/src/etc/platform-intrinsics/generator.py +++ b/src/etc/platform-intrinsics/generator.py @@ -14,11 +14,13 @@ import sys import re import textwrap +import itertools SPEC = re.compile( - r'^(?:(?P[iusfIUSF])(?:\((?P\d+)-(?P\d+)\)|' + r'^(?:(?PV)|(?P[iusfIUSF])(?:\((?P\d+)-(?P\d+)\)|' r'(?P\d+)(:?/(?P\d+))?)' - r'|(?P\d+)(?P[vShdnwus]*)(?Px\d+)?)$' + r'|(?P\d+))(?P\.\d+)?(?P[vShdnwusfDMC]*)(?Px\d+)?' + r'(?:(?PPm|Pc)(?P/.*)?|(?P->.*))?$' ) class PlatformInfo(object): @@ -68,18 +70,35 @@ def lookup(raw): {k: lookup(v) for k, v in data.items()}) class PlatformTypeInfo(object): - def __init__(self, llvm_name, properties): - self.properties = properties - self.llvm_name = llvm_name + def __init__(self, llvm_name, properties, elems = None): + if elems is None: + self.properties = properties + self.llvm_name = llvm_name + else: + assert properties is None and llvm_name is None + self.properties = {} + self.elems = elems + + def __repr__(self): + return ''.format(self.llvm_name, self.properties) def __getattr__(self, name): return self.properties[name] + def __getitem__(self, idx): + return self.elems[idx] + def vectorize(self, length, width_info): props = self.properties.copy() props.update(width_info) return PlatformTypeInfo('v{}{}'.format(length, self.llvm_name), props) + def pointer(self, llvm_elem): + name = self.llvm_name if llvm_elem is None else llvm_elem.llvm_name + return PlatformTypeInfo('p0{}'.format(name), self.properties) + +BITWIDTH_POINTER = '' + class Type(object): def __init__(self, bitwidth): self._bitwidth = bitwidth @@ -87,18 +106,39 @@ def __init__(self, bitwidth): def bitwidth(self): return self._bitwidth - def modify(self, spec, width): + def modify(self, spec, width, previous): raise NotImplementedError() + def __ne__(self, other): + return not (self == other) + +class Void(Type): + def __init__(self): + Type.__init__(self, 0) + + def compiler_ctor(self): + return 'void()' + + def rust_name(self): + return '()' + + def type_info(self, platform_info): + return None + + def __eq__(self, other): + return isinstance(other, Void) + class Number(Type): def __init__(self, bitwidth): Type.__init__(self, bitwidth) - def modify(self, spec, width): + def modify(self, spec, width, previous): if spec == 'u': return Unsigned(self.bitwidth()) elif spec == 's': return Signed(self.bitwidth()) + elif spec == 'f': + return Float(self.bitwidth()) elif spec == 'w': return self.__class__(self.bitwidth() * 2) elif spec == 'n': @@ -111,11 +151,16 @@ def modify(self, spec, width): def type_info(self, platform_info): return platform_info.number_type_info(self) + def __eq__(self, other): + # print(self, other) + return self.__class__ == other.__class__ and self.bitwidth() == other.bitwidth() + class Signed(Number): def __init__(self, bitwidth, llvm_bitwidth = None): Number.__init__(self, bitwidth) self._llvm_bitwidth = llvm_bitwidth + def compiler_ctor(self): if self._llvm_bitwidth is None: return 'i({})'.format(self.bitwidth()) @@ -164,26 +209,47 @@ def rust_name(self): return 'f{}'.format(self.bitwidth()) class Vector(Type): - def __init__(self, elem, length): + def __init__(self, elem, length, bitcast = None): assert isinstance(elem, Type) and not isinstance(elem, Vector) Type.__init__(self, elem.bitwidth() * length) self._length = length self._elem = elem + assert bitcast is None or (isinstance(bitcast, Vector) and + bitcast._bitcast is None and + bitcast._elem.bitwidth() == elem.bitwidth()) + if bitcast is not None and bitcast._elem != elem: + self._bitcast = bitcast._elem + else: + self._bitcast = None - def modify(self, spec, width): - if spec == 'h': + def modify(self, spec, width, previous): + if spec == 'S': + return self._elem + elif spec == 'h': return Vector(self._elem, self._length // 2) elif spec == 'd': return Vector(self._elem, self._length * 2) elif spec.startswith('x'): new_bitwidth = int(spec[1:]) return Vector(self._elem, new_bitwidth // self._elem.bitwidth()) + elif spec.startswith('->'): + bitcast_to = TypeSpec(spec[2:]) + choices = list(bitcast_to.enumerate(width, previous)) + assert len(choices) == 1 + bitcast_to = choices[0] + return Vector(self._elem, self._length, bitcast_to) else: - return Vector(self._elem.modify(spec, width), self._length) + return Vector(self._elem.modify(spec, width, previous), self._length) def compiler_ctor(self): - return 'v({}, {})'.format(self._elem.compiler_ctor(), self._length) + if self._bitcast is None: + return 'v({}, {})'.format(self._elem.compiler_ctor(), + self._length) + else: + return 'v_({}, {}, {})'.format(self._elem.compiler_ctor(), + self._bitcast.compiler_ctor(), + self._length) def rust_name(self): return '{}x{}'.format(self._elem.rust_name(), self._length) @@ -193,6 +259,51 @@ def type_info(self, platform_info): return elem_info.vectorize(self._length, platform_info.width_info(self.bitwidth())) + def __eq__(self, other): + return isinstance(other, Vector) and self._length == other._length and \ + self._elem == other._elem and self._bitcast == other._bitcast + +class Pointer(Type): + def __init__(self, elem, llvm_elem, const): + self._elem = elem; + self._llvm_elem = llvm_elem + self._const = const + Type.__init__(self, BITWIDTH_POINTER) + + def modify(self, spec, width, previous): + if spec == 'D': + return self._elem + elif spec == 'M': + return Pointer(self._elem, self._llvm_elem, False) + elif spec == 'C': + return Pointer(self._elem, self._llvm_elem, True) + else: + return Pointer(self._elem.modify(spec, width, previous), self._llvm_elem, self._const) + + def compiler_ctor(self): + if self._llvm_elem is None: + llvm_elem = 'None' + else: + llvm_elem = 'Some({})'.format(self._llvm_elem.compiler_ctor()) + return 'p({}, {}, {})'.format('true' if self._const else 'false', + self._elem.compiler_ctor(), + llvm_elem) + + def rust_name(self): + return '*{} {}'.format('const' if self._const else 'mut', + self._elem.rust_name()) + + def type_info(self, platform_info): + if self._llvm_elem is None: + llvm_elem = None + else: + llvm_elem = self._llvm_elem.type_info(platform_info) + return self._elem.type_info(platform_info).pointer(llvm_elem) + + def __eq__(self, other): + return isinstance(other, Pointer) and self._const == other._const \ + and self._elem == other._elem and self._llvm_elem == other._llvm_elem + class Aggregate(Type): def __init__(self, flatten, elems): self._flatten = flatten @@ -202,6 +313,14 @@ def __init__(self, flatten, elems): def __repr__(self): return ''.format(self._elems) + def modify(self, spec, width, previous): + if spec.startswith('.'): + num = int(spec[1:]) + return self._elems[num] + else: + print(spec) + raise NotImplementedError() + def compiler_ctor(self): return 'agg({}, vec![{}])'.format('true' if self._flatten else 'false', ', '.join(elem.compiler_ctor() for elem in self._elems)) @@ -210,8 +329,11 @@ def rust_name(self): return '({})'.format(', '.join(elem.rust_name() for elem in self._elems)) def type_info(self, platform_info): - #return PlatformTypeInfo(None, None, self._llvm_name) - return None + return PlatformTypeInfo(None, None, [elem.type_info(platform_info) for elem in self._elems]) + + def __eq__(self, other): + return isinstance(other, Aggregate) and self._flatten == other._flatten and \ + self._elems == other._elems TYPE_ID_LOOKUP = {'i': [Signed, Unsigned], @@ -219,6 +341,22 @@ def type_info(self, platform_info): 'u': [Unsigned], 'f': [Float]} +def ptrify(match, elem, width, previous): + ptr = match.group('pointer') + if ptr is None: + return elem + else: + llvm_ptr = match.group('llvm_pointer') + if llvm_ptr is None: + llvm_elem = None + else: + assert llvm_ptr.startswith('/') + options = list(TypeSpec(llvm_ptr[1:]).enumerate(width, previous)) + assert len(options) == 1 + llvm_elem = options[0] + assert ptr in ('Pc', 'Pm') + return Pointer(elem, llvm_elem, ptr == 'Pc') + class TypeSpec(object): def __init__(self, spec): if not isinstance(spec, list): @@ -226,71 +364,103 @@ def __init__(self, spec): self.spec = spec - def enumerate(self, width): + def enumerate(self, width, previous): for spec in self.spec: match = SPEC.match(spec) - if match: + if match is not None: id = match.group('id') - is_vector = id.islower() - type_ctors = TYPE_ID_LOOKUP[id.lower()] - - start = match.group('start') - if start is not None: - end = match.group('end') - llvm_width = None + reference = match.group('reference') + + modifiers = [] + index = match.group('index') + if index is not None: + modifiers.append(index) + modifiers += list(match.group('modifiers') or '') + force = match.group('force_width') + if force is not None: + modifiers.append(force) + bitcast = match.group('bitcast') + if bitcast is not None: + modifiers.append(bitcast) + + if match.group('void') is not None: + assert spec == 'V' + yield Void() + elif id is not None: + is_vector = id.islower() + type_ctors = TYPE_ID_LOOKUP[id.lower()] + + start = match.group('start') + if start is not None: + end = match.group('end') + llvm_width = None + else: + start = end = match.group('width') + llvm_width = match.group('llvm_width') + start = int(start) + end = int(end) + + bitwidth = start + while bitwidth <= end: + for ctor in type_ctors: + if llvm_width is not None: + assert not is_vector + llvm_width = int(llvm_width) + assert llvm_width < bitwidth + scalar = ctor(bitwidth, llvm_width) + else: + scalar = ctor(bitwidth) + + if is_vector: + elem = Vector(scalar, width // bitwidth) + else: + assert bitcast is None + elem = scalar + + for x in modifiers: + elem = elem.modify(x, width, previous) + yield ptrify(match, elem, width, previous) + bitwidth *= 2 + elif reference is not None: + reference = int(reference) + assert reference < len(previous), \ + 'referring to argument {}, but only {} are known'.format(reference, + len(previous)) + ret = previous[reference] + for x in modifiers: + ret = ret.modify(x, width, previous) + yield ptrify(match, ret, width, previous) else: - start = end = match.group('width') - llvm_width = match.group('llvm_width') - start = int(start) - end = int(end) - - bitwidth = start - while bitwidth <= end: - for ctor in type_ctors: - if llvm_width is not None: - assert not is_vector - llvm_width = int(llvm_width) - assert llvm_width < bitwidth - scalar = ctor(bitwidth, llvm_width) - else: - scalar = ctor(bitwidth) - - if is_vector: - yield Vector(scalar, width // bitwidth) - else: - yield scalar - bitwidth *= 2 + assert False, 'matched `{}`, but didn\'t understand it?'.format(spec) + elif spec.startswith('('): + if spec.endswith(')'): + true_spec = spec[1:-1] + flatten = False + elif spec.endswith(')f'): + true_spec = spec[1:-2] + flatten = True + else: + assert False, 'found unclosed aggregate `{}`'.format(spec) + + for elems in itertools.product(*(TypeSpec(subspec).enumerate(width, previous) + for subspec in true_spec.split(','))): + yield Aggregate(flatten, elems) + elif spec.startswith('['): + if spec.endswith(']'): + true_spec = spec[1:-1] + flatten = False + elif spec.endswith(']f'): + true_spec = spec[1:-2] + flatten = True + else: + assert False, 'found unclosed aggregate `{}`'.format(spec) + elem_spec, count = true_spec.split(';') + + count = int(count) + for elem in TypeSpec(elem_spec).enumerate(width, previous): + yield Aggregate(flatten, [elem] * count) else: - print('Failed to parse: `{}`'.format(spec), file=sys.stderr) - - def resolve(self, width, zero): - assert len(self.spec) == 1 - spec = self.spec[0] - match = SPEC.match(spec) - if match: - id = match.group('id') - if id is not None: - options = list(self.enumerate(width)) - assert len(options) == 1 - return options[0] - reference = match.group('reference') - if reference != '0': - raise NotImplementedError('only argument 0 (return value) references are supported') - ret = zero - for x in match.group('modifiers') or []: - ret = ret.modify(x, width) - force = match.group('force_width') - if force is not None: - ret = ret.modify(force, width) - return ret - elif spec.startswith('('): - if spec.endswith(')'): - raise NotImplementedError() - elif spec.endswith(')f'): - true_spec = spec[1:-2] - flatten = True - elems = [TypeSpec(subspec).resolve(width, zero) for subspec in true_spec.split(',')] - return Aggregate(flatten, elems) + assert False, 'Failed to parse `{}`'.format(spec) class GenericIntrinsic(object): def __init__(self, platform, intrinsic, widths, llvm_name, ret, args): @@ -305,10 +475,22 @@ def monomorphise(self): for width in self.widths: # must be a power of two assert width & (width - 1) == 0 - for ret in self.ret.enumerate(width): - args = [arg.resolve(width, ret) for arg in self.args] - yield MonomorphicIntrinsic(self._platform, self.intrinsic, width, self.llvm_name, - ret, args) + def recur(processed, untouched): + if untouched == []: + ret = processed[0] + args = processed[1:] + yield MonomorphicIntrinsic(self._platform, self.intrinsic, width, + self.llvm_name, + ret, args) + else: + raw_arg = untouched[0] + rest = untouched[1:] + for arg in raw_arg.enumerate(width, processed): + for intr in recur(processed + [arg], rest): + yield intr + + for x in recur([], [self.ret] + self.args): + yield x class MonomorphicIntrinsic(object): def __init__(self, platform, intrinsic, width, llvm_name, ret, args): @@ -369,7 +551,18 @@ def parse_args(): ## Type specifier grammar ``` - type := vector | scalar | aggregate | reference + type := core_type modifier* suffix? + + core_type := void | vector | scalar | aggregate | reference + + modifier := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' | + 'x' number | '.' number + suffix := pointer | bitcast + pointer := 'Pm' llvm_pointer? | 'Pc' llvm_pointer? + llvm_pointer := '/' type + bitcast := '->' type + + void := 'V' vector := vector_elem width | vector_elem := 'i' | 'u' | 's' | 'f' @@ -378,18 +571,20 @@ def parse_args(): scalar_type := 'U' | 'S' | 'F' llvm_width := '/' number - aggregate := '(' (type),* ')' 'f'? - - reference := number modifiers* - modifiers := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' | - 'x' number + aggregate := '(' (type),* ')' 'f'? | '[' type ';' number ']' 'f'? + reference := number width = number | '(' number '-' number ')' number = [0-9]+ ``` + ## Void + + The `V` type corresponds to `void` in LLVM (`()` in + Rust). It's likely to only work in return position. + ## Vectors The vector grammar is a pattern describing many possibilities @@ -433,6 +628,12 @@ def parse_args(): - no `f` corresponds to `declare ... @llvm.foo({float, i32})`. - having an `f` corresponds to `declare ... @llvm.foo(float, i32)`. + The `[type;number]` form is a just shorter way to write + `(...)`, except avoids doing a cartesian product of generic + types, e.g. `[S32;2]` is the same as `(S32, S32)`, while + `[I32;2]` is describing just the two types `(S32,S32)` and + `(U32,U32)` (i.e. doesn't include `(S32,U32)`, `(U32,S32)` as + `(I32,I32)` would). (Currently aggregates can not contain other aggregates.) @@ -441,19 +642,49 @@ def parse_args(): A reference uses the type of another argument, with possible modifications. The number refers to the type to use, starting with 0 == return value, 1 == first argument, 2 == second - argument, etc. (Currently only referencing 0, the return - value, is supported.) + argument, etc. + + ## Affixes + + The `modifier` and `suffix` adaptors change the precise + representation. ### Modifiers - 'v': put a scalar into a vector of the current width (u32 -> u32x4, when width == 128) + - 'S': get the scalar element of a vector (u32x4 -> u32) - 'h': half the length of the vector (u32x4 -> u32x2) - 'd': double the length of the vector (u32x2 -> u32x4) - 'n': narrow the element of the vector (u32x4 -> u16x4) - 'w': widen the element of the vector (u16x4 -> u32x4) - - 'u': force an integer (vector or scalar) to be unsigned (i32x4 -> u32x4) - - 's': force an integer (vector or scalar) to be signed (u32x4 -> i32x4) + - 'u': force a number (vector or scalar) to be unsigned int (f32x4 -> u32x4) + - 's': force a number (vector or scalar) to be signed int (u32x4 -> i32x4) + - 'f': force a number (vector or scalar) to be float (u32x4 -> f32x4) - 'x' number: force the type to be a vector of bitwidth `number`. + - '.' number: get the `number`th element of an aggregate + - 'D': dereference a pointer (*mut u32 -> u32) + - 'C': make a pointer const (*mut u32 -> *const u32) + - 'M': make a pointer mut (*const u32 -> *mut u32) + + ### Pointers + + Pointers can be created of any type by appending a `P*` + suffix. The `m` vs. `c` chooses mut vs. const. e.g. `S32Pm` + corresponds to `*mut i32`, and `i32Pc` corresponds (with width + 128) to `*const i8x16`, `*const u32x4`, etc. + + The type after the `/` (optional) represents the type used + internally to LLVM, e.g. `S32pm/S8` is exposed as `*mut i32` + in Rust, but is `i8*` in LLVM. (This defaults to the main + type). + + ### Bitcast + + The `'->' type` bitcast suffix will cause the value to be + bitcast to the right-hand type when calling the intrinsic, + e.g. `s32->f32` will expose the intrinsic as `i32x4` at the + Rust level, but will cast that vector to `f32x4` when calling + the LLVM intrinsic. ''')) parser.add_argument('--format', choices=FORMATS, required=True, help = 'Output format.') @@ -502,7 +733,7 @@ def open(self, platform): #![allow(unused_imports)] -use {{Intrinsic, i, i_, u, u_, f, v, agg}}; +use {{Intrinsic, i, i_, u, u_, f, v, v_, agg, p, void}}; use IntrinsicDef::Named; use rustc::middle::ty; diff --git a/src/etc/platform-intrinsics/x86/avx.json b/src/etc/platform-intrinsics/x86/avx.json index 4ac82fb90e900..2c1492c2954c8 100644 --- a/src/etc/platform-intrinsics/x86/avx.json +++ b/src/etc/platform-intrinsics/x86/avx.json @@ -36,6 +36,20 @@ "ret": "f(32-64)", "args": ["0", "0"] }, + { + "intrinsic": "{0.width_mm}_maskload_{0.data_type}", + "width": [128, 256], + "llvm": "maskload.{0.data_type_short}{0.width_suffix}", + "ret": ["f(32-64)"], + "args": ["0SPc/S8", "0s->0"] + }, + { + "intrinsic": "{3.width_mm}_maskstore_{3.data_type}", + "width": [128, 256], + "llvm": "maskstore.{3.data_type_short}{3.width_suffix}", + "ret": "V", + "args": ["F(32-64)Pm/S8", "1Dsv->1Dv", "1Dv"] + }, { "intrinsic": "256_min_{0.data_type}", "width": [256], @@ -78,6 +92,20 @@ "ret": "f32", "args": ["f32"] }, + { + "intrinsic": "256_storeu_{2.data_type}", + "width": [256], + "llvm": "storeu.ps.256", + "ret": "V", + "args": ["f(32-64)Pm/U8", "1D"] + }, + { + "intrinsic": "256_storeu_si256", + "width": [256], + "llvm": "storeu.dq.256", + "ret": "V", + "args": ["u8Pm/U8", "1D"] + }, { "intrinsic": "256_sqrt_{0.data_type}", "width": [256], @@ -147,6 +175,20 @@ "llvm": "ptestz.256", "ret": "S32", "args": ["u64", "u64"] + }, + { + "intrinsic": "256_zeroall", + "width": [256], + "llvm": "vzeroall", + "ret": "V", + "args": [] + }, + { + "intrinsic": "256_zeroupper", + "width": [256], + "llvm": "vzeroupper", + "ret": "V", + "args": [] } ] } diff --git a/src/etc/platform-intrinsics/x86/avx2.json b/src/etc/platform-intrinsics/x86/avx2.json index bd260ec02e930..e88ff3d2b806d 100644 --- a/src/etc/platform-intrinsics/x86/avx2.json +++ b/src/etc/platform-intrinsics/x86/avx2.json @@ -4,21 +4,21 @@ { "intrinsic": "256_abs_{0.data_type}", "width": [256], - "llvm": "avx2.pabs.{0.data_type_short}", + "llvm": "pabs.{0.data_type_short}", "ret": "s(8-32)", "args": ["0"] }, { "intrinsic": "256_adds_{0.data_type}", "width": [256], - "llvm": "avx2.padd{0.kind_short}s.{0.data_type_short}", + "llvm": "padd{0.kind_short}s.{0.data_type_short}", "ret": "i(8-16)", "args": ["0", "0"] }, { "intrinsic": "256_avg_{0.data_type}", "width": [256], - "llvm": "avx2.pavg.{0.data_type_short}", + "llvm": "pavg.{0.data_type_short}", "ret": "u(8-16)", "args": ["0", "0"] }, @@ -64,6 +64,48 @@ "ret": "s16", "args": ["s8", "s8"] }, + { + "intrinsic": "{0.width_mm}_mask_i32gather_{0.data_type}", + "width": [128, 256], + "llvm": "gather.d.{0.data_type_short}{0.width_suffix}", + "ret": ["s32", "f32"], + "args": ["0", "0SPc/S8", "s32", "0s->0", "S32/8"] + }, + { + "intrinsic": "{0.width_mm}_mask_i32gather_{0.data_type}", + "width": [128, 256], + "llvm": "gather.d.{0.data_type_short}{0.width_suffix}", + "ret": ["s64", "f64"], + "args": ["0", "0SPc/S8", "s32x128", "0s->0", "S32/8"] + }, + { + "intrinsic": "{3.width_mm}_mask_i64gather_{0.data_type}", + "width": [128, 256], + "llvm": "gather.q.{0.data_type_short}{0.width_suffix}", + "ret": ["s32x128", "f32x128"], + "args": ["0", "0SPc/S8", "s64", "0s->0", "S32/8"] + }, + { + "intrinsic": "{0.width_mm}_mask_i64gather_{0.data_type}", + "width": [128, 256], + "llvm": "gather.q.{0.data_type_short}{0.width_suffix}", + "ret": ["s64", "f64"], + "args": ["0", "0SPc/S8", "s64", "0s->0", "S32/8"] + }, + { + "intrinsic": "{0.width_mm}_maskload_{0.data_type}", + "width": [128, 256], + "llvm": "maskload.{0.data_type_short}{0.width_suffix}", + "ret": ["s(32-64)"], + "args": ["0Pc/S8", "0"] + }, + { + "intrinsic": "{2.width_mm}_maskstore_{2.data_type}", + "width": [128, 256], + "llvm": "maskstore.{2.data_type_short}{2.width_suffix}", + "ret": "V", + "args": ["S(32-64)Pm/S8", "1Dv", "2"] + }, { "intrinsic": "256_max_{0.data_type}", "width": [256], diff --git a/src/etc/platform-intrinsics/x86/sse.json b/src/etc/platform-intrinsics/x86/sse.json index 27da842934c0c..adff0dc41b2af 100644 --- a/src/etc/platform-intrinsics/x86/sse.json +++ b/src/etc/platform-intrinsics/x86/sse.json @@ -42,6 +42,13 @@ "llvm": "!llvm.sqrt.v4f32", "ret": "f32", "args": ["0"] + }, + { + "intrinsic": "_storeu_ps", + "width": [128], + "llvm": "storeu.ps", + "ret": "V", + "args": ["F32Pm/S8", "f32"] } ] } diff --git a/src/etc/platform-intrinsics/x86/sse2.json b/src/etc/platform-intrinsics/x86/sse2.json index abd0b369573a0..d09980d95f31b 100644 --- a/src/etc/platform-intrinsics/x86/sse2.json +++ b/src/etc/platform-intrinsics/x86/sse2.json @@ -15,6 +15,13 @@ "ret": "u(8-16)", "args": ["0", "0"] }, + { + "intrinsic": "_lfence", + "width": [128], + "llvm": "lfence", + "ret": "V", + "args": [] + }, { "intrinsic": "_madd_epi16", "width": [128], @@ -22,6 +29,13 @@ "ret": "s32", "args": ["s16", "s16"] }, + { + "intrinsic": "_maskmoveu_si128", + "width": [128], + "llvm": "maskmov.dqu", + "ret": "V", + "args": ["u8", "u8", "U8Pm"] + }, { "intrinsic": "_max_{0.data_type}", "width": [128], @@ -36,6 +50,13 @@ "ret": "f64", "args": ["0", "0"] }, + { + "intrinsic": "_mfence", + "width": [128], + "llvm": "fence", + "ret": "V", + "args": [] + }, { "intrinsic": "_min_{0.data_type}", "width": [128], @@ -99,6 +120,13 @@ "ret": "u64", "args": ["u8", "u8"] }, + { + "intrinsic": "_sfence", + "width": [128], + "llvm": "sfence", + "ret": "V", + "args": [] + }, { "intrinsic": "_sqrt_pd", "width": [128], @@ -106,6 +134,20 @@ "ret": "f64", "args": ["0"] }, + { + "intrinsic": "_storeu_pd", + "width": [128], + "llvm": "storeu.pd", + "ret": "V", + "args": ["F64Pm/U8", "f64"] + }, + { + "intrinsic": "_storeu_si128", + "width": [128], + "llvm": "storeu.dq", + "ret": "V", + "args": ["u8Pm/U8", "u8"] + }, { "intrinsic": "_subs_{0.data_type}", "width": [128], diff --git a/src/etc/platform-intrinsics/x86/sse3.json b/src/etc/platform-intrinsics/x86/sse3.json index 376e32fa91568..ed13595929d1b 100644 --- a/src/etc/platform-intrinsics/x86/sse3.json +++ b/src/etc/platform-intrinsics/x86/sse3.json @@ -21,6 +21,13 @@ "llvm": "hsub.{0.data_type}", "ret": "f(32-64)", "args": ["0", "0"] + }, + { + "intrinsic": "_lddqu_si128", + "width": [128], + "llvm": "ldu.dq", + "ret": "u8", + "args": ["0Pc/S8"] } ] } diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 0959029b953b8..8c785b109236d 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -19,6 +19,7 @@ integer constants", issue = "27778")] +use borrow::{Borrow, BorrowMut}; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; use convert::{AsRef, AsMut}; @@ -70,6 +71,20 @@ macro_rules! array_impls { } } + #[stable(feature = "array_borrow", since = "1.4.0")] + impl Borrow<[T]> for [T; $N] { + fn borrow(&self) -> &[T] { + self + } + } + + #[stable(feature = "array_borrow", since = "1.4.0")] + impl BorrowMut<[T]> for [T; $N] { + fn borrow_mut(&mut self) -> &mut [T] { + self + } + } + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for [T; $N] { fn clone(&self) -> [T; $N] { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 767eab69733c3..8d592c9262958 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -667,7 +667,7 @@ fn is_useful(cx: &MatchCheckCtxt, match real_pat.node { hir::PatIdent(hir::BindByRef(..), _, _) => { - left_ty.builtin_deref(false).unwrap().ty + left_ty.builtin_deref(false, NoPreference).unwrap().ty } _ => left_ty, } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index a8c80d52209e4..ba7c675817f5d 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -400,7 +400,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { // a bind-by-ref means that the base_ty will be the type of the ident itself, // but what we want here is the type of the underlying value being borrowed. // So peel off one-level, turning the &T into T. - match base_ty.builtin_deref(false) { + match base_ty.builtin_deref(false, ty::NoPreference) { Some(t) => t.ty, None => { return Err(()); } } @@ -897,7 +897,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { None => base_cmt }; let base_cmt_ty = base_cmt.ty; - match base_cmt_ty.builtin_deref(true) { + match base_cmt_ty.builtin_deref(true, ty::NoPreference) { Some(mt) => { let ret = self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty, @@ -1044,7 +1044,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { span:elt.span(), cat:cat_deref(base_cmt.clone(), 0, ptr), mutbl:m, - ty: match base_cmt.ty.builtin_deref(false) { + ty: match base_cmt.ty.builtin_deref(false, ty::NoPreference) { Some(mt) => mt.ty, None => self.tcx().sess.bug("Found non-derefable type") }, diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index 3c6e939833fff..3a2602cd5b448 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -92,14 +92,13 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>, // Check methods for violations. let mut violations: Vec<_> = tcx.trait_items(trait_def_id).iter() - .flat_map(|item| { + .filter_map(|item| { match *item { ty::MethodTraitItem(ref m) => { object_safety_violation_for_method(tcx, trait_def_id, &**m) .map(|code| ObjectSafetyViolation::Method(m.clone(), code)) - .into_iter() } - _ => None.into_iter(), + _ => None, } }) .collect(); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 541bc8896aa3e..2e17a063775c6 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -29,6 +29,7 @@ pub use self::BoundRegion::*; pub use self::TypeVariants::*; pub use self::IntVarValue::*; pub use self::CopyImplementationError::*; +pub use self::LvaluePreference::*; pub use self::BuiltinBound::Send as BoundSend; pub use self::BuiltinBound::Sized as BoundSized; @@ -4828,6 +4829,21 @@ impl<'tcx> TyS<'tcx> { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum LvaluePreference { + PreferMutLvalue, + NoPreference +} + +impl LvaluePreference { + pub fn from_mutbl(m: hir::Mutability) -> Self { + match m { + hir::MutMutable => PreferMutLvalue, + hir::MutImmutable => NoPreference, + } + } +} + /// Describes whether a type is representable. For types that are not /// representable, 'SelfRecursive' and 'ContainsRecursive' are used to /// distinguish between types that are recursive with themselves and types that @@ -5073,12 +5089,15 @@ impl<'tcx> TyS<'tcx> { // // The parameter `explicit` indicates if this is an *explicit* dereference. // Some types---notably unsafe ptrs---can only be dereferenced explicitly. - pub fn builtin_deref(&self, explicit: bool) -> Option> { + pub fn builtin_deref(&self, explicit: bool, pref: LvaluePreference) + -> Option> + { match self.sty { TyBox(ty) => { Some(TypeAndMut { ty: ty, - mutbl: hir::MutImmutable, + mutbl: + if pref == PreferMutLvalue { hir::MutMutable } else { hir::MutImmutable }, }) }, TyRef(_, mt) => Some(mt), @@ -5183,7 +5202,7 @@ impl<'tcx> TyS<'tcx> { } None => {} } - match adjusted_ty.builtin_deref(true) { + match adjusted_ty.builtin_deref(true, NoPreference) { Some(mt) => { adjusted_ty = mt.ty; } None => { cx.sess.span_bug( diff --git a/src/librustc_platform_intrinsics/aarch64.rs b/src/librustc_platform_intrinsics/aarch64.rs index 1f581d8ce855a..a3084d903e27f 100644 --- a/src/librustc_platform_intrinsics/aarch64.rs +++ b/src/librustc_platform_intrinsics/aarch64.rs @@ -13,7 +13,7 @@ #![allow(unused_imports)] -use {Intrinsic, i, u, f, v, agg}; +use {Intrinsic, i, i_, u, u_, f, v, v_, agg, p, void}; use IntrinsicDef::Named; use rustc::middle::ty; @@ -1910,6 +1910,606 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(u(8), 16), definition: Named("llvm.aarch64.neon.rbit.v16i8") }, + "ld2_s8" => Intrinsic { + inputs: vec![p(true, i(8), Some(v(i(8), 8)))], + output: agg(false, vec![v(i(8), 8), v(i(8), 8)]), + definition: Named("llvm.aarch64.neon.ld2.v8i8.p0v8i8") + }, + "ld2_u8" => Intrinsic { + inputs: vec![p(true, u(8), Some(v(u(8), 8)))], + output: agg(false, vec![v(u(8), 8), v(u(8), 8)]), + definition: Named("llvm.aarch64.neon.ld2.v8i8.p0v8i8") + }, + "ld2_s16" => Intrinsic { + inputs: vec![p(true, i(16), Some(v(i(16), 4)))], + output: agg(false, vec![v(i(16), 4), v(i(16), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4i16.p0v4i16") + }, + "ld2_u16" => Intrinsic { + inputs: vec![p(true, u(16), Some(v(u(16), 4)))], + output: agg(false, vec![v(u(16), 4), v(u(16), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4i16.p0v4i16") + }, + "ld2_s32" => Intrinsic { + inputs: vec![p(true, i(32), Some(v(i(32), 2)))], + output: agg(false, vec![v(i(32), 2), v(i(32), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2i32.p0v2i32") + }, + "ld2_u32" => Intrinsic { + inputs: vec![p(true, u(32), Some(v(u(32), 2)))], + output: agg(false, vec![v(u(32), 2), v(u(32), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2i32.p0v2i32") + }, + "ld2_s64" => Intrinsic { + inputs: vec![p(true, i(64), Some(v(i(64), 1)))], + output: agg(false, vec![v(i(64), 1), v(i(64), 1)]), + definition: Named("llvm.aarch64.neon.ld2.v1i64.p0v1i64") + }, + "ld2_u64" => Intrinsic { + inputs: vec![p(true, u(64), Some(v(u(64), 1)))], + output: agg(false, vec![v(u(64), 1), v(u(64), 1)]), + definition: Named("llvm.aarch64.neon.ld2.v1i64.p0v1i64") + }, + "ld2_f32" => Intrinsic { + inputs: vec![p(true, f(32), Some(v(f(32), 2)))], + output: agg(false, vec![v(f(32), 2), v(f(32), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2f32.p0v2f32") + }, + "ld2_f64" => Intrinsic { + inputs: vec![p(true, f(64), Some(v(f(64), 1)))], + output: agg(false, vec![v(f(64), 1), v(f(64), 1)]), + definition: Named("llvm.aarch64.neon.ld2.v1f64.p0v1f64") + }, + "ld2q_s8" => Intrinsic { + inputs: vec![p(true, i(8), Some(v(i(8), 16)))], + output: agg(false, vec![v(i(8), 16), v(i(8), 16)]), + definition: Named("llvm.aarch64.neon.ld2.v16i8.p0v16i8") + }, + "ld2q_u8" => Intrinsic { + inputs: vec![p(true, u(8), Some(v(u(8), 16)))], + output: agg(false, vec![v(u(8), 16), v(u(8), 16)]), + definition: Named("llvm.aarch64.neon.ld2.v16i8.p0v16i8") + }, + "ld2q_s16" => Intrinsic { + inputs: vec![p(true, i(16), Some(v(i(16), 8)))], + output: agg(false, vec![v(i(16), 8), v(i(16), 8)]), + definition: Named("llvm.aarch64.neon.ld2.v8i16.p0v8i16") + }, + "ld2q_u16" => Intrinsic { + inputs: vec![p(true, u(16), Some(v(u(16), 8)))], + output: agg(false, vec![v(u(16), 8), v(u(16), 8)]), + definition: Named("llvm.aarch64.neon.ld2.v8i16.p0v8i16") + }, + "ld2q_s32" => Intrinsic { + inputs: vec![p(true, i(32), Some(v(i(32), 4)))], + output: agg(false, vec![v(i(32), 4), v(i(32), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4i32.p0v4i32") + }, + "ld2q_u32" => Intrinsic { + inputs: vec![p(true, u(32), Some(v(u(32), 4)))], + output: agg(false, vec![v(u(32), 4), v(u(32), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4i32.p0v4i32") + }, + "ld2q_s64" => Intrinsic { + inputs: vec![p(true, i(64), Some(v(i(64), 2)))], + output: agg(false, vec![v(i(64), 2), v(i(64), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2i64.p0v2i64") + }, + "ld2q_u64" => Intrinsic { + inputs: vec![p(true, u(64), Some(v(u(64), 2)))], + output: agg(false, vec![v(u(64), 2), v(u(64), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2i64.p0v2i64") + }, + "ld2q_f32" => Intrinsic { + inputs: vec![p(true, f(32), Some(v(f(32), 4)))], + output: agg(false, vec![v(f(32), 4), v(f(32), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4f32.p0v4f32") + }, + "ld2q_f64" => Intrinsic { + inputs: vec![p(true, f(64), Some(v(f(64), 2)))], + output: agg(false, vec![v(f(64), 2), v(f(64), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2f64.p0v2f64") + }, + "ld3_s8" => Intrinsic { + inputs: vec![p(true, i(8), Some(v(i(8), 8)))], + output: agg(false, vec![v(i(8), 8), v(i(8), 8), v(i(8), 8)]), + definition: Named("llvm.aarch64.neon.ld3.v8i8.p0v8i8") + }, + "ld3_u8" => Intrinsic { + inputs: vec![p(true, u(8), Some(v(u(8), 8)))], + output: agg(false, vec![v(u(8), 8), v(u(8), 8), v(u(8), 8)]), + definition: Named("llvm.aarch64.neon.ld3.v8i8.p0v8i8") + }, + "ld3_s16" => Intrinsic { + inputs: vec![p(true, i(16), Some(v(i(16), 4)))], + output: agg(false, vec![v(i(16), 4), v(i(16), 4), v(i(16), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4i16.p0v4i16") + }, + "ld3_u16" => Intrinsic { + inputs: vec![p(true, u(16), Some(v(u(16), 4)))], + output: agg(false, vec![v(u(16), 4), v(u(16), 4), v(u(16), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4i16.p0v4i16") + }, + "ld3_s32" => Intrinsic { + inputs: vec![p(true, i(32), Some(v(i(32), 2)))], + output: agg(false, vec![v(i(32), 2), v(i(32), 2), v(i(32), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2i32.p0v2i32") + }, + "ld3_u32" => Intrinsic { + inputs: vec![p(true, u(32), Some(v(u(32), 2)))], + output: agg(false, vec![v(u(32), 2), v(u(32), 2), v(u(32), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2i32.p0v2i32") + }, + "ld3_s64" => Intrinsic { + inputs: vec![p(true, i(64), Some(v(i(64), 1)))], + output: agg(false, vec![v(i(64), 1), v(i(64), 1), v(i(64), 1)]), + definition: Named("llvm.aarch64.neon.ld3.v1i64.p0v1i64") + }, + "ld3_u64" => Intrinsic { + inputs: vec![p(true, u(64), Some(v(u(64), 1)))], + output: agg(false, vec![v(u(64), 1), v(u(64), 1), v(u(64), 1)]), + definition: Named("llvm.aarch64.neon.ld3.v1i64.p0v1i64") + }, + "ld3_f32" => Intrinsic { + inputs: vec![p(true, f(32), Some(v(f(32), 2)))], + output: agg(false, vec![v(f(32), 2), v(f(32), 2), v(f(32), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2f32.p0v2f32") + }, + "ld3_f64" => Intrinsic { + inputs: vec![p(true, f(64), Some(v(f(64), 1)))], + output: agg(false, vec![v(f(64), 1), v(f(64), 1), v(f(64), 1)]), + definition: Named("llvm.aarch64.neon.ld3.v1f64.p0v1f64") + }, + "ld3q_s8" => Intrinsic { + inputs: vec![p(true, i(8), Some(v(i(8), 16)))], + output: agg(false, vec![v(i(8), 16), v(i(8), 16), v(i(8), 16)]), + definition: Named("llvm.aarch64.neon.ld3.v16i8.p0v16i8") + }, + "ld3q_u8" => Intrinsic { + inputs: vec![p(true, u(8), Some(v(u(8), 16)))], + output: agg(false, vec![v(u(8), 16), v(u(8), 16), v(u(8), 16)]), + definition: Named("llvm.aarch64.neon.ld3.v16i8.p0v16i8") + }, + "ld3q_s16" => Intrinsic { + inputs: vec![p(true, i(16), Some(v(i(16), 8)))], + output: agg(false, vec![v(i(16), 8), v(i(16), 8), v(i(16), 8)]), + definition: Named("llvm.aarch64.neon.ld3.v8i16.p0v8i16") + }, + "ld3q_u16" => Intrinsic { + inputs: vec![p(true, u(16), Some(v(u(16), 8)))], + output: agg(false, vec![v(u(16), 8), v(u(16), 8), v(u(16), 8)]), + definition: Named("llvm.aarch64.neon.ld3.v8i16.p0v8i16") + }, + "ld3q_s32" => Intrinsic { + inputs: vec![p(true, i(32), Some(v(i(32), 4)))], + output: agg(false, vec![v(i(32), 4), v(i(32), 4), v(i(32), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4i32.p0v4i32") + }, + "ld3q_u32" => Intrinsic { + inputs: vec![p(true, u(32), Some(v(u(32), 4)))], + output: agg(false, vec![v(u(32), 4), v(u(32), 4), v(u(32), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4i32.p0v4i32") + }, + "ld3q_s64" => Intrinsic { + inputs: vec![p(true, i(64), Some(v(i(64), 2)))], + output: agg(false, vec![v(i(64), 2), v(i(64), 2), v(i(64), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2i64.p0v2i64") + }, + "ld3q_u64" => Intrinsic { + inputs: vec![p(true, u(64), Some(v(u(64), 2)))], + output: agg(false, vec![v(u(64), 2), v(u(64), 2), v(u(64), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2i64.p0v2i64") + }, + "ld3q_f32" => Intrinsic { + inputs: vec![p(true, f(32), Some(v(f(32), 4)))], + output: agg(false, vec![v(f(32), 4), v(f(32), 4), v(f(32), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4f32.p0v4f32") + }, + "ld3q_f64" => Intrinsic { + inputs: vec![p(true, f(64), Some(v(f(64), 2)))], + output: agg(false, vec![v(f(64), 2), v(f(64), 2), v(f(64), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2f64.p0v2f64") + }, + "ld4_s8" => Intrinsic { + inputs: vec![p(true, i(8), Some(v(i(8), 8)))], + output: agg(false, vec![v(i(8), 8), v(i(8), 8), v(i(8), 8), v(i(8), 8)]), + definition: Named("llvm.aarch64.neon.ld4.v8i8.p0v8i8") + }, + "ld4_u8" => Intrinsic { + inputs: vec![p(true, u(8), Some(v(u(8), 8)))], + output: agg(false, vec![v(u(8), 8), v(u(8), 8), v(u(8), 8), v(u(8), 8)]), + definition: Named("llvm.aarch64.neon.ld4.v8i8.p0v8i8") + }, + "ld4_s16" => Intrinsic { + inputs: vec![p(true, i(16), Some(v(i(16), 4)))], + output: agg(false, vec![v(i(16), 4), v(i(16), 4), v(i(16), 4), v(i(16), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4i16.p0v4i16") + }, + "ld4_u16" => Intrinsic { + inputs: vec![p(true, u(16), Some(v(u(16), 4)))], + output: agg(false, vec![v(u(16), 4), v(u(16), 4), v(u(16), 4), v(u(16), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4i16.p0v4i16") + }, + "ld4_s32" => Intrinsic { + inputs: vec![p(true, i(32), Some(v(i(32), 2)))], + output: agg(false, vec![v(i(32), 2), v(i(32), 2), v(i(32), 2), v(i(32), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2i32.p0v2i32") + }, + "ld4_u32" => Intrinsic { + inputs: vec![p(true, u(32), Some(v(u(32), 2)))], + output: agg(false, vec![v(u(32), 2), v(u(32), 2), v(u(32), 2), v(u(32), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2i32.p0v2i32") + }, + "ld4_s64" => Intrinsic { + inputs: vec![p(true, i(64), Some(v(i(64), 1)))], + output: agg(false, vec![v(i(64), 1), v(i(64), 1), v(i(64), 1), v(i(64), 1)]), + definition: Named("llvm.aarch64.neon.ld4.v1i64.p0v1i64") + }, + "ld4_u64" => Intrinsic { + inputs: vec![p(true, u(64), Some(v(u(64), 1)))], + output: agg(false, vec![v(u(64), 1), v(u(64), 1), v(u(64), 1), v(u(64), 1)]), + definition: Named("llvm.aarch64.neon.ld4.v1i64.p0v1i64") + }, + "ld4_f32" => Intrinsic { + inputs: vec![p(true, f(32), Some(v(f(32), 2)))], + output: agg(false, vec![v(f(32), 2), v(f(32), 2), v(f(32), 2), v(f(32), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2f32.p0v2f32") + }, + "ld4_f64" => Intrinsic { + inputs: vec![p(true, f(64), Some(v(f(64), 1)))], + output: agg(false, vec![v(f(64), 1), v(f(64), 1), v(f(64), 1), v(f(64), 1)]), + definition: Named("llvm.aarch64.neon.ld4.v1f64.p0v1f64") + }, + "ld4q_s8" => Intrinsic { + inputs: vec![p(true, i(8), Some(v(i(8), 16)))], + output: agg(false, vec![v(i(8), 16), v(i(8), 16), v(i(8), 16), v(i(8), 16)]), + definition: Named("llvm.aarch64.neon.ld4.v16i8.p0v16i8") + }, + "ld4q_u8" => Intrinsic { + inputs: vec![p(true, u(8), Some(v(u(8), 16)))], + output: agg(false, vec![v(u(8), 16), v(u(8), 16), v(u(8), 16), v(u(8), 16)]), + definition: Named("llvm.aarch64.neon.ld4.v16i8.p0v16i8") + }, + "ld4q_s16" => Intrinsic { + inputs: vec![p(true, i(16), Some(v(i(16), 8)))], + output: agg(false, vec![v(i(16), 8), v(i(16), 8), v(i(16), 8), v(i(16), 8)]), + definition: Named("llvm.aarch64.neon.ld4.v8i16.p0v8i16") + }, + "ld4q_u16" => Intrinsic { + inputs: vec![p(true, u(16), Some(v(u(16), 8)))], + output: agg(false, vec![v(u(16), 8), v(u(16), 8), v(u(16), 8), v(u(16), 8)]), + definition: Named("llvm.aarch64.neon.ld4.v8i16.p0v8i16") + }, + "ld4q_s32" => Intrinsic { + inputs: vec![p(true, i(32), Some(v(i(32), 4)))], + output: agg(false, vec![v(i(32), 4), v(i(32), 4), v(i(32), 4), v(i(32), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4i32.p0v4i32") + }, + "ld4q_u32" => Intrinsic { + inputs: vec![p(true, u(32), Some(v(u(32), 4)))], + output: agg(false, vec![v(u(32), 4), v(u(32), 4), v(u(32), 4), v(u(32), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4i32.p0v4i32") + }, + "ld4q_s64" => Intrinsic { + inputs: vec![p(true, i(64), Some(v(i(64), 2)))], + output: agg(false, vec![v(i(64), 2), v(i(64), 2), v(i(64), 2), v(i(64), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2i64.p0v2i64") + }, + "ld4q_u64" => Intrinsic { + inputs: vec![p(true, u(64), Some(v(u(64), 2)))], + output: agg(false, vec![v(u(64), 2), v(u(64), 2), v(u(64), 2), v(u(64), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2i64.p0v2i64") + }, + "ld4q_f32" => Intrinsic { + inputs: vec![p(true, f(32), Some(v(f(32), 4)))], + output: agg(false, vec![v(f(32), 4), v(f(32), 4), v(f(32), 4), v(f(32), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4f32.p0v4f32") + }, + "ld4q_f64" => Intrinsic { + inputs: vec![p(true, f(64), Some(v(f(64), 2)))], + output: agg(false, vec![v(f(64), 2), v(f(64), 2), v(f(64), 2), v(f(64), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2f64.p0v2f64") + }, + "ld2_dup_s8" => Intrinsic { + inputs: vec![p(true, i(8), None)], + output: agg(false, vec![v(i(8), 8), v(i(8), 8)]), + definition: Named("llvm.aarch64.neon.ld2.v8i8.p0i8") + }, + "ld2_dup_u8" => Intrinsic { + inputs: vec![p(true, u(8), None)], + output: agg(false, vec![v(u(8), 8), v(u(8), 8)]), + definition: Named("llvm.aarch64.neon.ld2.v8i8.p0i8") + }, + "ld2_dup_s16" => Intrinsic { + inputs: vec![p(true, i(16), None)], + output: agg(false, vec![v(i(16), 4), v(i(16), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4i16.p0i16") + }, + "ld2_dup_u16" => Intrinsic { + inputs: vec![p(true, u(16), None)], + output: agg(false, vec![v(u(16), 4), v(u(16), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4i16.p0i16") + }, + "ld2_dup_s32" => Intrinsic { + inputs: vec![p(true, i(32), None)], + output: agg(false, vec![v(i(32), 2), v(i(32), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2i32.p0i32") + }, + "ld2_dup_u32" => Intrinsic { + inputs: vec![p(true, u(32), None)], + output: agg(false, vec![v(u(32), 2), v(u(32), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2i32.p0i32") + }, + "ld2_dup_s64" => Intrinsic { + inputs: vec![p(true, i(64), None)], + output: agg(false, vec![v(i(64), 1), v(i(64), 1)]), + definition: Named("llvm.aarch64.neon.ld2.v1i64.p0i64") + }, + "ld2_dup_u64" => Intrinsic { + inputs: vec![p(true, u(64), None)], + output: agg(false, vec![v(u(64), 1), v(u(64), 1)]), + definition: Named("llvm.aarch64.neon.ld2.v1i64.p0i64") + }, + "ld2_dup_f32" => Intrinsic { + inputs: vec![p(true, f(32), None)], + output: agg(false, vec![v(f(32), 2), v(f(32), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2f32.p0f32") + }, + "ld2_dup_f64" => Intrinsic { + inputs: vec![p(true, f(64), None)], + output: agg(false, vec![v(f(64), 1), v(f(64), 1)]), + definition: Named("llvm.aarch64.neon.ld2.v1f64.p0f64") + }, + "ld2q_dup_s8" => Intrinsic { + inputs: vec![p(true, i(8), None)], + output: agg(false, vec![v(i(8), 16), v(i(8), 16)]), + definition: Named("llvm.aarch64.neon.ld2.v16i8.p0i8") + }, + "ld2q_dup_u8" => Intrinsic { + inputs: vec![p(true, u(8), None)], + output: agg(false, vec![v(u(8), 16), v(u(8), 16)]), + definition: Named("llvm.aarch64.neon.ld2.v16i8.p0i8") + }, + "ld2q_dup_s16" => Intrinsic { + inputs: vec![p(true, i(16), None)], + output: agg(false, vec![v(i(16), 8), v(i(16), 8)]), + definition: Named("llvm.aarch64.neon.ld2.v8i16.p0i16") + }, + "ld2q_dup_u16" => Intrinsic { + inputs: vec![p(true, u(16), None)], + output: agg(false, vec![v(u(16), 8), v(u(16), 8)]), + definition: Named("llvm.aarch64.neon.ld2.v8i16.p0i16") + }, + "ld2q_dup_s32" => Intrinsic { + inputs: vec![p(true, i(32), None)], + output: agg(false, vec![v(i(32), 4), v(i(32), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4i32.p0i32") + }, + "ld2q_dup_u32" => Intrinsic { + inputs: vec![p(true, u(32), None)], + output: agg(false, vec![v(u(32), 4), v(u(32), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4i32.p0i32") + }, + "ld2q_dup_s64" => Intrinsic { + inputs: vec![p(true, i(64), None)], + output: agg(false, vec![v(i(64), 2), v(i(64), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2i64.p0i64") + }, + "ld2q_dup_u64" => Intrinsic { + inputs: vec![p(true, u(64), None)], + output: agg(false, vec![v(u(64), 2), v(u(64), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2i64.p0i64") + }, + "ld2q_dup_f32" => Intrinsic { + inputs: vec![p(true, f(32), None)], + output: agg(false, vec![v(f(32), 4), v(f(32), 4)]), + definition: Named("llvm.aarch64.neon.ld2.v4f32.p0f32") + }, + "ld2q_dup_f64" => Intrinsic { + inputs: vec![p(true, f(64), None)], + output: agg(false, vec![v(f(64), 2), v(f(64), 2)]), + definition: Named("llvm.aarch64.neon.ld2.v2f64.p0f64") + }, + "ld3_dup_s8" => Intrinsic { + inputs: vec![p(true, i(8), None)], + output: agg(false, vec![v(i(8), 8), v(i(8), 8), v(i(8), 8)]), + definition: Named("llvm.aarch64.neon.ld3.v8i8.p0i8") + }, + "ld3_dup_u8" => Intrinsic { + inputs: vec![p(true, u(8), None)], + output: agg(false, vec![v(u(8), 8), v(u(8), 8), v(u(8), 8)]), + definition: Named("llvm.aarch64.neon.ld3.v8i8.p0i8") + }, + "ld3_dup_s16" => Intrinsic { + inputs: vec![p(true, i(16), None)], + output: agg(false, vec![v(i(16), 4), v(i(16), 4), v(i(16), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4i16.p0i16") + }, + "ld3_dup_u16" => Intrinsic { + inputs: vec![p(true, u(16), None)], + output: agg(false, vec![v(u(16), 4), v(u(16), 4), v(u(16), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4i16.p0i16") + }, + "ld3_dup_s32" => Intrinsic { + inputs: vec![p(true, i(32), None)], + output: agg(false, vec![v(i(32), 2), v(i(32), 2), v(i(32), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2i32.p0i32") + }, + "ld3_dup_u32" => Intrinsic { + inputs: vec![p(true, u(32), None)], + output: agg(false, vec![v(u(32), 2), v(u(32), 2), v(u(32), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2i32.p0i32") + }, + "ld3_dup_s64" => Intrinsic { + inputs: vec![p(true, i(64), None)], + output: agg(false, vec![v(i(64), 1), v(i(64), 1), v(i(64), 1)]), + definition: Named("llvm.aarch64.neon.ld3.v1i64.p0i64") + }, + "ld3_dup_u64" => Intrinsic { + inputs: vec![p(true, u(64), None)], + output: agg(false, vec![v(u(64), 1), v(u(64), 1), v(u(64), 1)]), + definition: Named("llvm.aarch64.neon.ld3.v1i64.p0i64") + }, + "ld3_dup_f32" => Intrinsic { + inputs: vec![p(true, f(32), None)], + output: agg(false, vec![v(f(32), 2), v(f(32), 2), v(f(32), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2f32.p0f32") + }, + "ld3_dup_f64" => Intrinsic { + inputs: vec![p(true, f(64), None)], + output: agg(false, vec![v(f(64), 1), v(f(64), 1), v(f(64), 1)]), + definition: Named("llvm.aarch64.neon.ld3.v1f64.p0f64") + }, + "ld3q_dup_s8" => Intrinsic { + inputs: vec![p(true, i(8), None)], + output: agg(false, vec![v(i(8), 16), v(i(8), 16), v(i(8), 16)]), + definition: Named("llvm.aarch64.neon.ld3.v16i8.p0i8") + }, + "ld3q_dup_u8" => Intrinsic { + inputs: vec![p(true, u(8), None)], + output: agg(false, vec![v(u(8), 16), v(u(8), 16), v(u(8), 16)]), + definition: Named("llvm.aarch64.neon.ld3.v16i8.p0i8") + }, + "ld3q_dup_s16" => Intrinsic { + inputs: vec![p(true, i(16), None)], + output: agg(false, vec![v(i(16), 8), v(i(16), 8), v(i(16), 8)]), + definition: Named("llvm.aarch64.neon.ld3.v8i16.p0i16") + }, + "ld3q_dup_u16" => Intrinsic { + inputs: vec![p(true, u(16), None)], + output: agg(false, vec![v(u(16), 8), v(u(16), 8), v(u(16), 8)]), + definition: Named("llvm.aarch64.neon.ld3.v8i16.p0i16") + }, + "ld3q_dup_s32" => Intrinsic { + inputs: vec![p(true, i(32), None)], + output: agg(false, vec![v(i(32), 4), v(i(32), 4), v(i(32), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4i32.p0i32") + }, + "ld3q_dup_u32" => Intrinsic { + inputs: vec![p(true, u(32), None)], + output: agg(false, vec![v(u(32), 4), v(u(32), 4), v(u(32), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4i32.p0i32") + }, + "ld3q_dup_s64" => Intrinsic { + inputs: vec![p(true, i(64), None)], + output: agg(false, vec![v(i(64), 2), v(i(64), 2), v(i(64), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2i64.p0i64") + }, + "ld3q_dup_u64" => Intrinsic { + inputs: vec![p(true, u(64), None)], + output: agg(false, vec![v(u(64), 2), v(u(64), 2), v(u(64), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2i64.p0i64") + }, + "ld3q_dup_f32" => Intrinsic { + inputs: vec![p(true, f(32), None)], + output: agg(false, vec![v(f(32), 4), v(f(32), 4), v(f(32), 4)]), + definition: Named("llvm.aarch64.neon.ld3.v4f32.p0f32") + }, + "ld3q_dup_f64" => Intrinsic { + inputs: vec![p(true, f(64), None)], + output: agg(false, vec![v(f(64), 2), v(f(64), 2), v(f(64), 2)]), + definition: Named("llvm.aarch64.neon.ld3.v2f64.p0f64") + }, + "ld4_dup_s8" => Intrinsic { + inputs: vec![p(true, i(8), None)], + output: agg(false, vec![v(i(8), 8), v(i(8), 8), v(i(8), 8), v(i(8), 8)]), + definition: Named("llvm.aarch64.neon.ld4.v8i8.p0i8") + }, + "ld4_dup_u8" => Intrinsic { + inputs: vec![p(true, u(8), None)], + output: agg(false, vec![v(u(8), 8), v(u(8), 8), v(u(8), 8), v(u(8), 8)]), + definition: Named("llvm.aarch64.neon.ld4.v8i8.p0i8") + }, + "ld4_dup_s16" => Intrinsic { + inputs: vec![p(true, i(16), None)], + output: agg(false, vec![v(i(16), 4), v(i(16), 4), v(i(16), 4), v(i(16), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4i16.p0i16") + }, + "ld4_dup_u16" => Intrinsic { + inputs: vec![p(true, u(16), None)], + output: agg(false, vec![v(u(16), 4), v(u(16), 4), v(u(16), 4), v(u(16), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4i16.p0i16") + }, + "ld4_dup_s32" => Intrinsic { + inputs: vec![p(true, i(32), None)], + output: agg(false, vec![v(i(32), 2), v(i(32), 2), v(i(32), 2), v(i(32), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2i32.p0i32") + }, + "ld4_dup_u32" => Intrinsic { + inputs: vec![p(true, u(32), None)], + output: agg(false, vec![v(u(32), 2), v(u(32), 2), v(u(32), 2), v(u(32), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2i32.p0i32") + }, + "ld4_dup_s64" => Intrinsic { + inputs: vec![p(true, i(64), None)], + output: agg(false, vec![v(i(64), 1), v(i(64), 1), v(i(64), 1), v(i(64), 1)]), + definition: Named("llvm.aarch64.neon.ld4.v1i64.p0i64") + }, + "ld4_dup_u64" => Intrinsic { + inputs: vec![p(true, u(64), None)], + output: agg(false, vec![v(u(64), 1), v(u(64), 1), v(u(64), 1), v(u(64), 1)]), + definition: Named("llvm.aarch64.neon.ld4.v1i64.p0i64") + }, + "ld4_dup_f32" => Intrinsic { + inputs: vec![p(true, f(32), None)], + output: agg(false, vec![v(f(32), 2), v(f(32), 2), v(f(32), 2), v(f(32), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2f32.p0f32") + }, + "ld4_dup_f64" => Intrinsic { + inputs: vec![p(true, f(64), None)], + output: agg(false, vec![v(f(64), 1), v(f(64), 1), v(f(64), 1), v(f(64), 1)]), + definition: Named("llvm.aarch64.neon.ld4.v1f64.p0f64") + }, + "ld4q_dup_s8" => Intrinsic { + inputs: vec![p(true, i(8), None)], + output: agg(false, vec![v(i(8), 16), v(i(8), 16), v(i(8), 16), v(i(8), 16)]), + definition: Named("llvm.aarch64.neon.ld4.v16i8.p0i8") + }, + "ld4q_dup_u8" => Intrinsic { + inputs: vec![p(true, u(8), None)], + output: agg(false, vec![v(u(8), 16), v(u(8), 16), v(u(8), 16), v(u(8), 16)]), + definition: Named("llvm.aarch64.neon.ld4.v16i8.p0i8") + }, + "ld4q_dup_s16" => Intrinsic { + inputs: vec![p(true, i(16), None)], + output: agg(false, vec![v(i(16), 8), v(i(16), 8), v(i(16), 8), v(i(16), 8)]), + definition: Named("llvm.aarch64.neon.ld4.v8i16.p0i16") + }, + "ld4q_dup_u16" => Intrinsic { + inputs: vec![p(true, u(16), None)], + output: agg(false, vec![v(u(16), 8), v(u(16), 8), v(u(16), 8), v(u(16), 8)]), + definition: Named("llvm.aarch64.neon.ld4.v8i16.p0i16") + }, + "ld4q_dup_s32" => Intrinsic { + inputs: vec![p(true, i(32), None)], + output: agg(false, vec![v(i(32), 4), v(i(32), 4), v(i(32), 4), v(i(32), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4i32.p0i32") + }, + "ld4q_dup_u32" => Intrinsic { + inputs: vec![p(true, u(32), None)], + output: agg(false, vec![v(u(32), 4), v(u(32), 4), v(u(32), 4), v(u(32), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4i32.p0i32") + }, + "ld4q_dup_s64" => Intrinsic { + inputs: vec![p(true, i(64), None)], + output: agg(false, vec![v(i(64), 2), v(i(64), 2), v(i(64), 2), v(i(64), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2i64.p0i64") + }, + "ld4q_dup_u64" => Intrinsic { + inputs: vec![p(true, u(64), None)], + output: agg(false, vec![v(u(64), 2), v(u(64), 2), v(u(64), 2), v(u(64), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2i64.p0i64") + }, + "ld4q_dup_f32" => Intrinsic { + inputs: vec![p(true, f(32), None)], + output: agg(false, vec![v(f(32), 4), v(f(32), 4), v(f(32), 4), v(f(32), 4)]), + definition: Named("llvm.aarch64.neon.ld4.v4f32.p0f32") + }, + "ld4q_dup_f64" => Intrinsic { + inputs: vec![p(true, f(64), None)], + output: agg(false, vec![v(f(64), 2), v(f(64), 2), v(f(64), 2), v(f(64), 2)]), + definition: Named("llvm.aarch64.neon.ld4.v2f64.p0f64") + }, "padd_s8" => Intrinsic { inputs: vec![v(i(8), 8), v(i(8), 8)], output: v(i(8), 8), diff --git a/src/librustc_platform_intrinsics/arm.rs b/src/librustc_platform_intrinsics/arm.rs index 8ea725ee95df8..89b147027b5e8 100644 --- a/src/librustc_platform_intrinsics/arm.rs +++ b/src/librustc_platform_intrinsics/arm.rs @@ -13,7 +13,7 @@ #![allow(unused_imports)] -use {Intrinsic, i, u, f, v, agg}; +use {Intrinsic, i, i_, u, u_, f, v, agg, p}; use IntrinsicDef::Named; use rustc::middle::ty; diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs index 1727347ef7bd5..9aee15b05df4c 100755 --- a/src/librustc_platform_intrinsics/lib.rs +++ b/src/librustc_platform_intrinsics/lib.rs @@ -30,10 +30,11 @@ pub struct Intrinsic { #[derive(Clone, Hash, Eq, PartialEq)] pub enum Type { + Void, Integer(/* signed */ bool, u8, /* llvm width */ u8), Float(u8), - Pointer(Box), - Vector(Box, u8), + Pointer(Box, Option>, /* const */ bool), + Vector(Box, Option>, u8), Aggregate(bool, Vec), } @@ -47,10 +48,19 @@ fn u(width: u8) -> Type { Type::Integer(false, width, width) } #[allow(dead_code)] fn u_(width: u8, llvm_width: u8) -> Type { Type::Integer(false, width, llvm_width) } fn f(width: u8) -> Type { Type::Float(width) } -fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) } +fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), None, length) } +fn v_(x: Type, bitcast: Type, length: u8) -> Type { + Type::Vector(Box::new(x), Some(Box::new(bitcast)), length) +} fn agg(flatten: bool, types: Vec) -> Type { Type::Aggregate(flatten, types) } +fn p(const_: bool, elem: Type, llvm_elem: Option) -> Type { + Type::Pointer(Box::new(elem), llvm_elem.map(Box::new), const_) +} +fn void() -> Type { + Type::Void +} mod x86; mod arm; diff --git a/src/librustc_platform_intrinsics/x86.rs b/src/librustc_platform_intrinsics/x86.rs index 64c31ccb50d4a..2dfd00e9ce3bf 100644 --- a/src/librustc_platform_intrinsics/x86.rs +++ b/src/librustc_platform_intrinsics/x86.rs @@ -13,7 +13,7 @@ #![allow(unused_imports)] -use {Intrinsic, i, i_, u, u_, f, v, agg}; +use {Intrinsic, i, i_, u, u_, f, v, v_, agg, p, void}; use IntrinsicDef::Named; use rustc::middle::ty; @@ -50,6 +50,11 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(f(32), 4), definition: Named("llvm.sqrt.v4f32") }, + "_storeu_ps" => Intrinsic { + inputs: vec![p(false, f(32), Some(i(8))), v(f(32), 4)], + output: void(), + definition: Named("llvm.x86.sse.storeu.ps") + }, "_adds_epi8" => Intrinsic { inputs: vec![v(i(8), 16), v(i(8), 16)], output: v(i(8), 16), @@ -80,11 +85,21 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(u(16), 8), definition: Named("llvm.x86.sse2.pavg.w") }, + "_lfence" => Intrinsic { + inputs: vec![], + output: void(), + definition: Named("llvm.x86.sse2.lfence") + }, "_madd_epi16" => Intrinsic { inputs: vec![v(i(16), 8), v(i(16), 8)], output: v(i(32), 4), definition: Named("llvm.x86.sse2.pmadd.wd") }, + "_maskmoveu_si128" => Intrinsic { + inputs: vec![v(u(8), 16), v(u(8), 16), p(false, u(8), None)], + output: void(), + definition: Named("llvm.x86.sse2.maskmov.dqu") + }, "_max_epi16" => Intrinsic { inputs: vec![v(i(16), 8), v(i(16), 8)], output: v(i(16), 8), @@ -100,6 +115,11 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(f(64), 2), definition: Named("llvm.x86.sse2.max.pd") }, + "_mfence" => Intrinsic { + inputs: vec![], + output: void(), + definition: Named("llvm.x86.sse2.fence") + }, "_min_epi16" => Intrinsic { inputs: vec![v(i(16), 8), v(i(16), 8)], output: v(i(16), 8), @@ -160,11 +180,26 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(u(64), 2), definition: Named("llvm.x86.sse2.psad.bw") }, + "_sfence" => Intrinsic { + inputs: vec![], + output: void(), + definition: Named("llvm.x86.sse2.sfence") + }, "_sqrt_pd" => Intrinsic { inputs: vec![v(f(64), 2)], output: v(f(64), 2), definition: Named("llvm.sqrt.v2f64") }, + "_storeu_pd" => Intrinsic { + inputs: vec![p(false, f(64), Some(u(8))), v(f(64), 2)], + output: void(), + definition: Named("llvm.x86.sse2.storeu.pd") + }, + "_storeu_si128" => Intrinsic { + inputs: vec![p(false, v(u(8), 16), Some(u(8))), v(u(8), 16)], + output: void(), + definition: Named("llvm.x86.sse2.storeu.dq") + }, "_subs_epi8" => Intrinsic { inputs: vec![v(i(8), 16), v(i(8), 16)], output: v(i(8), 16), @@ -215,6 +250,11 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(f(64), 2), definition: Named("llvm.x86.sse3.hsub.pd") }, + "_lddqu_si128" => Intrinsic { + inputs: vec![p(true, v(u(8), 16), Some(i(8)))], + output: v(u(8), 16), + definition: Named("llvm.x86.sse3.ldu.dq") + }, "_abs_epi8" => Intrinsic { inputs: vec![v(i(8), 16)], output: v(i(8), 16), @@ -490,6 +530,46 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(f(64), 4), definition: Named("llvm.x86.avx.max.pd.256") }, + "_maskload_ps" => Intrinsic { + inputs: vec![p(true, f(32), Some(i(8))), v_(i(32), f(32), 4)], + output: v(f(32), 4), + definition: Named("llvm.x86.avx.maskload.ps") + }, + "_maskload_pd" => Intrinsic { + inputs: vec![p(true, f(64), Some(i(8))), v_(i(64), f(64), 2)], + output: v(f(64), 2), + definition: Named("llvm.x86.avx.maskload.pd") + }, + "256_maskload_ps" => Intrinsic { + inputs: vec![p(true, f(32), Some(i(8))), v_(i(32), f(32), 8)], + output: v(f(32), 8), + definition: Named("llvm.x86.avx.maskload.ps.256") + }, + "256_maskload_pd" => Intrinsic { + inputs: vec![p(true, f(64), Some(i(8))), v_(i(64), f(64), 4)], + output: v(f(64), 4), + definition: Named("llvm.x86.avx.maskload.pd.256") + }, + "_maskstore_ps" => Intrinsic { + inputs: vec![p(false, f(32), Some(i(8))), v_(i(32), f(32), 4), v(f(32), 4)], + output: void(), + definition: Named("llvm.x86.avx.maskstore.ps") + }, + "_maskstore_pd" => Intrinsic { + inputs: vec![p(false, f(64), Some(i(8))), v_(i(64), f(64), 2), v(f(64), 2)], + output: void(), + definition: Named("llvm.x86.avx.maskstore.pd") + }, + "256_maskstore_ps" => Intrinsic { + inputs: vec![p(false, f(32), Some(i(8))), v_(i(32), f(32), 8), v(f(32), 8)], + output: void(), + definition: Named("llvm.x86.avx.maskstore.ps.256") + }, + "256_maskstore_pd" => Intrinsic { + inputs: vec![p(false, f(64), Some(i(8))), v_(i(64), f(64), 4), v(f(64), 4)], + output: void(), + definition: Named("llvm.x86.avx.maskstore.pd.256") + }, "256_min_ps" => Intrinsic { inputs: vec![v(f(32), 8), v(f(32), 8)], output: v(f(32), 8), @@ -540,6 +620,21 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(f(32), 8), definition: Named("llvm.x86.avx.rsqrt.ps.256") }, + "256_storeu_ps" => Intrinsic { + inputs: vec![p(false, v(f(32), 8), Some(u(8))), v(f(32), 8)], + output: void(), + definition: Named("llvm.x86.avx.storeu.ps.256") + }, + "256_storeu_pd" => Intrinsic { + inputs: vec![p(false, v(f(64), 4), Some(u(8))), v(f(64), 4)], + output: void(), + definition: Named("llvm.x86.avx.storeu.ps.256") + }, + "256_storeu_si256" => Intrinsic { + inputs: vec![p(false, v(u(8), 32), Some(u(8))), v(u(8), 32)], + output: void(), + definition: Named("llvm.x86.avx.storeu.dq.256") + }, "256_sqrt_ps" => Intrinsic { inputs: vec![v(f(32), 8)], output: v(f(32), 8), @@ -625,50 +720,60 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: i(32), definition: Named("llvm.x86.avx.ptestz.256") }, + "256_zeroall" => Intrinsic { + inputs: vec![], + output: void(), + definition: Named("llvm.x86.avx.vzeroall") + }, + "256_zeroupper" => Intrinsic { + inputs: vec![], + output: void(), + definition: Named("llvm.x86.avx.vzeroupper") + }, "256_abs_epi8" => Intrinsic { inputs: vec![v(i(8), 32)], output: v(i(8), 32), - definition: Named("llvm.x86.avx2.avx2.pabs.b") + definition: Named("llvm.x86.avx2.pabs.b") }, "256_abs_epi16" => Intrinsic { inputs: vec![v(i(16), 16)], output: v(i(16), 16), - definition: Named("llvm.x86.avx2.avx2.pabs.w") + definition: Named("llvm.x86.avx2.pabs.w") }, "256_abs_epi32" => Intrinsic { inputs: vec![v(i(32), 8)], output: v(i(32), 8), - definition: Named("llvm.x86.avx2.avx2.pabs.d") + definition: Named("llvm.x86.avx2.pabs.d") }, "256_adds_epi8" => Intrinsic { inputs: vec![v(i(8), 32), v(i(8), 32)], output: v(i(8), 32), - definition: Named("llvm.x86.avx2.avx2.padds.b") + definition: Named("llvm.x86.avx2.padds.b") }, "256_adds_epu8" => Intrinsic { inputs: vec![v(u(8), 32), v(u(8), 32)], output: v(u(8), 32), - definition: Named("llvm.x86.avx2.avx2.paddus.b") + definition: Named("llvm.x86.avx2.paddus.b") }, "256_adds_epi16" => Intrinsic { inputs: vec![v(i(16), 16), v(i(16), 16)], output: v(i(16), 16), - definition: Named("llvm.x86.avx2.avx2.padds.w") + definition: Named("llvm.x86.avx2.padds.w") }, "256_adds_epu16" => Intrinsic { inputs: vec![v(u(16), 16), v(u(16), 16)], output: v(u(16), 16), - definition: Named("llvm.x86.avx2.avx2.paddus.w") + definition: Named("llvm.x86.avx2.paddus.w") }, "256_avg_epu8" => Intrinsic { inputs: vec![v(u(8), 32), v(u(8), 32)], output: v(u(8), 32), - definition: Named("llvm.x86.avx2.avx2.pavg.b") + definition: Named("llvm.x86.avx2.pavg.b") }, "256_avg_epu16" => Intrinsic { inputs: vec![v(u(16), 16), v(u(16), 16)], output: v(u(16), 16), - definition: Named("llvm.x86.avx2.avx2.pavg.w") + definition: Named("llvm.x86.avx2.pavg.w") }, "256_hadd_epi16" => Intrinsic { inputs: vec![v(i(16), 16), v(i(16), 16)], @@ -710,6 +815,126 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option { output: v(i(16), 16), definition: Named("llvm.x86.avx2.pmadd.ub.sw") }, + "_mask_i32gather_epi32" => Intrinsic { + inputs: vec![v(i(32), 4), p(true, i(32), Some(i(8))), v(i(32), 4), v(i(32), 4), i_(32, 8)], + output: v(i(32), 4), + definition: Named("llvm.x86.avx2.gather.d.d") + }, + "_mask_i32gather_ps" => Intrinsic { + inputs: vec![v(f(32), 4), p(true, f(32), Some(i(8))), v(i(32), 4), v_(i(32), f(32), 4), i_(32, 8)], + output: v(f(32), 4), + definition: Named("llvm.x86.avx2.gather.d.ps") + }, + "256_mask_i32gather_epi32" => Intrinsic { + inputs: vec![v(i(32), 8), p(true, i(32), Some(i(8))), v(i(32), 8), v(i(32), 8), i_(32, 8)], + output: v(i(32), 8), + definition: Named("llvm.x86.avx2.gather.d.d.256") + }, + "256_mask_i32gather_ps" => Intrinsic { + inputs: vec![v(f(32), 8), p(true, f(32), Some(i(8))), v(i(32), 8), v_(i(32), f(32), 8), i_(32, 8)], + output: v(f(32), 8), + definition: Named("llvm.x86.avx2.gather.d.ps.256") + }, + "_mask_i32gather_epi64" => Intrinsic { + inputs: vec![v(i(64), 2), p(true, i(64), Some(i(8))), v(i(32), 4), v(i(64), 2), i_(32, 8)], + output: v(i(64), 2), + definition: Named("llvm.x86.avx2.gather.d.q") + }, + "_mask_i32gather_pd" => Intrinsic { + inputs: vec![v(f(64), 2), p(true, f(64), Some(i(8))), v(i(32), 4), v_(i(64), f(64), 2), i_(32, 8)], + output: v(f(64), 2), + definition: Named("llvm.x86.avx2.gather.d.pd") + }, + "256_mask_i32gather_epi64" => Intrinsic { + inputs: vec![v(i(64), 4), p(true, i(64), Some(i(8))), v(i(32), 4), v(i(64), 4), i_(32, 8)], + output: v(i(64), 4), + definition: Named("llvm.x86.avx2.gather.d.q.256") + }, + "256_mask_i32gather_pd" => Intrinsic { + inputs: vec![v(f(64), 4), p(true, f(64), Some(i(8))), v(i(32), 4), v_(i(64), f(64), 4), i_(32, 8)], + output: v(f(64), 4), + definition: Named("llvm.x86.avx2.gather.d.pd.256") + }, + "_mask_i64gather_epi32" => Intrinsic { + inputs: vec![v(i(32), 4), p(true, i(32), Some(i(8))), v(i(64), 2), v(i(32), 4), i_(32, 8)], + output: v(i(32), 4), + definition: Named("llvm.x86.avx2.gather.q.d") + }, + "_mask_i64gather_ps" => Intrinsic { + inputs: vec![v(f(32), 4), p(true, f(32), Some(i(8))), v(i(64), 2), v_(i(32), f(32), 4), i_(32, 8)], + output: v(f(32), 4), + definition: Named("llvm.x86.avx2.gather.q.ps") + }, + "256_mask_i64gather_epi32" => Intrinsic { + inputs: vec![v(i(32), 4), p(true, i(32), Some(i(8))), v(i(64), 4), v(i(32), 4), i_(32, 8)], + output: v(i(32), 4), + definition: Named("llvm.x86.avx2.gather.q.d") + }, + "256_mask_i64gather_ps" => Intrinsic { + inputs: vec![v(f(32), 4), p(true, f(32), Some(i(8))), v(i(64), 4), v_(i(32), f(32), 4), i_(32, 8)], + output: v(f(32), 4), + definition: Named("llvm.x86.avx2.gather.q.ps") + }, + "_mask_i64gather_epi64" => Intrinsic { + inputs: vec![v(i(64), 2), p(true, i(64), Some(i(8))), v(i(64), 2), v(i(64), 2), i_(32, 8)], + output: v(i(64), 2), + definition: Named("llvm.x86.avx2.gather.q.q") + }, + "_mask_i64gather_pd" => Intrinsic { + inputs: vec![v(f(64), 2), p(true, f(64), Some(i(8))), v(i(64), 2), v_(i(64), f(64), 2), i_(32, 8)], + output: v(f(64), 2), + definition: Named("llvm.x86.avx2.gather.q.pd") + }, + "256_mask_i64gather_epi64" => Intrinsic { + inputs: vec![v(i(64), 4), p(true, i(64), Some(i(8))), v(i(64), 4), v(i(64), 4), i_(32, 8)], + output: v(i(64), 4), + definition: Named("llvm.x86.avx2.gather.q.q.256") + }, + "256_mask_i64gather_pd" => Intrinsic { + inputs: vec![v(f(64), 4), p(true, f(64), Some(i(8))), v(i(64), 4), v_(i(64), f(64), 4), i_(32, 8)], + output: v(f(64), 4), + definition: Named("llvm.x86.avx2.gather.q.pd.256") + }, + "_maskload_epi32" => Intrinsic { + inputs: vec![p(true, v(i(32), 4), Some(i(8))), v(i(32), 4)], + output: v(i(32), 4), + definition: Named("llvm.x86.avx2.maskload.d") + }, + "_maskload_epi64" => Intrinsic { + inputs: vec![p(true, v(i(64), 2), Some(i(8))), v(i(64), 2)], + output: v(i(64), 2), + definition: Named("llvm.x86.avx2.maskload.q") + }, + "256_maskload_epi32" => Intrinsic { + inputs: vec![p(true, v(i(32), 8), Some(i(8))), v(i(32), 8)], + output: v(i(32), 8), + definition: Named("llvm.x86.avx2.maskload.d.256") + }, + "256_maskload_epi64" => Intrinsic { + inputs: vec![p(true, v(i(64), 4), Some(i(8))), v(i(64), 4)], + output: v(i(64), 4), + definition: Named("llvm.x86.avx2.maskload.q.256") + }, + "_maskstore_epi32" => Intrinsic { + inputs: vec![p(false, i(32), Some(i(8))), v(i(32), 4), v(i(32), 4)], + output: void(), + definition: Named("llvm.x86.avx2.maskstore.d") + }, + "_maskstore_epi64" => Intrinsic { + inputs: vec![p(false, i(64), Some(i(8))), v(i(64), 2), v(i(64), 2)], + output: void(), + definition: Named("llvm.x86.avx2.maskstore.q") + }, + "256_maskstore_epi32" => Intrinsic { + inputs: vec![p(false, i(32), Some(i(8))), v(i(32), 8), v(i(32), 8)], + output: void(), + definition: Named("llvm.x86.avx2.maskstore.d.256") + }, + "256_maskstore_epi64" => Intrinsic { + inputs: vec![p(false, i(64), Some(i(8))), v(i(64), 4), v(i(64), 4)], + output: void(), + definition: Named("llvm.x86.avx2.maskstore.q.256") + }, "256_max_epi8" => Intrinsic { inputs: vec![v(i(8), 32), v(i(8), 32)], output: v(i(8), 32), diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 9960d022d5300..62b2f2949fab6 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -71,13 +71,14 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> { span: SpanUtils<'l>, fmt: FmtStrs<'l>, - cur_scope: NodeId + cur_scope: NodeId, } impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { pub fn new(tcx: &'l ty::ctxt<'tcx>, analysis: &'l ty::CrateAnalysis, - output_file: Box) -> DumpCsvVisitor<'l, 'tcx> { + output_file: Box) + -> DumpCsvVisitor<'l, 'tcx> { let span_utils = SpanUtils::new(&tcx.sess); DumpCsvVisitor { sess: &tcx.sess, @@ -85,16 +86,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { save_ctxt: SaveContext::from_span_utils(tcx, span_utils.clone()), analysis: analysis, span: span_utils.clone(), - fmt: FmtStrs::new(box Recorder { - out: output_file, - dump_spans: false, - }, span_utils), - cur_scope: 0 + fmt: FmtStrs::new(box Recorder { out: output_file, dump_spans: false }, + span_utils), + cur_scope: 0, } } - fn nest(&mut self, scope_id: NodeId, f: F) where - F: FnOnce(&mut DumpCsvVisitor<'l, 'tcx>), + fn nest(&mut self, scope_id: NodeId, f: F) + where F: FnOnce(&mut DumpCsvVisitor<'l, 'tcx>) { let parent_scope = self.cur_scope; self.cur_scope = scope_id; @@ -140,9 +139,11 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { let mut segs = vec!(); for (i, (seg, span)) in path.segments.iter().zip(&spans).enumerate() { segs.push(seg.clone()); - let sub_path = ast::Path{span: *span, // span for the last segment - global: path.global, - segments: segs}; + let sub_path = ast::Path { + span: *span, // span for the last segment + global: path.global, + segments: segs, + }; let qualname = if i == 0 && path.global { format!("::{}", path_to_string(&sub_path)) } else { @@ -271,7 +272,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { def::DefPrimTy(_) => { self.sess.span_bug(span, &format!("lookup_def_kind for unexpected item: {:?}", def)); - }, + } } } @@ -357,9 +358,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { } } - fn process_struct_field_def(&mut self, - field: &ast::StructField, - parent_id: NodeId) { + fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) { let field_data = self.save_ctxt.get_field_data(field, parent_id); if let Some(field_data) = field_data { self.fmt.field_str(field.span, @@ -374,7 +373,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { // Dump generic params bindings, then visit_generics fn process_generic_params(&mut self, - generics:&ast::Generics, + generics: &ast::Generics, full_span: Span, prefix: &str, id: NodeId) { @@ -427,11 +426,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { self.nest(item.id, |v| v.visit_block(&body)); } - fn process_static_or_const_item(&mut self, - item: &ast::Item, - typ: &ast::Ty, - expr: &ast::Expr) - { + fn process_static_or_const_item(&mut self, item: &ast::Item, typ: &ast::Ty, expr: &ast::Expr) { let var_data = self.save_ctxt.get_item_data(item); down_cast_data!(var_data, VariableData, self, item.span); self.fmt.static_str(item.span, @@ -452,8 +447,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { ident: &ast::Ident, span: Span, typ: &ast::Ty, - expr: &ast::Expr) - { + expr: &ast::Expr) { let qualname = format!("::{}", self.tcx.map.path_to_string(id)); let sub_span = self.span.sub_span_after_keyword(span, @@ -641,8 +635,8 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { sub_span, id, item.id); - }, - None => () + } + None => (), } } @@ -653,8 +647,8 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { } } - fn process_mod(&mut self, - item: &ast::Item) { // The module in question, represented as an item. + // `item` is the module in question, represented as an item. + fn process_mod(&mut self, item: &ast::Item) { let mod_data = self.save_ctxt.get_item_data(item); down_cast_data!(mod_data, ModData, self, item.span); self.fmt.mod_str(item.span, @@ -665,10 +659,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { &mod_data.filename); } - fn process_path(&mut self, - id: NodeId, - path: &ast::Path, - ref_kind: Option) { + fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option) { if generated_code(path.span) { return; } @@ -737,7 +728,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { def::DefStruct(_) | def::DefVariant(..) | def::DefFn(..) => self.write_sub_paths_truncated(path, false), - _ => {}, + _ => {} } } @@ -783,9 +774,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { visit::walk_expr_opt(self, base) } - fn process_method_call(&mut self, - ex: &ast::Expr, - args: &Vec>) { + fn process_method_call(&mut self, ex: &ast::Expr, args: &Vec>) { if let Some(call_data) = self.save_ctxt.get_expr_data(ex) { down_cast_data!(call_data, MethodCallData, self, ex.span); self.fmt.meth_call_str(ex.span, @@ -799,7 +788,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { visit::walk_exprs(self, &args); } - fn process_pat(&mut self, p:&ast::Pat) { + fn process_pat(&mut self, p: &ast::Pat) { if generated_code(p.span) { return; } @@ -827,7 +816,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { self.visit_pat(&field.pat); } } - _ => visit::walk_pat(self, p) + _ => visit::walk_pat(self, p), } } } @@ -851,10 +840,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { sub_span, def_id, self.cur_scope), - None => {}, + None => {} } Some(def_id) - }, + } None => None, }; @@ -902,20 +891,19 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { match plid.node { ast::PathListIdent { id, .. } => { match self.lookup_type_ref(id) { - Some(def_id) => - match self.lookup_def_kind(id, plid.span) { - Some(kind) => { - self.fmt.ref_str( + Some(def_id) => match self.lookup_def_kind(id, plid.span) { + Some(kind) => { + self.fmt.ref_str( kind, plid.span, Some(plid.span), def_id, self.cur_scope); - } - None => () - }, - None => () + } + None => (), + }, + None => (), } - }, - ast::PathListMod { .. } => () + } + ast::PathListMod { .. } => (), } } @@ -978,7 +966,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { self.visit_ty(&**ty); self.process_generic_params(ty_params, item.span, &qualname, item.id); - }, + } ast::ItemMac(_) => (), _ => visit::walk_item(self, item), } @@ -1048,14 +1036,14 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { sub_span, id, self.cur_scope); - }, - None => () + } + None => (), } self.write_sub_paths_truncated(path, false); visit::walk_path(self, path); - }, + } _ => visit::walk_ty(self, t), } } @@ -1101,7 +1089,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { field_data.ref_id, field_data.scope); } - }, + } ast::ExprTupField(ref sub_ex, idx) => { if generated_code(sub_ex.span) { return @@ -1125,7 +1113,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { &format!("Expected struct or tuple \ type, found {:?}", ty)), } - }, + } ast::ExprClosure(_, ref decl, ref body) => { if generated_code(body.span) { return @@ -1146,7 +1134,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { // walk the body self.nest(ex.id, |v| v.visit_block(&**body)); - }, + } _ => { visit::walk_expr(self, ex) } @@ -1182,7 +1170,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { } let def = def_map.get(&id).unwrap().full_def(); match def { - def::DefLocal(id) => { + def::DefLocal(id) => { let value = if immut == ast::MutImmutable { self.span.snippet(p.span).to_string() } else { @@ -1205,7 +1193,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { def::DefConst(..) | def::DefAssociatedConst(..) => {} _ => error!("unexpected definition kind when processing collected paths: {:?}", - def) + def), } } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 42a7ea0a69353..9c6f1a0eb5a89 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -176,7 +176,7 @@ pub struct MethodCallData { impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { - pub fn new(tcx: &'l ty::ctxt<'tcx>) -> SaveContext <'l, 'tcx> { + pub fn new(tcx: &'l ty::ctxt<'tcx>) -> SaveContext<'l, 'tcx> { let span_utils = SpanUtils::new(&tcx.sess); SaveContext::from_span_utils(tcx, span_utils) } @@ -184,10 +184,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn from_span_utils(tcx: &'l ty::ctxt<'tcx>, span_utils: SpanUtils<'l>) -> SaveContext<'l, 'tcx> { - SaveContext { - tcx: tcx, - span_utils: span_utils, - } + SaveContext { tcx: tcx, span_utils: span_utils } } // List external crates used by the current crate. @@ -268,7 +265,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: self.enclosing_scope(item.id), filename: filename, }) - }, + } ast::ItemEnum(..) => { let enum_name = format!("::{}", self.tcx.map.path_to_string(item.id)); let val = self.span_utils.snippet(item.span); @@ -281,7 +278,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { qualname: enum_name, scope: self.enclosing_scope(item.id), }) - }, + } ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => { let mut type_data = None; let sub_span; @@ -297,7 +294,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: parent, ref_id: id, }); - }, + } _ => { // Less useful case, impl for a compound type. let span = typ.span; @@ -341,17 +338,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { value: "".to_owned(), type_value: typ, }) - }, + } _ => None, } } // FIXME would be nice to take a MethodItem here, but the ast provides both // trait and impl flavours, so the caller must do the disassembly. - pub fn get_method_data(&self, - id: ast::NodeId, - name: ast::Name, - span: Span) -> FunctionData { + pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> FunctionData { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. let qualname = match self.tcx.impl_of_method(DefId::local(id)) { @@ -367,7 +361,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { result.push_str(" as "); result.push_str( &self.tcx.item_path_str(def_id)); - }, + } None => {} } result.push_str(">"); @@ -377,14 +371,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { self.tcx.sess.span_bug(span, &format!("Container {} for method {} not an impl?", impl_id.node, id)); - }, + } } - }, + } _ => { self.tcx.sess.span_bug(span, &format!("Container {} for method {} is not a node item {:?}", impl_id.node, id, self.tcx.map.get(impl_id.node))); - }, + } }, None => match self.tcx.trait_of_item(DefId::local(id)) { Some(def_id) => { @@ -398,11 +392,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { def_id.node, id)); } } - }, + } None => { self.tcx.sess.span_bug(span, &format!("Could not find container for method {}", id)); - }, + } }, }; @@ -492,7 +486,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id; let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() { ty::ImplContainer(_) => (Some(method_id), None), - ty::TraitContainer(_) => (None, Some(method_id)) + ty::TraitContainer(_) => (None, Some(method_id)), }; let sub_span = self.span_utils.sub_span_for_meth_name(expr.span); let parent = self.enclosing_scope(expr.id); @@ -513,10 +507,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - pub fn get_path_data(&self, - id: NodeId, - path: &ast::Path) - -> Option { + pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option { let def_map = self.tcx.def_map.borrow(); if !def_map.contains_key(&id) { self.tcx.sess.span_bug(path.span, @@ -583,7 +574,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ref_id: def_id, decl_id: Some(decl_id), })) - }, + } def::DefFn(def_id, _) => { Some(Data::FunctionCallData(FunctionCallData { ref_id: def_id, @@ -663,9 +654,7 @@ struct PathCollector { impl PathCollector { fn new() -> PathCollector { - PathCollector { - collected_paths: vec![], - } + PathCollector { collected_paths: vec![] } } } @@ -722,7 +711,7 @@ pub fn process_crate(tcx: &ty::ctxt, None => { info!("Could not find crate name, using 'unknown_crate'"); String::from("unknown_crate") - }, + } }; info!("Dumping crate {}", cratename); @@ -775,5 +764,5 @@ fn escape(s: String) -> String { // If the expression is a macro expansion or other generated code, run screaming // and don't index. pub fn generated_code(span: Span) -> bool { - span.expn_id != NO_EXPANSION || span == DUMMY_SP + span.expn_id != NO_EXPANSION || span == DUMMY_SP } diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs index f9c3bf0694b1e..f8e6864985364 100644 --- a/src/librustc_trans/save/recorder.rs +++ b/src/librustc_trans/save/recorder.rs @@ -18,14 +18,14 @@ use middle::def_id::DefId; use std::io::Write; use syntax::ast; -use syntax::ast::{NodeId}; +use syntax::ast::NodeId; use syntax::codemap::*; const ZERO_DEF_ID: DefId = DefId { node: 0, krate: 0 }; pub struct Recorder { // output file - pub out: Box, + pub out: Box, pub dump_spans: bool, } @@ -37,11 +37,7 @@ impl Recorder { } } - pub fn dump_span(&mut self, - su: SpanUtils, - kind: &str, - span: Span, - _sub_span: Option) { + pub fn dump_span(&mut self, su: SpanUtils, kind: &str, span: Span, _sub_span: Option) { assert!(self.dump_spans); let result = format!("span,kind,{},{},text,\"{}\"\n", kind, su.extent_str(span), escape(su.snippet(span))); @@ -96,10 +92,7 @@ pub enum Row { impl<'a> FmtStrs<'a> { pub fn new(rec: Box, span: SpanUtils<'a>) -> FmtStrs<'a> { - FmtStrs { - recorder: rec, - span: span, - } + FmtStrs { recorder: rec, span: span } } // A map from kind of item to a tuple of @@ -111,47 +104,51 @@ impl<'a> FmtStrs<'a> { match r { Variable => ("variable", vec!("id","name","qualname","value","type","scopeid"), - true, true), + true, + true), Enum => ("enum", vec!("id","qualname","scopeid","value"), true, true), Variant => ("variant", vec!("id","name","qualname","type","value","scopeid"), - true, true), + true, + true), VariantStruct => ("variant_struct", vec!("id","ctor_id","qualname","type","value","scopeid"), - true, true), + true, + true), Function => ("function", vec!("id","qualname","declid","declidcrate","scopeid"), - true, true), + true, + true), MethodDecl => ("method_decl", vec!("id","qualname","scopeid"), true, true), Struct => ("struct", vec!("id","ctor_id","qualname","scopeid","value"), true, true), Trait => ("trait", vec!("id","qualname","scopeid","value"), true, true), Impl => ("impl", vec!("id","refid","refidcrate","traitid","traitidcrate","scopeid"), - true, true), + true, + true), Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false), - UseAlias => ("use_alias", - vec!("id","refid","refidcrate","name","scopeid"), - true, true), + UseAlias => ("use_alias", vec!("id","refid","refidcrate","name","scopeid"), true, true), UseGlob => ("use_glob", vec!("id","value","scopeid"), true, true), ExternCrate => ("extern_crate", vec!("id","name","location","crate","scopeid"), - true, true), + true, + true), Inheritance => ("inheritance", vec!("base","basecrate","derived","derivedcrate"), - true, false), + true, + false), MethodCall => ("method_call", vec!("refid","refidcrate","declid","declidcrate","scopeid"), - true, true), + true, + true), Typedef => ("typedef", vec!("id","qualname","value"), true, true), ExternalCrate => ("external_crate", vec!("name","crate","file_name"), false, false), Crate => ("crate", vec!("name"), true, false), FnCall => ("fn_call", vec!("refid","refidcrate","qualname","scopeid"), true, true), ModRef => ("mod_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true), VarRef => ("var_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true), - TypeRef => ("type_ref", - vec!("refid","refidcrate","qualname","scopeid"), - true, true), - FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true) + TypeRef => ("type_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true), + FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true), } } @@ -159,7 +156,8 @@ impl<'a> FmtStrs<'a> { kind: &'static str, fields: &Vec<&'static str>, values: Vec, - span: Span) -> Option { + span: Span) + -> Option { if values.len() != fields.len() { self.span.sess.span_bug(span, &format!( "Mismatch between length of fields for '{}', expected '{}', found '{}'", @@ -183,10 +181,7 @@ impl<'a> FmtStrs<'a> { })) } - pub fn record_without_span(&mut self, - kind: Row, - values: Vec, - span: Span) { + pub fn record_without_span(&mut self, kind: Row, values: Vec, span: Span) { let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind); if needs_span { @@ -387,7 +382,7 @@ impl<'a> FmtStrs<'a> { scope_id: NodeId) { let values = match decl_id { Some(decl_id) => svec!(id, name, decl_id.node, decl_id.krate, scope_id), - None => svec!(id, name, "", "", scope_id) + None => svec!(id, name, "", "", scope_id), }; self.check_and_record(Function, span, @@ -476,7 +471,7 @@ impl<'a> FmtStrs<'a> { parent: NodeId) { let (mod_node, mod_crate) = match mod_id { Some(mod_id) => (mod_id.node, mod_id.krate), - None => (0, 0) + None => (0, 0), }; self.check_and_record(UseAlias, span, @@ -528,7 +523,7 @@ impl<'a> FmtStrs<'a> { span: Span, sub_span: Option, id: DefId, - scope_id:NodeId) { + scope_id: NodeId) { self.check_and_record(FnCall, span, sub_span, @@ -543,11 +538,11 @@ impl<'a> FmtStrs<'a> { scope_id: NodeId) { let (dfn, dfk) = match defid { Some(defid) => (defid.node, defid.krate), - None => (0, 0) + None => (0, 0), }; let (dcn, dck) = match declid { Some(declid) => (s!(declid.node), s!(declid.krate)), - None => ("".to_string(), "".to_string()) + None => ("".to_string(), "".to_string()), }; self.check_and_record(MethodCall, span, @@ -555,11 +550,7 @@ impl<'a> FmtStrs<'a> { svec!(dfn, dfk, dcn, dck, scope_id)); } - pub fn sub_mod_ref_str(&mut self, - span: Span, - sub_span: Span, - qualname: &str, - parent:NodeId) { + pub fn sub_mod_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str, parent: NodeId) { self.record_with_span(ModRef, span, sub_span, @@ -578,29 +569,21 @@ impl<'a> FmtStrs<'a> { svec!(id, qualname, value)); } - pub fn crate_str(&mut self, - span: Span, - name: &str) { + pub fn crate_str(&mut self, span: Span, name: &str) { self.record_with_span(Crate, span, span, svec!(name)); } - pub fn external_crate_str(&mut self, - span: Span, - name: &str, - num: ast::CrateNum) { + pub fn external_crate_str(&mut self, span: Span, name: &str, num: ast::CrateNum) { let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo); self.record_without_span(ExternalCrate, svec!(name, num, lo_loc.file.name), span); } - pub fn sub_type_ref_str(&mut self, - span: Span, - sub_span: Span, - qualname: &str) { + pub fn sub_type_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str) { self.record_with_span(TypeRef, span, sub_span, diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index ee7b1c4ff6e29..5647e88658a3b 100644 --- a/src/librustc_trans/save/span_utils.rs +++ b/src/librustc_trans/save/span_utils.rs @@ -17,7 +17,7 @@ use std::cell::Cell; use syntax::ast; use syntax::codemap::*; use syntax::parse::lexer; -use syntax::parse::lexer::{Reader,StringReader}; +use syntax::parse::lexer::{Reader, StringReader}; use syntax::parse::token; use syntax::parse::token::{keywords, Token}; @@ -29,10 +29,7 @@ pub struct SpanUtils<'a> { impl<'a> SpanUtils<'a> { pub fn new(sess: &'a Session) -> SpanUtils<'a> { - SpanUtils { - sess: sess, - err_count: Cell::new(0) - } + SpanUtils { sess: sess, err_count: Cell::new(0) } } // Standard string for extents/location. @@ -62,8 +59,7 @@ impl<'a> SpanUtils<'a> { match sub_span { None => None, Some(sub) => { - let FileMapAndBytePos {fm, pos} = - self.sess.codemap().lookup_byte_offset(span.lo); + let FileMapAndBytePos {fm, pos} = self.sess.codemap().lookup_byte_offset(span.lo); let base = pos + fm.start_pos; Some(Span { lo: base + self.sess.codemap().lookup_byte_offset(sub.lo).pos, @@ -107,8 +103,7 @@ impl<'a> SpanUtils<'a> { if ts.tok == token::Eof { return self.make_sub_span(span, result) } - if bracket_count == 0 && - (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { + if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { result = Some(ts.sp); } @@ -116,7 +111,7 @@ impl<'a> SpanUtils<'a> { token::Lt => 1, token::Gt => -1, token::BinOp(token::Shr) => -2, - _ => 0 + _ => 0, } } } @@ -130,8 +125,7 @@ impl<'a> SpanUtils<'a> { if ts.tok == token::Eof { return None; } - if bracket_count == 0 && - (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { + if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { return self.make_sub_span(span, Some(ts.sp)); } @@ -139,7 +133,7 @@ impl<'a> SpanUtils<'a> { token::Lt => 1, token::Gt => -1, token::BinOp(token::Shr) => -2, - _ => 0 + _ => 0, } } } @@ -156,20 +150,16 @@ impl<'a> SpanUtils<'a> { last_span = None; let mut next = toks.real_token(); - if (next.tok == token::OpenDelim(token::Paren) || - next.tok == token::Lt) && - bracket_count == 0 && - prev.tok.is_ident() { + if (next.tok == token::OpenDelim(token::Paren) || next.tok == token::Lt) && + bracket_count == 0 && prev.tok.is_ident() { result = Some(prev.sp); } - if bracket_count == 0 && - next.tok == token::ModSep { + if bracket_count == 0 && next.tok == token::ModSep { let old = prev; prev = next; next = toks.real_token(); - if next.tok == token::Lt && - old.tok.is_ident() { + if next.tok == token::Lt && old.tok.is_ident() { result = Some(old.sp); } } @@ -178,7 +168,7 @@ impl<'a> SpanUtils<'a> { token::OpenDelim(token::Paren) | token::Lt => 1, token::CloseDelim(token::Paren) | token::Gt => -1, token::BinOp(token::Shr) => -2, - _ => 0 + _ => 0, }; if prev.tok.is_ident() && bracket_count == 0 { @@ -202,9 +192,7 @@ impl<'a> SpanUtils<'a> { loop { let next = toks.real_token(); - if (next.tok == token::Lt || - next.tok == token::Colon) && - bracket_count == 0 && + if (next.tok == token::Lt || next.tok == token::Colon) && bracket_count == 0 && prev.tok.is_ident() { result = Some(prev.sp); } @@ -214,7 +202,7 @@ impl<'a> SpanUtils<'a> { token::Gt => -1, token::BinOp(token::Shl) => 2, token::BinOp(token::Shr) => -2, - _ => 0 + _ => 0, }; if next.tok == token::Eof { @@ -265,7 +253,7 @@ impl<'a> SpanUtils<'a> { token::Gt => -1, token::BinOp(token::Shl) => 2, token::BinOp(token::Shr) => -2, - _ => 0 + _ => 0, }; // Ignore the `>::` in `::AssocTy`. @@ -316,21 +304,15 @@ impl<'a> SpanUtils<'a> { } } - pub fn sub_span_after_keyword(&self, - span: Span, - keyword: keywords::Keyword) -> Option { + pub fn sub_span_after_keyword(&self, span: Span, keyword: keywords::Keyword) -> Option { self.sub_span_after(span, |t| t.is_keyword(keyword)) } - pub fn sub_span_after_token(&self, - span: Span, - tok: Token) -> Option { + pub fn sub_span_after_token(&self, span: Span, tok: Token) -> Option { self.sub_span_after(span, |t| t == tok) } - fn sub_span_after bool>(&self, - span: Span, - f: F) -> Option { + fn sub_span_after bool>(&self, span: Span, f: F) -> Option { let mut toks = self.retokenise_span(span); loop { let ts = toks.real_token(); diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index d139819a79f9e..a3ba174a6e5a4 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -155,7 +155,7 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, v: ValueRef, ty: Ty<'tcx>) -> (ValueRef, Ty<'tcx>) { - match ty.builtin_deref(true) { + match ty.builtin_deref(true, ty::NoPreference) { Some(mt) => { if type_is_sized(cx.tcx(), mt.ty) { (const_deref_ptr(cx, v), mt.ty) @@ -329,7 +329,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, param_substs, &target); - let pointee_ty = ty.builtin_deref(true) + let pointee_ty = ty.builtin_deref(true, ty::NoPreference) .expect("consts: unsizing got non-pointer type").ty; let (base, old_info) = if !type_is_sized(cx.tcx(), pointee_ty) { // Normally, the source is a thin pointer and we are @@ -344,7 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, (llconst, None) }; - let unsized_ty = target.builtin_deref(true) + let unsized_ty = target.builtin_deref(true, ty::NoPreference) .expect("consts: unsizing got non-pointer target type").ty; let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to(); let base = ptrcast(base, ptr_ty); @@ -642,7 +642,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } if type_is_fat_ptr(cx.tcx(), t_expr) { // Fat pointer casts. - let t_cast_inner = t_cast.builtin_deref(true).expect("cast to non-pointer").ty; + let t_cast_inner = + t_cast.builtin_deref(true, ty::NoPreference).expect("cast to non-pointer").ty; let ptr_ty = type_of::in_memory_type_of(cx, t_cast_inner).ptr_to(); let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]), ptr_ty); diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 83644beae22d2..9dc96ff72ebad 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -780,7 +780,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let ref_ty = // invoked methods have LB regions instantiated: bcx.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap().unwrap(); - let elt_ty = match ref_ty.builtin_deref(true) { + let elt_ty = match ref_ty.builtin_deref(true, ty::NoPreference) { None => { bcx.tcx().sess.span_bug(index_expr.span, "index method didn't return a \ @@ -1971,7 +1971,8 @@ pub fn cast_is_noop<'tcx>(tcx: &ty::ctxt<'tcx>, return true; } - match (t_in.builtin_deref(true), t_out.builtin_deref(true)) { + match (t_in.builtin_deref(true, ty::NoPreference), + t_out.builtin_deref(true, ty::NoPreference)) { (Some(ty::TypeAndMut{ ty: t_in, .. }), Some(ty::TypeAndMut{ ty: t_out, .. })) => { t_in == t_out } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index abe72aed323f2..bcfd44d8835d7 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -936,6 +936,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, any_changes_needed: &mut bool) -> Vec { use intrinsics::Type::*; match *t { + Void => vec![Type::void(ccx)], Integer(_signed, width, llvm_width) => { *any_changes_needed |= width != llvm_width; vec![Type::ix(ccx, llvm_width as u64)] @@ -947,14 +948,29 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => unreachable!() } } - Pointer(_) => unimplemented!(), - Vector(ref t, length) => { + Pointer(ref t, ref llvm_elem, _const) => { + *any_changes_needed |= llvm_elem.is_some(); + + let t = llvm_elem.as_ref().unwrap_or(t); + let elem = one(ty_to_type(ccx, t, + any_changes_needed)); + vec![elem.ptr_to()] + } + Vector(ref t, ref llvm_elem, length) => { + *any_changes_needed |= llvm_elem.is_some(); + + let t = llvm_elem.as_ref().unwrap_or(t); let elem = one(ty_to_type(ccx, t, any_changes_needed)); vec![Type::vector(&elem, length as u64)] } - Aggregate(false, _) => unimplemented!(), + Aggregate(false, ref contents) => { + let elems = contents.iter() + .map(|t| one(ty_to_type(ccx, t, any_changes_needed))) + .collect::>(); + vec![Type::struct_(ccx, &elems, false)] + } Aggregate(true, ref contents) => { *any_changes_needed = true; contents.iter() @@ -965,8 +981,9 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } // This allows an argument list like `foo, (bar, baz), - // qux` to be converted into `foo, bar, baz, qux`, and - // integer arguments to be truncated as needed. + // qux` to be converted into `foo, bar, baz, qux`, integer + // arguments to be truncated as needed and pointers to be + // cast. fn modify_as_needed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: &intrinsics::Type, arg_type: Ty<'tcx>, @@ -991,6 +1008,16 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }) .collect() } + intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => { + let llvm_elem = one(ty_to_type(bcx.ccx(), llvm_elem, &mut false)); + vec![PointerCast(bcx, llarg, + llvm_elem.ptr_to())] + } + intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => { + let llvm_elem = one(ty_to_type(bcx.ccx(), llvm_elem, &mut false)); + vec![BitCast(bcx, llarg, + Type::vector(&llvm_elem, length as u64))] + } intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => { // the LLVM intrinsic uses a smaller integer // size than the C intrinsic's signature, so @@ -1027,7 +1054,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }; assert_eq!(inputs.len(), llargs.len()); - match intr.definition { + let val = match intr.definition { intrinsics::IntrinsicDef::Named(name) => { let f = declare::declare_cfn(ccx, name, @@ -1035,6 +1062,20 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, tcx.mk_nil()); Call(bcx, f, &llargs, None, call_debug_location) } + }; + + match intr.output { + intrinsics::Type::Aggregate(flatten, ref elems) => { + // the output is a tuple so we need to munge it properly + assert!(!flatten); + + for i in 0..elems.len() { + let val = ExtractValue(bcx, val, i); + Store(bcx, val, StructGEP(bcx, llresult, i)); + } + C_nil(ccx) + } + _ => val, } } }; diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index f6f7586de5c51..2ce06786db281 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -15,10 +15,10 @@ use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding}; use middle::pat_util::pat_is_resolved_const; use middle::privacy::{AllPublic, LastMod}; use middle::subst::Substs; -use middle::ty::{self, Ty, HasTypeFlags}; +use middle::ty::{self, Ty, HasTypeFlags, LvaluePreference}; use check::{check_expr, check_expr_has_type, check_expr_with_expectation}; use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation}; -use check::{check_expr_with_lvalue_pref, LvaluePreference}; +use check::{check_expr_with_lvalue_pref}; use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type}; use require_same_types; use util::nodemap::FnvHashMap; @@ -292,7 +292,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span)); tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut { ty: tcx.mk_slice(inner_ty), - mutbl: expected_ty.builtin_deref(true).map(|mt| mt.mutbl) + mutbl: expected_ty.builtin_deref(true, ty::NoPreference).map(|mt| mt.mutbl) .unwrap_or(hir::MutImmutable) }) } @@ -310,7 +310,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } if let Some(ref slice) = *slice { let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span)); - let mutbl = expected_ty.builtin_deref(true) + let mutbl = expected_ty.builtin_deref(true, ty::NoPreference) .map_or(hir::MutImmutable, |mt| mt.mutbl); let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut { @@ -399,7 +399,7 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let tcx = pcx.fcx.ccx.tcx; if pat_is_binding(&tcx.def_map, inner) { let expected = fcx.infcx().shallow_resolve(expected); - expected.builtin_deref(true).map_or(true, |mt| match mt.ty.sty { + expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty { ty::TyTrait(_) => { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 65366fb9176b4..948b7dd156192 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -18,7 +18,6 @@ use super::err_args; use super::Expectation; use super::expected_types_for_fn_args; use super::FnCtxt; -use super::LvaluePreference; use super::method; use super::structurally_resolved_type; use super::TupleArgumentsFlag; @@ -28,7 +27,7 @@ use super::write_call; use CrateCtxt; use middle::def_id::{DefId, LOCAL_CRATE}; use middle::infer; -use middle::ty::{self, Ty}; +use middle::ty::{self, LvaluePreference, Ty}; use syntax::codemap::Span; use syntax::parse::token; use syntax::ptr::P; diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index d6140fbe954e4..65409afa52d10 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -60,13 +60,13 @@ //! sort of a minor point so I've opted to leave it for later---after all //! we may want to adjust precisely when coercions occur. -use check::{autoderef, FnCtxt, LvaluePreference, UnresolvedTypeAction}; +use check::{autoderef, FnCtxt, UnresolvedTypeAction}; use middle::infer::{self, Coercion}; use middle::traits::{self, ObligationCause}; use middle::traits::{predicate_for_trait_def, report_selection_error}; use middle::ty::{AutoDerefRef, AdjustDerefRef}; -use middle::ty::{self, TypeAndMut, Ty, TypeError}; +use middle::ty::{self, LvaluePreference, TypeAndMut, Ty, TypeError}; use middle::ty_relate::RelateResult; use util::common::indent; diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 0c8bdc0ee04a3..d1f898d82fdd3 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -464,6 +464,10 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( }; match *expected { + Void => match t.sty { + ty::TyTuple(ref v) if v.is_empty() => {}, + _ => simple_error(&format!("`{}`", t), "()"), + }, // (The width we pass to LLVM doesn't concern the type checker.) Integer(signed, bits, _llvm_width) => match (signed, bits, &t.sty) { (true, 8, &ty::TyInt(hir::IntTy::TyI8)) | @@ -485,8 +489,21 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( _ => simple_error(&format!("`{}`", t), &format!("`f{n}`", n = bits)), }, - Pointer(_) => unimplemented!(), - Vector(ref inner_expected, len) => { + Pointer(ref inner_expected, ref _llvm_type, const_) => { + match t.sty { + ty::TyRawPtr(ty::TypeAndMut { ty, mutbl }) => { + if (mutbl == hir::MutImmutable) != const_ { + simple_error(&format!("`{}`", t), + if const_ {"const pointer"} else {"mut pointer"}) + } + match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal, + inner_expected, ty) + } + _ => simple_error(&format!("`{}`", t), + &format!("raw pointer")), + } + } + Vector(ref inner_expected, ref _llvm_type, len) => { if !t.is_simd() { simple_error(&format!("non-simd type `{}`", t), "simd type"); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 217c9ebacb3c9..040e644a94d1f 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -10,12 +10,12 @@ use super::probe; -use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand}; +use check::{self, FnCtxt, callee, demand}; use check::UnresolvedTypeAction; use middle::def_id::DefId; use middle::subst::{self}; use middle::traits; -use middle::ty::{self, Ty}; +use middle::ty::{self, NoPreference, PreferMutLvalue, Ty}; use middle::ty_fold::TypeFoldable; use middle::infer; use middle::infer::InferCtxt; @@ -534,7 +534,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { } Some(ty::AutoPtr(_, _)) => { (adr.autoderefs, adr.unsize.map(|target| { - target.builtin_deref(false) + target.builtin_deref(false, NoPreference) .expect("fixup: AutoPtr is not &T").ty })) } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 5adc71b229f4e..b04899f5ecdc7 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -14,13 +14,13 @@ use super::{CandidateSource, ImplSource, TraitSource}; use super::suggest; use check; -use check::{FnCtxt, NoPreference, UnresolvedTypeAction}; +use check::{FnCtxt, UnresolvedTypeAction}; use middle::def_id::DefId; use middle::fast_reject; use middle::subst; use middle::subst::Subst; use middle::traits; -use middle::ty::{self, RegionEscape, Ty, ToPolyTraitRef, TraitRef}; +use middle::ty::{self, NoPreference, RegionEscape, Ty, ToPolyTraitRef, TraitRef}; use middle::ty::HasTypeFlags; use middle::ty_fold::TypeFoldable; use middle::infer; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index d9f691d065ba2..6961f3444d908 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -324,7 +324,7 @@ fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } check::autoderef(fcx, span, rcvr_ty, None, - check::UnresolvedTypeAction::Ignore, check::NoPreference, + check::UnresolvedTypeAction::Ignore, ty::NoPreference, |ty, _| { if is_local(ty) { Some(()) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a5fc9ce6a958a..c4368a3898d3a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -76,7 +76,6 @@ type parameter). */ -pub use self::LvaluePreference::*; pub use self::Expectation::*; pub use self::compare_method::{compare_impl_method, compare_const_impl}; use self::TupleArgumentsFlag::*; @@ -95,6 +94,7 @@ use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace use middle::traits::{self, report_fulfillment_errors}; use middle::ty::{FnSig, GenericPredicates, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; +use middle::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty}; use middle::ty::{MethodCall, MethodCallee}; use middle::ty_fold::{TypeFolder, TypeFoldable}; @@ -2086,21 +2086,6 @@ impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum LvaluePreference { - PreferMutLvalue, - NoPreference -} - -impl LvaluePreference { - pub fn from_mutbl(m: hir::Mutability) -> Self { - match m { - hir::MutMutable => PreferMutLvalue, - hir::MutImmutable => NoPreference, - } - } -} - /// Whether `autoderef` requires types to resolve. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum UnresolvedTypeAction { @@ -2156,7 +2141,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, } // Otherwise, deref if type is derefable: - let mt = match resolved_t.builtin_deref(false) { + let mt = match resolved_t.builtin_deref(false, lvalue_pref) { Some(mt) => Some(mt), None => { let method_call = @@ -2245,7 +2230,7 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } // method returns &T, but the type as visible to user is T, so deref - ret_ty.builtin_deref(true) + ret_ty.builtin_deref(true, NoPreference) } None => None, } @@ -3293,7 +3278,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } hir::UnDeref => { oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t); - oprnd_t = match oprnd_t.builtin_deref(true) { + oprnd_t = match oprnd_t.builtin_deref(true, NoPreference) { Some(mt) => mt.ty, None => match try_overloaded_deref(fcx, expr.span, Some(MethodCall::expr(expr.id)), diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index bdca8ae444bd4..07754e8506b9c 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -17,12 +17,11 @@ use super::{ demand, method, FnCtxt, - PreferMutLvalue, structurally_resolved_type, }; use middle::def_id::DefId; use middle::traits; -use middle::ty::{Ty, HasTypeFlags}; +use middle::ty::{Ty, HasTypeFlags, PreferMutLvalue}; use syntax::ast; use syntax::parse::token; use rustc_front::hir; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index ab67dfebdacfe..844e143b9fa5b 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1031,7 +1031,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, r_deref_expr, *r_ptr); } - match derefd_ty.builtin_deref(true) { + match derefd_ty.builtin_deref(true, ty::NoPreference) { Some(mt) => derefd_ty = mt.ty, /* if this type can't be dereferenced, then there's already an error in the session saying so. Just bail out for now */ diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index dfce7a9c31584..8a2f8b1cf4bb0 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2475,6 +2475,24 @@ struct Bar { x: Foo } ``` "##, +//NB: not currently reachable +E0247: r##" +This error indicates an attempt to use a module name where a type is expected. +For example: + +``` +mod MyMod { + mod MySubMod { } +} + +fn do_something(x: MyMod::MySubMod) { } +``` + +In this example, we're attempting to take a parameter of type `MyMod::MySubMod` +in the do_something function. This is not legal: `MyMod::MySubMod` is a module +name, not a type. +"##, + E0248: r##" This error indicates an attempt to use a value where a type is expected. For example: @@ -3291,7 +3309,6 @@ register_diagnostics! { E0242, // internal error looking up a definition E0245, // not a trait // E0246, // invalid recursive type - E0247, // found module name used as a type // E0319, // trait impls for defaulted traits allowed just for structs/enums E0320, // recursive overflow during dropck E0321, // extended coherence rules for defaulted traits violated diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 4597db41e907d..82578172802f6 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -103,8 +103,8 @@ //! `Some` and `None`. //! * `std::result::Result::`{ //! [`self`](../result/enum.Result.html), -//! [`Some`](../result/enum.Result.html), -//! [`None`](../result/enum.Result.html) +//! [`Ok`](../result/enum.Result.html), +//! [`Err`](../result/enum.Result.html) //! }. //! The ubiquitous `Result` type and its two [variants][book-enums], //! `Ok` and `Err`. diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 35e3c1d4663e0..9534a107d1616 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -60,6 +60,9 @@ extern "system" { type SymFromAddrFn = extern "system" fn(libc::HANDLE, u64, *mut u64, *mut SYMBOL_INFO) -> libc::BOOL; +type SymGetLineFromAddr64Fn = + extern "system" fn(libc::HANDLE, u64, *mut u32, + *mut IMAGEHLP_LINE64) -> libc::BOOL; type SymInitializeFn = extern "system" fn(libc::HANDLE, *mut libc::c_void, libc::BOOL) -> libc::BOOL; @@ -99,6 +102,14 @@ struct SYMBOL_INFO { Name: [libc::c_char; MAX_SYM_NAME], } +#[repr(C)] +struct IMAGEHLP_LINE64 { + SizeOfStruct: u32, + Key: *const libc::c_void, + LineNumber: u32, + Filename: *const libc::c_char, + Address: u64, +} #[repr(C)] enum ADDRESS_MODE { diff --git a/src/libstd/sys/windows/printing/msvc.rs b/src/libstd/sys/windows/printing/msvc.rs index 25cef04ca969b..81d19374fea2d 100644 --- a/src/libstd/sys/windows/printing/msvc.rs +++ b/src/libstd/sys/windows/printing/msvc.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use sys_common::backtrace::output; +use sys_common::backtrace::{output, output_fileline}; use ffi::CStr; use dynamic_lib::DynamicLibrary; -use super::{SymFromAddrFn, SYMBOL_INFO, MAX_SYM_NAME}; +use super::{SymFromAddrFn, SymGetLineFromAddr64Fn, SYMBOL_INFO, MAX_SYM_NAME, IMAGEHLP_LINE64}; use io; use io::prelude::*; use intrinsics; @@ -20,6 +20,7 @@ use libc; pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, process: libc::HANDLE) -> io::Result<()> { let SymFromAddr = sym!(dbghelp, "SymFromAddr", SymFromAddrFn); + let SymGetLineFromAddr64 = sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn); let mut info: SYMBOL_INFO = unsafe { intrinsics::init() }; info.MaxNameLen = MAX_SYM_NAME as libc::c_ulong; @@ -29,7 +30,7 @@ pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, proce info.SizeOfStruct = 88; let mut displacement = 0u64; - let ret = SymFromAddr(process, addr as u64, &mut displacement, &mut info); + let ret = SymFromAddr(process, addr, &mut displacement, &mut info); let name = if ret == libc::TRUE { let ptr = info.Name.as_ptr() as *const libc::c_char; @@ -38,5 +39,20 @@ pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, proce None }; - output(w, i, addr as usize as *mut libc::c_void, name) + try!(output(w, i, addr as usize as *mut libc::c_void, name)); + + // Now find out the filename and line number + let mut line: IMAGEHLP_LINE64 = unsafe { intrinsics::init() }; + line.SizeOfStruct = ::mem::size_of::() as u32; + + let mut displacement = 0u32; + let ret = SymGetLineFromAddr64(process, addr, &mut displacement, &mut line); + if ret == libc::TRUE { + output_fileline(w, + unsafe { CStr::from_ptr(line.Filename).to_bytes() }, + line.LineNumber as libc::c_int, + false) + } else { + Ok(()) + } } diff --git a/src/rustbook/book.rs b/src/rustbook/book.rs index 2d630d8fe8de7..e14c3346cc155 100644 --- a/src/rustbook/book.rs +++ b/src/rustbook/book.rs @@ -102,7 +102,7 @@ pub fn parse_summary(input: &mut Read, src: &Path) -> Result> top_items.push(BookItem { title: "Introduction".to_string(), path: PathBuf::from("README.md"), - path_to_root: PathBuf::from("."), + path_to_root: PathBuf::from(""), children: vec!(), }); diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index a1f4539443d9b..aca0db4e1adbe 100644 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -52,16 +52,16 @@ fn write_toc(book: &Book, current_page: &BookItem, out: &mut Write) -> io::Resul current_page: &BookItem, out: &mut Write) -> io::Result<()> { let class_string = if item.path == current_page.path { - "class='active'" + "class='active'" } else { - "" + "" }; try!(writeln!(out, "
  • {} {}", - class_string, - current_page.path_to_root.join(&item.path).with_extension("html").display(), - section, - item.title)); + class_string, + current_page.path_to_root.join(&item.path).with_extension("html").display(), + section, + item.title)); if !item.children.is_empty() { try!(writeln!(out, "
      ")); let _ = walk_items(&item.children[..], section, current_page, out); diff --git a/src/test/run-pass/backtrace-debuginfo-aux.rs b/src/test/run-pass/backtrace-debuginfo-aux.rs index f0d36ea976ef7..48df600214ad0 100644 --- a/src/test/run-pass/backtrace-debuginfo-aux.rs +++ b/src/test/run-pass/backtrace-debuginfo-aux.rs @@ -15,7 +15,11 @@ pub fn callback(f: F) where F: FnOnce((&'static str, u32)) { f((file!(), line!())) } -#[inline(always)] +// LLVM does not yet output the required debug info to support showing inlined +// function calls in backtraces when targetting MSVC, so disable inlining in +// this case. +#[cfg_attr(not(target_env = "msvc"), inline(always))] +#[cfg_attr(target_env = "msvc", inline(never))] pub fn callback_inlined(f: F) where F: FnOnce((&'static str, u32)) { f((file!(), line!())) } diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index 5feca9422f656..b6400c68f5367 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -32,7 +32,7 @@ macro_rules! pos { not(target_os = "ios"), not(target_os = "android"), not(all(target_os = "linux", target_arch = "arm"))), - all(windows, target_env = "gnu", not(target_arch = "x86"))))] + all(windows, not(target_arch = "x86"))))] macro_rules! dump_and_die { ($($pos:expr),*) => ({ // FIXME(#18285): we cannot include the current position because @@ -48,7 +48,7 @@ macro_rules! dump_and_die { not(target_os = "ios"), not(target_os = "android"), not(all(target_os = "linux", target_arch = "arm"))), - all(windows, target_env = "gnu", not(target_arch = "x86")))))] + all(windows, not(target_arch = "x86")))))] macro_rules! dump_and_die { ($($pos:expr),*) => ({ let _ = [$($pos),*]; }) } @@ -69,7 +69,10 @@ type Pos = (&'static str, u32); // this goes to stdout and each line has to be occurred // in the following backtrace to stderr with a correct order. fn dump_filelines(filelines: &[Pos]) { - for &(file, line) in filelines.iter().rev() { + // Skip top frame for MSVC, because it sees the macro rather than + // the containing function. + let skip = if cfg!(target_env = "msvc") {1} else {0}; + for &(file, line) in filelines.iter().rev().skip(skip) { // extract a basename let basename = file.split(&['/', '\\'][..]).last().unwrap(); println!("{}:{}", basename, line); @@ -88,12 +91,18 @@ fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { }); } -#[inline(always)] +// LLVM does not yet output the required debug info to support showing inlined +// function calls in backtraces when targetting MSVC, so disable inlining in +// this case. +#[cfg_attr(not(target_env = "msvc"), inline(always))] +#[cfg_attr(target_env = "msvc", inline(never))] fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { check!(counter; main_pos, outer_pos); check!(counter; main_pos, outer_pos); - #[inline(always)] + // Again, disable inlining for MSVC. + #[cfg_attr(not(target_env = "msvc"), inline(always))] + #[cfg_attr(target_env = "msvc", inline(never))] fn inner_further_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos, inner_pos: Pos) { check!(counter; main_pos, outer_pos, inner_pos); } diff --git a/src/test/run-pass/issue-26205.rs b/src/test/run-pass/issue-26205.rs new file mode 100644 index 0000000000000..dd34612af0fc6 --- /dev/null +++ b/src/test/run-pass/issue-26205.rs @@ -0,0 +1,39 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::{Deref, DerefMut}; + +struct Foo; + +impl Foo { + fn foo_mut(&mut self) {} +} + +struct Bar(Foo); + +impl Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &self.0 + } +} + +impl DerefMut for Bar { + fn deref_mut(&mut self) -> &mut Foo { + &mut self.0 + } +} + +fn test(mut bar: Box) { + bar.foo_mut(); +} + +fn main() {}